[Zion][Denali] Move to MSI for AHCI devices.

This will allow us to properly do interrupts for XHCI devices in the
future.

Also move PCI device header parsing to a shared library.

Get rid of the old irq register format which supplied an irq number and
instead pass the appropriate irq number back out to the caller.
This commit is contained in:
Drew Galbraith 2025-05-05 23:13:59 -07:00
parent c645405ca8
commit f26fd73116
21 changed files with 371 additions and 124 deletions

View file

@ -6,6 +6,7 @@ use mammoth::{
thread,
zion::ZError,
};
use pci::PciDevice;
use crate::ahci::{
port::{AhciDeviceDetection, AhciInterfacePowerManagement},
@ -14,36 +15,8 @@ use crate::ahci::{
use super::{hba::AhciHba, port::AhciPortHba, port_controller::PortController};
#[derive(Debug)]
#[repr(C, packed)]
pub struct PciDeviceHeader {
pub vendor_id: u16,
pub device_id: u16,
pub command_reg: u16,
pub status_reg: u16,
pub revision: u8,
pub prog_interface: u8,
pub subclass: u8,
pub class_code: u8,
pub cache_line_size: u8,
pub latency_timer: u8,
pub header_type: u8,
pub bist: u8,
pub bars: [u32; 5],
pub abar: u32,
__: u32,
pub subsystem_id: u32,
pub expansion_rom: u32,
pub cap_ptr: u8,
___: [u8; 7],
pub interrupt_line: u8,
pub interrupt_pin: u8,
pub min_grant: u8,
pub max_latency: u8,
}
pub struct AhciController {
pci_header: &'static mut PciDeviceHeader,
pci_device: Mutex<PciDevice>,
hba: Mutex<&'static mut AhciHba>,
ports: [Option<PortController>; 32],
hba_vaddr: u64,
@ -51,13 +24,13 @@ pub struct AhciController {
impl AhciController {
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 pci_device = PciDevice::from_cap(pci_memory).unwrap();
let hba_vaddr = mem::map_direct_physical_and_leak(pci_header.abar as u64, 0x1100);
let hba_vaddr =
mem::map_direct_physical_and_leak(pci_device.header().bars[5] as u64, 0x1100);
let hba = unsafe { (hba_vaddr as *mut AhciHba).as_mut().unwrap() };
let mut controller = Self {
pci_header,
pci_device: Mutex::new(pci_device),
hba: Mutex::new(hba),
ports: [const { None }; 32],
hba_vaddr,
@ -100,17 +73,8 @@ impl AhciController {
}
}
fn irq_num(&self) -> u64 {
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
),
}
fn register_irq(&self) -> Result<Capability, ZError> {
self.pci_device.lock().register_msi()
}
fn handle_irq(&self) {
@ -184,9 +148,8 @@ impl AhciController {
pub fn spawn_irq_thread(controller: Arc<AhciController>) -> thread::JoinHandle {
let irq_thread = move || {
let irq_num = controller.irq_num();
let irq_port =
mammoth::port::PortServer::from_cap(mammoth::syscall::register_irq(irq_num).unwrap());
let irq_port_cap = controller.register_irq().unwrap();
let irq_port = mammoth::port::PortServer::from_cap(irq_port_cap);
controller.hba.lock().global_host_control.update(|ghc| {
ghc.set_interrupt_enable(true);
});