diff --git a/rust/sys/denali/src/ahci/controller.rs b/rust/sys/denali/src/ahci/controller.rs index 07783c8..0f166bd 100644 --- a/rust/sys/denali/src/ahci/controller.rs +++ b/rust/sys/denali/src/ahci/controller.rs @@ -127,7 +127,7 @@ impl AhciController { .unwrap() }; - let sata_status = port.sata_status; + let sata_status = port.sata_status.read(); if (sata_status.device_detection() != AhciDeviceDetection::CommunicationEstablished) || (sata_status.interface_power_management() != AhciInterfacePowerManagement::Active) @@ -238,25 +238,8 @@ struct PortController<'a> { impl<'a> PortController<'a> { 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); + ahci_port_hba.init(command_paddr, command_paddr + 0x400); let mut controller = Self { ahci_port_hba, @@ -276,7 +259,7 @@ impl<'a> PortController<'a> { } pub fn identify(&mut self) -> Result<(), ZError> { - if self.ahci_port_hba.signature == 0x101 { + if self.ahci_port_hba.signature.read() == 0x101 { let sector_size = self.sector_size.clone(); let sector_cnt = self.sector_cnt.clone(); let callback = move |c: &Command| { @@ -307,7 +290,7 @@ impl<'a> PortController<'a> { }; self.issue_command(Arc::from(Command::identify(Box::new(callback))?))?; } else { - let sig = self.ahci_port_hba.signature; + let sig = self.ahci_port_hba.signature.read(); mammoth::debug!("Skipping non-sata sig: {:#0x}", sig); } Ok(()) @@ -327,7 +310,7 @@ impl<'a> PortController<'a> { 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; + self.ahci_port_hba.issue_command(slot); Ok(()) } @@ -373,7 +356,7 @@ impl<'a> PortController<'a> { } fn handle_interrupt(&mut self) { - let int_status = self.ahci_port_hba.interrupt_status; + let int_status = self.ahci_port_hba.interrupt_status.read(); if int_status.device_to_host_register_fis_interrupt() { assert_eq!( self.recieved_fis().device_to_host_register_fis.fis_type as u8, @@ -391,12 +374,14 @@ impl<'a> PortController<'a> { ); } - self.ahci_port_hba.interrupt_status = - AhciPortInterruptStatus::new().with_device_to_host_register_fis_interrupt(true); + self.ahci_port_hba.interrupt_status.write( + 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); + self.ahci_port_hba + .interrupt_status + .write(AhciPortInterruptStatus::new().with_pio_setup_fis_interrupt(true)); } for i in 0..32 { @@ -407,7 +392,7 @@ impl<'a> PortController<'a> { // 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 (self.ahci_port_hba.command_issue.read() & int_offset) != int_offset { if let Some(_) = &self.command_slots[i] { self.finish_command(i); self.command_slots[i] = None; diff --git a/rust/sys/denali/src/ahci/port.rs b/rust/sys/denali/src/ahci/port.rs index d209791..e32abc5 100644 --- a/rust/sys/denali/src/ahci/port.rs +++ b/rust/sys/denali/src/ahci/port.rs @@ -1,4 +1,5 @@ use bitfield_struct::bitfield; +use mammoth::mem::Volatile; #[bitfield(u32)] pub struct AhciPortInterruptStatus { @@ -380,24 +381,55 @@ pub struct AhciDeviceSleep { } #[derive(Debug)] -#[repr(C, packed)] +#[repr(C)] pub struct AhciPortHba { - pub command_list_base: u64, - pub fis_base: u64, - pub interrupt_status: AhciPortInterruptStatus, - pub interrupt_enable: AhciPortInterruptEnable, - pub command: AhciPortCommandAndStatus, - __: u32, - 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, + pub command_list_base: Volatile, + pub fis_base: Volatile, + pub interrupt_status: Volatile, + pub interrupt_enable: Volatile, + pub command: Volatile, + __: Volatile, + pub task_file_data: Volatile, + pub signature: Volatile, + pub sata_status: Volatile, + pub sata_control: Volatile, + pub sata_error: Volatile, + pub sata_active: Volatile, + pub command_issue: Volatile, + pub sata_notification: Volatile, + pub fis_based_switching_ctl: Volatile, + pub device_sleep: Volatile, } const _: () = assert!(size_of::() == 0x48); + +impl AhciPortHba { + pub fn init(&mut self, command_list_phys: u64, fis_phys: u64) { + let sata_status = self.sata_status.read(); + assert_eq!( + sata_status.device_detection(), + AhciDeviceDetection::CommunicationEstablished + ); + assert_eq!( + sata_status.interface_power_management(), + AhciInterfacePowerManagement::Active, + ); + + self.command_list_base.write(command_list_phys); + self.fis_base.write(fis_phys); + + self.interrupt_enable + .write(AhciPortInterruptEnable::from_bits(0xFFFF_FFFF)); + // Overwrite all errors. + self.sata_error.write(AhciSataError::from_bits(0xFFFF_FFFF)); + + self.command.update(|command| { + *command = command.with_fis_recieve_enable(true).with_start(true); + }); + } + + pub fn issue_command(&mut self, slot: usize) { + assert!(slot < 32); + self.command_issue.update(|ci| *ci |= 1 << slot); + } +}