diff --git a/rust/lib/mammoth/src/mem.rs b/rust/lib/mammoth/src/mem.rs index cef5dd6..6e7817c 100644 --- a/rust/lib/mammoth/src/mem.rs +++ b/rust/lib/mammoth/src/mem.rs @@ -41,6 +41,19 @@ impl MemoryRegion { }) } + pub fn contiguous_physical(size: u64) -> Result<(Self, u64), ZError> { + let (mem_cap, paddr) = syscall::memory_object_contiguous_physical(size)?; + let virt_addr = syscall::address_space_map(&mem_cap)?; + Ok(( + Self { + mem_cap, + virt_addr, + size, + }, + paddr, + )) + } + pub fn from_cap(mem_cap: Capability) -> Result { let virt_addr = syscall::address_space_map(&mem_cap)?; let size = syscall::memory_object_inspect(&mem_cap)?; diff --git a/rust/lib/mammoth/src/port.rs b/rust/lib/mammoth/src/port.rs index 1972fcd..34bddb1 100644 --- a/rust/lib/mammoth/src/port.rs +++ b/rust/lib/mammoth/src/port.rs @@ -40,6 +40,15 @@ impl PortServer { Ok(u16::from_le_bytes(bytes)) } + + pub fn recv_null(&self) -> Result<(), ZError> { + let mut caps: [z_cap_t; 0] = []; + let mut bytes: [u8; 0] = []; + + port_recv(&self.port_cap, &mut bytes, &mut caps)?; + + Ok(()) + } } pub struct PortClient { diff --git a/rust/lib/mammoth/src/syscall.rs b/rust/lib/mammoth/src/syscall.rs index cfec2f1..565a2c1 100644 --- a/rust/lib/mammoth/src/syscall.rs +++ b/rust/lib/mammoth/src/syscall.rs @@ -158,6 +158,21 @@ pub fn memory_object_direct_physical(paddr: u64, size: u64) -> Result Result<(Capability, u64), ZError> { + let mut vmmo_cap = 0; + let mut paddr = 0; + syscall( + zion::kZionMemoryObjectCreateContiguous, + &zion::ZMemoryObjectCreateContiguousReq { + size, + paddr: &mut paddr, + vmmo_cap: &mut vmmo_cap, + }, + )?; + + Ok((Capability::take(vmmo_cap), paddr)) +} + pub fn memory_object_inspect(mem_cap: &Capability) -> Result { let mut mem_size = 0; syscall( diff --git a/rust/sys/denali/src/ahci/command.rs b/rust/sys/denali/src/ahci/command.rs new file mode 100644 index 0000000..5870587 --- /dev/null +++ b/rust/sys/denali/src/ahci/command.rs @@ -0,0 +1,264 @@ +#[derive(Debug)] +#[repr(C, packed)] +pub struct CommandHeader { + pub command: u16, + pub prd_table_length: u16, + pub prd_byte_count: u32, + pub command_table_base_addr: u64, + __: u64, + ___: u64, +} + +pub type CommandList = [CommandHeader; 32]; + +#[allow(dead_code)] +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(u8)] +pub enum FisType { + RegisterHostToDevice = 0x27, // Register FIS - host to device + RegisterDeviceToHost = 0x34, // Register FIS - device to host + DmaActivate = 0x39, // DMA activate FIS - device to host + DmaSetup = 0x41, // DMA setup FIS - bidirectional + Data = 0x46, // Data FIS - bidirectional + BistActivate = 0x58, // BIST activate FIS - bidirectional + PioSetup = 0x5F, // PIO setup FIS - device to host + SetDeviceBits = 0xA1, // Set device bits FIS - device to host + Unknown = 0x0, +} + +#[allow(dead_code)] +#[derive(Copy, Clone, Debug)] +#[repr(C, packed)] +pub struct DmaFis { + // DWORD 0 + fis_type: u8, // FIS_TYPE_DMA_SETUP + pmport_dia: u8, // Port multiplier + + __: u16, // Reserved + + // DWORD 1&2 + dma_buffer_id: u64, // DMA Buffer Identifier. Used to Identify DMA buffer + // in host memory. SATA Spec says host specific and not + // in Spec. Trying AHCI spec might work. + + // DWORD 3 + ___: u32, + + // DWORD 4 + dma_buffer_offest: u32, // Byte offset into buffer. First 2 bits must be 0 + + // DWORD 5 + transfer_count: u32, // Number of bytes to transfer. Bit 0 must be 0 + + // DWORD 6 + ____: u32, // Reserved +} + +const _: () = assert!(size_of::() == 28); + +#[allow(dead_code)] +#[derive(Copy, Clone, Debug)] +#[repr(C, packed)] +pub struct PioSetupFis { + // DWORD 0 + fis_type: FisType, // FIS_TYPE_PIO_SETUP + + pmport_di: u8, // Port multiplier + + status: u8, // Status register + error: u8, // Error register + + // DWORD 1 + lba0: u8, // LBA low register, 7:0 + lba1: u8, // LBA mid register, 15:8 + lba2: u8, // LBA high register, 23:16 + device: u8, // Device register + + // DWORD 2 + lba3: u8, // LBA register, 31:24 + lba4: u8, // LBA register, 39:32 + lba5: u8, // LBA register, 47:40 + __: u8, // Reserved + + // DWORD 3 + countl: u8, // Count register, 7:0 + counth: u8, // Count register, 15:8 + ___: u8, // Reserved + e_status: u8, // New value of status register + + // DWORD 4 + tc: u16, // Transfer count + ____: u16, // Reserved +} + +const _: () = assert!(size_of::() == 20); + +#[derive(Clone, Copy, Debug)] +#[repr(u8)] +pub enum SataCommand { + IdentifyDevice = 0xEC, + DmaReadExt = 0x25, +} + +#[allow(dead_code)] // Read by memory. +#[derive(Clone, Copy, Debug)] +#[repr(C)] +pub struct HostToDeviceRegisterFis { + fis_type: FisType, // FIS_TYPE_REG_H2D + pmp_and_c: u8, + command: SataCommand, // Command register + featurel: u8, // Feature register, 7:0 + + // DWORD 1 + lba0: u8, // LBA low register, 7:0 + lba1: u8, // LBA mid register, 15:8 + lba2: u8, // LBA high register, 23:16 + device: u8, // Device register + + // DWORD 2 + lba3: u8, // LBA register, 31:24 + lba4: u8, // LBA register, 39:32 + lba5: u8, // LBA register, 47:40 + featureh: u8, // Feature register, 15:8 + + // DWORD 3 + count: u16, + icc: u8, // Isochronous command completion + control: u8, // Control register + + // DWORD 4 + reserved: u32, // Reserved +} + +const _: () = assert!(size_of::() == 20); + +impl HostToDeviceRegisterFis { + pub fn new_command(command: SataCommand, lba: u64, sectors: u16) -> Self { + Self { + fis_type: FisType::RegisterHostToDevice, + pmp_and_c: 0x80, // Set command bit + command, + featurel: 0, + + lba0: (lba & 0xFF) as u8, + lba1: ((lba >> 8) & 0xFF) as u8, + lba2: ((lba >> 16) & 0xFF) as u8, + device: (1 << 6), // ATA LBA Mode + + lba3: ((lba >> 24) & 0xFF) as u8, + lba4: ((lba >> 32) & 0xFF) as u8, + lba5: ((lba >> 40) & 0xFF) as u8, + featureh: 0, + + count: sectors, + icc: 0, + control: 0, + + reserved: 0, + } + } +} + +#[derive(Copy, Clone, Debug)] +#[repr(C, packed)] +pub struct DeviceToHostRegisterFis { + // DWORD 0 + pub fis_type: FisType, // FIS_TYPE_REG_D2H + + pub pmport_and_i: u8, + + pub status: u8, // Status register + pub error: u8, // Error register + + // DWORD 1 + pub lba0: u8, // LBA low register, 7:0 + pub lba1: u8, // LBA mid register, 15:8 + pub lba2: u8, // LBA high register, 23:16 + pub device: u8, // Device register + + // DWORD 2 + pub lba3: u8, // LBA register, 31:24 + pub lba4: u8, // LBA register, 39:32 + pub lba5: u8, // LBA register, 47:40 + __: u8, + + // DWORD 3 + pub count: u16, + ___: u16, + + ____: u32, +} + +const _: () = assert!(size_of::() == 20); + +#[derive(Copy, Clone, Debug)] +#[repr(C, packed)] +pub struct SetDeviceBitsFis { + fis_type: FisType, + pmport_and_i: u8, + status: u8, + error: u8, + reserved: u32, +} + +const _: () = assert!(size_of::() == 8); + +#[derive(Debug)] +#[repr(C, packed)] +pub struct ReceivedFis { + pub dma_fis: DmaFis, + __: u32, + + pub pio_set_fis: PioSetupFis, + ___: [u8; 12], + + pub device_to_host_register_fis: DeviceToHostRegisterFis, + ____: u32, + + pub set_device_bits_fis: SetDeviceBitsFis, + + pub unknown_fis: [u8; 64], +} + +const _: () = assert!(size_of::() == 0xA0); + +#[derive(Copy, Clone)] +#[repr(C)] +pub union CommandFis { + pub host_to_device: HostToDeviceRegisterFis, + + // Used to ensure the repr is + pub __: [u8; 64], +} + +const _: () = assert!(size_of::() == 0x40); + +impl core::fmt::Debug for CommandFis { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + f.write_fmt(format_args!("{:?}", unsafe { self.host_to_device })) + } +} + +#[derive(Copy, Clone, Debug)] +#[repr(C, packed)] +pub struct PhysicalRegionDescriptor { + pub region_address: u64, + __: u32, + // bit 0 must be one. + // 21:0 is byte count + // 31 is Interrupt on Completion + pub byte_count: u32, +} + +const _: () = assert!(size_of::() == 0x10); + +#[derive(Debug)] +#[repr(C, packed)] +pub struct CommandTable { + pub command_fis: CommandFis, + pub atapi_command: [u8; 0x10], + __: [u8; 0x30], + pub prdt: [PhysicalRegionDescriptor; 8], +} + +const _: () = assert!(size_of::() == 0x100); diff --git a/rust/sys/denali/src/ahci/controller.rs b/rust/sys/denali/src/ahci/controller.rs index 71bdc70..b0c3c3e 100644 --- a/rust/sys/denali/src/ahci/controller.rs +++ b/rust/sys/denali/src/ahci/controller.rs @@ -1,9 +1,21 @@ use alloc::boxed::Box; -use core::{ffi::c_void, mem::MaybeUninit}; +use alloc::rc::Rc; +use core::ffi::c_void; use mammoth::{mem::MemoryRegion, thread::Thread, zion::ZError}; -use super::{hba::AhciHba, port::AhciPortHba}; +use crate::ahci::command::FisType; +use crate::ahci::port::{ + AhciDeviceDetection, AhciInterfacePowerManagement, AhciPortInterruptStatus, +}; + +use super::command::{ + CommandList, CommandTable, HostToDeviceRegisterFis, ReceivedFis, SataCommand, +}; +use super::{ + hba::AhciHba, + port::{AhciPortHba, AhciPortInterruptEnable, AhciSataError}, +}; #[derive(Debug)] #[repr(C, packed)] @@ -60,13 +72,18 @@ impl AhciController { irq_thread: None, ports: [const { None }; 32], }; - mammoth::debug!("{:?}", controller.pci_header()); controller.init(); controller } + pub fn join(&self) -> Result<(), ZError> { + self.irq_thread.as_ref().unwrap().join() + } + fn init(&mut self) { - self.ahci_hba().global_host_control.with_hba_reset(true); + 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() { @@ -74,13 +91,13 @@ impl AhciController { } } - self.ahci_hba().global_host_control.with_ahci_enable(true); + self.ahci_hba().global_host_control.set_ahci_enable(true); mammoth::syscall::thread_sleep(50).unwrap(); self.register_irq(); - self.init_ports(); + self.init_ports().unwrap(); } fn run_server(&self) -> Result, ZError> { @@ -117,12 +134,26 @@ impl AhciController { self.ahci_hba() .global_host_control - .with_interrupt_enable(true); + .set_interrupt_enable(true); } - fn irq_loop(&self) {} + fn irq_loop(&mut self) { + loop { + self.irq_port.as_ref().unwrap().recv_null().unwrap(); - fn init_ports(&mut self) { + for i in 0..self.ahci_hba().capabilities.num_ports() { + let int_offset = 1 << i; + if (self.ahci_hba().interrupt_status & int_offset) == int_offset { + if let Some(port) = &mut self.ports[i as usize] { + port.handle_interrupt(); + self.ahci_hba().interrupt_status &= !int_offset; + } + } + } + } + } + + fn init_ports(&mut self) -> Result<(), ZError> { 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 { @@ -141,10 +172,23 @@ impl AhciController { .unwrap() }; - self.ports[i] = Some(PortController::new(port)); - self.ports[i].as_ref().unwrap().identify(); - mammoth::debug!("Identifying port {}", i); + let sata_status = port.sata_status; + if (sata_status.device_detection() != AhciDeviceDetection::CommunicationEstablished) + || (sata_status.interface_power_management() + != AhciInterfacePowerManagement::Active) + { + mammoth::debug!( + "Skipping port {}, no communcation. Status: {:?}", + i, + sata_status + ); + continue; + } + + self.ports[i] = Some(PortController::new(port)?); + self.ports[i].as_mut().unwrap().identify()?; } + Ok(()) } pub fn pci_header(&self) -> &mut PciDeviceHeader { @@ -170,14 +214,195 @@ impl AhciController { } } +struct Command { + command: SataCommand, + lba: u64, + sector_cnt: u16, + paddr: u64, + + #[allow(dead_code)] // We need to own this even if we never access it. + memory_region: MemoryRegion, +} + +impl Command { + pub fn identify() -> Result { + let (memory_region, paddr) = MemoryRegion::contiguous_physical(512)?; + + Ok(Self { + command: SataCommand::IdentifyDevice, + lba: 0, + sector_cnt: 1, + paddr, + memory_region, + }) + } +} + +impl From<&Command> for HostToDeviceRegisterFis { + fn from(val: &Command) -> Self { + HostToDeviceRegisterFis::new_command(val.command, val.lba, val.sector_cnt) + } +} + struct PortController<'a> { - ahci_port_hba: &'a AhciPortHba, + ahci_port_hba: &'a mut AhciPortHba, + command_slots: [Option>; 32], + command_structures: MemoryRegion, + command_paddr: u64, } impl<'a> PortController<'a> { - fn new(ahci_port_hba: &'a AhciPortHba) -> Self { - Self { ahci_port_hba } + fn new(ahci_port_hba: &'a mut AhciPortHba) -> Result { + let sata_status = ahci_port_hba.sata_status; + assert_eq!( + sata_status.device_detection(), + AhciDeviceDetection::CommunicationEstablished + ); + assert_eq!( + sata_status.interface_power_management(), + AhciInterfacePowerManagement::Active, + ); + let (command_structures, command_paddr) = MemoryRegion::contiguous_physical(0x2500)?; + ahci_port_hba.command_list_base = command_paddr; + ahci_port_hba.fis_base = command_paddr + 0x400; + + ahci_port_hba.interrupt_enable = AhciPortInterruptEnable::from_bits(0xFFFF_FFFF); + // Overwrite all errors. + ahci_port_hba.sata_error = AhciSataError::from_bits(0xFFFF_FFFF); + + let command = ahci_port_hba.command; + ahci_port_hba.command = command.with_fis_recieve_enable(true).with_start(true); + + let mut controller = Self { + ahci_port_hba, + command_slots: [const { None }; 32], + command_structures, + command_paddr, + }; + + // This leaves space for 8 prdt entries. + for i in 0..32 { + controller.command_list()[i].command_table_base_addr = + (command_paddr + 0x500) + (0x100 * (i as u64)); + } + + Ok(controller) } - pub fn identify(&self) {} + pub fn identify(&mut self) -> Result<(), ZError> { + if self.ahci_port_hba.signature == 0x101 { + self.issue_command(Rc::from(Command::identify()?))?; + } else { + let sig = self.ahci_port_hba.signature; + mammoth::debug!("Skipping non-sata sig: {:#0x}", sig); + } + Ok(()) + } + + fn issue_command(&mut self, command: Rc) -> Result<(), ZError> { + let slot = self.select_slot()?; + self.command_slots[slot] = Some(command.clone()); + + self.command_tables()[slot].command_fis.host_to_device = command.clone().as_ref().into(); + + self.command_tables()[slot].prdt[0].region_address = command.paddr; + self.command_tables()[slot].prdt[0].byte_count = 512 * (command.sector_cnt as u32); + + self.command_list()[slot].prd_table_length = 1; + + self.command_list()[slot].command = + (size_of::() as u16 / 4) & 0x1F; + self.command_list()[slot].command |= 1 << 7; + self.ahci_port_hba.command_issue |= 1 << slot; + Ok(()) + } + + fn select_slot(&self) -> Result { + for i in 0..self.command_slots.len() { + match self.command_slots[i] { + None => return Ok(i), + _ => {} + } + } + return Err(ZError::EXHAUSTED); + } + + fn command_list(&mut self) -> &mut CommandList { + unsafe { + self.command_structures + .mut_slice::() + .as_mut_ptr() + .cast::() + .as_mut() + .unwrap() + } + } + + fn recieved_fis(&mut self) -> &mut ReceivedFis { + unsafe { + self.command_structures.mut_slice::()[0x400..] + .as_mut_ptr() + .cast::() + .as_mut() + .unwrap() + } + } + + fn command_tables(&mut self) -> &mut [CommandTable; 32] { + unsafe { + self.command_structures.mut_slice::()[0x500..] + .as_mut_ptr() + .cast::<[CommandTable; 32]>() + .as_mut() + .unwrap() + } + } + + fn handle_interrupt(&mut self) { + let int_status = self.ahci_port_hba.interrupt_status; + if int_status.device_to_host_register_fis_interrupt() { + assert_eq!( + self.recieved_fis().device_to_host_register_fis.fis_type as u8, + FisType::RegisterDeviceToHost as u8 + ); + if self.recieved_fis().device_to_host_register_fis.error != 0 { + mammoth::debug!( + "D2H err: {:#0x}", + self.recieved_fis().device_to_host_register_fis.error + ); + + mammoth::debug!( + "Status: {:#0x}", + self.recieved_fis().device_to_host_register_fis.status + ); + } + + self.ahci_port_hba.interrupt_status = + AhciPortInterruptStatus::new().with_device_to_host_register_fis_interrupt(true); + } + if int_status.pio_setup_fis_interrupt() { + self.ahci_port_hba.interrupt_status = + AhciPortInterruptStatus::new().with_pio_setup_fis_interrupt(true); + } + + for i in 0..32 { + let int_offset = 1 << i; + + // If there is no longer a command issued on a slot and we have something in + // the command list we know that this is the command that finished. + // FIXME: This could cause a race condition when issuing a command if a different + // interrupt triggers between us setting the command in the command slot and + // actually issuing the command. + if (self.ahci_port_hba.command_issue & int_offset) != int_offset { + if let Some(_) = &self.command_slots[i] { + self.finish_command(i); + self.command_slots[i] = None; + } + } + } + } + + fn finish_command(&self, slot: usize) { + mammoth::debug!("Finishing command in slot {}", slot); + } } diff --git a/rust/sys/denali/src/ahci/mod.rs b/rust/sys/denali/src/ahci/mod.rs index 36a1d0f..ba0ede2 100644 --- a/rust/sys/denali/src/ahci/mod.rs +++ b/rust/sys/denali/src/ahci/mod.rs @@ -1,3 +1,4 @@ +mod command; mod controller; mod hba; mod port; diff --git a/rust/sys/denali/src/ahci/port.rs b/rust/sys/denali/src/ahci/port.rs index 773bdde..d209791 100644 --- a/rust/sys/denali/src/ahci/port.rs +++ b/rust/sys/denali/src/ahci/port.rs @@ -1,61 +1,61 @@ use bitfield_struct::bitfield; #[bitfield(u32)] -struct AhciPortInterruptStatus { - device_to_host_register_fis_interrupt: bool, - pio_setup_fis_interrupt: bool, - dma_setup_fis_interrupt: bool, - set_device_bits_interrupt: bool, +pub struct AhciPortInterruptStatus { + pub device_to_host_register_fis_interrupt: bool, + pub pio_setup_fis_interrupt: bool, + pub dma_setup_fis_interrupt: bool, + pub set_device_bits_interrupt: bool, #[bits(access = RO)] - unknown_fis_interrupt: bool, - descriptor_prossed: bool, + pub unknown_fis_interrupt: bool, + pub descriptor_prossed: bool, #[bits(access = RO)] - port_connect_change_status: bool, - device_mechanical_presence_status: bool, + pub port_connect_change_status: bool, + pub device_mechanical_presence_status: bool, #[bits(14)] __: u32, #[bits(access = RO)] - phy_rdy_change_status: bool, - incorrect_port_multiplier_status: bool, - overflow_status: bool, + pub phy_rdy_change_status: bool, + pub incorrect_port_multiplier_status: bool, + pub overflow_status: bool, __: bool, - interface_non_fatal_error_status: bool, - interface_fatal_error_status: bool, - host_bus_data_error_status: bool, - host_bus_fatal_error_status: bool, - task_file_error_status: bool, - cold_port_detect_status: bool, + pub interface_non_fatal_error_status: bool, + pub interface_fatal_error_status: bool, + pub host_bus_data_error_status: bool, + pub host_bus_fatal_error_status: bool, + pub task_file_error_status: bool, + pub cold_port_detect_status: bool, } #[bitfield(u32)] -struct AhciPortInterruptEnable { - device_to_host_register_fis_enable: bool, - pio_setup_fis_enable: bool, - dma_setup_fis_enable: bool, - set_device_bits_fis_enable: bool, - unknown_fis_enable: bool, - descriptor_processed_enable: bool, - port_change_enable: bool, - device_mechanical_presence_enable: bool, +pub struct AhciPortInterruptEnable { + pub device_to_host_register_fis_enable: bool, + pub pio_setup_fis_enable: bool, + pub dma_setup_fis_enable: bool, + pub set_device_bits_fis_enable: bool, + pub unknown_fis_enable: bool, + pub descriptor_processed_enable: bool, + pub port_change_enable: bool, + pub device_mechanical_presence_enable: bool, #[bits(14)] __: u32, - phy_rdy_change_enable: bool, - incorrect_port_multiplier_enable: bool, - overflow_enable: bool, + pub phy_rdy_change_enable: bool, + pub incorrect_port_multiplier_enable: bool, + pub overflow_enable: bool, __: bool, - interface_non_fatal_error_enable: bool, - interface_fatal_error_enable: bool, - host_bus_data_error_enable: bool, - host_bust_fatal_error_enable: bool, - task_file_error_enable: bool, - cold_presence_detect_enable: bool, + pub interface_non_fatal_error_enable: bool, + pub interface_fatal_error_enable: bool, + pub host_bus_data_error_enable: bool, + pub host_bust_fatal_error_enable: bool, + pub task_file_error_enable: bool, + pub cold_presence_detect_enable: bool, } #[repr(u8)] @@ -87,50 +87,50 @@ impl InterfaceCommunicationControl { } #[bitfield(u32)] -struct AhciPortCommandAndStatus { - start: bool, - spin_up_device: bool, - power_on_device: bool, - command_list_overide: bool, - fis_recieve_enable: bool, +pub struct AhciPortCommandAndStatus { + pub start: bool, + pub spin_up_device: bool, + pub power_on_device: bool, + pub command_list_overide: bool, + pub fis_recieve_enable: bool, #[bits(3)] __: u8, #[bits(5, access = RO)] - current_command_slot: u8, + pub current_command_slot: u8, #[bits(access = RO)] - mechanical_presence_switch_state: bool, + pub mechanical_presence_switch_state: bool, #[bits(access = RO)] - fis_receive_running: bool, + pub fis_receive_running: bool, #[bits(access = RO)] - command_list_running: bool, + pub command_list_running: bool, #[bits(access = RO)] - cold_presence_state: bool, - port_multipler_attached: bool, + pub cold_presence_state: bool, + pub port_multipler_attached: bool, #[bits(access = RO)] - hot_plug_capable_port: bool, + pub hot_plug_capable_port: bool, #[bits(access = RO)] - mechanical_presence_switch_attached_to_port: bool, + pub mechanical_presence_switch_attached_to_port: bool, #[bits(access = RO)] - cold_presence_detection: bool, + pub cold_presence_detection: bool, #[bits(access = RO)] - external_sata_port: bool, + pub external_sata_port: bool, #[bits(access = RO)] - fis_base_switch_capable: bool, - automatic_partial_to_slumber_transitions_enable: bool, - device_is_atapi: bool, - drive_led_on_atapi_enable: bool, - aggressive_power_link_management_enable: bool, - aggressive_slumber_partial: bool, + pub fis_base_switch_capable: bool, + pub automatic_partial_to_slumber_transitions_enable: bool, + pub device_is_atapi: bool, + pub drive_led_on_atapi_enable: bool, + pub aggressive_power_link_management_enable: bool, + pub aggressive_slumber_partial: bool, #[bits(4)] - interface_communication_control: InterfaceCommunicationControl, + pub interface_communication_control: InterfaceCommunicationControl, } #[bitfield(u32)] -struct AhciPortTaskFileData { +pub struct AhciPortTaskFileData { #[bits(access = RO)] err_status: bool, #[bits(2, access = RO)] @@ -149,9 +149,9 @@ struct AhciPortTaskFileData { __: u16, } -#[derive(Debug)] +#[derive(Copy, Clone, Debug, PartialEq)] #[repr(u8)] -enum AhciDeviceDetection { +pub enum AhciDeviceDetection { NoDevice = 0x0, NoCommunication = 0x1, CommunicationEstablished = 0x3, @@ -171,9 +171,9 @@ impl AhciDeviceDetection { } } -#[derive(Debug)] +#[derive(Copy, Clone, Debug)] #[repr(u8)] -enum AhciCurrentInterfaceSpeed { +pub enum AhciCurrentInterfaceSpeed { NoDevice = 0x0, Gen1 = 0x1, Gen2 = 0x2, @@ -193,9 +193,9 @@ impl AhciCurrentInterfaceSpeed { } } -#[derive(Debug)] +#[derive(Copy, Clone, Debug, PartialEq)] #[repr(u8)] -enum AhciInterfacePowerManagement { +pub enum AhciInterfacePowerManagement { NoDevice = 0x0, Active = 0x1, PartialPower = 0x2, @@ -218,15 +218,16 @@ impl AhciInterfacePowerManagement { } #[bitfield(u32)] -struct AhciSataStatus { +#[derive(PartialEq)] +pub struct AhciSataStatus { #[bits(4, access = RO)] - device_detection: AhciDeviceDetection, + pub device_detection: AhciDeviceDetection, #[bits(4, access = RO)] - current_interface_speed: AhciCurrentInterfaceSpeed, + pub current_interface_speed: AhciCurrentInterfaceSpeed, #[bits(4, access = RO)] - interface_power_management: AhciInterfacePowerManagement, + pub interface_power_management: AhciInterfacePowerManagement, #[bits(20)] __: u32, @@ -283,7 +284,7 @@ impl AhciSpeedAllowed { } #[bitfield(u32)] -struct AhciSataControl { +pub struct AhciSataControl { #[bits(4)] device_detection_initialization: AhciDeviceDetectionInitialization, @@ -301,39 +302,39 @@ struct AhciSataControl { } #[bitfield(u32)] -struct AhciSataError { - recovered_data_integrity_error: bool, - recovered_communications_error: bool, +pub struct AhciSataError { + pub recovered_data_integrity_error: bool, + pub recovered_communications_error: bool, #[bits(6)] __: u8, - transient_data_integrity_error: bool, - persisten_communication_or_data_integrity_error: bool, - protocol_error: bool, - internal_error: bool, + pub transient_data_integrity_error: bool, + pub persisten_communication_or_data_integrity_error: bool, + pub protocol_error: bool, + pub internal_error: bool, #[bits(4)] __: u8, - phy_ready_change: bool, - phy_internal_error: bool, - comm_wake: bool, - decode_error: bool, + pub phy_ready_change: bool, + pub phy_internal_error: bool, + pub comm_wake: bool, + pub decode_error: bool, __: bool, - crc_error: bool, - handshake_error: bool, - link_sequence_error: bool, - transport_state_transition_error: bool, - uknown_fis_type: bool, - exchanged: bool, + pub crc_error: bool, + pub handshake_error: bool, + pub link_sequence_error: bool, + pub transport_state_transition_error: bool, + pub uknown_fis_type: bool, + pub exchanged: bool, #[bits(5)] __: u8, } #[bitfield(u32)] -struct AhciFisBasedSwitchingControl { +pub struct AhciFisBasedSwitchingControl { enable: bool, device_error_clear: bool, @@ -357,7 +358,7 @@ struct AhciFisBasedSwitchingControl { } #[bitfield(u32)] -struct AhciDeviceSleep { +pub struct AhciDeviceSleep { aggressive_device_sleep_enable: bool, #[bits(access = RO)] @@ -378,22 +379,25 @@ struct AhciDeviceSleep { __: u8, } +#[derive(Debug)] #[repr(C, packed)] pub struct AhciPortHba { - command_list_base: u64, - fis_base: u64, - interrupt_status: AhciPortInterruptStatus, - interrupt_enable: AhciPortInterruptEnable, - command: AhciPortCommandAndStatus, + pub command_list_base: u64, + pub fis_base: u64, + pub interrupt_status: AhciPortInterruptStatus, + pub interrupt_enable: AhciPortInterruptEnable, + pub command: AhciPortCommandAndStatus, __: u32, - task_file_data: AhciPortTaskFileData, - signature: u32, - sata_status: AhciSataStatus, - sata_control: AhciSataControl, - sata_error: AhciSataError, - sata_active: u32, - command_issue: u32, - sata_notification: u32, - fis_based_switching_ctl: AhciFisBasedSwitchingControl, - device_sleep: AhciDeviceSleep, + pub task_file_data: AhciPortTaskFileData, + pub signature: u32, + pub sata_status: AhciSataStatus, + pub sata_control: AhciSataControl, + pub sata_error: AhciSataError, + pub sata_active: u32, + pub command_issue: u32, + pub sata_notification: u32, + pub fis_based_switching_ctl: AhciFisBasedSwitchingControl, + pub device_sleep: AhciDeviceSleep, } + +const _: () = assert!(size_of::() == 0x48); diff --git a/rust/sys/denali/src/bin/denali.rs b/rust/sys/denali/src/bin/denali.rs index b4860f6..080fafe 100644 --- a/rust/sys/denali/src/bin/denali.rs +++ b/rust/sys/denali/src/bin/denali.rs @@ -24,7 +24,7 @@ extern "C" fn main() -> z_err_t { .unwrap(), ); - mammoth::debug!("AHCI ABAR {:#x}", ahci_controller.pci_header().abar as u64); - mammoth::debug!("AHCI Capabilities: {:?}", ahci_controller.ahci_hba()); + ahci_controller.join().unwrap(); + 0 }