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