xref: /DragonOS/kernel/src/driver/disk/ahci/mod.rs (revision 8d94ea66a3eb3e02039730c8d08e9bead8c344b8)
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 as *mut HbaMem).as_mut().unwrap() };
97         hba_mem_list.push(unsafe { (virtaddr 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