Only trigger future on poll in controller.
This commit is contained in:
parent
caa1b9c952
commit
b270c7c9aa
|
@ -5,6 +5,7 @@ use core::ops::DerefMut;
|
||||||
use core::pin::Pin;
|
use core::pin::Pin;
|
||||||
use core::task::{Context, Poll, Waker};
|
use core::task::{Context, Poll, Waker};
|
||||||
|
|
||||||
|
use alloc::boxed::Box;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use mammoth::cap::Capability;
|
use mammoth::cap::Capability;
|
||||||
use mammoth::sync::Mutex;
|
use mammoth::sync::Mutex;
|
||||||
|
@ -201,11 +202,12 @@ enum CommandStatus {
|
||||||
|
|
||||||
struct CommandFuture {
|
struct CommandFuture {
|
||||||
status: Arc<Mutex<CommandStatus>>,
|
status: Arc<Mutex<CommandStatus>>,
|
||||||
|
trigger: Box<dyn Fn() + Sync>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommandFuture {
|
impl CommandFuture {
|
||||||
fn new(status: Arc<Mutex<CommandStatus>>) -> Self {
|
fn new(status: Arc<Mutex<CommandStatus>>, trigger: Box<dyn Fn() + Sync>) -> Self {
|
||||||
Self { status }
|
Self { status, trigger }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,10 +221,12 @@ impl Future for CommandFuture {
|
||||||
type Output = ();
|
type Output = ();
|
||||||
|
|
||||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||||
let mut status = self.deref_mut().status.lock();
|
let s = self.deref_mut();
|
||||||
|
let mut status = s.status.lock();
|
||||||
match status.deref() {
|
match status.deref() {
|
||||||
CommandStatus::NotSent => {
|
CommandStatus::NotSent => {
|
||||||
*status = CommandStatus::Pending(cx.waker().clone());
|
*status = CommandStatus::Pending(cx.waker().clone());
|
||||||
|
(s.trigger)();
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
}
|
}
|
||||||
CommandStatus::Pending(_) => Poll::Pending,
|
CommandStatus::Pending(_) => Poll::Pending,
|
||||||
|
@ -269,7 +273,7 @@ struct CommandStructures {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PortController {
|
struct PortController {
|
||||||
ahci_port_hba: Mutex<&'static mut AhciPortHba>,
|
ahci_port_hba: Arc<Mutex<&'static mut AhciPortHba>>,
|
||||||
command_structures: Mutex<CommandStructures>,
|
command_structures: Mutex<CommandStructures>,
|
||||||
|
|
||||||
command_slots: [Arc<Mutex<CommandStatus>>; 32],
|
command_slots: [Arc<Mutex<CommandStatus>>; 32],
|
||||||
|
@ -301,7 +305,7 @@ impl PortController {
|
||||||
let command_slots = array::from_fn(|_| Arc::new(Mutex::new(CommandStatus::Empty)));
|
let command_slots = array::from_fn(|_| Arc::new(Mutex::new(CommandStatus::Empty)));
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
ahci_port_hba: Mutex::new(ahci_port_hba),
|
ahci_port_hba: Arc::new(Mutex::new(ahci_port_hba)),
|
||||||
command_structures: Mutex::new(CommandStructures {
|
command_structures: Mutex::new(CommandStructures {
|
||||||
command_list,
|
command_list,
|
||||||
received_fis,
|
received_fis,
|
||||||
|
@ -318,7 +322,15 @@ impl PortController {
|
||||||
fn issue_command(&self, command: &Command) -> Result<CommandFuture, ZError> {
|
fn issue_command(&self, command: &Command) -> Result<CommandFuture, ZError> {
|
||||||
let slot = self.select_slot()?;
|
let slot = self.select_slot()?;
|
||||||
let command_slot = self.command_slots[slot].clone();
|
let command_slot = self.command_slots[slot].clone();
|
||||||
let future = CommandFuture::new(command_slot);
|
|
||||||
|
let ahci_port_hba_clone = self.ahci_port_hba.clone();
|
||||||
|
let slot_clone = slot;
|
||||||
|
let future = CommandFuture::new(
|
||||||
|
command_slot,
|
||||||
|
Box::new(move || {
|
||||||
|
ahci_port_hba_clone.lock().issue_command(slot_clone);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
let mut command_structures = self.command_structures.lock();
|
let mut command_structures = self.command_structures.lock();
|
||||||
|
|
||||||
|
@ -336,10 +348,6 @@ impl PortController {
|
||||||
(size_of::<HostToDeviceRegisterFis>() as u16 / 4) & 0x1F;
|
(size_of::<HostToDeviceRegisterFis>() as u16 / 4) & 0x1F;
|
||||||
command_structures.command_list[slot].command |= 1 << 7;
|
command_structures.command_list[slot].command |= 1 << 7;
|
||||||
|
|
||||||
// FIXME: This is technically a poor future implementation since it starts work before it
|
|
||||||
// is polled.
|
|
||||||
self.ahci_port_hba.lock().issue_command(slot);
|
|
||||||
|
|
||||||
Ok(future)
|
Ok(future)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,15 +399,9 @@ impl PortController {
|
||||||
if (self.ahci_port_hba.lock().command_issue.read() & int_offset) != int_offset {
|
if (self.ahci_port_hba.lock().command_issue.read() & int_offset) != int_offset {
|
||||||
let mut command_status = self.command_slots[i].lock();
|
let mut command_status = self.command_slots[i].lock();
|
||||||
let mut did_complete = false;
|
let mut did_complete = false;
|
||||||
match command_status.deref() {
|
if let CommandStatus::Pending(ref waker) = command_status.deref() {
|
||||||
CommandStatus::NotSent => {
|
waker.wake_by_ref();
|
||||||
did_complete = true;
|
did_complete = true;
|
||||||
}
|
|
||||||
CommandStatus::Pending(ref waker) => {
|
|
||||||
waker.wake_by_ref();
|
|
||||||
did_complete = true;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if did_complete {
|
if did_complete {
|
||||||
|
|
Loading…
Reference in New Issue