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::verify_area; 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::syscall::SystemError; 10 use crate::{ 11 driver::disk::ahci::hba::{ 12 FisRegH2D, FisType, HbaCmdHeader, ATA_CMD_READ_DMA_EXT, ATA_CMD_WRITE_DMA_EXT, 13 ATA_DEV_BUSY, ATA_DEV_DRQ, 14 }, 15 kerror, 16 }; 17 18 use alloc::sync::Weak; 19 use alloc::{string::String, sync::Arc, vec::Vec}; 20 21 use core::fmt::Debug; 22 use core::sync::atomic::compiler_fence; 23 use core::{mem::size_of, ptr::write_bytes}; 24 25 /// @brief: 只支持MBR分区格式的磁盘结构体 26 pub struct AhciDisk { 27 pub name: String, 28 pub flags: u16, // 磁盘的状态flags 29 pub partitions: Vec<Arc<Partition>>, // 磁盘分区数组 30 // port: &'static mut HbaPort, // 控制硬盘的端口 31 pub ctrl_num: u8, 32 pub port_num: u8, 33 /// 指向LockAhciDisk的弱引用 34 self_ref: Weak<LockedAhciDisk>, 35 } 36 37 /// @brief: 带锁的AhciDisk 38 #[derive(Debug)] 39 pub struct LockedAhciDisk(pub SpinLock<AhciDisk>); 40 /// 函数实现 41 impl Debug for AhciDisk { 42 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 43 write!( 44 f, 45 "{{ name: {}, flags: {}, part_s: {:?} }}", 46 self.name, self.flags, self.partitions 47 )?; 48 return Ok(()); 49 } 50 } 51 52 impl AhciDisk { 53 fn read_at( 54 &self, 55 lba_id_start: crate::io::device::BlockId, // 起始lba编号 56 count: usize, // 读取lba的数量 57 buf: &mut [u8], 58 ) -> Result<usize, SystemError> { 59 compiler_fence(core::sync::atomic::Ordering::SeqCst); 60 let check_length = ((count - 1) >> 4) + 1; // prdt length 61 if count * 512 > buf.len() || check_length > u16::MAX as usize { 62 kerror!("ahci read: e2big"); 63 // 不可能的操作 64 return Err(SystemError::E2BIG); 65 } else if count == 0 { 66 return Ok(0); 67 } 68 69 let port = _port(self.ctrl_num, self.port_num); 70 volatile_write!(port.is, u32::MAX); // Clear pending interrupt bits 71 72 let slot = port.find_cmdslot().unwrap_or(u32::MAX); 73 74 if slot == u32::MAX { 75 return Err(SystemError::EIO); 76 } 77 78 #[allow(unused_unsafe)] 79 let cmdheader: &mut HbaCmdHeader = unsafe { 80 (phys_2_virt( 81 volatile_read!(port.clb) as usize 82 + slot as usize * size_of::<HbaCmdHeader>() as usize, 83 ) as *mut HbaCmdHeader) 84 .as_mut() 85 .unwrap() 86 }; 87 88 volatile_write_bit!( 89 cmdheader.cfl, 90 (1 << 5) - 1 as u8, 91 (size_of::<FisRegH2D>() / size_of::<u32>()) as u8 92 ); // Command FIS size 93 94 volatile_set_bit!(cmdheader.cfl, 1 << 6, false); // Read/Write bit : Read from device 95 volatile_write!(cmdheader.prdtl, check_length as u16); // PRDT entries count 96 97 // 设置数据存放地址 98 let mut buf_ptr = buf as *mut [u8] as *mut usize as usize; 99 100 // 由于目前的内存管理机制无法把用户空间的内存地址转换为物理地址,所以只能先把数据拷贝到内核空间 101 // TODO:在内存管理重构后,可以直接使用用户空间的内存地址 102 let user_buf = if unsafe { verify_area(buf_ptr as u64, buf.len() as u64) } { 103 true 104 } else { 105 false 106 }; 107 let mut kbuf = if user_buf { 108 let mut x: Vec<u8> = Vec::with_capacity(buf.len()); 109 unsafe { 110 x.set_len(buf.len()); 111 } 112 Some(x) 113 } else { 114 None 115 }; 116 117 if kbuf.is_some() { 118 buf_ptr = kbuf.as_mut().unwrap().as_mut_ptr() as usize; 119 } 120 121 #[allow(unused_unsafe)] 122 let cmdtbl = unsafe { 123 (phys_2_virt(volatile_read!(cmdheader.ctba) as usize) as *mut HbaCmdTable) 124 .as_mut() 125 .unwrap() // 必须使用 as_mut ,得到的才是原来的变量 126 }; 127 let mut tmp_count = count; 128 129 unsafe { 130 // 清空整个table的旧数据 131 write_bytes(cmdtbl, 0, 1); 132 } 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 volatile_write_bit!(cmdtbl.prdt_entry[i].dbc, (1 << 22) - 1, 8 * 1024 - 1); // 数据长度 prdt_entry.dbc 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 volatile_write_bit!( 147 cmdtbl.prdt_entry[las].dbc, 148 (1 << 22) - 1, 149 ((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: crate::io::device::BlockId, 215 count: usize, 216 buf: &[u8], 217 ) -> Result<usize, SystemError> { 218 compiler_fence(core::sync::atomic::Ordering::SeqCst); 219 let check_length = ((count - 1) >> 4) + 1; // prdt length 220 if count * 512 > buf.len() || check_length > u16::MAX as usize { 221 // 不可能的操作 222 return Err(SystemError::E2BIG); 223 } else if count == 0 { 224 return Ok(0); 225 } 226 227 let port = _port(self.ctrl_num, self.port_num); 228 229 volatile_write!(port.is, u32::MAX); // Clear pending interrupt bits 230 231 let slot = port.find_cmdslot().unwrap_or(u32::MAX); 232 233 if slot == u32::MAX { 234 return Err(SystemError::EIO); 235 } 236 237 compiler_fence(core::sync::atomic::Ordering::SeqCst); 238 #[allow(unused_unsafe)] 239 let cmdheader: &mut HbaCmdHeader = unsafe { 240 (phys_2_virt( 241 volatile_read!(port.clb) as usize 242 + slot as usize * size_of::<HbaCmdHeader>() as usize, 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 as 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 = if unsafe { verify_area(buf_ptr as u64, buf.len() as u64) } { 265 true 266 } else { 267 false 268 }; 269 let mut kbuf = if user_buf { 270 let mut x: Vec<u8> = Vec::with_capacity(buf.len()); 271 x.resize(buf.len(), 0); 272 x.copy_from_slice(buf); 273 Some(x) 274 } else { 275 None 276 }; 277 278 if kbuf.is_some() { 279 buf_ptr = kbuf.as_mut().unwrap().as_mut_ptr() as usize; 280 } 281 282 #[allow(unused_unsafe)] 283 let cmdtbl = unsafe { 284 (phys_2_virt(volatile_read!(cmdheader.ctba) as usize) as *mut HbaCmdTable) 285 .as_mut() 286 .unwrap() 287 }; 288 let mut tmp_count = count; 289 compiler_fence(core::sync::atomic::Ordering::SeqCst); 290 291 unsafe { 292 // 清空整个table的旧数据 293 write_bytes(cmdtbl, 0, 1); 294 } 295 296 // 8K bytes (16 sectors) per PRDT 297 for i in 0..((volatile_read!(cmdheader.prdtl) - 1) as usize) { 298 volatile_write!(cmdtbl.prdt_entry[i].dba, virt_2_phys(buf_ptr) as u64); 299 volatile_write_bit!(cmdtbl.prdt_entry[i].dbc, (1 << 22) - 1, 8 * 1024 - 1); // 数据长度 300 volatile_set_bit!(cmdtbl.prdt_entry[i].dbc, 1 << 31, true); // 允许中断 301 buf_ptr += 8 * 1024; 302 tmp_count -= 16; 303 } 304 305 // Last entry 306 let las = (volatile_read!(cmdheader.prdtl) - 1) as usize; 307 volatile_write!(cmdtbl.prdt_entry[las].dba, virt_2_phys(buf_ptr) as u64); 308 volatile_set_bit!(cmdtbl.prdt_entry[las].dbc, 1 << 31, true); // 允许中断 309 volatile_write_bit!( 310 cmdtbl.prdt_entry[las].dbc, 311 (1 << 22) - 1, 312 ((tmp_count << 9) - 1) as u32 313 ); // 数据长度 314 315 // 设置命令 316 let cmdfis = unsafe { 317 ((&mut cmdtbl.cfis) as *mut [u8] as *mut usize as *mut FisRegH2D) 318 .as_mut() 319 .unwrap() 320 }; 321 volatile_write!(cmdfis.fis_type, FisType::RegH2D as u8); 322 volatile_set_bit!(cmdfis.pm, 1 << 7, true); // command_bit set 323 volatile_write!(cmdfis.command, ATA_CMD_WRITE_DMA_EXT); 324 325 volatile_write!(cmdfis.lba0, (lba_id_start & 0xFF) as u8); 326 volatile_write!(cmdfis.lba1, ((lba_id_start >> 8) & 0xFF) as u8); 327 volatile_write!(cmdfis.lba2, ((lba_id_start >> 16) & 0xFF) as u8); 328 volatile_write!(cmdfis.lba3, ((lba_id_start >> 24) & 0xFF) as u8); 329 volatile_write!(cmdfis.lba4, ((lba_id_start >> 32) & 0xFF) as u8); 330 volatile_write!(cmdfis.lba5, ((lba_id_start >> 40) & 0xFF) as u8); 331 332 volatile_write!(cmdfis.countl, (count & 0xFF) as u8); 333 volatile_write!(cmdfis.counth, ((count >> 8) & 0xFF) as u8); 334 335 volatile_write!(cmdfis.device, 1 << 6); // LBA Mode 336 337 volatile_set_bit!(port.ci, 1 << slot, true); // Issue command 338 339 // 等待操作完成 340 loop { 341 if (volatile_read!(port.ci) & (1 << slot)) == 0 { 342 break; 343 } 344 if (volatile_read!(port.is) & HBA_PxIS_TFES) > 0 { 345 kerror!("Write disk error"); 346 return Err(SystemError::EIO); 347 } 348 } 349 350 compiler_fence(core::sync::atomic::Ordering::SeqCst); 351 // successfully read 352 return Ok(count * 512); 353 } 354 355 fn sync(&self) -> Result<(), SystemError> { 356 // 由于目前没有block cache, 因此sync返回成功即可 357 return Ok(()); 358 } 359 } 360 361 impl LockedAhciDisk { 362 pub fn new( 363 name: String, 364 flags: u16, 365 ctrl_num: u8, 366 port_num: u8, 367 ) -> Result<Arc<LockedAhciDisk>, SystemError> { 368 let mut part_s: Vec<Arc<Partition>> = Vec::new(); 369 370 // 构建磁盘结构体 371 let result: Arc<LockedAhciDisk> = Arc::new(LockedAhciDisk(SpinLock::new(AhciDisk { 372 name, 373 flags, 374 partitions: Default::default(), 375 ctrl_num, 376 port_num, 377 self_ref: Weak::default(), 378 }))); 379 380 let table: MbrDiskPartionTable = result.read_mbr_table()?; 381 let weak_this: Weak<LockedAhciDisk> = Arc::downgrade(&result); // 获取this的弱指针 382 383 // 求出有多少可用分区 384 for i in 0..4 { 385 if table.dpte[i].part_type != 0 { 386 part_s.push(Partition::new( 387 table.dpte[i].starting_sector() as u64, 388 table.dpte[i].starting_lba as u64, 389 table.dpte[i].total_sectors as u64, 390 weak_this.clone(), 391 i as u16, 392 )); 393 } 394 } 395 396 result.0.lock().partitions = part_s; 397 result.0.lock().self_ref = weak_this; 398 return Ok(result); 399 } 400 401 /// @brief: 从磁盘中读取 MBR 分区表结构体 TODO: Cursor 402 pub fn read_mbr_table(&self) -> Result<MbrDiskPartionTable, SystemError> { 403 let mut table: MbrDiskPartionTable = Default::default(); 404 405 // 数据缓冲区 406 let mut buf: Vec<u8> = Vec::new(); 407 buf.resize(size_of::<MbrDiskPartionTable>(), 0); 408 409 self.read_at(0, 1, &mut buf)?; 410 411 // 创建 Cursor 用于按字节读取 412 let mut cursor = VecCursor::new(buf); 413 cursor.seek(SeekFrom::SeekCurrent(446))?; 414 415 for i in 0..4 { 416 // kdebug!("infomation of partition {}:\n", i); 417 418 table.dpte[i].flags = cursor.read_u8()?; 419 table.dpte[i].starting_head = cursor.read_u8()?; 420 table.dpte[i].starting_sector_cylinder = cursor.read_u16()?; 421 table.dpte[i].part_type = cursor.read_u8()?; 422 table.dpte[i].ending_head = cursor.read_u8()?; 423 table.dpte[i].ending_sector_cylingder = cursor.read_u16()?; 424 table.dpte[i].starting_lba = cursor.read_u32()?; 425 table.dpte[i].total_sectors = cursor.read_u32()?; 426 427 // kdebug!("dpte[i] = {:?}", table.dpte[i]); 428 } 429 table.bs_trailsig = cursor.read_u16()?; 430 // kdebug!("bs_trailsig = {}", unsafe { 431 // read_unaligned(addr_of!(table.bs_trailsig)) 432 // }); 433 434 return Ok(table); 435 } 436 } 437 438 impl BlockDevice for LockedAhciDisk { 439 #[inline] 440 fn as_any_ref(&self) -> &dyn core::any::Any { 441 self 442 } 443 444 #[inline] 445 fn blk_size_log2(&self) -> u8 { 446 9 447 } 448 449 #[inline] 450 fn read_at( 451 &self, 452 lba_id_start: crate::io::device::BlockId, 453 count: usize, 454 buf: &mut [u8], 455 ) -> Result<usize, SystemError> { 456 // kdebug!( 457 // "ahci read at {lba_id_start}, count={count}, lock={:?}", 458 // self.0 459 // ); 460 return self.0.lock().read_at(lba_id_start, count, buf); 461 } 462 463 #[inline] 464 fn write_at( 465 &self, 466 lba_id_start: crate::io::device::BlockId, 467 count: usize, 468 buf: &[u8], 469 ) -> Result<usize, SystemError> { 470 self.0.lock().write_at(lba_id_start, count, buf) 471 } 472 473 fn sync(&self) -> Result<(), SystemError> { 474 return self.0.lock().sync(); 475 } 476 477 #[inline] 478 fn device(&self) -> Arc<dyn crate::io::device::Device> { 479 return self.0.lock().self_ref.upgrade().unwrap(); 480 } 481 482 fn block_size(&self) -> usize { 483 todo!() 484 } 485 486 fn partitions(&self) -> Vec<Arc<Partition>> { 487 return self.0.lock().partitions.clone(); 488 } 489 } 490