xref: /DragonOS/kernel/src/driver/disk/ahci/ahcidisk.rs (revision 36fd013004ee0bd5fc7cfb452ba22531a83a859c)
1 use super::{_port, hba::HbaCmdTable, virt_2_phys};
2 use crate::driver::disk::ahci::HBA_PxIS_TFES;
3 use crate::filesystem::mbr::MbrDiskPartionTable;
4 use crate::include::bindings::bindings::verify_area;
5 use crate::io::{device::BlockDevice, disk_info::Partition, SeekFrom};
6 
7 use crate::libs::{spinlock::SpinLock, vec_cursor::VecCursor};
8 use crate::mm::phys_2_virt;
9 use crate::syscall::SystemError;
10 use crate::{
11     driver::disk::ahci::hba::{
12         FisRegH2D, FisType, HbaCmdHeader, ATA_CMD_READ_DMA_EXT, ATA_CMD_WRITE_DMA_EXT,
13         ATA_DEV_BUSY, ATA_DEV_DRQ,
14     },
15     kerror,
16 };
17 
18 use alloc::sync::Weak;
19 use alloc::{string::String, sync::Arc, vec::Vec};
20 
21 use core::fmt::Debug;
22 use core::sync::atomic::compiler_fence;
23 use core::{mem::size_of, ptr::write_bytes};
24 
25 /// @brief: 只支持MBR分区格式的磁盘结构体
26 pub struct AhciDisk {
27     pub name: String,
28     pub flags: u16,                      // 磁盘的状态flags
29     pub partitions: Vec<Arc<Partition>>, // 磁盘分区数组
30     // port: &'static mut HbaPort,      // 控制硬盘的端口
31     pub ctrl_num: u8,
32     pub port_num: u8,
33     /// 指向LockAhciDisk的弱引用
34     self_ref: Weak<LockedAhciDisk>,
35 }
36 
37 /// @brief: 带锁的AhciDisk
38 #[derive(Debug)]
39 pub struct LockedAhciDisk(pub SpinLock<AhciDisk>);
40 /// 函数实现
41 impl Debug for AhciDisk {
42     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
43         write!(
44             f,
45             "{{ name: {}, flags: {}, part_s: {:?} }}",
46             self.name, self.flags, self.partitions
47         )?;
48         return Ok(());
49     }
50 }
51 
52 impl AhciDisk {
53     fn read_at(
54         &self,
55         lba_id_start: crate::io::device::BlockId, // 起始lba编号
56         count: usize,                             // 读取lba的数量
57         buf: &mut [u8],
58     ) -> Result<usize, SystemError> {
59         compiler_fence(core::sync::atomic::Ordering::SeqCst);
60         let check_length = ((count - 1) >> 4) + 1; // prdt length
61         if count * 512 > buf.len() || check_length > u16::MAX as usize {
62             kerror!("ahci read: e2big");
63             // 不可能的操作
64             return Err(SystemError::E2BIG);
65         } else if count == 0 {
66             return Ok(0);
67         }
68 
69         let port = _port(self.ctrl_num, self.port_num);
70         volatile_write!(port.is, u32::MAX); // Clear pending interrupt bits
71 
72         let slot = port.find_cmdslot().unwrap_or(u32::MAX);
73 
74         if slot == u32::MAX {
75             return Err(SystemError::EIO);
76         }
77 
78         #[allow(unused_unsafe)]
79         let cmdheader: &mut HbaCmdHeader = unsafe {
80             (phys_2_virt(
81                 volatile_read!(port.clb) as usize
82                     + slot as usize * size_of::<HbaCmdHeader>() as usize,
83             ) as *mut HbaCmdHeader)
84                 .as_mut()
85                 .unwrap()
86         };
87 
88         volatile_write_bit!(
89             cmdheader.cfl,
90             (1 << 5) - 1 as u8,
91             (size_of::<FisRegH2D>() / size_of::<u32>()) as u8
92         ); // Command FIS size
93 
94         volatile_set_bit!(cmdheader.cfl, 1 << 6, false); //  Read/Write bit : Read from device
95         volatile_write!(cmdheader.prdtl, check_length as u16); // PRDT entries count
96 
97         // 设置数据存放地址
98         let mut buf_ptr = buf as *mut [u8] as *mut usize as usize;
99 
100         // 由于目前的内存管理机制无法把用户空间的内存地址转换为物理地址,所以只能先把数据拷贝到内核空间
101         // TODO:在内存管理重构后,可以直接使用用户空间的内存地址
102         let user_buf = if unsafe { verify_area(buf_ptr as u64, buf.len() as u64) } {
103             true
104         } else {
105             false
106         };
107         let mut kbuf = if user_buf {
108             let mut x: Vec<u8> = Vec::with_capacity(buf.len());
109             unsafe {
110                 x.set_len(buf.len());
111             }
112             Some(x)
113         } else {
114             None
115         };
116 
117         if kbuf.is_some() {
118             buf_ptr = kbuf.as_mut().unwrap().as_mut_ptr() as usize;
119         }
120 
121         #[allow(unused_unsafe)]
122         let cmdtbl = unsafe {
123             (phys_2_virt(volatile_read!(cmdheader.ctba) as usize) as *mut HbaCmdTable)
124                 .as_mut()
125                 .unwrap() // 必须使用 as_mut ,得到的才是原来的变量
126         };
127         let mut tmp_count = count;
128 
129         unsafe {
130             // 清空整个table的旧数据
131             write_bytes(cmdtbl, 0, 1);
132         }
133 
134         // 8K bytes (16 sectors) per PRDT
135         for i in 0..((volatile_read!(cmdheader.prdtl) - 1) as usize) {
136             volatile_write!(cmdtbl.prdt_entry[i].dba, virt_2_phys(buf_ptr) as u64);
137             volatile_write_bit!(cmdtbl.prdt_entry[i].dbc, (1 << 22) - 1, 8 * 1024 - 1); // 数据长度 prdt_entry.dbc
138             volatile_set_bit!(cmdtbl.prdt_entry[i].dbc, 1 << 31, true); // 允许中断 prdt_entry.i
139             buf_ptr += 8 * 1024;
140             tmp_count -= 16;
141         }
142 
143         // Last entry
144         let las = (volatile_read!(cmdheader.prdtl) - 1) as usize;
145         volatile_write!(cmdtbl.prdt_entry[las].dba, virt_2_phys(buf_ptr) as u64);
146         volatile_write_bit!(
147             cmdtbl.prdt_entry[las].dbc,
148             (1 << 22) - 1,
149             ((tmp_count << 9) - 1) as u32
150         ); // 数据长度
151         volatile_set_bit!(cmdtbl.prdt_entry[las].dbc, 1 << 31, true); // 允许中断
152 
153         // 设置命令
154         let cmdfis = unsafe {
155             ((&mut cmdtbl.cfis) as *mut [u8] as *mut usize as *mut FisRegH2D)
156                 .as_mut()
157                 .unwrap()
158         };
159         volatile_write!(cmdfis.fis_type, FisType::RegH2D as u8);
160         volatile_set_bit!(cmdfis.pm, 1 << 7, true); // command_bit set
161         volatile_write!(cmdfis.command, ATA_CMD_READ_DMA_EXT);
162 
163         volatile_write!(cmdfis.lba0, (lba_id_start & 0xFF) as u8);
164         volatile_write!(cmdfis.lba1, ((lba_id_start >> 8) & 0xFF) as u8);
165         volatile_write!(cmdfis.lba2, ((lba_id_start >> 16) & 0xFF) as u8);
166         volatile_write!(cmdfis.lba3, ((lba_id_start >> 24) & 0xFF) as u8);
167         volatile_write!(cmdfis.lba4, ((lba_id_start >> 32) & 0xFF) as u8);
168         volatile_write!(cmdfis.lba5, ((lba_id_start >> 40) & 0xFF) as u8);
169 
170         volatile_write!(cmdfis.countl, (count & 0xFF) as u8);
171         volatile_write!(cmdfis.counth, ((count >> 8) & 0xFF) as u8);
172 
173         volatile_write!(cmdfis.device, 1 << 6); // LBA Mode
174 
175         // 等待之前的操作完成
176         let mut spin_count = 0;
177         const SPIN_LIMIT: u32 = 10000;
178 
179         while (volatile_read!(port.tfd) as u8 & (ATA_DEV_BUSY | ATA_DEV_DRQ)) > 0
180             && spin_count < SPIN_LIMIT
181         {
182             spin_count += 1;
183         }
184 
185         if spin_count == SPIN_LIMIT {
186             kerror!("Port is hung");
187             return Err(SystemError::EIO);
188         }
189 
190         volatile_set_bit!(port.ci, 1 << slot, true); // Issue command
191                                                      // kdebug!("To wait ahci read complete.");
192                                                      // 等待操作完成
193         loop {
194             if (volatile_read!(port.ci) & (1 << slot)) == 0 {
195                 break;
196             }
197             if (volatile_read!(port.is) & HBA_PxIS_TFES) > 0 {
198                 kerror!("Read disk error");
199                 return Err(SystemError::EIO);
200             }
201         }
202 
203         if kbuf.is_some() {
204             buf.copy_from_slice(kbuf.as_ref().unwrap());
205         }
206 
207         compiler_fence(core::sync::atomic::Ordering::SeqCst);
208         // successfully read
209         return Ok(count * 512);
210     }
211 
212     fn write_at(
213         &self,
214         lba_id_start: crate::io::device::BlockId,
215         count: usize,
216         buf: &[u8],
217     ) -> Result<usize, SystemError> {
218         compiler_fence(core::sync::atomic::Ordering::SeqCst);
219         let check_length = ((count - 1) >> 4) + 1; // prdt length
220         if count * 512 > buf.len() || check_length > u16::MAX as usize {
221             // 不可能的操作
222             return Err(SystemError::E2BIG);
223         } else if count == 0 {
224             return Ok(0);
225         }
226 
227         let port = _port(self.ctrl_num, self.port_num);
228 
229         volatile_write!(port.is, u32::MAX); // Clear pending interrupt bits
230 
231         let slot = port.find_cmdslot().unwrap_or(u32::MAX);
232 
233         if slot == u32::MAX {
234             return Err(SystemError::EIO);
235         }
236 
237         compiler_fence(core::sync::atomic::Ordering::SeqCst);
238         #[allow(unused_unsafe)]
239         let cmdheader: &mut HbaCmdHeader = unsafe {
240             (phys_2_virt(
241                 volatile_read!(port.clb) as usize
242                     + slot as usize * size_of::<HbaCmdHeader>() as usize,
243             ) as *mut HbaCmdHeader)
244                 .as_mut()
245                 .unwrap()
246         };
247         compiler_fence(core::sync::atomic::Ordering::SeqCst);
248 
249         volatile_write_bit!(
250             cmdheader.cfl,
251             (1 << 5) - 1 as u8,
252             (size_of::<FisRegH2D>() / size_of::<u32>()) as u8
253         ); // Command FIS size
254 
255         volatile_set_bit!(cmdheader.cfl, 7 << 5, true); // (p,c,w)都设置为1, Read/Write bit :  Write from device
256         volatile_write!(cmdheader.prdtl, check_length as u16); // PRDT entries count
257 
258         // 设置数据存放地址
259         compiler_fence(core::sync::atomic::Ordering::SeqCst);
260         let mut buf_ptr = buf as *const [u8] as *mut usize as usize;
261 
262         // 由于目前的内存管理机制无法把用户空间的内存地址转换为物理地址,所以只能先把数据拷贝到内核空间
263         // TODO:在内存管理重构后,可以直接使用用户空间的内存地址
264         let user_buf = if unsafe { verify_area(buf_ptr as u64, buf.len() as u64) } {
265             true
266         } else {
267             false
268         };
269         let mut kbuf = if user_buf {
270             let mut x: Vec<u8> = Vec::with_capacity(buf.len());
271             x.resize(buf.len(), 0);
272             x.copy_from_slice(buf);
273             Some(x)
274         } else {
275             None
276         };
277 
278         if kbuf.is_some() {
279             buf_ptr = kbuf.as_mut().unwrap().as_mut_ptr() as usize;
280         }
281 
282         #[allow(unused_unsafe)]
283         let cmdtbl = unsafe {
284             (phys_2_virt(volatile_read!(cmdheader.ctba) as usize) as *mut HbaCmdTable)
285                 .as_mut()
286                 .unwrap()
287         };
288         let mut tmp_count = count;
289         compiler_fence(core::sync::atomic::Ordering::SeqCst);
290 
291         unsafe {
292             // 清空整个table的旧数据
293             write_bytes(cmdtbl, 0, 1);
294         }
295 
296         // 8K bytes (16 sectors) per PRDT
297         for i in 0..((volatile_read!(cmdheader.prdtl) - 1) as usize) {
298             volatile_write!(cmdtbl.prdt_entry[i].dba, virt_2_phys(buf_ptr) as u64);
299             volatile_write_bit!(cmdtbl.prdt_entry[i].dbc, (1 << 22) - 1, 8 * 1024 - 1); // 数据长度
300             volatile_set_bit!(cmdtbl.prdt_entry[i].dbc, 1 << 31, true); // 允许中断
301             buf_ptr += 8 * 1024;
302             tmp_count -= 16;
303         }
304 
305         // Last entry
306         let las = (volatile_read!(cmdheader.prdtl) - 1) as usize;
307         volatile_write!(cmdtbl.prdt_entry[las].dba, virt_2_phys(buf_ptr) as u64);
308         volatile_set_bit!(cmdtbl.prdt_entry[las].dbc, 1 << 31, true); // 允许中断
309         volatile_write_bit!(
310             cmdtbl.prdt_entry[las].dbc,
311             (1 << 22) - 1,
312             ((tmp_count << 9) - 1) as u32
313         ); // 数据长度
314 
315         // 设置命令
316         let cmdfis = unsafe {
317             ((&mut cmdtbl.cfis) as *mut [u8] as *mut usize as *mut FisRegH2D)
318                 .as_mut()
319                 .unwrap()
320         };
321         volatile_write!(cmdfis.fis_type, FisType::RegH2D as u8);
322         volatile_set_bit!(cmdfis.pm, 1 << 7, true); // command_bit set
323         volatile_write!(cmdfis.command, ATA_CMD_WRITE_DMA_EXT);
324 
325         volatile_write!(cmdfis.lba0, (lba_id_start & 0xFF) as u8);
326         volatile_write!(cmdfis.lba1, ((lba_id_start >> 8) & 0xFF) as u8);
327         volatile_write!(cmdfis.lba2, ((lba_id_start >> 16) & 0xFF) as u8);
328         volatile_write!(cmdfis.lba3, ((lba_id_start >> 24) & 0xFF) as u8);
329         volatile_write!(cmdfis.lba4, ((lba_id_start >> 32) & 0xFF) as u8);
330         volatile_write!(cmdfis.lba5, ((lba_id_start >> 40) & 0xFF) as u8);
331 
332         volatile_write!(cmdfis.countl, (count & 0xFF) as u8);
333         volatile_write!(cmdfis.counth, ((count >> 8) & 0xFF) as u8);
334 
335         volatile_write!(cmdfis.device, 1 << 6); // LBA Mode
336 
337         volatile_set_bit!(port.ci, 1 << slot, true); // Issue command
338 
339         // 等待操作完成
340         loop {
341             if (volatile_read!(port.ci) & (1 << slot)) == 0 {
342                 break;
343             }
344             if (volatile_read!(port.is) & HBA_PxIS_TFES) > 0 {
345                 kerror!("Write disk error");
346                 return Err(SystemError::EIO);
347             }
348         }
349 
350         compiler_fence(core::sync::atomic::Ordering::SeqCst);
351         // successfully read
352         return Ok(count * 512);
353     }
354 
355     fn sync(&self) -> Result<(), SystemError> {
356         // 由于目前没有block cache, 因此sync返回成功即可
357         return Ok(());
358     }
359 }
360 
361 impl LockedAhciDisk {
362     pub fn new(
363         name: String,
364         flags: u16,
365         ctrl_num: u8,
366         port_num: u8,
367     ) -> Result<Arc<LockedAhciDisk>, SystemError> {
368         let mut part_s: Vec<Arc<Partition>> = Vec::new();
369 
370         // 构建磁盘结构体
371         let result: Arc<LockedAhciDisk> = Arc::new(LockedAhciDisk(SpinLock::new(AhciDisk {
372             name,
373             flags,
374             partitions: Default::default(),
375             ctrl_num,
376             port_num,
377             self_ref: Weak::default(),
378         })));
379 
380         let table: MbrDiskPartionTable = result.read_mbr_table()?;
381         let weak_this: Weak<LockedAhciDisk> = Arc::downgrade(&result); // 获取this的弱指针
382 
383         // 求出有多少可用分区
384         for i in 0..4 {
385             if table.dpte[i].part_type != 0 {
386                 part_s.push(Partition::new(
387                     table.dpte[i].starting_sector() as u64,
388                     table.dpte[i].starting_lba as u64,
389                     table.dpte[i].total_sectors as u64,
390                     weak_this.clone(),
391                     i as u16,
392                 ));
393             }
394         }
395 
396         result.0.lock().partitions = part_s;
397         result.0.lock().self_ref = weak_this;
398         return Ok(result);
399     }
400 
401     /// @brief: 从磁盘中读取 MBR 分区表结构体 TODO: Cursor
402     pub fn read_mbr_table(&self) -> Result<MbrDiskPartionTable, SystemError> {
403         let mut table: MbrDiskPartionTable = Default::default();
404 
405         // 数据缓冲区
406         let mut buf: Vec<u8> = Vec::new();
407         buf.resize(size_of::<MbrDiskPartionTable>(), 0);
408 
409         self.read_at(0, 1, &mut buf)?;
410 
411         // 创建 Cursor 用于按字节读取
412         let mut cursor = VecCursor::new(buf);
413         cursor.seek(SeekFrom::SeekCurrent(446))?;
414 
415         for i in 0..4 {
416             // kdebug!("infomation of partition {}:\n", i);
417 
418             table.dpte[i].flags = cursor.read_u8()?;
419             table.dpte[i].starting_head = cursor.read_u8()?;
420             table.dpte[i].starting_sector_cylinder = cursor.read_u16()?;
421             table.dpte[i].part_type = cursor.read_u8()?;
422             table.dpte[i].ending_head = cursor.read_u8()?;
423             table.dpte[i].ending_sector_cylingder = cursor.read_u16()?;
424             table.dpte[i].starting_lba = cursor.read_u32()?;
425             table.dpte[i].total_sectors = cursor.read_u32()?;
426 
427             // kdebug!("dpte[i] = {:?}", table.dpte[i]);
428         }
429         table.bs_trailsig = cursor.read_u16()?;
430         // kdebug!("bs_trailsig = {}", unsafe {
431         //     read_unaligned(addr_of!(table.bs_trailsig))
432         // });
433 
434         return Ok(table);
435     }
436 }
437 
438 impl BlockDevice for LockedAhciDisk {
439     #[inline]
440     fn as_any_ref(&self) -> &dyn core::any::Any {
441         self
442     }
443 
444     #[inline]
445     fn blk_size_log2(&self) -> u8 {
446         9
447     }
448 
449     #[inline]
450     fn read_at(
451         &self,
452         lba_id_start: crate::io::device::BlockId,
453         count: usize,
454         buf: &mut [u8],
455     ) -> Result<usize, SystemError> {
456         // kdebug!(
457         //     "ahci read at {lba_id_start}, count={count}, lock={:?}",
458         //     self.0
459         // );
460         return self.0.lock().read_at(lba_id_start, count, buf);
461     }
462 
463     #[inline]
464     fn write_at(
465         &self,
466         lba_id_start: crate::io::device::BlockId,
467         count: usize,
468         buf: &[u8],
469     ) -> Result<usize, SystemError> {
470         self.0.lock().write_at(lba_id_start, count, buf)
471     }
472 
473     fn sync(&self) -> Result<(), SystemError> {
474         return self.0.lock().sync();
475     }
476 
477     #[inline]
478     fn device(&self) -> Arc<dyn crate::io::device::Device> {
479         return self.0.lock().self_ref.upgrade().unwrap();
480     }
481 
482     fn block_size(&self) -> usize {
483         todo!()
484     }
485 
486     fn partitions(&self) -> Vec<Arc<Partition>> {
487         return self.0.lock().partitions.clone();
488     }
489 }
490