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