diff --git a/rust/lib/mammoth/src/port.rs b/rust/lib/mammoth/src/port.rs index 8a86518..1972fcd 100644 --- a/rust/lib/mammoth/src/port.rs +++ b/rust/lib/mammoth/src/port.rs @@ -13,6 +13,10 @@ impl PortServer { }) } + pub fn from_cap(port_cap: Capability) -> Self { + Self { port_cap } + } + pub fn create_client_cap(&self) -> Result { self.port_cap .duplicate(!kZionPerm_Read) diff --git a/rust/lib/mammoth/src/syscall.rs b/rust/lib/mammoth/src/syscall.rs index 5b83756..cfec2f1 100644 --- a/rust/lib/mammoth/src/syscall.rs +++ b/rust/lib/mammoth/src/syscall.rs @@ -295,6 +295,18 @@ pub fn port_poll( Ok((num_bytes, num_caps)) } +pub fn register_irq(irq_num: u64) -> Result { + let mut port_cap: z_cap_t = 0; + syscall( + zion::kZionIrqRegister, + &zion::ZIrqRegisterReq { + irq_num, + port_cap: &mut port_cap, + }, + )?; + Ok(Capability::take(port_cap)) +} + pub fn endpoint_create() -> Result { let mut endpoint_cap: z_cap_t = 0; syscall( diff --git a/rust/sys/denali/src/ahci/controller.rs b/rust/sys/denali/src/ahci/controller.rs index abde094..71bdc70 100644 --- a/rust/sys/denali/src/ahci/controller.rs +++ b/rust/sys/denali/src/ahci/controller.rs @@ -1,7 +1,11 @@ -use mammoth::mem::MemoryRegion; +use alloc::boxed::Box; +use core::{ffi::c_void, mem::MaybeUninit}; -use bitfield_struct::bitfield; +use mammoth::{mem::MemoryRegion, thread::Thread, zion::ZError}; +use super::{hba::AhciHba, port::AhciPortHba}; + +#[derive(Debug)] #[repr(C, packed)] pub struct PciDeviceHeader { pub vendor_id: u16, @@ -20,7 +24,7 @@ pub struct PciDeviceHeader { pub abar: u32, __: u32, pub subsystem_id: u32, - pub expansion_rom: u16, + pub expansion_rom: u32, pub cap_ptr: u8, ___: [u8; 7], pub interrupt_line: u8, @@ -29,166 +33,12 @@ pub struct PciDeviceHeader { pub max_latency: u8, } -const fn increment(val: u8) -> u8 { - val + 1 -} - -#[derive(Debug, PartialEq, Eq)] -#[repr(u8)] -enum InterfaceSpeedSupport { - Reserved = 0b0000, - // 1.5 Gbps - Gen1 = 0b0001, - // 3 Gbps - Gen2 = 0b0010, - // 6 Gbps - Gen3 = 0b0011, - Unknown = 0b1111, -} - -impl InterfaceSpeedSupport { - const fn from_bits(value: u8) -> Self { - match value { - 0b0000 => Self::Reserved, - 0b0001 => Self::Gen1, - 0b0010 => Self::Gen2, - 0b0011 => Self::Gen3, - _ => Self::Unknown, - } - } -} - -#[bitfield(u32)] -pub struct AhciCapabilities { - #[bits(5, access = RO, from = increment)] - num_ports: u8, - - #[bits(access = RO)] - supports_external_sata: bool, - - #[bits(access = RO)] - enclosure_management_supported: bool, - - #[bits(access = RO)] - command_completed_coalescing_supported: bool, - - #[bits(5, access = RO, from = increment)] - num_commands: u8, - - #[bits(access = RO)] - partial_state_capable: bool, - - #[bits(access = RO)] - slumber_state_capable: bool, - - #[bits(access = RO)] - pio_multiple_drq_block: bool, - - #[bits(access = RO)] - fis_based_switching_supported: bool, - - #[bits(access = RO)] - supports_port_multiplier: bool, - - #[bits(access = RO)] - supports_ahci_mode_only: bool, - - __: bool, - - #[bits(4, access = RO)] - interface_speed_support: InterfaceSpeedSupport, - - #[bits(access = RO)] - supports_command_list_override: bool, - - #[bits(access = RO)] - supports_activity_led: bool, - - #[bits(access = RO)] - supports_aggressive_link_power_management: bool, - - #[bits(access = RO)] - supports_staggered_spin_up: bool, - - #[bits(access = RO)] - supports_mechanical_presence_switch: bool, - - #[bits(access = RO)] - supports_snotification_register: bool, - - #[bits(access = RO)] - supports_native_command_queueing: bool, - - #[bits(access = RO)] - supports_64_bit_addressing: bool, -} - -#[bitfield(u32)] -pub struct AhciGlobalControl { - hba_reset: bool, - interrupt_enable: bool, - - #[bits(access = RO)] - msi_revert_to_single_message: bool, - - #[bits(28)] - __: u32, - - ahci_enable: bool, -} - -#[bitfield(u32)] -pub struct AhciCapabilitiesExtended { - #[bits(access = RO)] - bios_os_handoff: bool, - - #[bits(access = RO)] - nvmhci_present: bool, - - #[bits(access = RO)] - automatic_partial_to_slumber_transitions: bool, - - #[bits(access = RO)] - supports_device_sleep: bool, - - #[bits(access = RO)] - supports_aggressive_device_sleep_management: bool, - - #[bits(27)] - __: u32, -} - -#[bitfield(u32)] -pub struct AhciBiosHandoffControl { - bios_owned_semaphore: bool, - os_owned_semaphore: bool, - smi_on_os_ownership_change_enable: bool, - os_ownership_change: bool, - bios_busy: bool, - - #[bits(27)] - __: u32, -} - -#[derive(Debug)] -#[repr(C, packed)] -pub struct AhciHba { - pub capabilities: AhciCapabilities, - global_host_control: AhciGlobalControl, - interrupt_status: u32, - port_implemented: u32, - version: u32, - ccc_ctl: u32, // 0x14, Command completion coalescing control - ccc_pts: u32, // 0x18, Command completion coalescing ports - em_loc: u32, // 0x1C, Enclosure management location - em_ctl: u32, // 0x20, Enclosure management control - capabilities_ext: AhciCapabilitiesExtended, - bohc: AhciBiosHandoffControl, -} - pub struct AhciController { pci_memory: MemoryRegion, hba_memory: MemoryRegion, + irq_port: Option, + irq_thread: Option>, + ports: [Option>; 32], } impl AhciController { @@ -203,9 +53,97 @@ impl AhciController { }; let hba_memory = MemoryRegion::direct_physical(pci_device_header.abar as u64, 0x1100).unwrap(); - Self { + let mut controller = Self { pci_memory, hba_memory, + irq_port: None, + irq_thread: None, + ports: [const { None }; 32], + }; + mammoth::debug!("{:?}", controller.pci_header()); + controller.init(); + controller + } + + fn init(&mut self) { + self.ahci_hba().global_host_control.with_hba_reset(true); + + loop { + if !self.ahci_hba().global_host_control.hba_reset() { + break; + } + } + + self.ahci_hba().global_host_control.with_ahci_enable(true); + + mammoth::syscall::thread_sleep(50).unwrap(); + + self.register_irq(); + + self.init_ports(); + } + + fn run_server(&self) -> Result, ZError> { + let thread_entry = |server_ptr: *const c_void| { + let server = unsafe { + (server_ptr as *mut Self) + .as_mut() + .expect("Failed to convert to server") + }; + server.irq_loop(); + }; + Thread::spawn( + thread_entry, + self as *const Self as *const core::ffi::c_void, + ) + } + + fn register_irq(&mut self) { + let irq_num = 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.irq_port = Some(mammoth::port::PortServer::from_cap( + mammoth::syscall::register_irq(irq_num).unwrap(), + )); + + self.irq_thread = Some(self.run_server().unwrap()); + + self.ahci_hba() + .global_host_control + .with_interrupt_enable(true); + } + + fn irq_loop(&self) {} + + fn init_ports(&mut self) { + for i in 0..(self.ahci_hba().capabilities.num_ports() as usize) { + let port_index = 1 << i; + if (self.ahci_hba().port_implemented & port_index) != port_index { + mammoth::debug!("Skipping port {}, not implemented", i); + continue; + } + + let port_offset: usize = 0x100 + (0x80 * i); + let port_size = size_of::(); + let port_limit = port_offset + port_size; + let port = unsafe { + self.hba_memory.mut_slice::()[port_offset..port_limit] + .as_mut_ptr() + .cast::() + .as_mut() + .unwrap() + }; + + self.ports[i] = Some(PortController::new(port)); + self.ports[i].as_ref().unwrap().identify(); + mammoth::debug!("Identifying port {}", i); } } @@ -231,3 +169,15 @@ impl AhciController { } } } + +struct PortController<'a> { + ahci_port_hba: &'a AhciPortHba, +} + +impl<'a> PortController<'a> { + fn new(ahci_port_hba: &'a AhciPortHba) -> Self { + Self { ahci_port_hba } + } + + pub fn identify(&self) {} +} diff --git a/rust/sys/denali/src/ahci/hba.rs b/rust/sys/denali/src/ahci/hba.rs new file mode 100644 index 0000000..f9dbde9 --- /dev/null +++ b/rust/sys/denali/src/ahci/hba.rs @@ -0,0 +1,158 @@ +use bitfield_struct::bitfield; + +const fn increment(val: u8) -> u8 { + val + 1 +} + +#[derive(Debug, PartialEq, Eq)] +#[repr(u8)] +enum InterfaceSpeedSupport { + Reserved = 0b0000, + // 1.5 Gbps + Gen1 = 0b0001, + // 3 Gbps + Gen2 = 0b0010, + // 6 Gbps + Gen3 = 0b0011, + Unknown = 0b1111, +} + +impl InterfaceSpeedSupport { + const fn from_bits(value: u8) -> Self { + match value { + 0b0000 => Self::Reserved, + 0b0001 => Self::Gen1, + 0b0010 => Self::Gen2, + 0b0011 => Self::Gen3, + _ => Self::Unknown, + } + } +} + +#[bitfield(u32)] +pub struct AhciCapabilities { + #[bits(5, access = RO, from = increment)] + pub num_ports: u8, + + #[bits(access = RO)] + supports_external_sata: bool, + + #[bits(access = RO)] + enclosure_management_supported: bool, + + #[bits(access = RO)] + command_completed_coalescing_supported: bool, + + #[bits(5, access = RO, from = increment)] + num_commands: u8, + + #[bits(access = RO)] + partial_state_capable: bool, + + #[bits(access = RO)] + slumber_state_capable: bool, + + #[bits(access = RO)] + pio_multiple_drq_block: bool, + + #[bits(access = RO)] + fis_based_switching_supported: bool, + + #[bits(access = RO)] + supports_port_multiplier: bool, + + #[bits(access = RO)] + supports_ahci_mode_only: bool, + + __: bool, + + #[bits(4, access = RO)] + interface_speed_support: InterfaceSpeedSupport, + + #[bits(access = RO)] + supports_command_list_override: bool, + + #[bits(access = RO)] + supports_activity_led: bool, + + #[bits(access = RO)] + supports_aggressive_link_power_management: bool, + + #[bits(access = RO)] + supports_staggered_spin_up: bool, + + #[bits(access = RO)] + supports_mechanical_presence_switch: bool, + + #[bits(access = RO)] + supports_snotification_register: bool, + + #[bits(access = RO)] + supports_native_command_queueing: bool, + + #[bits(access = RO)] + supports_64_bit_addressing: bool, +} + +#[bitfield(u32)] +pub struct AhciGlobalControl { + pub hba_reset: bool, + pub interrupt_enable: bool, + + #[bits(access = RO)] + pub msi_revert_to_single_message: bool, + + #[bits(28)] + __: u32, + + pub ahci_enable: bool, +} + +#[bitfield(u32)] +pub struct AhciCapabilitiesExtended { + #[bits(access = RO)] + bios_os_handoff: bool, + + #[bits(access = RO)] + nvmhci_present: bool, + + #[bits(access = RO)] + automatic_partial_to_slumber_transitions: bool, + + #[bits(access = RO)] + supports_device_sleep: bool, + + #[bits(access = RO)] + supports_aggressive_device_sleep_management: bool, + + #[bits(27)] + __: u32, +} + +#[bitfield(u32)] +pub struct AhciBiosHandoffControl { + bios_owned_semaphore: bool, + os_owned_semaphore: bool, + smi_on_os_ownership_change_enable: bool, + os_ownership_change: bool, + bios_busy: bool, + + #[bits(27)] + __: u32, +} + +#[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, +} diff --git a/rust/sys/denali/src/ahci/mod.rs b/rust/sys/denali/src/ahci/mod.rs index de3958b..36a1d0f 100644 --- a/rust/sys/denali/src/ahci/mod.rs +++ b/rust/sys/denali/src/ahci/mod.rs @@ -1,4 +1,5 @@ mod controller; +mod hba; mod port; pub use controller::AhciController; diff --git a/rust/sys/denali/src/ahci/port.rs b/rust/sys/denali/src/ahci/port.rs index 7b1e10e..773bdde 100644 --- a/rust/sys/denali/src/ahci/port.rs +++ b/rust/sys/denali/src/ahci/port.rs @@ -1,3 +1,5 @@ +use bitfield_struct::bitfield; + #[bitfield(u32)] struct AhciPortInterruptStatus { device_to_host_register_fis_interrupt: bool, @@ -377,7 +379,7 @@ struct AhciDeviceSleep { } #[repr(C, packed)] -struct AhciPortHba { +pub struct AhciPortHba { command_list_base: u64, fis_base: u64, interrupt_status: AhciPortInterruptStatus,