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