Make handle interrupt non-mutable in ahci controller.
This commit is contained in:
parent
017367c4de
commit
c97d39c36b
|
@ -49,8 +49,9 @@ pub struct PciDeviceHeader {
|
|||
|
||||
pub struct AhciController {
|
||||
pci_header: &'static mut PciDeviceHeader,
|
||||
hba: &'static mut AhciHba,
|
||||
hba: Mutex<&'static mut AhciHba>,
|
||||
ports: [Option<PortController>; 32],
|
||||
hba_vaddr: u64,
|
||||
}
|
||||
|
||||
impl AhciController {
|
||||
|
@ -62,15 +63,16 @@ impl AhciController {
|
|||
let hba = unsafe { (hba_vaddr as *mut AhciHba).as_mut().unwrap() };
|
||||
let mut controller = Self {
|
||||
pci_header,
|
||||
hba,
|
||||
hba: Mutex::new(hba),
|
||||
ports: [const { None }; 32],
|
||||
hba_vaddr,
|
||||
};
|
||||
controller.init();
|
||||
controller
|
||||
}
|
||||
|
||||
fn init(&mut self) {
|
||||
self.hba.init();
|
||||
self.hba.lock().init();
|
||||
|
||||
self.init_ports().unwrap();
|
||||
}
|
||||
|
@ -88,13 +90,14 @@ impl AhciController {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_irq(&mut self) {
|
||||
for i in 0..self.hba.capabilities.read().num_ports() {
|
||||
fn handle_irq(&self) {
|
||||
let mut hba = self.hba.lock();
|
||||
for i in 0..hba.capabilities.read().num_ports() {
|
||||
let int_offset = 1 << i;
|
||||
if (self.hba.interrupt_status.read() & int_offset) == int_offset {
|
||||
if let Some(port) = &mut self.ports[i as usize] {
|
||||
if (hba.interrupt_status.read() & int_offset) == int_offset {
|
||||
if let Some(port) = &self.ports[i as usize] {
|
||||
port.handle_interrupt();
|
||||
self.hba.interrupt_status.update(|is| {
|
||||
hba.interrupt_status.update(|is| {
|
||||
*is &= !int_offset;
|
||||
});
|
||||
}
|
||||
|
@ -103,16 +106,17 @@ impl AhciController {
|
|||
}
|
||||
|
||||
fn init_ports(&mut self) -> Result<(), ZError> {
|
||||
for i in 0..(self.hba.capabilities.read().num_ports() as usize) {
|
||||
let hba = self.hba.lock();
|
||||
for i in 0..(hba.capabilities.read().num_ports() as usize) {
|
||||
let port_index = 1 << i;
|
||||
if (self.hba.port_implemented.read() & port_index) != port_index {
|
||||
if (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 = unsafe {
|
||||
(((self.hba as *mut _ as usize) + port_offset) as *mut AhciPortHba)
|
||||
((self.hba_vaddr as usize + port_offset) as *mut AhciPortHba)
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
};
|
||||
|
@ -137,17 +141,17 @@ impl AhciController {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn spawn_irq_thread(controller: Arc<Mutex<AhciController>>) -> thread::JoinHandle {
|
||||
pub fn spawn_irq_thread(controller: Arc<AhciController>) -> thread::JoinHandle {
|
||||
let irq_thread = move || {
|
||||
let irq_num = controller.lock().irq_num();
|
||||
let irq_num = controller.irq_num();
|
||||
let irq_port =
|
||||
mammoth::port::PortServer::from_cap(mammoth::syscall::register_irq(irq_num).unwrap());
|
||||
controller.lock().hba.global_host_control.update(|ghc| {
|
||||
controller.hba.lock().global_host_control.update(|ghc| {
|
||||
ghc.set_interrupt_enable(true);
|
||||
});
|
||||
loop {
|
||||
irq_port.recv_null().unwrap();
|
||||
controller.lock().handle_irq();
|
||||
controller.handle_irq();
|
||||
}
|
||||
};
|
||||
thread::spawn(irq_thread)
|
||||
|
@ -191,12 +195,12 @@ impl From<&Command> for HostToDeviceRegisterFis {
|
|||
}
|
||||
|
||||
struct PortController {
|
||||
ahci_port_hba: &'static mut AhciPortHba,
|
||||
ahci_port_hba: Mutex<&'static mut AhciPortHba>,
|
||||
command_list: &'static mut CommandList,
|
||||
received_fis: &'static mut ReceivedFis,
|
||||
command_tables: &'static mut [CommandTable; 32],
|
||||
|
||||
command_slots: [Option<Arc<Command>>; 32],
|
||||
command_slots: Mutex<[Option<Arc<Command>>; 32]>,
|
||||
|
||||
// FIXME: These should probably be something like a OnceCell (or OnceLock).
|
||||
sector_size: Arc<Mutex<Option<u64>>>,
|
||||
|
@ -227,18 +231,19 @@ impl PortController {
|
|||
}
|
||||
|
||||
Self {
|
||||
ahci_port_hba,
|
||||
ahci_port_hba: Mutex::new(ahci_port_hba),
|
||||
command_list,
|
||||
received_fis,
|
||||
command_tables,
|
||||
command_slots: [const { None }; 32],
|
||||
command_slots: Mutex::new([const { None }; 32]),
|
||||
sector_size: Arc::new(Mutex::new(None)),
|
||||
sector_cnt: Arc::new(Mutex::new(None)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn identify(&mut self) -> Result<(), ZError> {
|
||||
if self.ahci_port_hba.signature.read() == 0x101 {
|
||||
let sig = self.ahci_port_hba.lock().signature.read();
|
||||
if sig == 0x101 {
|
||||
let sector_size = self.sector_size.clone();
|
||||
let sector_cnt = self.sector_cnt.clone();
|
||||
let callback = move |c: &Command| {
|
||||
|
@ -265,11 +270,10 @@ impl PortController {
|
|||
.lock()
|
||||
.deref_mut()
|
||||
.insert(new_sector_size as u64);
|
||||
let _ = sector_cnt.lock().deref_mut().insert(lba_count as u64);
|
||||
let _ = sector_cnt.lock().deref_mut().insert(lba_count);
|
||||
};
|
||||
self.issue_command(Arc::from(Command::identify(Box::new(callback))?))?;
|
||||
} else {
|
||||
let sig = self.ahci_port_hba.signature.read();
|
||||
mammoth::debug!("Skipping non-sata sig: {:#0x}", sig);
|
||||
}
|
||||
Ok(())
|
||||
|
@ -277,7 +281,7 @@ impl PortController {
|
|||
|
||||
fn issue_command(&mut self, command: Arc<Command>) -> Result<(), ZError> {
|
||||
let slot = self.select_slot()?;
|
||||
self.command_slots[slot] = Some(command.clone());
|
||||
self.command_slots.lock()[slot] = Some(command.clone());
|
||||
|
||||
self.command_tables[slot].command_fis.host_to_device = command.clone().as_ref().into();
|
||||
|
||||
|
@ -288,22 +292,22 @@ impl PortController {
|
|||
|
||||
self.command_list[slot].command = (size_of::<HostToDeviceRegisterFis>() as u16 / 4) & 0x1F;
|
||||
self.command_list[slot].command |= 1 << 7;
|
||||
self.ahci_port_hba.issue_command(slot);
|
||||
self.ahci_port_hba.lock().issue_command(slot);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn select_slot(&self) -> Result<usize, ZError> {
|
||||
for i in 0..self.command_slots.len() {
|
||||
match self.command_slots[i] {
|
||||
None => return Ok(i),
|
||||
_ => {}
|
||||
let slots = self.command_slots.lock();
|
||||
for i in 0..slots.len() {
|
||||
if slots[i].is_none() {
|
||||
return Ok(i);
|
||||
}
|
||||
}
|
||||
return Err(ZError::EXHAUSTED);
|
||||
Err(ZError::EXHAUSTED)
|
||||
}
|
||||
|
||||
fn handle_interrupt(&mut self) {
|
||||
let int_status = self.ahci_port_hba.interrupt_status.read();
|
||||
fn handle_interrupt(&self) {
|
||||
let int_status = self.ahci_port_hba.lock().interrupt_status.read();
|
||||
if int_status.device_to_host_register_fis_interrupt() {
|
||||
assert_eq!(
|
||||
self.received_fis.device_to_host_register_fis.fis_type as u8,
|
||||
|
@ -321,12 +325,13 @@ impl PortController {
|
|||
);
|
||||
}
|
||||
|
||||
self.ahci_port_hba.interrupt_status.write(
|
||||
self.ahci_port_hba.lock().interrupt_status.write(
|
||||
AhciPortInterruptStatus::new().with_device_to_host_register_fis_interrupt(true),
|
||||
);
|
||||
}
|
||||
if int_status.pio_setup_fis_interrupt() {
|
||||
self.ahci_port_hba
|
||||
.lock()
|
||||
.interrupt_status
|
||||
.write(AhciPortInterruptStatus::new().with_pio_setup_fis_interrupt(true));
|
||||
}
|
||||
|
@ -339,16 +344,16 @@ impl PortController {
|
|||
// 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.read() & int_offset) != int_offset {
|
||||
if let Some(_) = &self.command_slots[i] {
|
||||
self.finish_command(i);
|
||||
self.command_slots[i] = None;
|
||||
}
|
||||
if (self.ahci_port_hba.lock().command_issue.read() & int_offset) != int_offset
|
||||
&& self.command_slots.lock()[i].is_some()
|
||||
{
|
||||
self.finish_command(i);
|
||||
self.command_slots.lock()[i] = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn finish_command(&self, slot: usize) {
|
||||
self.command_slots[slot].as_ref().unwrap().callback()
|
||||
self.command_slots.lock()[slot].as_ref().unwrap().callback()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ extern "C" fn main() -> z_err_t {
|
|||
.get_ahci_info()
|
||||
.expect("Failed to get ahci info");
|
||||
|
||||
let ahci_controller = Arc::new(Mutex::new(AhciController::new(
|
||||
mammoth::cap::Capability::take(ahci_info.ahci_region),
|
||||
let ahci_controller = Arc::new(AhciController::new(mammoth::cap::Capability::take(
|
||||
ahci_info.ahci_region,
|
||||
)));
|
||||
|
||||
let thread = spawn_irq_thread(ahci_controller.clone());
|
||||
|
|
Loading…
Reference in New Issue