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::syscall;
|
||||||
use crate::zion::ZError;
|
use crate::zion::ZError;
|
||||||
use alloc::slice;
|
use alloc::slice;
|
||||||
|
use core::fmt::Debug;
|
||||||
|
use core::ptr::{addr_of, addr_of_mut};
|
||||||
|
|
||||||
#[cfg(feature = "hosted")]
|
#[cfg(feature = "hosted")]
|
||||||
use linked_list_allocator::LockedHeap;
|
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");
|
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) {
|
fn init(&mut self) {
|
||||||
self.ahci_hba().global_host_control.set_hba_reset(true);
|
self.ahci_hba().init();
|
||||||
|
|
||||||
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.init_ports().unwrap();
|
self.init_ports().unwrap();
|
||||||
}
|
}
|
||||||
|
@ -107,21 +95,23 @@ impl AhciController {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_irq(&mut self) {
|
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;
|
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] {
|
if let Some(port) = &mut self.ports[i as usize] {
|
||||||
port.handle_interrupt();
|
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> {
|
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;
|
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);
|
mammoth::debug!("Skipping port {}, not implemented", i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -188,7 +178,9 @@ pub fn spawn_irq_thread(controller: Arc<Mutex<AhciController>>) -> thread::JoinH
|
||||||
.lock()
|
.lock()
|
||||||
.ahci_hba()
|
.ahci_hba()
|
||||||
.global_host_control
|
.global_host_control
|
||||||
.set_interrupt_enable(true);
|
.update(|ghc| {
|
||||||
|
ghc.set_interrupt_enable(true);
|
||||||
|
});
|
||||||
loop {
|
loop {
|
||||||
irq_port.recv_null().unwrap();
|
irq_port.recv_null().unwrap();
|
||||||
controller.lock().handle_irq();
|
controller.lock().handle_irq();
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use bitfield_struct::bitfield;
|
use bitfield_struct::bitfield;
|
||||||
|
use mammoth::mem::Volatile;
|
||||||
|
|
||||||
const fn increment(val: u8) -> u8 {
|
const fn increment(val: u8) -> u8 {
|
||||||
val + 1
|
val + 1
|
||||||
|
@ -144,15 +145,37 @@ pub struct AhciBiosHandoffControl {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct AhciHba {
|
pub struct AhciHba {
|
||||||
pub capabilities: AhciCapabilities,
|
pub capabilities: Volatile<AhciCapabilities>,
|
||||||
pub global_host_control: AhciGlobalControl,
|
pub global_host_control: Volatile<AhciGlobalControl>,
|
||||||
pub interrupt_status: u32,
|
pub interrupt_status: Volatile<u32>,
|
||||||
pub port_implemented: u32,
|
pub port_implemented: Volatile<u32>,
|
||||||
pub version: u32,
|
pub version: Volatile<u32>,
|
||||||
pub ccc_ctl: u32, // 0x14, Command completion coalescing control
|
pub ccc_ctl: Volatile<u32>, // 0x14, Command completion coalescing control
|
||||||
pub ccc_pts: u32, // 0x18, Command completion coalescing ports
|
pub ccc_pts: Volatile<u32>, // 0x18, Command completion coalescing ports
|
||||||
pub em_loc: u32, // 0x1C, Enclosure management location
|
pub em_loc: Volatile<u32>, // 0x1C, Enclosure management location
|
||||||
pub em_ctl: u32, // 0x20, Enclosure management control
|
pub em_ctl: Volatile<u32>, // 0x20, Enclosure management control
|
||||||
pub capabilities_ext: AhciCapabilitiesExtended,
|
pub capabilities_ext: Volatile<AhciCapabilitiesExtended>,
|
||||||
pub bohc: AhciBiosHandoffControl,
|
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