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