Move init implementation into hba and introduce volatile.

This commit is contained in:
Drew Galbraith 2025-01-31 18:03:04 -08:00
parent 34bd3b80d3
commit 741b605a1c
3 changed files with 86 additions and 30 deletions

View File

@ -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<T> {
/// TODO: This should maybe be MaybeUninit.
data: T,
}
impl<T> Volatile<T> {
pub fn read(&self) -> T
where
T: Copy,
{
unsafe { addr_of!(self.data).cast::<T>().read_volatile() }
}
pub fn write(&mut self, data: T) {
unsafe {
addr_of_mut!(self.data).cast::<T>().write_volatile(data);
}
}
pub fn update<F>(&mut self, func: F)
where
T: Copy,
F: Fn(&mut T),
{
let mut data = self.read();
func(&mut data);
self.write(data);
}
}
impl<T> Debug for Volatile<T>
where
T: Debug + Copy,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:?}", self.read())
}
}

View File

@ -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<Mutex<AhciController>>) -> 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();

View File

@ -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<AhciCapabilities>,
pub global_host_control: Volatile<AhciGlobalControl>,
pub interrupt_status: Volatile<u32>,
pub port_implemented: Volatile<u32>,
pub version: Volatile<u32>,
pub ccc_ctl: Volatile<u32>, // 0x14, Command completion coalescing control
pub ccc_pts: Volatile<u32>, // 0x18, Command completion coalescing ports
pub em_loc: Volatile<u32>, // 0x1C, Enclosure management location
pub em_ctl: Volatile<u32>, // 0x20, Enclosure management control
pub capabilities_ext: Volatile<AhciCapabilitiesExtended>,
pub bohc: Volatile<AhciBiosHandoffControl>,
}
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();
}
}