1 use super::{_port, hba::HbaCmdTable, virt_2_phys}; 2 use crate::driver::disk::ahci::HBA_PxIS_TFES; 3 use crate::filesystem::mbr::MbrDiskPartionTable; 4 use crate::include::bindings::bindings::{E2BIG, EIO}; 5 use crate::io::{device::BlockDevice, disk_info::Partition, SeekFrom}; 6 7 use crate::libs::{spinlock::SpinLock, vec_cursor::VecCursor}; 8 use crate::mm::phys_2_virt; 9 use crate::{ 10 driver::disk::ahci::hba::{ 11 FisRegH2D, FisType, HbaCmdHeader, ATA_CMD_READ_DMA_EXT, ATA_CMD_WRITE_DMA_EXT, 12 ATA_DEV_BUSY, ATA_DEV_DRQ, 13 }, 14 kerror, 15 }; 16 17 use alloc::sync::Weak; 18 use alloc::{string::String, sync::Arc, vec::Vec}; 19 20 use core::fmt::Debug; 21 use core::sync::atomic::compiler_fence; 22 use core::{mem::size_of, ptr::write_bytes}; 23 24 /// @brief: 只支持MBR分区格式的磁盘结构体 25 pub struct AhciDisk { 26 pub name: String, 27 pub flags: u16, // 磁盘的状态flags 28 pub partitions: Vec<Arc<Partition>>, // 磁盘分区数组 29 // port: &'static mut HbaPort, // 控制硬盘的端口 30 pub ctrl_num: u8, 31 pub port_num: u8, 32 /// 指向LockAhciDisk的弱引用 33 self_ref: Weak<LockedAhciDisk>, 34 } 35 36 /// @brief: 带锁的AhciDisk 37 #[derive(Debug)] 38 pub struct LockedAhciDisk(pub SpinLock<AhciDisk>); 39 /// 函数实现 40 impl Debug for AhciDisk { 41 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 42 write!( 43 f, 44 "{{ name: {}, flags: {}, part_s: {:?} }}", 45 self.name, self.flags, self.partitions 46 )?; 47 return Ok(()); 48 } 49 } 50 51 impl AhciDisk { 52 fn read_at( 53 &self, 54 lba_id_start: crate::io::device::BlockId, // 起始lba编号 55 count: usize, // 读取lba的数量 56 buf: &mut [u8], 57 ) -> Result<usize, i32> { 58 compiler_fence(core::sync::atomic::Ordering::SeqCst); 59 let check_length = ((count - 1) >> 4) + 1; // prdt length 60 if count * 512 > buf.len() || check_length > u16::MAX as usize { 61 kerror!("ahci read: e2big"); 62 // 不可能的操作 63 return Err(-(E2BIG as i32)); 64 } else if count == 0 { 65 return Ok(0); 66 } 67 68 let port = _port(self.ctrl_num, self.port_num); 69 volatile_write!(port.is, u32::MAX); // Clear pending interrupt bits 70 71 let slot = port.find_cmdslot().unwrap_or(u32::MAX); 72 73 if slot == u32::MAX { 74 return Err(-(EIO as i32)); 75 } 76 77 #[allow(unused_unsafe)] 78 let cmdheader: &mut HbaCmdHeader = unsafe { 79 (phys_2_virt( 80 volatile_read!(port.clb) as usize 81 + slot as usize * size_of::<HbaCmdHeader>() as usize, 82 ) as *mut HbaCmdHeader) 83 .as_mut() 84 .unwrap() 85 }; 86 87 volatile_write_bit!( 88 cmdheader.cfl, 89 (1 << 5) - 1 as u8, 90 (size_of::<FisRegH2D>() / size_of::<u32>()) as u8 91 ); // Command FIS size 92 93 volatile_set_bit!(cmdheader.cfl, 1 << 6, false); // Read/Write bit : Read from device 94 volatile_write!(cmdheader.prdtl, check_length as u16); // PRDT entries count 95 96 // 设置数据存放地址 97 let mut buf_ptr = buf as *mut [u8] as *mut usize as usize; 98 #[allow(unused_unsafe)] 99 let cmdtbl = unsafe { 100 (phys_2_virt(volatile_read!(cmdheader.ctba) as usize) as *mut HbaCmdTable) 101 .as_mut() 102 .unwrap() // 必须使用 as_mut ,得到的才是原来的变量 103 }; 104 let mut tmp_count = count; 105 106 unsafe { 107 // 清空整个table的旧数据 108 write_bytes(cmdtbl, 0, 1); 109 } 110 111 // 8K bytes (16 sectors) per PRDT 112 for i in 0..((volatile_read!(cmdheader.prdtl) - 1) as usize) { 113 volatile_write!(cmdtbl.prdt_entry[i].dba, virt_2_phys(buf_ptr) as u64); 114 volatile_write_bit!(cmdtbl.prdt_entry[i].dbc, (1 << 22) - 1, 8 * 1024 - 1); // 数据长度 prdt_entry.dbc 115 volatile_set_bit!(cmdtbl.prdt_entry[i].dbc, 1 << 31, true); // 允许中断 prdt_entry.i 116 buf_ptr += 8 * 1024; 117 tmp_count -= 16; 118 } 119 120 // Last entry 121 let las = (volatile_read!(cmdheader.prdtl) - 1) as usize; 122 volatile_write!(cmdtbl.prdt_entry[las].dba, virt_2_phys(buf_ptr) as u64); 123 volatile_write_bit!( 124 cmdtbl.prdt_entry[las].dbc, 125 (1 << 22) - 1, 126 ((tmp_count << 9) - 1) as u32 127 ); // 数据长度 128 volatile_set_bit!(cmdtbl.prdt_entry[las].dbc, 1 << 31, true); // 允许中断 129 130 // 设置命令 131 let cmdfis = unsafe { 132 ((&mut cmdtbl.cfis) as *mut [u8] as *mut usize as *mut FisRegH2D) 133 .as_mut() 134 .unwrap() 135 }; 136 volatile_write!(cmdfis.fis_type, FisType::RegH2D as u8); 137 volatile_set_bit!(cmdfis.pm, 1 << 7, true); // command_bit set 138 volatile_write!(cmdfis.command, ATA_CMD_READ_DMA_EXT); 139 140 volatile_write!(cmdfis.lba0, (lba_id_start & 0xFF) as u8); 141 volatile_write!(cmdfis.lba1, ((lba_id_start >> 8) & 0xFF) as u8); 142 volatile_write!(cmdfis.lba2, ((lba_id_start >> 16) & 0xFF) as u8); 143 volatile_write!(cmdfis.lba3, ((lba_id_start >> 24) & 0xFF) as u8); 144 volatile_write!(cmdfis.lba4, ((lba_id_start >> 32) & 0xFF) as u8); 145 volatile_write!(cmdfis.lba5, ((lba_id_start >> 40) & 0xFF) as u8); 146 147 volatile_write!(cmdfis.countl, (count & 0xFF) as u8); 148 volatile_write!(cmdfis.counth, ((count >> 8) & 0xFF) as u8); 149 150 volatile_write!(cmdfis.device, 1 << 6); // LBA Mode 151 152 // 等待之前的操作完成 153 let mut spin_count = 0; 154 const SPIN_LIMIT: u32 = 10000; 155 156 while (volatile_read!(port.tfd) as u8 & (ATA_DEV_BUSY | ATA_DEV_DRQ)) > 0 157 && spin_count < SPIN_LIMIT 158 { 159 spin_count += 1; 160 } 161 162 if spin_count == SPIN_LIMIT { 163 kerror!("Port is hung"); 164 return Err(-(EIO as i32)); 165 } 166 167 volatile_set_bit!(port.ci, 1 << slot, true); // Issue command 168 // kdebug!("To wait ahci read complete."); 169 // 等待操作完成 170 loop { 171 if (volatile_read!(port.ci) & (1 << slot)) == 0 { 172 break; 173 } 174 if (volatile_read!(port.is) & HBA_PxIS_TFES) > 0 { 175 kerror!("Read disk error"); 176 return Err(-(EIO as i32)); 177 } 178 } 179 180 compiler_fence(core::sync::atomic::Ordering::SeqCst); 181 // successfully read 182 return Ok(count * 512); 183 } 184 185 fn write_at( 186 &self, 187 lba_id_start: crate::io::device::BlockId, 188 count: usize, 189 buf: &[u8], 190 ) -> Result<usize, i32> { 191 compiler_fence(core::sync::atomic::Ordering::SeqCst); 192 let check_length = ((count - 1) >> 4) + 1; // prdt length 193 if count * 512 > buf.len() || check_length > u16::MAX as usize { 194 // 不可能的操作 195 return Err(-(E2BIG as i32)); 196 } else if count == 0 { 197 return Ok(0); 198 } 199 200 let port = _port(self.ctrl_num, self.port_num); 201 202 volatile_write!(port.is, u32::MAX); // Clear pending interrupt bits 203 204 let slot = port.find_cmdslot().unwrap_or(u32::MAX); 205 206 if slot == u32::MAX { 207 return Err(-(EIO as i32)); 208 } 209 210 compiler_fence(core::sync::atomic::Ordering::SeqCst); 211 #[allow(unused_unsafe)] 212 let cmdheader: &mut HbaCmdHeader = unsafe { 213 (phys_2_virt( 214 volatile_read!(port.clb) as usize 215 + slot as usize * size_of::<HbaCmdHeader>() as usize, 216 ) as *mut HbaCmdHeader) 217 .as_mut() 218 .unwrap() 219 }; 220 compiler_fence(core::sync::atomic::Ordering::SeqCst); 221 222 volatile_write_bit!( 223 cmdheader.cfl, 224 (1 << 5) - 1 as u8, 225 (size_of::<FisRegH2D>() / size_of::<u32>()) as u8 226 ); // Command FIS size 227 228 volatile_set_bit!(cmdheader.cfl, 7 << 5, true); // (p,c,w)都设置为1, Read/Write bit : Write from device 229 volatile_write!(cmdheader.prdtl, check_length as u16); // PRDT entries count 230 231 // 设置数据存放地址 232 compiler_fence(core::sync::atomic::Ordering::SeqCst); 233 let mut buf_ptr = buf as *const [u8] as *mut usize as usize; 234 #[allow(unused_unsafe)] 235 let cmdtbl = unsafe { 236 (phys_2_virt(volatile_read!(cmdheader.ctba) as usize) as *mut HbaCmdTable) 237 .as_mut() 238 .unwrap() 239 }; 240 let mut tmp_count = count; 241 compiler_fence(core::sync::atomic::Ordering::SeqCst); 242 243 unsafe { 244 // 清空整个table的旧数据 245 write_bytes(cmdtbl, 0, 1); 246 } 247 248 // 8K bytes (16 sectors) per PRDT 249 for i in 0..((volatile_read!(cmdheader.prdtl) - 1) as usize) { 250 volatile_write!(cmdtbl.prdt_entry[i].dba, virt_2_phys(buf_ptr) as u64); 251 volatile_write_bit!(cmdtbl.prdt_entry[i].dbc, (1 << 22) - 1, 8 * 1024 - 1); // 数据长度 252 volatile_set_bit!(cmdtbl.prdt_entry[i].dbc, 1 << 31, true); // 允许中断 253 buf_ptr += 8 * 1024; 254 tmp_count -= 16; 255 } 256 257 // Last entry 258 let las = (volatile_read!(cmdheader.prdtl) - 1) as usize; 259 volatile_write!(cmdtbl.prdt_entry[las].dba, virt_2_phys(buf_ptr) as u64); 260 volatile_set_bit!(cmdtbl.prdt_entry[las].dbc, 1 << 31, true); // 允许中断 261 volatile_write_bit!( 262 cmdtbl.prdt_entry[las].dbc, 263 (1 << 22) - 1, 264 ((tmp_count << 9) - 1) as u32 265 ); // 数据长度 266 267 // 设置命令 268 let cmdfis = unsafe { 269 ((&mut cmdtbl.cfis) as *mut [u8] as *mut usize as *mut FisRegH2D) 270 .as_mut() 271 .unwrap() 272 }; 273 volatile_write!(cmdfis.fis_type, FisType::RegH2D as u8); 274 volatile_set_bit!(cmdfis.pm, 1 << 7, true); // command_bit set 275 volatile_write!(cmdfis.command, ATA_CMD_WRITE_DMA_EXT); 276 277 volatile_write!(cmdfis.lba0, (lba_id_start & 0xFF) as u8); 278 volatile_write!(cmdfis.lba1, ((lba_id_start >> 8) & 0xFF) as u8); 279 volatile_write!(cmdfis.lba2, ((lba_id_start >> 16) & 0xFF) as u8); 280 volatile_write!(cmdfis.lba3, ((lba_id_start >> 24) & 0xFF) as u8); 281 volatile_write!(cmdfis.lba4, ((lba_id_start >> 32) & 0xFF) as u8); 282 volatile_write!(cmdfis.lba5, ((lba_id_start >> 40) & 0xFF) as u8); 283 284 volatile_write!(cmdfis.countl, (count & 0xFF) as u8); 285 volatile_write!(cmdfis.counth, ((count >> 8) & 0xFF) as u8); 286 287 volatile_write!(cmdfis.device, 1 << 6); // LBA Mode 288 289 volatile_set_bit!(port.ci, 1 << slot, true); // Issue command 290 291 // 等待操作完成 292 loop { 293 if (volatile_read!(port.ci) & (1 << slot)) == 0 { 294 break; 295 } 296 if (volatile_read!(port.is) & HBA_PxIS_TFES) > 0 { 297 kerror!("Write disk error"); 298 return Err(-(EIO as i32)); 299 } 300 } 301 302 compiler_fence(core::sync::atomic::Ordering::SeqCst); 303 // successfully read 304 return Ok(count * 512); 305 } 306 307 fn sync(&self) -> Result<(), i32> { 308 // 由于目前没有block cache, 因此sync返回成功即可 309 return Ok(()); 310 } 311 } 312 313 impl LockedAhciDisk { 314 pub fn new( 315 name: String, 316 flags: u16, 317 ctrl_num: u8, 318 port_num: u8, 319 ) -> Result<Arc<LockedAhciDisk>, i32> { 320 let mut part_s: Vec<Arc<Partition>> = Vec::new(); 321 322 // 构建磁盘结构体 323 let result: Arc<LockedAhciDisk> = Arc::new(LockedAhciDisk(SpinLock::new(AhciDisk { 324 name, 325 flags, 326 partitions: Default::default(), 327 ctrl_num, 328 port_num, 329 self_ref: Weak::default(), 330 }))); 331 332 let table: MbrDiskPartionTable = result.read_mbr_table()?; 333 let weak_this: Weak<LockedAhciDisk> = Arc::downgrade(&result); // 获取this的弱指针 334 335 // 求出有多少可用分区 336 for i in 0..4 { 337 if table.dpte[i].part_type != 0 { 338 part_s.push(Partition::new( 339 table.dpte[i].starting_sector() as u64, 340 table.dpte[i].starting_lba as u64, 341 table.dpte[i].total_sectors as u64, 342 weak_this.clone(), 343 i as u16, 344 )); 345 } 346 } 347 348 result.0.lock().partitions = part_s; 349 result.0.lock().self_ref = weak_this; 350 return Ok(result); 351 } 352 353 /// @brief: 从磁盘中读取 MBR 分区表结构体 TODO: Cursor 354 pub fn read_mbr_table(&self) -> Result<MbrDiskPartionTable, i32> { 355 let mut table: MbrDiskPartionTable = Default::default(); 356 357 // 数据缓冲区 358 let mut buf: Vec<u8> = Vec::new(); 359 buf.resize(size_of::<MbrDiskPartionTable>(), 0); 360 361 self.read_at(0, 1, &mut buf)?; 362 363 // 创建 Cursor 用于按字节读取 364 let mut cursor = VecCursor::new(buf); 365 cursor.seek(SeekFrom::SeekCurrent(446))?; 366 367 for i in 0..4 { 368 // kdebug!("infomation of partition {}:\n", i); 369 370 table.dpte[i].flags = cursor.read_u8()?; 371 table.dpte[i].starting_head = cursor.read_u8()?; 372 table.dpte[i].starting_sector_cylinder = cursor.read_u16()?; 373 table.dpte[i].part_type = cursor.read_u8()?; 374 table.dpte[i].ending_head = cursor.read_u8()?; 375 table.dpte[i].ending_sector_cylingder = cursor.read_u16()?; 376 table.dpte[i].starting_lba = cursor.read_u32()?; 377 table.dpte[i].total_sectors = cursor.read_u32()?; 378 379 // kdebug!("dpte[i] = {:?}", table.dpte[i]); 380 } 381 table.bs_trailsig = cursor.read_u16()?; 382 // kdebug!("bs_trailsig = {}", unsafe { 383 // read_unaligned(addr_of!(table.bs_trailsig)) 384 // }); 385 386 return Ok(table); 387 } 388 } 389 390 impl BlockDevice for LockedAhciDisk { 391 #[inline] 392 fn as_any_ref(&self) -> &dyn core::any::Any { 393 self 394 } 395 396 #[inline] 397 fn blk_size_log2(&self) -> u8 { 398 9 399 } 400 401 #[inline] 402 fn read_at( 403 &self, 404 lba_id_start: crate::io::device::BlockId, 405 count: usize, 406 buf: &mut [u8], 407 ) -> Result<usize, i32> { 408 // kdebug!( 409 // "ahci read at {lba_id_start}, count={count}, lock={:?}", 410 // self.0 411 // ); 412 return self.0.lock().read_at(lba_id_start, count, buf); 413 } 414 415 #[inline] 416 fn write_at( 417 &self, 418 lba_id_start: crate::io::device::BlockId, 419 count: usize, 420 buf: &[u8], 421 ) -> Result<usize, i32> { 422 self.0.lock().write_at(lba_id_start, count, buf) 423 } 424 425 fn sync(&self) -> Result<(), i32> { 426 return self.0.lock().sync(); 427 } 428 429 #[inline] 430 fn device(&self) -> Arc<dyn crate::io::device::Device> { 431 return self.0.lock().self_ref.upgrade().unwrap(); 432 } 433 434 fn block_size(&self) -> usize { 435 todo!() 436 } 437 438 fn partitions(&self) -> Vec<Arc<Partition>> { 439 return self.0.lock().partitions.clone(); 440 } 441 } 442