Move init implementation into hba and introduce volatile.
This commit is contained in:
parent
34bd3b80d3
commit
741b605a1c
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue