DragonOS/kernel/src/driver/disk/ahci/mod.rs

144 lines
5.6 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 导出 ahci 相关的 module
pub mod ahci_inode;
pub mod ahcidisk;
pub mod hba;
use crate::arch::MMArch;
use crate::driver::base::block::manager::block_dev_manager;
use crate::driver::block::cache::cached_block_device::BlockCache;
use crate::driver::disk::ahci::ahcidisk::LockedAhciDisk;
use crate::driver::pci::pci::{
get_pci_device_structure_mut, PciDeviceStructure, PCI_DEVICE_LINKEDLIST,
};
use crate::driver::disk::ahci::{
hba::HbaMem,
hba::{HbaPort, HbaPortType},
};
use crate::libs::rwlock::RwLockWriteGuard;
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
use crate::mm::{MemoryManagementArch, VirtAddr};
use alloc::{boxed::Box, collections::LinkedList, vec::Vec};
use core::sync::atomic::compiler_fence;
use log::debug;
use system_error::SystemError;
// 仅module内可见 全局数据区 hbr_port, disks
static LOCKED_HBA_MEM_LIST: SpinLock<Vec<&mut HbaMem>> = SpinLock::new(Vec::new());
const AHCI_CLASS: u8 = 0x1;
const AHCI_SUBCLASS: u8 = 0x6;
/* TFES - Task File Error Status */
#[allow(non_upper_case_globals)]
pub const HBA_PxIS_TFES: u32 = 1 << 30;
/// @brief 寻找所有的ahci设备
/// @param list 链表的写锁
/// @return Result<Vec<&'a mut Box<dyn PciDeviceStructure>>, SystemError> 成功则返回包含所有ahci设备结构体的可变引用的链表失败则返回err
fn ahci_device_search<'a>(
list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>,
) -> Result<Vec<&'a mut Box<dyn PciDeviceStructure>>, SystemError> {
let result = get_pci_device_structure_mut(list, AHCI_CLASS, AHCI_SUBCLASS);
if result.is_empty() {
return Err(SystemError::ENODEV);
}
return Ok(result);
}
/// @brief: 初始化 ahci
pub fn ahci_init() -> Result<(), SystemError> {
let mut list = PCI_DEVICE_LINKEDLIST.write();
let ahci_device = ahci_device_search(&mut list)?;
for device in ahci_device {
let standard_device = device.as_standard_device_mut().unwrap();
standard_device.bar_ioremap();
// 对于每一个ahci控制器分配一块空间
let ahci_port_base_vaddr =
Box::leak(Box::new([0u8; (1 << 20) as usize])) as *mut u8 as usize;
let virtaddr = standard_device
.bar()
.ok_or(SystemError::EACCES)?
.get_bar(5)
.or(Err(SystemError::EACCES))?
.virtual_address()
.unwrap();
// 最后把这个引用列表放入到全局列表
let mut hba_mem_list = LOCKED_HBA_MEM_LIST.lock();
//这里两次unsafe转引用规避rust只能有一个可变引用的检查提高运行速度
let hba_mem = unsafe { (virtaddr.data() as *mut HbaMem).as_mut().unwrap() };
hba_mem_list.push(unsafe { (virtaddr.data() as *mut HbaMem).as_mut().unwrap() });
let pi = volatile_read!(hba_mem.pi);
let hba_mem_index = hba_mem_list.len() - 1;
drop(hba_mem_list);
// 初始化所有的port
for j in 0..32 {
if (pi >> j) & 1 > 0 {
let hba_mem_list = LOCKED_HBA_MEM_LIST.lock();
let hba_mem_port = &mut hba_mem.ports[j];
let tp = hba_mem_port.check_type();
match tp {
HbaPortType::None => {
debug!("<ahci_rust_init> Find a None type Disk.");
}
HbaPortType::Unknown(err) => {
debug!("<ahci_rust_init> Find a Unknown({:?}) type Disk.", err);
}
_ => {
debug!("<ahci_rust_init> Find a {:?} type Disk.", tp);
// 计算地址
let fb = unsafe {
MMArch::virt_2_phys(VirtAddr::new(
ahci_port_base_vaddr + (32 << 10) + (j << 8),
))
}
.unwrap()
.data();
let clb = unsafe {
MMArch::virt_2_phys(VirtAddr::new(ahci_port_base_vaddr + (j << 10)))
.unwrap()
.data()
};
let ctbas = (0..32)
.map(|x| unsafe {
MMArch::virt_2_phys(VirtAddr::new(
ahci_port_base_vaddr + (40 << 10) + (j << 13) + (x << 8),
))
.unwrap()
.data() as u64
})
.collect::<Vec<_>>();
// 初始化 port
hba_mem_port.init(clb as u64, fb as u64, &ctbas);
drop(hba_mem_list);
compiler_fence(core::sync::atomic::Ordering::SeqCst);
let ahci_disk = LockedAhciDisk::new(hba_mem_index as u8, j as u8)?;
block_dev_manager()
.register(ahci_disk)
.expect("register ahci disk failed");
debug!("start register ahci device");
}
}
}
}
BlockCache::init();
}
compiler_fence(core::sync::atomic::Ordering::SeqCst);
return Ok(());
}
/// @brief: 通过 ctrl_num 和 port_num 获取 port
fn _port(ctrl_num: u8, port_num: u8) -> &'static mut HbaPort {
let list: SpinLockGuard<Vec<&mut HbaMem>> = LOCKED_HBA_MEM_LIST.lock();
let port: &HbaPort = &list[ctrl_num as usize].ports[port_num as usize];
return unsafe { (port as *const HbaPort as *mut HbaPort).as_mut().unwrap() };
}