From 04effd44f82e4999a44a2921ce7372b6b25c30a1 Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Fri, 31 Jan 2025 21:23:42 -0800 Subject: [PATCH] Move Ahci Port Controller to hold raw references. --- rust/lib/mammoth/src/mem.rs | 7 ++ rust/sys/denali/src/ahci/controller.rs | 106 ++++++++++--------------- 2 files changed, 50 insertions(+), 63 deletions(-) diff --git a/rust/lib/mammoth/src/mem.rs b/rust/lib/mammoth/src/mem.rs index 6cf662d..3b634af 100644 --- a/rust/lib/mammoth/src/mem.rs +++ b/rust/lib/mammoth/src/mem.rs @@ -152,3 +152,10 @@ where 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) +} diff --git a/rust/sys/denali/src/ahci/controller.rs b/rust/sys/denali/src/ahci/controller.rs index 0f166bd..20dda6e 100644 --- a/rust/sys/denali/src/ahci/controller.rs +++ b/rust/sys/denali/src/ahci/controller.rs @@ -3,7 +3,7 @@ use core::ops::DerefMut; use alloc::boxed::Box; use alloc::sync::Arc; use mammoth::sync::Mutex; -use mammoth::thread; +use mammoth::{mem, thread}; use mammoth::{mem::MemoryRegion, zion::ZError}; @@ -15,10 +15,7 @@ use crate::ahci::port::{ use super::command::{ CommandList, CommandTable, HostToDeviceRegisterFis, ReceivedFis, SataCommand, }; -use super::{ - hba::AhciHba, - port::{AhciPortHba, AhciPortInterruptEnable, AhciSataError}, -}; +use super::{hba::AhciHba, port::AhciPortHba}; #[derive(Debug)] #[repr(C, packed)] @@ -51,7 +48,7 @@ pub struct PciDeviceHeader { pub struct AhciController { pci_memory: MemoryRegion, hba_memory: MemoryRegion, - ports: [Option>; 32], + ports: [Option; 32], } impl AhciController { @@ -140,7 +137,7 @@ impl AhciController { continue; } - self.ports[i] = Some(PortController::new(port)?); + self.ports[i] = Some(PortController::new(port)); self.ports[i].as_mut().unwrap().identify()?; } Ok(()) @@ -226,36 +223,51 @@ impl From<&Command> for HostToDeviceRegisterFis { } } -struct PortController<'a> { - ahci_port_hba: &'a mut AhciPortHba, +struct PortController { + 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>; 32], - command_structures: MemoryRegion, // FIXME: These should probably be something like a OnceCell (or OnceLock). sector_size: Arc>>, sector_cnt: Arc>>, } -impl<'a> PortController<'a> { - fn new(ahci_port_hba: &'a mut AhciPortHba) -> Result { - let (command_structures, command_paddr) = MemoryRegion::contiguous_physical(0x2500)?; +impl PortController { + fn new(ahci_port_hba: &'static mut AhciPortHba) -> Self { + let (command_vaddr, command_paddr) = mem::map_physical_and_leak(0x2500); ahci_port_hba.init(command_paddr, command_paddr + 0x400); - let mut controller = Self { - ahci_port_hba, - command_slots: [const { None }; 32], - command_structures, - sector_size: Arc::new(Mutex::new(None)), - sector_cnt: Arc::new(Mutex::new(None)), + let command_list = unsafe { (command_vaddr as *mut CommandList).as_mut().unwrap() }; + let received_fis = unsafe { + ((command_vaddr + 0x400) as *mut ReceivedFis) + .as_mut() + .unwrap() + }; + let command_tables = unsafe { + ((command_vaddr + 0x500) as *mut [CommandTable; 32]) + .as_mut() + .unwrap() }; // This leaves space for 8 prdt entries. 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)); } - 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> { @@ -300,16 +312,15 @@ impl<'a> PortController<'a> { let slot = self.select_slot()?; 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].byte_count = 512 * (command.sector_cnt as u32); + 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_list()[slot].prd_table_length = 1; + self.command_list[slot].prd_table_length = 1; - self.command_list()[slot].command = - (size_of::() as u16 / 4) & 0x1F; - self.command_list()[slot].command |= 1 << 7; + self.command_list[slot].command = (size_of::() as u16 / 4) & 0x1F; + self.command_list[slot].command |= 1 << 7; self.ahci_port_hba.issue_command(slot); Ok(()) } @@ -324,53 +335,22 @@ impl<'a> PortController<'a> { return Err(ZError::EXHAUSTED); } - fn command_list(&mut self) -> &mut CommandList { - unsafe { - self.command_structures - .mut_slice::() - .as_mut_ptr() - .cast::() - .as_mut() - .unwrap() - } - } - - fn recieved_fis(&mut self) -> &mut ReceivedFis { - unsafe { - self.command_structures.mut_slice::()[0x400..] - .as_mut_ptr() - .cast::() - .as_mut() - .unwrap() - } - } - - fn command_tables(&mut self) -> &mut [CommandTable; 32] { - unsafe { - self.command_structures.mut_slice::()[0x500..] - .as_mut_ptr() - .cast::<[CommandTable; 32]>() - .as_mut() - .unwrap() - } - } - fn handle_interrupt(&mut self) { let int_status = self.ahci_port_hba.interrupt_status.read(); if int_status.device_to_host_register_fis_interrupt() { 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 ); - if self.recieved_fis().device_to_host_register_fis.error != 0 { + if self.received_fis.device_to_host_register_fis.error != 0 { mammoth::debug!( "D2H err: {:#0x}", - self.recieved_fis().device_to_host_register_fis.error + self.received_fis.device_to_host_register_fis.error ); mammoth::debug!( "Status: {:#0x}", - self.recieved_fis().device_to_host_register_fis.status + self.received_fis.device_to_host_register_fis.status ); }