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