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