Store ahci hba and pci device header as mut references

This commit is contained in:
Drew Galbraith 2025-01-31 21:38:06 -08:00
parent 04effd44f8
commit 017367c4de
3 changed files with 38 additions and 59 deletions

View File

@ -153,6 +153,19 @@ where
}
}
pub fn map_cap_and_leak(mem_cap: Capability) -> u64 {
let vaddr = syscall::address_space_map(&mem_cap).unwrap();
mem_cap.release();
vaddr
}
pub fn map_direct_physical_and_leak(paddr: u64, size: u64) -> u64 {
let mem_cap = syscall::memory_object_direct_physical(paddr, size).unwrap();
let vaddr = syscall::address_space_map(&mem_cap).unwrap();
mem_cap.release();
vaddr
}
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();

View File

@ -1,7 +1,9 @@
use core::ops::DerefMut;
use core::ptr::addr_of_mut;
use alloc::boxed::Box;
use alloc::sync::Arc;
use mammoth::cap::Capability;
use mammoth::sync::Mutex;
use mammoth::{mem, thread};
@ -46,26 +48,21 @@ pub struct PciDeviceHeader {
}
pub struct AhciController {
pci_memory: MemoryRegion,
hba_memory: MemoryRegion,
pci_header: &'static mut PciDeviceHeader,
hba: &'static mut AhciHba,
ports: [Option<PortController>; 32],
}
impl AhciController {
pub fn new(pci_memory: MemoryRegion) -> Self {
let pci_device_header = unsafe {
pci_memory
.mut_slice::<u8>()
.as_mut_ptr()
.cast::<PciDeviceHeader>()
.as_mut()
.unwrap()
};
let hba_memory =
MemoryRegion::direct_physical(pci_device_header.abar as u64, 0x1100).unwrap();
pub fn new(pci_memory: Capability) -> Self {
let pci_vaddr = mem::map_cap_and_leak(pci_memory);
let pci_header = unsafe { (pci_vaddr as *mut PciDeviceHeader).as_mut().unwrap() };
let hba_vaddr = mem::map_direct_physical_and_leak(pci_header.abar as u64, 0x1100);
let hba = unsafe { (hba_vaddr as *mut AhciHba).as_mut().unwrap() };
let mut controller = Self {
pci_memory,
hba_memory,
pci_header,
hba,
ports: [const { None }; 32],
};
controller.init();
@ -73,31 +70,31 @@ impl AhciController {
}
fn init(&mut self) {
self.ahci_hba().init();
self.hba.init();
self.init_ports().unwrap();
}
fn irq_num(&self) -> u64 {
match self.pci_header().interrupt_pin {
match self.pci_header.interrupt_pin {
1 => mammoth::zion::kZIrqPci1,
2 => mammoth::zion::kZIrqPci2,
3 => mammoth::zion::kZIrqPci3,
4 => mammoth::zion::kZIrqPci4,
_ => panic!(
"Unrecognized pci interrupt pin {}",
self.pci_header().interrupt_pin
self.pci_header.interrupt_pin
),
}
}
fn handle_irq(&mut self) {
for i in 0..self.ahci_hba().capabilities.read().num_ports() {
for i in 0..self.hba.capabilities.read().num_ports() {
let int_offset = 1 << i;
if (self.ahci_hba().interrupt_status.read() & int_offset) == int_offset {
if (self.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.update(|is| {
self.hba.interrupt_status.update(|is| {
*is &= !int_offset;
});
}
@ -106,20 +103,16 @@ impl AhciController {
}
fn init_ports(&mut self) -> Result<(), ZError> {
for i in 0..(self.ahci_hba().capabilities.read().num_ports() as usize) {
for i in 0..(self.hba.capabilities.read().num_ports() as usize) {
let port_index = 1 << i;
if (self.ahci_hba().port_implemented.read() & port_index) != port_index {
if (self.hba.port_implemented.read() & port_index) != port_index {
mammoth::debug!("Skipping port {}, not implemented", i);
continue;
}
let port_offset: usize = 0x100 + (0x80 * i);
let port_size = size_of::<AhciPortHba>();
let port_limit = port_offset + port_size;
let port = unsafe {
self.hba_memory.mut_slice::<u8>()[port_offset..port_limit]
.as_mut_ptr()
.cast::<AhciPortHba>()
(((self.hba as *mut _ as usize) + port_offset) as *mut AhciPortHba)
.as_mut()
.unwrap()
};
@ -142,28 +135,6 @@ impl AhciController {
}
Ok(())
}
pub fn pci_header(&self) -> &mut PciDeviceHeader {
unsafe {
self.pci_memory
.mut_slice::<u8>()
.as_mut_ptr()
.cast::<PciDeviceHeader>()
.as_mut()
.unwrap()
}
}
pub fn ahci_hba(&self) -> &mut AhciHba {
unsafe {
self.hba_memory
.mut_slice::<u8>()
.as_mut_ptr()
.cast::<AhciHba>()
.as_mut()
.unwrap()
}
}
}
pub fn spawn_irq_thread(controller: Arc<Mutex<AhciController>>) -> thread::JoinHandle {
@ -171,13 +142,9 @@ pub fn spawn_irq_thread(controller: Arc<Mutex<AhciController>>) -> thread::JoinH
let irq_num = controller.lock().irq_num();
let irq_port =
mammoth::port::PortServer::from_cap(mammoth::syscall::register_irq(irq_num).unwrap());
controller
.lock()
.ahci_hba()
.global_host_control
.update(|ghc| {
ghc.set_interrupt_enable(true);
});
controller.lock().hba.global_host_control.update(|ghc| {
ghc.set_interrupt_enable(true);
});
loop {
irq_port.recv_null().unwrap();
controller.lock().handle_irq();

View File

@ -21,8 +21,7 @@ extern "C" fn main() -> z_err_t {
.expect("Failed to get ahci info");
let ahci_controller = Arc::new(Mutex::new(AhciController::new(
mammoth::mem::MemoryRegion::from_cap(mammoth::cap::Capability::take(ahci_info.ahci_region))
.unwrap(),
mammoth::cap::Capability::take(ahci_info.ahci_region),
)));
let thread = spawn_irq_thread(ahci_controller.clone());