xref: /DragonOS/kernel/src/driver/disk/ahci/ahcidisk.rs (revision 0dd8ff43325b494ea777dbe6e552fdc77b9dabc8)
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::{Device, DeviceType, KObject};
6 use crate::driver::disk::ahci::HBA_PxIS_TFES;
7 use crate::filesystem::mbr::MbrDiskPartionTable;
8 use crate::include::bindings::bindings::verify_area;
9 
10 use crate::kdebug;
11 use crate::libs::{spinlock::SpinLock, vec_cursor::VecCursor};
12 use crate::mm::phys_2_virt;
13 use crate::syscall::SystemError;
14 use crate::{
15     driver::disk::ahci::hba::{
16         FisRegH2D, FisType, HbaCmdHeader, ATA_CMD_READ_DMA_EXT, ATA_CMD_WRITE_DMA_EXT,
17         ATA_DEV_BUSY, ATA_DEV_DRQ,
18     },
19     kerror,
20 };
21 
22 use alloc::sync::Weak;
23 use alloc::{string::String, sync::Arc, vec::Vec};
24 
25 use core::fmt::Debug;
26 use core::sync::atomic::{compiler_fence, Ordering};
27 use core::{mem::size_of, ptr::write_bytes};
28 
29 /// @brief: 只支持MBR分区格式的磁盘结构体
30 pub struct AhciDisk {
31     pub name: String,
32     pub flags: u16,                      // 磁盘的状态flags
33     pub partitions: Vec<Arc<Partition>>, // 磁盘分区数组
34     // port: &'static mut HbaPort,      // 控制硬盘的端口
35     pub ctrl_num: u8,
36     pub port_num: u8,
37     /// 指向LockAhciDisk的弱引用
38     self_ref: Weak<LockedAhciDisk>,
39 }
40 
41 /// @brief: 带锁的AhciDisk
42 #[derive(Debug)]
43 pub struct LockedAhciDisk(pub SpinLock<AhciDisk>);
44 /// 函数实现
45 impl Debug for AhciDisk {
46     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
47         write!(
48             f,
49             "{{ name: {}, flags: {}, part_s: {:?} }}",
50             self.name, self.flags, self.partitions
51         )?;
52         return Ok(());
53     }
54 }
55 
56 impl AhciDisk {
57     fn read_at(
58         &self,
59         lba_id_start: BlockId, // 起始lba编号
60         count: usize,          // 读取lba的数量
61         buf: &mut [u8],
62     ) -> Result<usize, SystemError> {
63         assert!((buf.len() & 511) == 0);
64         compiler_fence(core::sync::atomic::Ordering::SeqCst);
65         let check_length = ((count - 1) >> 4) + 1; // prdt length
66         if count * 512 > buf.len() || check_length > 8 as usize {
67             kerror!("ahci read: e2big");
68             // 不可能的操作
69             return Err(SystemError::E2BIG);
70         } else if count == 0 {
71             return Ok(0);
72         }
73 
74         let port = _port(self.ctrl_num, self.port_num);
75         volatile_write!(port.is, u32::MAX); // Clear pending interrupt bits
76 
77         let slot = port.find_cmdslot().unwrap_or(u32::MAX);
78 
79         if slot == u32::MAX {
80             return Err(SystemError::EIO);
81         }
82 
83         #[allow(unused_unsafe)]
84         let cmdheader: &mut HbaCmdHeader = unsafe {
85             (phys_2_virt(
86                 volatile_read!(port.clb) as usize
87                     + slot as usize * size_of::<HbaCmdHeader>() as usize,
88             ) as *mut HbaCmdHeader)
89                 .as_mut()
90                 .unwrap()
91         };
92 
93         cmdheader.cfl = (size_of::<FisRegH2D>() / size_of::<u32>()) as u8;
94 
95         volatile_set_bit!(cmdheader.cfl, 1 << 6, false); //  Read/Write bit : Read from device
96         volatile_write!(cmdheader.prdtl, check_length as u16); // PRDT entries count
97 
98         // 设置数据存放地址
99         let mut buf_ptr = buf as *mut [u8] as *mut usize as usize;
100 
101         // 由于目前的内存管理机制无法把用户空间的内存地址转换为物理地址,所以只能先把数据拷贝到内核空间
102         // TODO:在内存管理重构后,可以直接使用用户空间的内存地址
103         let user_buf = if unsafe { verify_area(buf_ptr as u64, buf.len() as u64) } {
104             true
105         } else {
106             false
107         };
108         let mut kbuf = if user_buf {
109             let mut x: Vec<u8> = Vec::new();
110             x.resize(buf.len(), 0);
111             Some(x)
112         } else {
113             None
114         };
115 
116         if kbuf.is_some() {
117             buf_ptr = kbuf.as_mut().unwrap().as_mut_ptr() as usize;
118         }
119 
120         #[allow(unused_unsafe)]
121         let cmdtbl = unsafe {
122             (phys_2_virt(volatile_read!(cmdheader.ctba) as usize) as *mut HbaCmdTable)
123                 .as_mut()
124                 .unwrap() // 必须使用 as_mut ,得到的才是原来的变量
125         };
126         let mut tmp_count = count;
127 
128         unsafe {
129             // 清空整个table的旧数据
130             write_bytes(cmdtbl, 0, 1);
131         }
132         // kdebug!("cmdheader.prdtl={}", volatile_read!(cmdheader.prdtl));
133 
134         // 8K bytes (16 sectors) per PRDT
135         for i in 0..((volatile_read!(cmdheader.prdtl) - 1) as usize) {
136             volatile_write!(cmdtbl.prdt_entry[i].dba, virt_2_phys(buf_ptr) as u64);
137             cmdtbl.prdt_entry[i].dbc = 8 * 1024 - 1;
138             volatile_set_bit!(cmdtbl.prdt_entry[i].dbc, 1 << 31, true); // 允许中断 prdt_entry.i
139             buf_ptr += 8 * 1024;
140             tmp_count -= 16;
141         }
142 
143         // Last entry
144         let las = (volatile_read!(cmdheader.prdtl) - 1) as usize;
145         volatile_write!(cmdtbl.prdt_entry[las].dba, virt_2_phys(buf_ptr) as u64);
146         cmdtbl.prdt_entry[las].dbc = ((tmp_count << 9) - 1) as u32; // 数据长度
147 
148         volatile_set_bit!(cmdtbl.prdt_entry[las].dbc, 1 << 31, true); // 允许中断
149 
150         // 设置命令
151         let cmdfis = unsafe {
152             ((&mut cmdtbl.cfis) as *mut [u8] as *mut usize as *mut FisRegH2D)
153                 .as_mut()
154                 .unwrap()
155         };
156         volatile_write!(cmdfis.fis_type, FisType::RegH2D as u8);
157         volatile_set_bit!(cmdfis.pm, 1 << 7, true); // command_bit set
158         volatile_write!(cmdfis.command, ATA_CMD_READ_DMA_EXT);
159 
160         volatile_write!(cmdfis.lba0, (lba_id_start & 0xFF) as u8);
161         volatile_write!(cmdfis.lba1, ((lba_id_start >> 8) & 0xFF) as u8);
162         volatile_write!(cmdfis.lba2, ((lba_id_start >> 16) & 0xFF) as u8);
163         volatile_write!(cmdfis.lba3, ((lba_id_start >> 24) & 0xFF) as u8);
164         volatile_write!(cmdfis.lba4, ((lba_id_start >> 32) & 0xFF) as u8);
165         volatile_write!(cmdfis.lba5, ((lba_id_start >> 40) & 0xFF) as u8);
166 
167         volatile_write!(cmdfis.countl, (count & 0xFF) as u8);
168         volatile_write!(cmdfis.counth, ((count >> 8) & 0xFF) as u8);
169 
170         volatile_write!(cmdfis.device, 1 << 6); // LBA Mode
171 
172         // 等待之前的操作完成
173         let mut spin_count = 0;
174         const SPIN_LIMIT: u32 = 10000;
175 
176         while (volatile_read!(port.tfd) as u8 & (ATA_DEV_BUSY | ATA_DEV_DRQ)) > 0
177             && spin_count < SPIN_LIMIT
178         {
179             spin_count += 1;
180         }
181 
182         if spin_count == SPIN_LIMIT {
183             kerror!("Port is hung");
184             return Err(SystemError::EIO);
185         }
186 
187         volatile_set_bit!(port.ci, 1 << slot, true); // Issue command
188                                                      // kdebug!("To wait ahci read complete.");
189                                                      // 等待操作完成
190         loop {
191             if (volatile_read!(port.ci) & (1 << slot)) == 0 {
192                 break;
193             }
194             if (volatile_read!(port.is) & HBA_PxIS_TFES) > 0 {
195                 kerror!("Read disk error");
196                 return Err(SystemError::EIO);
197             }
198         }
199 
200         if kbuf.is_some() {
201             buf.copy_from_slice(kbuf.as_ref().unwrap());
202         }
203 
204         compiler_fence(core::sync::atomic::Ordering::SeqCst);
205         // successfully read
206         return Ok(count * 512);
207     }
208 
209     fn write_at(
210         &self,
211         lba_id_start: BlockId,
212         count: usize,
213         buf: &[u8],
214     ) -> Result<usize, SystemError> {
215         assert!((buf.len() & 511) == 0);
216         compiler_fence(core::sync::atomic::Ordering::SeqCst);
217         let check_length = ((count - 1) >> 4) + 1; // prdt length
218         if count * 512 > buf.len() || check_length > 8 as usize {
219             // 不可能的操作
220             return Err(SystemError::E2BIG);
221         } else if count == 0 {
222             return Ok(0);
223         }
224 
225         let port = _port(self.ctrl_num, self.port_num);
226 
227         volatile_write!(port.is, u32::MAX); // Clear pending interrupt bits
228 
229         let slot = port.find_cmdslot().unwrap_or(u32::MAX);
230 
231         if slot == u32::MAX {
232             return Err(SystemError::EIO);
233         }
234 
235         compiler_fence(core::sync::atomic::Ordering::SeqCst);
236         #[allow(unused_unsafe)]
237         let cmdheader: &mut HbaCmdHeader = unsafe {
238             (phys_2_virt(
239                 volatile_read!(port.clb) as usize
240                     + slot as usize * size_of::<HbaCmdHeader>() as usize,
241             ) as *mut HbaCmdHeader)
242                 .as_mut()
243                 .unwrap()
244         };
245         compiler_fence(core::sync::atomic::Ordering::SeqCst);
246 
247         volatile_write_bit!(
248             cmdheader.cfl,
249             (1 << 5) - 1 as 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(core::sync::atomic::Ordering::SeqCst);
258         let mut buf_ptr = buf as *const [u8] as *mut usize as usize;
259 
260         // 由于目前的内存管理机制无法把用户空间的内存地址转换为物理地址,所以只能先把数据拷贝到内核空间
261         // TODO:在内存管理重构后,可以直接使用用户空间的内存地址
262         let user_buf = if unsafe { verify_area(buf_ptr as u64, buf.len() as u64) } {
263             true
264         } else {
265             false
266         };
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 
436 impl Device for LockedAhciDisk {
437     fn dev_type(&self) -> DeviceType {
438         return DeviceType::Block;
439     }
440 
441     fn as_any_ref(&self) -> &dyn core::any::Any {
442         return self;
443     }
444 
445     fn id_table(&self) -> crate::driver::base::device::IdTable {
446         todo!()
447     }
448 
449     fn set_sys_info(&self, _sys_info: Option<Arc<dyn crate::filesystem::vfs::IndexNode>>) {
450         todo!()
451     }
452 
453     fn sys_info(&self) -> Option<Arc<dyn crate::filesystem::vfs::IndexNode>> {
454         todo!()
455     }
456 }
457 
458 impl BlockDevice for LockedAhciDisk {
459     #[inline]
460     fn as_any_ref(&self) -> &dyn core::any::Any {
461         self
462     }
463 
464     #[inline]
465     fn blk_size_log2(&self) -> u8 {
466         9
467     }
468 
469     fn sync(&self) -> Result<(), SystemError> {
470         return self.0.lock().sync();
471     }
472 
473     #[inline]
474     fn device(&self) -> Arc<dyn Device> {
475         return self.0.lock().self_ref.upgrade().unwrap();
476     }
477 
478     fn block_size(&self) -> usize {
479         todo!()
480     }
481 
482     fn partitions(&self) -> Vec<Arc<Partition>> {
483         return self.0.lock().partitions.clone();
484     }
485 
486     #[inline]
487     fn read_at(
488         &self,
489         lba_id_start: BlockId, // 起始lba编号
490         count: usize,          // 读取lba的数量
491         buf: &mut [u8],
492     ) -> Result<usize, SystemError> {
493         self.0.lock().read_at(lba_id_start, count, buf)
494     }
495 
496     #[inline]
497     fn write_at(
498         &self,
499         lba_id_start: BlockId,
500         count: usize,
501         buf: &[u8],
502     ) -> Result<usize, SystemError> {
503         self.0.lock().write_at(lba_id_start, count, buf)
504     }
505 }
506