xref: /DragonOS/kernel/src/driver/disk/ahci/ahcidisk.rs (revision 370472f7288b568c7b80815f5b150daf4496446c)
1 use super::{_port, hba::HbaCmdTable, virt_2_phys};
2 use crate::driver::base::block::block_device::{BlockDevice, BlockId};
3 use crate::driver::base::block::disk_info::Partition;
4 use crate::driver::base::block::SeekFrom;
5 use crate::driver::base::class::Class;
6 use crate::driver::base::device::bus::Bus;
7 
8 use crate::driver::base::device::driver::Driver;
9 use crate::driver::base::device::{Device, DeviceType, IdTable};
10 use crate::driver::base::kobject::{KObjType, KObject, KObjectState};
11 use crate::driver::base::kset::KSet;
12 use crate::driver::disk::ahci::HBA_PxIS_TFES;
13 
14 use crate::filesystem::kernfs::KernFSInode;
15 use crate::filesystem::mbr::MbrDiskPartionTable;
16 
17 use crate::kdebug;
18 use crate::libs::rwlock::{RwLockReadGuard, RwLockWriteGuard};
19 use crate::libs::{spinlock::SpinLock, vec_cursor::VecCursor};
20 use crate::mm::{phys_2_virt, verify_area, VirtAddr};
21 use crate::{
22     driver::disk::ahci::hba::{
23         FisRegH2D, FisType, HbaCmdHeader, ATA_CMD_READ_DMA_EXT, ATA_CMD_WRITE_DMA_EXT,
24         ATA_DEV_BUSY, ATA_DEV_DRQ,
25     },
26     kerror,
27 };
28 use system_error::SystemError;
29 
30 use alloc::sync::Weak;
31 use alloc::{string::String, sync::Arc, vec::Vec};
32 
33 use core::fmt::Debug;
34 use core::sync::atomic::{compiler_fence, Ordering};
35 use core::{mem::size_of, ptr::write_bytes};
36 
37 /// @brief: 只支持MBR分区格式的磁盘结构体
38 pub struct AhciDisk {
39     pub name: String,
40     pub flags: u16,                      // 磁盘的状态flags
41     pub partitions: Vec<Arc<Partition>>, // 磁盘分区数组
42     // port: &'static mut HbaPort,      // 控制硬盘的端口
43     pub ctrl_num: u8,
44     pub port_num: u8,
45     /// 指向LockAhciDisk的弱引用
46     self_ref: Weak<LockedAhciDisk>,
47 }
48 
49 /// @brief: 带锁的AhciDisk
50 #[derive(Debug)]
51 pub struct LockedAhciDisk(pub SpinLock<AhciDisk>);
52 /// 函数实现
53 impl Debug for AhciDisk {
54     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
55         write!(
56             f,
57             "{{ name: {}, flags: {}, part_s: {:?} }}",
58             self.name, self.flags, self.partitions
59         )?;
60         return Ok(());
61     }
62 }
63 
64 impl AhciDisk {
65     fn read_at(
66         &self,
67         lba_id_start: BlockId, // 起始lba编号
68         count: usize,          // 读取lba的数量
69         buf: &mut [u8],
70     ) -> Result<usize, SystemError> {
71         assert!((buf.len() & 511) == 0);
72         compiler_fence(core::sync::atomic::Ordering::SeqCst);
73         let check_length = ((count - 1) >> 4) + 1; // prdt length
74         if count * 512 > buf.len() || check_length > 8_usize {
75             kerror!("ahci read: e2big");
76             // 不可能的操作
77             return Err(SystemError::E2BIG);
78         } else if count == 0 {
79             return Ok(0);
80         }
81 
82         let port = _port(self.ctrl_num, self.port_num);
83         volatile_write!(port.is, u32::MAX); // Clear pending interrupt bits
84 
85         let slot = port.find_cmdslot().unwrap_or(u32::MAX);
86 
87         if slot == u32::MAX {
88             return Err(SystemError::EIO);
89         }
90 
91         #[allow(unused_unsafe)]
92         let cmdheader: &mut HbaCmdHeader = unsafe {
93             (phys_2_virt(
94                 volatile_read!(port.clb) as usize + slot as usize * size_of::<HbaCmdHeader>(),
95             ) as *mut HbaCmdHeader)
96                 .as_mut()
97                 .unwrap()
98         };
99 
100         cmdheader.cfl = (size_of::<FisRegH2D>() / size_of::<u32>()) as u8;
101 
102         volatile_set_bit!(cmdheader.cfl, 1 << 6, false); //  Read/Write bit : Read from device
103         volatile_write!(cmdheader.prdtl, check_length as u16); // PRDT entries count
104 
105         // 设置数据存放地址
106         let mut buf_ptr = buf as *mut [u8] as *mut usize as usize;
107 
108         // 由于目前的内存管理机制无法把用户空间的内存地址转换为物理地址,所以只能先把数据拷贝到内核空间
109         // TODO:在内存管理重构后,可以直接使用用户空间的内存地址
110 
111         let user_buf = verify_area(VirtAddr::new(buf_ptr), buf.len()).is_ok();
112         let mut kbuf = if user_buf {
113             let x: Vec<u8> = vec![0; buf.len()];
114             Some(x)
115         } else {
116             None
117         };
118 
119         if kbuf.is_some() {
120             buf_ptr = kbuf.as_mut().unwrap().as_mut_ptr() as usize;
121         }
122 
123         #[allow(unused_unsafe)]
124         let cmdtbl = unsafe {
125             (phys_2_virt(volatile_read!(cmdheader.ctba) as usize) as *mut HbaCmdTable)
126                 .as_mut()
127                 .unwrap() // 必须使用 as_mut ,得到的才是原来的变量
128         };
129         let mut tmp_count = count;
130 
131         unsafe {
132             // 清空整个table的旧数据
133             write_bytes(cmdtbl, 0, 1);
134         }
135         // kdebug!("cmdheader.prdtl={}", volatile_read!(cmdheader.prdtl));
136 
137         // 8K bytes (16 sectors) per PRDT
138         for i in 0..((volatile_read!(cmdheader.prdtl) - 1) as usize) {
139             volatile_write!(cmdtbl.prdt_entry[i].dba, virt_2_phys(buf_ptr) as u64);
140             cmdtbl.prdt_entry[i].dbc = 8 * 1024 - 1;
141             volatile_set_bit!(cmdtbl.prdt_entry[i].dbc, 1 << 31, true); // 允许中断 prdt_entry.i
142             buf_ptr += 8 * 1024;
143             tmp_count -= 16;
144         }
145 
146         // Last entry
147         let las = (volatile_read!(cmdheader.prdtl) - 1) as usize;
148         volatile_write!(cmdtbl.prdt_entry[las].dba, virt_2_phys(buf_ptr) as u64);
149         cmdtbl.prdt_entry[las].dbc = ((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: BlockId,
215         count: usize,
216         buf: &[u8],
217     ) -> Result<usize, SystemError> {
218         assert!((buf.len() & 511) == 0);
219         compiler_fence(core::sync::atomic::Ordering::SeqCst);
220         let check_length = ((count - 1) >> 4) + 1; // prdt length
221         if count * 512 > buf.len() || check_length > 8 {
222             // 不可能的操作
223             return Err(SystemError::E2BIG);
224         } else if count == 0 {
225             return Ok(0);
226         }
227 
228         let port = _port(self.ctrl_num, self.port_num);
229 
230         volatile_write!(port.is, u32::MAX); // Clear pending interrupt bits
231 
232         let slot = port.find_cmdslot().unwrap_or(u32::MAX);
233 
234         if slot == u32::MAX {
235             return Err(SystemError::EIO);
236         }
237 
238         compiler_fence(core::sync::atomic::Ordering::SeqCst);
239         #[allow(unused_unsafe)]
240         let cmdheader: &mut HbaCmdHeader = unsafe {
241             (phys_2_virt(
242                 volatile_read!(port.clb) as usize + slot as usize * size_of::<HbaCmdHeader>(),
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_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 = verify_area(VirtAddr::new(buf_ptr), buf.len()).is_ok();
265         let mut kbuf = if user_buf {
266             let mut x: Vec<u8> = vec![0; buf.len()];
267             x.resize(buf.len(), 0);
268             x.copy_from_slice(buf);
269             Some(x)
270         } else {
271             None
272         };
273 
274         if kbuf.is_some() {
275             buf_ptr = kbuf.as_mut().unwrap().as_mut_ptr() as usize;
276         }
277 
278         #[allow(unused_unsafe)]
279         let cmdtbl = unsafe {
280             (phys_2_virt(volatile_read!(cmdheader.ctba) as usize) as *mut HbaCmdTable)
281                 .as_mut()
282                 .unwrap()
283         };
284         let mut tmp_count = count;
285         compiler_fence(core::sync::atomic::Ordering::SeqCst);
286 
287         unsafe {
288             // 清空整个table的旧数据
289             write_bytes(cmdtbl, 0, 1);
290         }
291 
292         // 8K bytes (16 sectors) per PRDT
293         for i in 0..((volatile_read!(cmdheader.prdtl) - 1) as usize) {
294             volatile_write!(cmdtbl.prdt_entry[i].dba, virt_2_phys(buf_ptr) as u64);
295             volatile_write_bit!(cmdtbl.prdt_entry[i].dbc, (1 << 22) - 1, 8 * 1024 - 1); // 数据长度
296             volatile_set_bit!(cmdtbl.prdt_entry[i].dbc, 1 << 31, true); // 允许中断
297             buf_ptr += 8 * 1024;
298             tmp_count -= 16;
299         }
300 
301         // Last entry
302         let las = (volatile_read!(cmdheader.prdtl) - 1) as usize;
303         volatile_write!(cmdtbl.prdt_entry[las].dba, virt_2_phys(buf_ptr) as u64);
304         volatile_set_bit!(cmdtbl.prdt_entry[las].dbc, 1 << 31, true); // 允许中断
305         volatile_write_bit!(
306             cmdtbl.prdt_entry[las].dbc,
307             (1 << 22) - 1,
308             ((tmp_count << 9) - 1) as u32
309         ); // 数据长度
310 
311         // 设置命令
312         let cmdfis = unsafe {
313             ((&mut cmdtbl.cfis) as *mut [u8] as *mut usize as *mut FisRegH2D)
314                 .as_mut()
315                 .unwrap()
316         };
317         volatile_write!(cmdfis.fis_type, FisType::RegH2D as u8);
318         volatile_set_bit!(cmdfis.pm, 1 << 7, true); // command_bit set
319         volatile_write!(cmdfis.command, ATA_CMD_WRITE_DMA_EXT);
320 
321         volatile_write!(cmdfis.lba0, (lba_id_start & 0xFF) as u8);
322         volatile_write!(cmdfis.lba1, ((lba_id_start >> 8) & 0xFF) as u8);
323         volatile_write!(cmdfis.lba2, ((lba_id_start >> 16) & 0xFF) as u8);
324         volatile_write!(cmdfis.lba3, ((lba_id_start >> 24) & 0xFF) as u8);
325         volatile_write!(cmdfis.lba4, ((lba_id_start >> 32) & 0xFF) as u8);
326         volatile_write!(cmdfis.lba5, ((lba_id_start >> 40) & 0xFF) as u8);
327 
328         volatile_write!(cmdfis.countl, (count & 0xFF) as u8);
329         volatile_write!(cmdfis.counth, ((count >> 8) & 0xFF) as u8);
330 
331         volatile_write!(cmdfis.device, 1 << 6); // LBA Mode
332 
333         volatile_set_bit!(port.ci, 1 << slot, true); // Issue command
334 
335         // 等待操作完成
336         loop {
337             if (volatile_read!(port.ci) & (1 << slot)) == 0 {
338                 break;
339             }
340             if (volatile_read!(port.is) & HBA_PxIS_TFES) > 0 {
341                 kerror!("Write disk error");
342                 return Err(SystemError::EIO);
343             }
344         }
345 
346         compiler_fence(core::sync::atomic::Ordering::SeqCst);
347         // successfully read
348         return Ok(count * 512);
349     }
350 
351     fn sync(&self) -> Result<(), SystemError> {
352         // 由于目前没有block cache, 因此sync返回成功即可
353         return Ok(());
354     }
355 }
356 
357 impl LockedAhciDisk {
358     pub fn new(
359         name: String,
360         flags: u16,
361         ctrl_num: u8,
362         port_num: u8,
363     ) -> Result<Arc<LockedAhciDisk>, SystemError> {
364         // 构建磁盘结构体
365         let result: Arc<LockedAhciDisk> = Arc::new(LockedAhciDisk(SpinLock::new(AhciDisk {
366             name,
367             flags,
368             partitions: Default::default(),
369             ctrl_num,
370             port_num,
371             self_ref: Weak::default(),
372         })));
373 
374         let table: MbrDiskPartionTable = result.read_mbr_table()?;
375 
376         // 求出有多少可用分区
377         for i in 0..4 {
378             compiler_fence(Ordering::SeqCst);
379             if table.dpte[i].part_type != 0 {
380                 let w = Arc::downgrade(&result);
381                 result.0.lock().partitions.push(Partition::new(
382                     table.dpte[i].starting_sector() as u64,
383                     table.dpte[i].starting_lba as u64,
384                     table.dpte[i].total_sectors as u64,
385                     w,
386                     i as u16,
387                 ));
388             }
389         }
390 
391         result.0.lock().self_ref = Arc::downgrade(&result);
392 
393         return Ok(result);
394     }
395 
396     /// @brief: 从磁盘中读取 MBR 分区表结构体 TODO: Cursor
397     pub fn read_mbr_table(&self) -> Result<MbrDiskPartionTable, SystemError> {
398         let mut table: MbrDiskPartionTable = Default::default();
399 
400         // 数据缓冲区
401         let mut buf: Vec<u8> = vec![0; size_of::<MbrDiskPartionTable>()];
402         buf.resize(size_of::<MbrDiskPartionTable>(), 0);
403 
404         self.read_at_sync(0, 1, &mut buf)?;
405         // 创建 Cursor 用于按字节读取
406         let mut cursor = VecCursor::new(buf);
407         cursor.seek(SeekFrom::SeekCurrent(446))?;
408 
409         for i in 0..4 {
410             kdebug!("infomation of partition {}:\n", i);
411 
412             table.dpte[i].flags = cursor.read_u8()?;
413             table.dpte[i].starting_head = cursor.read_u8()?;
414             table.dpte[i].starting_sector_cylinder = cursor.read_u16()?;
415             table.dpte[i].part_type = cursor.read_u8()?;
416             table.dpte[i].ending_head = cursor.read_u8()?;
417             table.dpte[i].ending_sector_cylingder = cursor.read_u16()?;
418             table.dpte[i].starting_lba = cursor.read_u32()?;
419             table.dpte[i].total_sectors = cursor.read_u32()?;
420 
421             kdebug!("dpte[i] = {:?}", table.dpte[i]);
422         }
423         table.bs_trailsig = cursor.read_u16()?;
424         // kdebug!("bs_trailsig = {}", unsafe {
425         //     read_unaligned(addr_of!(table.bs_trailsig))
426         // });
427 
428         return Ok(table);
429     }
430 }
431 
432 impl KObject for LockedAhciDisk {
433     fn as_any_ref(&self) -> &dyn core::any::Any {
434         self
435     }
436 
437     fn inode(&self) -> Option<Arc<KernFSInode>> {
438         todo!()
439     }
440 
441     fn kobj_type(&self) -> Option<&'static dyn KObjType> {
442         todo!()
443     }
444 
445     fn kset(&self) -> Option<Arc<KSet>> {
446         todo!()
447     }
448 
449     fn parent(&self) -> Option<Weak<dyn KObject>> {
450         todo!()
451     }
452 
453     fn set_inode(&self, _inode: Option<Arc<KernFSInode>>) {
454         todo!()
455     }
456 
457     fn kobj_state(&self) -> RwLockReadGuard<KObjectState> {
458         todo!()
459     }
460 
461     fn kobj_state_mut(&self) -> RwLockWriteGuard<KObjectState> {
462         todo!()
463     }
464 
465     fn set_kobj_state(&self, _state: KObjectState) {
466         todo!()
467     }
468 
469     fn name(&self) -> alloc::string::String {
470         todo!()
471     }
472 
473     fn set_name(&self, _name: alloc::string::String) {
474         todo!()
475     }
476 
477     fn set_kset(&self, _kset: Option<Arc<KSet>>) {
478         todo!()
479     }
480 
481     fn set_parent(&self, _parent: Option<Weak<dyn KObject>>) {
482         todo!()
483     }
484 
485     fn set_kobj_type(&self, _ktype: Option<&'static dyn KObjType>) {
486         todo!()
487     }
488 }
489 
490 impl Device for LockedAhciDisk {
491     fn dev_type(&self) -> DeviceType {
492         return DeviceType::Block;
493     }
494 
495     fn id_table(&self) -> IdTable {
496         todo!()
497     }
498 
499     fn bus(&self) -> Option<Weak<dyn Bus>> {
500         todo!("LockedAhciDisk::bus()")
501     }
502 
503     fn set_bus(&self, _bus: Option<Weak<dyn Bus>>) {
504         todo!("LockedAhciDisk::set_bus()")
505     }
506 
507     fn driver(&self) -> Option<Arc<dyn Driver>> {
508         todo!("LockedAhciDisk::driver()")
509     }
510 
511     fn is_dead(&self) -> bool {
512         false
513     }
514 
515     fn set_driver(&self, _driver: Option<Weak<dyn Driver>>) {
516         todo!("LockedAhciDisk::set_driver()")
517     }
518 
519     fn can_match(&self) -> bool {
520         todo!()
521     }
522 
523     fn set_can_match(&self, _can_match: bool) {
524         todo!()
525     }
526 
527     fn state_synced(&self) -> bool {
528         todo!()
529     }
530 
531     fn set_class(&self, _class: Option<Weak<dyn Class>>) {
532         todo!()
533     }
534 }
535 
536 impl BlockDevice for LockedAhciDisk {
537     #[inline]
538     fn as_any_ref(&self) -> &dyn core::any::Any {
539         self
540     }
541 
542     #[inline]
543     fn blk_size_log2(&self) -> u8 {
544         9
545     }
546 
547     fn sync(&self) -> Result<(), SystemError> {
548         return self.0.lock().sync();
549     }
550 
551     #[inline]
552     fn device(&self) -> Arc<dyn Device> {
553         return self.0.lock().self_ref.upgrade().unwrap();
554     }
555 
556     fn block_size(&self) -> usize {
557         todo!()
558     }
559 
560     fn partitions(&self) -> Vec<Arc<Partition>> {
561         return self.0.lock().partitions.clone();
562     }
563 
564     #[inline]
565     fn read_at_sync(
566         &self,
567         lba_id_start: BlockId, // 起始lba编号
568         count: usize,          // 读取lba的数量
569         buf: &mut [u8],
570     ) -> Result<usize, SystemError> {
571         self.0.lock().read_at(lba_id_start, count, buf)
572     }
573 
574     #[inline]
575     fn write_at_sync(
576         &self,
577         lba_id_start: BlockId,
578         count: usize,
579         buf: &[u8],
580     ) -> Result<usize, SystemError> {
581         self.0.lock().write_at(lba_id_start, count, buf)
582     }
583 }
584