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