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