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