diff --git a/kernel/src/drivers/block/ahci.rs b/kernel/src/drivers/block/ahci.rs index d5f9982..69a8f44 100644 --- a/kernel/src/drivers/block/ahci.rs +++ b/kernel/src/drivers/block/ahci.rs @@ -15,7 +15,7 @@ use crate::sync::FlagsGuard; use bitflags::*; use log::*; use rcore_memory::paging::PageTable; -use rcore_memory::PAGE_SIZE; +use rcore_memory::{PhysAddr, VirtAddr, PAGE_SIZE}; use volatile::Volatile; use rcore_fs::dev::BlockDevice; @@ -30,10 +30,10 @@ pub struct AHCI { header: usize, size: usize, rfis: usize, - cmd_list: usize, - cmd_table: usize, - data: usize, - port_addr: usize, + cmd_list: &'static mut [AHCICommandHeader], + cmd_table: &'static mut AHCICommandTable, + data: &'static mut [u8], + port: &'static mut AHCIPort, } pub struct AHCIDriver(Mutex); @@ -201,19 +201,7 @@ pub struct ATAIdentifyPacket { impl Driver for AHCIDriver { fn try_handle_interrupt(&self, _irq: Option) -> bool { - let driver = self.0.lock(); - - // ensure header page is mapped - let header = driver.header as usize; - let size = driver.size as usize; - if let None = active_table().get_entry(header) { - let mut current_addr = header; - while current_addr < header + size { - active_table().map_if_not_exists(current_addr, current_addr); - current_addr = current_addr + PAGE_SIZE; - } - } - return false; + false } fn device_type(&self) -> DeviceType { @@ -226,31 +214,13 @@ impl Driver for AHCIDriver { fn read_block(&self, block_id: usize, buf: &mut [u8]) -> bool { let mut driver = self.0.lock(); - // ensure header page is mapped - let header = driver.header as usize; - let size = driver.size as usize; - if let None = active_table().get_entry(header) { - let mut current_addr = header; - while current_addr < header + size { - active_table().map_if_not_exists(current_addr, current_addr); - current_addr = current_addr + PAGE_SIZE; - } - } - let port = unsafe { &mut *(driver.port_addr as *mut AHCIPort) }; - let cmd_headers = unsafe { - slice::from_raw_parts_mut( - driver.cmd_list as *mut AHCICommandHeader, - PAGE_SIZE / size_of::(), - ) - }; - cmd_headers[0].prdbc = 0; - cmd_headers[0].pwa_cfl = 0; - - let cmd_table = unsafe { &mut *(driver.cmd_table as *mut AHCICommandTable) }; + + driver.cmd_list[0].prdbc = 0; + driver.cmd_list[0].pwa_cfl = 0; + let len = min(BLOCK_SIZE, buf.len()); - let data = unsafe { slice::from_raw_parts(driver.data as *const u8, len) }; - let fis = unsafe { &mut *(cmd_table.cfis.as_ptr() as *mut SATAFISRegH2D) }; + let fis = unsafe { &mut *(driver.cmd_table.cfis.as_ptr() as *mut SATAFISRegH2D) }; // Register FIS from HBA to device fis.fis_type = FIS_REG_H2D; fis.cflags = 1 << 7; @@ -270,16 +240,16 @@ impl Driver for AHCIDriver { fis.lba_4 = (block_id >> 32) as u8; fis.lba_5 = (block_id >> 40) as u8; - port.ci.write(1 << 0); + driver.port.ci.write(1 << 0); loop { - let ci = port.ci.read(); + let ci = driver.port.ci.read(); if (ci & (1 << 0)) == 0 { break; } } - (&mut buf[..len]).clone_from_slice(&data); + buf[..len].clone_from_slice(&driver.data[0..len]); return true; } @@ -288,31 +258,13 @@ impl Driver for AHCIDriver { return false; } let mut driver = self.0.lock(); - // ensure header page is mapped - let header = driver.header as usize; - let size = driver.size as usize; - if let None = active_table().get_entry(header) { - let mut current_addr = header; - while current_addr < header + size { - active_table().map_if_not_exists(current_addr, current_addr); - current_addr = current_addr + PAGE_SIZE; - } - } - let port = unsafe { &mut *(driver.port_addr as *mut AHCIPort) }; - let cmd_headers = unsafe { - slice::from_raw_parts_mut( - driver.cmd_list as *mut AHCICommandHeader, - PAGE_SIZE / size_of::(), - ) - }; - cmd_headers[0].prdbc = 0; - cmd_headers[0].pwa_cfl = 1 << 6; // devic write - - let cmd_table = unsafe { &mut *(driver.cmd_table as *mut AHCICommandTable) }; - let data = unsafe { slice::from_raw_parts_mut(driver.data as *mut u8, BLOCK_SIZE) }; - data.clone_from_slice(&buf[..BLOCK_SIZE]); - - let fis = unsafe { &mut *(cmd_table.cfis.as_ptr() as *mut SATAFISRegH2D) }; + + driver.cmd_list[0].prdbc = 0; + driver.cmd_list[0].pwa_cfl = 1 << 6; // devic write + + driver.data[0..BLOCK_SIZE].clone_from_slice(&buf[..BLOCK_SIZE]); + + let fis = unsafe { &mut *(driver.cmd_table.cfis.as_ptr() as *mut SATAFISRegH2D) }; // Register FIS from HBA to device fis.fis_type = FIS_REG_H2D; fis.cflags = 1 << 7; @@ -333,10 +285,10 @@ impl Driver for AHCIDriver { fis.lba_4 = (block_id >> 32) as u8; fis.lba_5 = (block_id >> 40) as u8; - port.ci.write(1 << 0); + driver.port.ci.write(1 << 0); loop { - let ci = port.ci.read(); + let ci = driver.port.ci.read(); if (ci & (1 << 0)) == 0 { break; } @@ -349,7 +301,7 @@ const BLOCK_SIZE: usize = 512; fn from_ata_string(data: &[u8]) -> String { let mut swapped_data = Vec::new(); - assert!(data.len() % 2 == 0); + assert_eq!(data.len() % 2, 0); for i in (0..data.len()).step_by(2) { swapped_data.push(data[i + 1]); swapped_data.push(data[i]); @@ -357,13 +309,15 @@ fn from_ata_string(data: &[u8]) -> String { return String::from_utf8(swapped_data).unwrap(); } +/// Allocate consequent physical frames for DMA +fn alloc_dma(page_num: usize) -> (VirtAddr, PhysAddr) { + let layout = Layout::from_size_align(PAGE_SIZE * page_num, PAGE_SIZE).unwrap(); + let vaddr = unsafe { alloc_zeroed(layout) } as usize; + let paddr = active_table().get_entry(vaddr).unwrap().target(); + (vaddr, paddr) +} + pub fn ahci_init(irq: Option, header: usize, size: usize) -> Arc { - let _ = FlagsGuard::no_irq_region(); - let mut current_addr = header; - while current_addr < header + size { - active_table().map_if_not_exists(current_addr, current_addr); - current_addr = current_addr + PAGE_SIZE; - } let ghc = unsafe { &mut *(header as *mut AHCIGHC) }; // AHCI Enable @@ -390,27 +344,12 @@ pub fn ahci_init(irq: Option, header: usize, size: usize) -> Arc(), @@ -423,10 +362,10 @@ pub fn ahci_init(irq: Option, header: usize, size: usize) -> Arc> 32) as u32; cmd_table.prdt[0].dbc_i = (BLOCK_SIZE - 1) as u32; - cmd_headers[0].ctba0 = cmd_table_pa as u32; - cmd_headers[0].ctba_u0 = (cmd_table_pa >> 32) as u32; - cmd_headers[0].prdtl = 1; - cmd_headers[0].prdbc = 0; + cmd_list[0].ctba0 = cmd_table_pa as u32; + cmd_list[0].ctba_u0 = (cmd_table_pa >> 32) as u32; + cmd_list[0].prdtl = 1; + cmd_list[0].prdbc = 0; port.clb.write(cmd_list_pa as u32); port.clbu.write((cmd_list_pa >> 32) as u32); @@ -480,14 +419,16 @@ pub fn ahci_init(irq: Option, header: usize, size: usize) -> Arc {}