Move Ahci Port Controller to hold raw references.

This commit is contained in:
Drew Galbraith 2025-01-31 21:23:42 -08:00
parent 0024e38412
commit 04effd44f8
2 changed files with 50 additions and 63 deletions

View File

@ -152,3 +152,10 @@ where
write!(f, "{:?}", self.read()) write!(f, "{:?}", self.read())
} }
} }
pub fn map_physical_and_leak(size: u64) -> (u64, u64) {
let (mem_cap, paddr) = syscall::memory_object_contiguous_physical(size).unwrap();
let vaddr = syscall::address_space_map(&mem_cap).unwrap();
mem_cap.release();
(vaddr, paddr)
}

View File

@ -3,7 +3,7 @@ use core::ops::DerefMut;
use alloc::boxed::Box; use alloc::boxed::Box;
use alloc::sync::Arc; use alloc::sync::Arc;
use mammoth::sync::Mutex; use mammoth::sync::Mutex;
use mammoth::thread; use mammoth::{mem, thread};
use mammoth::{mem::MemoryRegion, zion::ZError}; use mammoth::{mem::MemoryRegion, zion::ZError};
@ -15,10 +15,7 @@ use crate::ahci::port::{
use super::command::{ use super::command::{
CommandList, CommandTable, HostToDeviceRegisterFis, ReceivedFis, SataCommand, CommandList, CommandTable, HostToDeviceRegisterFis, ReceivedFis, SataCommand,
}; };
use super::{ use super::{hba::AhciHba, port::AhciPortHba};
hba::AhciHba,
port::{AhciPortHba, AhciPortInterruptEnable, AhciSataError},
};
#[derive(Debug)] #[derive(Debug)]
#[repr(C, packed)] #[repr(C, packed)]
@ -51,7 +48,7 @@ pub struct PciDeviceHeader {
pub struct AhciController { pub struct AhciController {
pci_memory: MemoryRegion, pci_memory: MemoryRegion,
hba_memory: MemoryRegion, hba_memory: MemoryRegion,
ports: [Option<PortController<'static>>; 32], ports: [Option<PortController>; 32],
} }
impl AhciController { impl AhciController {
@ -140,7 +137,7 @@ impl AhciController {
continue; continue;
} }
self.ports[i] = Some(PortController::new(port)?); self.ports[i] = Some(PortController::new(port));
self.ports[i].as_mut().unwrap().identify()?; self.ports[i].as_mut().unwrap().identify()?;
} }
Ok(()) Ok(())
@ -226,36 +223,51 @@ impl From<&Command> for HostToDeviceRegisterFis {
} }
} }
struct PortController<'a> { struct PortController {
ahci_port_hba: &'a mut AhciPortHba, ahci_port_hba: &'static mut AhciPortHba,
command_list: &'static mut CommandList,
received_fis: &'static mut ReceivedFis,
command_tables: &'static mut [CommandTable; 32],
command_slots: [Option<Arc<Command>>; 32], command_slots: [Option<Arc<Command>>; 32],
command_structures: MemoryRegion,
// FIXME: These should probably be something like a OnceCell (or OnceLock). // FIXME: These should probably be something like a OnceCell (or OnceLock).
sector_size: Arc<Mutex<Option<u64>>>, sector_size: Arc<Mutex<Option<u64>>>,
sector_cnt: Arc<Mutex<Option<u64>>>, sector_cnt: Arc<Mutex<Option<u64>>>,
} }
impl<'a> PortController<'a> { impl PortController {
fn new(ahci_port_hba: &'a mut AhciPortHba) -> Result<Self, ZError> { fn new(ahci_port_hba: &'static mut AhciPortHba) -> Self {
let (command_structures, command_paddr) = MemoryRegion::contiguous_physical(0x2500)?; let (command_vaddr, command_paddr) = mem::map_physical_and_leak(0x2500);
ahci_port_hba.init(command_paddr, command_paddr + 0x400); ahci_port_hba.init(command_paddr, command_paddr + 0x400);
let mut controller = Self { let command_list = unsafe { (command_vaddr as *mut CommandList).as_mut().unwrap() };
ahci_port_hba, let received_fis = unsafe {
command_slots: [const { None }; 32], ((command_vaddr + 0x400) as *mut ReceivedFis)
command_structures, .as_mut()
sector_size: Arc::new(Mutex::new(None)), .unwrap()
sector_cnt: Arc::new(Mutex::new(None)), };
let command_tables = unsafe {
((command_vaddr + 0x500) as *mut [CommandTable; 32])
.as_mut()
.unwrap()
}; };
// This leaves space for 8 prdt entries. // This leaves space for 8 prdt entries.
for i in 0..32 { for i in 0..32 {
controller.command_list()[i].command_table_base_addr = command_list[i].command_table_base_addr =
(command_paddr + 0x500) + (0x100 * (i as u64)); (command_paddr + 0x500) + (0x100 * (i as u64));
} }
Ok(controller) Self {
ahci_port_hba,
command_list,
received_fis,
command_tables,
command_slots: [const { None }; 32],
sector_size: Arc::new(Mutex::new(None)),
sector_cnt: Arc::new(Mutex::new(None)),
}
} }
pub fn identify(&mut self) -> Result<(), ZError> { pub fn identify(&mut self) -> Result<(), ZError> {
@ -300,16 +312,15 @@ impl<'a> PortController<'a> {
let slot = self.select_slot()?; let slot = self.select_slot()?;
self.command_slots[slot] = Some(command.clone()); self.command_slots[slot] = Some(command.clone());
self.command_tables()[slot].command_fis.host_to_device = command.clone().as_ref().into(); self.command_tables[slot].command_fis.host_to_device = command.clone().as_ref().into();
self.command_tables()[slot].prdt[0].region_address = command.paddr; self.command_tables[slot].prdt[0].region_address = command.paddr;
self.command_tables()[slot].prdt[0].byte_count = 512 * (command.sector_cnt as u32); self.command_tables[slot].prdt[0].byte_count = 512 * (command.sector_cnt as u32);
self.command_list()[slot].prd_table_length = 1; self.command_list[slot].prd_table_length = 1;
self.command_list()[slot].command = self.command_list[slot].command = (size_of::<HostToDeviceRegisterFis>() as u16 / 4) & 0x1F;
(size_of::<HostToDeviceRegisterFis>() as u16 / 4) & 0x1F; self.command_list[slot].command |= 1 << 7;
self.command_list()[slot].command |= 1 << 7;
self.ahci_port_hba.issue_command(slot); self.ahci_port_hba.issue_command(slot);
Ok(()) Ok(())
} }
@ -324,53 +335,22 @@ impl<'a> PortController<'a> {
return Err(ZError::EXHAUSTED); return Err(ZError::EXHAUSTED);
} }
fn command_list(&mut self) -> &mut CommandList {
unsafe {
self.command_structures
.mut_slice::<u8>()
.as_mut_ptr()
.cast::<CommandList>()
.as_mut()
.unwrap()
}
}
fn recieved_fis(&mut self) -> &mut ReceivedFis {
unsafe {
self.command_structures.mut_slice::<u8>()[0x400..]
.as_mut_ptr()
.cast::<ReceivedFis>()
.as_mut()
.unwrap()
}
}
fn command_tables(&mut self) -> &mut [CommandTable; 32] {
unsafe {
self.command_structures.mut_slice::<u8>()[0x500..]
.as_mut_ptr()
.cast::<[CommandTable; 32]>()
.as_mut()
.unwrap()
}
}
fn handle_interrupt(&mut self) { fn handle_interrupt(&mut self) {
let int_status = self.ahci_port_hba.interrupt_status.read(); let int_status = self.ahci_port_hba.interrupt_status.read();
if int_status.device_to_host_register_fis_interrupt() { if int_status.device_to_host_register_fis_interrupt() {
assert_eq!( assert_eq!(
self.recieved_fis().device_to_host_register_fis.fis_type as u8, self.received_fis.device_to_host_register_fis.fis_type as u8,
FisType::RegisterDeviceToHost as u8 FisType::RegisterDeviceToHost as u8
); );
if self.recieved_fis().device_to_host_register_fis.error != 0 { if self.received_fis.device_to_host_register_fis.error != 0 {
mammoth::debug!( mammoth::debug!(
"D2H err: {:#0x}", "D2H err: {:#0x}",
self.recieved_fis().device_to_host_register_fis.error self.received_fis.device_to_host_register_fis.error
); );
mammoth::debug!( mammoth::debug!(
"Status: {:#0x}", "Status: {:#0x}",
self.recieved_fis().device_to_host_register_fis.status self.received_fis.device_to_host_register_fis.status
); );
} }