xref: /DragonOS/kernel/src/driver/disk/ahci/mod.rs (revision 7c28051e8c601312d3d0fd7bcb71bc71450d10c0)
1 // 导出 ahci 相关的 module
2 pub mod ahcidisk;
3 pub mod hba;
4 use crate::arch::MMArch;
5 use crate::driver::base::block::manager::block_dev_manager;
6 use crate::driver::block::cache::cached_block_device::BlockCache;
7 use crate::driver::disk::ahci::ahcidisk::LockedAhciDisk;
8 use crate::driver::pci::pci::{
9     get_pci_device_structure_mut, PciDeviceLinkedList, PciDeviceStructure, PCI_DEVICE_LINKEDLIST,
10 };
11 use alloc::sync::Arc;
12 
13 use crate::driver::disk::ahci::{
14     hba::HbaMem,
15     hba::{HbaPort, HbaPortType},
16 };
17 use crate::libs::spinlock::{SpinLock, SpinLockGuard};
18 use crate::mm::{MemoryManagementArch, VirtAddr};
19 use alloc::{boxed::Box, vec::Vec};
20 use core::sync::atomic::compiler_fence;
21 use log::debug;
22 use system_error::SystemError;
23 
24 // 仅module内可见 全局数据区  hbr_port, disks
25 static LOCKED_HBA_MEM_LIST: SpinLock<Vec<&mut HbaMem>> = SpinLock::new(Vec::new());
26 
27 const AHCI_CLASS: u8 = 0x1;
28 const AHCI_SUBCLASS: u8 = 0x6;
29 
30 /* TFES - Task File Error Status */
31 #[allow(non_upper_case_globals)]
32 pub const HBA_PxIS_TFES: u32 = 1 << 30;
33 
34 /// @brief 寻找所有的ahci设备
35 /// @param list 链表的写锁
36 /// @return Result<Vec<&'a mut Box<dyn PciDeviceStructure>>, SystemError>   成功则返回包含所有ahci设备结构体的可变引用的链表,失败则返回err
ahci_device_search( list: &PciDeviceLinkedList, ) -> Result<Vec<Arc<dyn PciDeviceStructure>>, SystemError>37 fn ahci_device_search(
38     list: &PciDeviceLinkedList,
39 ) -> Result<Vec<Arc<dyn PciDeviceStructure>>, SystemError> {
40     let result = get_pci_device_structure_mut(list, AHCI_CLASS, AHCI_SUBCLASS);
41 
42     if result.is_empty() {
43         return Err(SystemError::ENODEV);
44     }
45 
46     return Ok(result);
47 }
48 
49 /// @brief: 初始化 ahci
ahci_init() -> Result<(), SystemError>50 pub fn ahci_init() -> Result<(), SystemError> {
51     let list = &*PCI_DEVICE_LINKEDLIST;
52     let ahci_device = ahci_device_search(list)?;
53 
54     for device in ahci_device {
55         let standard_device = device.as_standard_device().unwrap();
56         standard_device.bar_ioremap();
57         // 对于每一个ahci控制器分配一块空间
58         let ahci_port_base_vaddr =
59             Box::leak(Box::new([0u8; (1 << 20) as usize])) as *mut u8 as usize;
60         let virtaddr = standard_device
61             .bar()
62             .ok_or(SystemError::EACCES)?
63             .read()
64             .get_bar(5)
65             .or(Err(SystemError::EACCES))?
66             .virtual_address()
67             .unwrap();
68         // 最后把这个引用列表放入到全局列表
69         let mut hba_mem_list = LOCKED_HBA_MEM_LIST.lock();
70         //这里两次unsafe转引用规避rust只能有一个可变引用的检查,提高运行速度
71         let hba_mem = unsafe { (virtaddr.data() as *mut HbaMem).as_mut().unwrap() };
72         hba_mem_list.push(unsafe { (virtaddr.data() as *mut HbaMem).as_mut().unwrap() });
73         let pi = volatile_read!(hba_mem.pi);
74         let hba_mem_index = hba_mem_list.len() - 1;
75         drop(hba_mem_list);
76         // 初始化所有的port
77         for j in 0..32 {
78             if (pi >> j) & 1 > 0 {
79                 let hba_mem_list = LOCKED_HBA_MEM_LIST.lock();
80                 let hba_mem_port = &mut hba_mem.ports[j];
81                 let tp = hba_mem_port.check_type();
82                 match tp {
83                     HbaPortType::None => {
84                         debug!("<ahci_rust_init> Find a None type Disk.");
85                     }
86                     HbaPortType::Unknown(err) => {
87                         debug!("<ahci_rust_init> Find a Unknown({:?}) type Disk.", err);
88                     }
89                     _ => {
90                         debug!("<ahci_rust_init> Find a {:?} type Disk.", tp);
91 
92                         // 计算地址
93                         let fb = unsafe {
94                             MMArch::virt_2_phys(VirtAddr::new(
95                                 ahci_port_base_vaddr + (32 << 10) + (j << 8),
96                             ))
97                         }
98                         .unwrap()
99                         .data();
100                         let clb = unsafe {
101                             MMArch::virt_2_phys(VirtAddr::new(ahci_port_base_vaddr + (j << 10)))
102                                 .unwrap()
103                                 .data()
104                         };
105                         let ctbas = (0..32)
106                             .map(|x| unsafe {
107                                 MMArch::virt_2_phys(VirtAddr::new(
108                                     ahci_port_base_vaddr + (40 << 10) + (j << 13) + (x << 8),
109                                 ))
110                                 .unwrap()
111                                 .data() as u64
112                             })
113                             .collect::<Vec<_>>();
114 
115                         // 初始化 port
116                         hba_mem_port.init(clb as u64, fb as u64, &ctbas);
117                         drop(hba_mem_list);
118                         compiler_fence(core::sync::atomic::Ordering::SeqCst);
119                         let ahci_disk = LockedAhciDisk::new(hba_mem_index as u8, j as u8)?;
120                         block_dev_manager()
121                             .register(ahci_disk)
122                             .expect("register ahci disk failed");
123 
124                         debug!("start register ahci device");
125                     }
126                 }
127             }
128         }
129         BlockCache::init();
130     }
131 
132     compiler_fence(core::sync::atomic::Ordering::SeqCst);
133     return Ok(());
134 }
135 
136 /// @brief: 通过 ctrl_num 和 port_num 获取 port
_port(ctrl_num: u8, port_num: u8) -> &'static mut HbaPort137 fn _port(ctrl_num: u8, port_num: u8) -> &'static mut HbaPort {
138     let list: SpinLockGuard<Vec<&mut HbaMem>> = LOCKED_HBA_MEM_LIST.lock();
139     let port: &HbaPort = &list[ctrl_num as usize].ports[port_num as usize];
140 
141     return unsafe { (port as *const HbaPort as *mut HbaPort).as_mut().unwrap() };
142 }
143