simplify AHCI mod stage 1

master
WangRunji 6 years ago
parent 11c5609171
commit 8d92b7b985

@ -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<AHCI>);
@ -201,19 +201,7 @@ pub struct ATAIdentifyPacket {
impl Driver for AHCIDriver {
fn try_handle_interrupt(&self, _irq: Option<u32>) -> 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::<AHCICommandHeader>(),
)
};
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::<AHCICommandHeader>(),
)
};
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<u32>, header: usize, size: usize) -> Arc<AHCIDriver> {
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<u32>, header: usize, size: usize) -> Arc<AHCIDriver
// Disable Port First
port.cmd.write(port.cmd.read() & !(1 << 4 | 1 << 0));
let rfis_va =
unsafe { alloc_zeroed(Layout::from_size_align(PAGE_SIZE, PAGE_SIZE).unwrap()) }
as usize;
let rfis_pa = active_table().get_entry(rfis_va).unwrap().target();
let (rfis_va, rfis_pa) = alloc_dma(1);
let (cmd_list_va, cmd_list_pa) = alloc_dma(1);
let (cmd_table_va, cmd_table_pa) = alloc_dma(1);
let (data_va, data_pa) = alloc_dma(1);
let cmd_list_va =
unsafe { alloc_zeroed(Layout::from_size_align(PAGE_SIZE, PAGE_SIZE).unwrap()) }
as usize;
let cmd_list_pa = active_table().get_entry(cmd_list_va).unwrap().target();
let cmd_table_va =
unsafe { alloc_zeroed(Layout::from_size_align(PAGE_SIZE, PAGE_SIZE).unwrap()) }
as usize;
let cmd_table_pa = active_table().get_entry(cmd_table_va).unwrap().target();
let data_va =
unsafe { alloc_zeroed(Layout::from_size_align(PAGE_SIZE, PAGE_SIZE).unwrap()) }
as usize;
let data_pa = active_table().get_entry(data_va).unwrap().target();
let cmd_headers = unsafe {
let cmd_list = unsafe {
slice::from_raw_parts_mut(
cmd_list_va as *mut AHCICommandHeader,
PAGE_SIZE / size_of::<AHCICommandHeader>(),
@ -423,10 +362,10 @@ pub fn ahci_init(irq: Option<u32>, header: usize, size: usize) -> Arc<AHCIDriver
cmd_table.prdt[0].dbau = (data_pa >> 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<u32>, header: usize, size: usize) -> Arc<AHCIDriver
);
}
let data = unsafe { slice::from_raw_parts_mut(data_va as *mut u8, BLOCK_SIZE) };
let driver = AHCIDriver(Mutex::new(AHCI {
header,
size,
rfis: rfis_va,
cmd_list: cmd_list_va,
cmd_table: cmd_table_va,
data: data_va,
port_addr: addr,
cmd_list,
cmd_table,
data,
port,
}));
let driver = Arc::new(driver);

@ -1,2 +1,2 @@
pub mod ahci;
pub mod virtio_blk;
pub mod ahci;

@ -1,11 +1,14 @@
use crate::consts::KERNEL_OFFSET;
use crate::drivers::block::*;
use crate::drivers::net::*;
use crate::drivers::{Driver, DRIVERS, NET_DRIVERS};
use crate::memory::active_table;
use alloc::collections::BTreeMap;
use alloc::string::String;
use alloc::sync::Arc;
use core::cmp::Ordering;
use pci::*;
use rcore_memory::{paging::PageTable, PAGE_SIZE};
use spin::Mutex;
use x86_64::instructions::port::Port;
@ -126,9 +129,12 @@ pub fn init_driver(dev: &PCIDevice) {
// 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA Controller [AHCI mode]
if let Some(BAR::Memory(addr, len, _, _)) = dev.bars[5] {
let irq = unsafe { enable(dev.loc) };
assert!(len as usize <= PAGE_SIZE);
let vaddr = KERNEL_OFFSET + addr as usize;
active_table().map(vaddr, addr as usize);
PCI_DRIVERS
.lock()
.insert(dev.loc, ahci::ahci_init(irq, addr as usize, len as usize));
.insert(dev.loc, ahci::ahci_init(irq, vaddr, len as usize));
}
}
_ => {}

Loading…
Cancel
Save