From 741b605a1c35a17a7aca8a16479fd2a2bfe29bbb Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Fri, 31 Jan 2025 18:03:04 -0800 Subject: [PATCH] Move init implementation into hba and introduce volatile. --- rust/lib/mammoth/src/mem.rs | 41 +++++++++++++++++++++++ rust/sys/denali/src/ahci/controller.rs | 30 +++++++---------- rust/sys/denali/src/ahci/hba.rs | 45 +++++++++++++++++++------- 3 files changed, 86 insertions(+), 30 deletions(-) diff --git a/rust/lib/mammoth/src/mem.rs b/rust/lib/mammoth/src/mem.rs index 6e7817c..6cf662d 100644 --- a/rust/lib/mammoth/src/mem.rs +++ b/rust/lib/mammoth/src/mem.rs @@ -2,6 +2,8 @@ use crate::cap::Capability; use crate::syscall; use crate::zion::ZError; use alloc::slice; +use core::fmt::Debug; +use core::ptr::{addr_of, addr_of_mut}; #[cfg(feature = "hosted")] use linked_list_allocator::LockedHeap; @@ -111,3 +113,42 @@ impl Drop for MemoryRegion { syscall::address_space_unmap(self.virt_addr, max).expect("Failed to unmap memory"); } } + +pub struct Volatile { + /// TODO: This should maybe be MaybeUninit. + data: T, +} + +impl Volatile { + pub fn read(&self) -> T + where + T: Copy, + { + unsafe { addr_of!(self.data).cast::().read_volatile() } + } + + pub fn write(&mut self, data: T) { + unsafe { + addr_of_mut!(self.data).cast::().write_volatile(data); + } + } + + pub fn update(&mut self, func: F) + where + T: Copy, + F: Fn(&mut T), + { + let mut data = self.read(); + func(&mut data); + self.write(data); + } +} + +impl Debug for Volatile +where + T: Debug + Copy, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{:?}", self.read()) + } +} diff --git a/rust/sys/denali/src/ahci/controller.rs b/rust/sys/denali/src/ahci/controller.rs index 6abf744..07783c8 100644 --- a/rust/sys/denali/src/ahci/controller.rs +++ b/rust/sys/denali/src/ahci/controller.rs @@ -76,19 +76,7 @@ impl AhciController { } fn init(&mut self) { - self.ahci_hba().global_host_control.set_hba_reset(true); - - mammoth::syscall::thread_sleep(50).unwrap(); - - loop { - if !self.ahci_hba().global_host_control.hba_reset() { - break; - } - } - - self.ahci_hba().global_host_control.set_ahci_enable(true); - - mammoth::syscall::thread_sleep(50).unwrap(); + self.ahci_hba().init(); self.init_ports().unwrap(); } @@ -107,21 +95,23 @@ impl AhciController { } fn handle_irq(&mut self) { - for i in 0..self.ahci_hba().capabilities.num_ports() { + for i in 0..self.ahci_hba().capabilities.read().num_ports() { let int_offset = 1 << i; - if (self.ahci_hba().interrupt_status & int_offset) == int_offset { + if (self.ahci_hba().interrupt_status.read() & int_offset) == int_offset { if let Some(port) = &mut self.ports[i as usize] { port.handle_interrupt(); - self.ahci_hba().interrupt_status &= !int_offset; + self.ahci_hba().interrupt_status.update(|is| { + *is &= !int_offset; + }); } } } } fn init_ports(&mut self) -> Result<(), ZError> { - for i in 0..(self.ahci_hba().capabilities.num_ports() as usize) { + for i in 0..(self.ahci_hba().capabilities.read().num_ports() as usize) { let port_index = 1 << i; - if (self.ahci_hba().port_implemented & port_index) != port_index { + if (self.ahci_hba().port_implemented.read() & port_index) != port_index { mammoth::debug!("Skipping port {}, not implemented", i); continue; } @@ -188,7 +178,9 @@ pub fn spawn_irq_thread(controller: Arc>) -> thread::JoinH .lock() .ahci_hba() .global_host_control - .set_interrupt_enable(true); + .update(|ghc| { + ghc.set_interrupt_enable(true); + }); loop { irq_port.recv_null().unwrap(); controller.lock().handle_irq(); diff --git a/rust/sys/denali/src/ahci/hba.rs b/rust/sys/denali/src/ahci/hba.rs index f9dbde9..2cfdc63 100644 --- a/rust/sys/denali/src/ahci/hba.rs +++ b/rust/sys/denali/src/ahci/hba.rs @@ -1,4 +1,5 @@ use bitfield_struct::bitfield; +use mammoth::mem::Volatile; const fn increment(val: u8) -> u8 { val + 1 @@ -144,15 +145,37 @@ pub struct AhciBiosHandoffControl { #[derive(Debug)] #[repr(C)] pub struct AhciHba { - pub capabilities: AhciCapabilities, - pub global_host_control: AhciGlobalControl, - pub interrupt_status: u32, - pub port_implemented: u32, - pub version: u32, - pub ccc_ctl: u32, // 0x14, Command completion coalescing control - pub ccc_pts: u32, // 0x18, Command completion coalescing ports - pub em_loc: u32, // 0x1C, Enclosure management location - pub em_ctl: u32, // 0x20, Enclosure management control - pub capabilities_ext: AhciCapabilitiesExtended, - pub bohc: AhciBiosHandoffControl, + pub capabilities: Volatile, + pub global_host_control: Volatile, + pub interrupt_status: Volatile, + pub port_implemented: Volatile, + pub version: Volatile, + pub ccc_ctl: Volatile, // 0x14, Command completion coalescing control + pub ccc_pts: Volatile, // 0x18, Command completion coalescing ports + pub em_loc: Volatile, // 0x1C, Enclosure management location + pub em_ctl: Volatile, // 0x20, Enclosure management control + pub capabilities_ext: Volatile, + pub bohc: Volatile, +} + +impl AhciHba { + pub fn init(&mut self) { + self.global_host_control.update(|ghc| { + ghc.set_hba_reset(true); + }); + + mammoth::syscall::thread_sleep(50).unwrap(); + + loop { + if !self.global_host_control.read().hba_reset() { + break; + } + } + + self.global_host_control.update(|ghc| { + ghc.set_ahci_enable(true); + }); + + mammoth::syscall::thread_sleep(50).unwrap(); + } }