1 // 导出 ahci 相关的 module 2 pub mod ahci_inode; 3 pub mod ahcidisk; 4 pub mod hba; 5 6 use crate::filesystem::vfs::io::device::BlockDevice; 7 // 依赖的rust工具包 8 use crate::driver::pci::pci::{ 9 get_pci_device_structure_mut, PciDeviceStructure, PCI_DEVICE_LINKEDLIST, 10 }; 11 use crate::filesystem::devfs::devfs_register; 12 use crate::filesystem::vfs::io::disk_info::BLK_GF_AHCI; 13 use crate::kerror; 14 use crate::libs::rwlock::RwLockWriteGuard; 15 use crate::libs::spinlock::{SpinLock, SpinLockGuard}; 16 use crate::mm::virt_2_phys; 17 use crate::syscall::SystemError; 18 use crate::{ 19 driver::disk::ahci::{ 20 ahcidisk::LockedAhciDisk, 21 hba::HbaMem, 22 hba::{HbaPort, HbaPortType}, 23 }, 24 kdebug, 25 }; 26 use ahci_inode::LockedAhciInode; 27 use alloc::{ 28 boxed::Box, 29 collections::LinkedList, 30 format, 31 string::{String, ToString}, 32 sync::Arc, 33 vec::Vec, 34 }; 35 use core::sync::atomic::compiler_fence; 36 37 // 仅module内可见 全局数据区 hbr_port, disks 38 static LOCKED_HBA_MEM_LIST: SpinLock<Vec<&mut HbaMem>> = SpinLock::new(Vec::new()); 39 static LOCKED_DISKS_LIST: SpinLock<Vec<Arc<LockedAhciDisk>>> = SpinLock::new(Vec::new()); 40 41 const AHCI_CLASS: u8 = 0x1; 42 const AHCI_SUBCLASS: u8 = 0x6; 43 44 /* TFES - Task File Error Status */ 45 #[allow(non_upper_case_globals)] 46 pub const HBA_PxIS_TFES: u32 = 1 << 30; 47 48 #[no_mangle] 49 pub extern "C" fn ahci_init() -> i32 { 50 let r = ahci_rust_init(); 51 if r.is_ok() { 52 return 0; 53 } else { 54 return r.unwrap_err().to_posix_errno(); 55 } 56 } 57 58 /// @brief 寻找所有的ahci设备 59 /// @param list 链表的写锁 60 /// @return Result<Vec<&'a mut Box<dyn PciDeviceStructure>>, SystemError> 成功则返回包含所有ahci设备结构体的可变引用的链表,失败则返回err 61 fn ahci_device_search<'a>( 62 list: &'a mut RwLockWriteGuard<'_, LinkedList<Box<dyn PciDeviceStructure>>>, 63 ) -> Result<Vec<&'a mut Box<dyn PciDeviceStructure>>, SystemError> { 64 let result = get_pci_device_structure_mut(list, AHCI_CLASS, AHCI_SUBCLASS); 65 66 if result.is_empty() { 67 return Err(SystemError::ENODEV); 68 } 69 kdebug!("{}", result.len()); 70 Ok(result) 71 } 72 73 /// @brief: 初始化 ahci 74 pub fn ahci_rust_init() -> Result<(), SystemError> { 75 let mut list = PCI_DEVICE_LINKEDLIST.write(); 76 let ahci_device = ahci_device_search(&mut list)?; 77 // 全局数据 - 列表 78 let mut disks_list = LOCKED_DISKS_LIST.lock(); 79 80 for device in ahci_device { 81 let standard_device = device.as_standard_device_mut().unwrap(); 82 standard_device.bar_ioremap(); 83 // 对于每一个ahci控制器分配一块空间 (目前slab algorithm最大支持1MB) 84 let ahci_port_base_vaddr = 85 Box::leak(Box::new([0u8; (1 << 20) as usize])) as *mut u8 as usize; 86 let virtaddr = standard_device 87 .bar() 88 .ok_or(SystemError::EACCES)? 89 .get_bar(5) 90 .or(Err(SystemError::EACCES))? 91 .virtual_address() 92 .unwrap(); 93 // 最后把这个引用列表放入到全局列表 94 let mut hba_mem_list = LOCKED_HBA_MEM_LIST.lock(); 95 //这里两次unsafe转引用规避rust只能有一个可变引用的检查,提高运行速度 96 let hba_mem = unsafe { (virtaddr.data() as *mut HbaMem).as_mut().unwrap() }; 97 hba_mem_list.push(unsafe { (virtaddr.data() as *mut HbaMem).as_mut().unwrap() }); 98 let pi = volatile_read!(hba_mem.pi); 99 let hba_mem_index = hba_mem_list.len() - 1; 100 drop(hba_mem_list); 101 // 初始化所有的port 102 let mut id = 0; 103 for j in 0..32 { 104 if (pi >> j) & 1 > 0 { 105 let hba_mem_list = LOCKED_HBA_MEM_LIST.lock(); 106 let hba_mem_port = &mut hba_mem.ports[j]; 107 let tp = hba_mem_port.check_type(); 108 match tp { 109 HbaPortType::None => { 110 kdebug!("<ahci_rust_init> Find a None type Disk."); 111 } 112 HbaPortType::Unknown(err) => { 113 kdebug!("<ahci_rust_init> Find a Unknown({:?}) type Disk.", err); 114 } 115 _ => { 116 kdebug!("<ahci_rust_init> Find a {:?} type Disk.", tp); 117 118 // 计算地址 119 let fb = virt_2_phys(ahci_port_base_vaddr + (32 << 10) + (j << 8)); 120 let clb = virt_2_phys(ahci_port_base_vaddr + (j << 10)); 121 let ctbas = (0..32) 122 .map(|x| { 123 virt_2_phys( 124 ahci_port_base_vaddr + (40 << 10) + (j << 13) + (x << 8), 125 ) as u64 126 }) 127 .collect::<Vec<_>>(); 128 129 // 初始化 port 130 hba_mem_port.init(clb as u64, fb as u64, &ctbas); 131 drop(hba_mem_list); 132 compiler_fence(core::sync::atomic::Ordering::SeqCst); 133 // 创建 disk 134 disks_list.push(LockedAhciDisk::new( 135 format!("ahci_disk_{}", id), 136 BLK_GF_AHCI, 137 hba_mem_index as u8, 138 j as u8, 139 )?); 140 id += 1; // ID 从0开始 141 142 kdebug!("start register ahci device"); 143 144 // 挂载到devfs上面去 145 let ret = devfs_register( 146 format!("ahci_{}", id).as_str(), 147 LockedAhciInode::new(disks_list.last().unwrap().clone()), 148 ); 149 if let Err(err) = ret { 150 kerror!( 151 "Ahci_{} ctrl = {}, port = {} failed to register, error code = {:?}", 152 id, 153 hba_mem_index as u8, 154 j, 155 err 156 ); 157 } 158 } 159 } 160 } 161 } 162 } 163 164 compiler_fence(core::sync::atomic::Ordering::SeqCst); 165 return Ok(()); 166 } 167 168 /// @brief: 获取所有的 disk 169 #[allow(dead_code)] 170 pub fn disks() -> Vec<Arc<LockedAhciDisk>> { 171 let disks_list = LOCKED_DISKS_LIST.lock(); 172 return disks_list.clone(); 173 } 174 175 /// @brief: 通过 name 获取 disk 176 pub fn get_disks_by_name(name: String) -> Result<Arc<LockedAhciDisk>, SystemError> { 177 let disks_list: SpinLockGuard<Vec<Arc<LockedAhciDisk>>> = LOCKED_DISKS_LIST.lock(); 178 let result = disks_list 179 .iter() 180 .find(|x| x.0.lock().name == name) 181 .ok_or(SystemError::ENXIO)? 182 .clone(); 183 return Ok(result); 184 } 185 186 /// @brief: 通过 ctrl_num 和 port_num 获取 port 187 fn _port(ctrl_num: u8, port_num: u8) -> &'static mut HbaPort { 188 let list: SpinLockGuard<Vec<&mut HbaMem>> = LOCKED_HBA_MEM_LIST.lock(); 189 let port: &HbaPort = &list[ctrl_num as usize].ports[port_num as usize]; 190 191 return unsafe { (port as *const HbaPort as *mut HbaPort).as_mut().unwrap() }; 192 } 193 194 /// @brief: 测试函数 195 pub fn __test_ahci() { 196 let _res = ahci_rust_init(); 197 let disk: Arc<LockedAhciDisk> = get_disks_by_name("ahci_disk_0".to_string()).unwrap(); 198 #[deny(overflowing_literals)] 199 let mut buf = [0u8; 3000usize]; 200 201 for i in 0..2000 { 202 buf[i] = i as u8; 203 } 204 205 let _dd = disk; 206 207 // 测试1, 写两个块,读4个块 208 // _dd.write_at(123, 2, &buf).unwrap(); 209 let mut read_buf = [0u8; 3000usize]; 210 _dd.read_at(122, 4, &mut read_buf).unwrap(); 211 212 // 测试2, 只读写一个字节 213 for i in 0..512 { 214 buf[i] = 233; 215 } 216 // _dd.write_at(123, 2, &buf).unwrap(); 217 let mut read_buf2 = [0u8; 3000usize]; 218 _dd.read_at(122, 4, &mut read_buf2).unwrap(); 219 } 220