Move command into its own file.

This commit is contained in:
Drew Galbraith 2025-02-01 14:49:41 -08:00
parent 4efeca661e
commit e34540b77e
4 changed files with 122 additions and 115 deletions

View File

@ -0,0 +1,112 @@
use core::{
future::Future,
ops::Deref,
ops::DerefMut,
pin::Pin,
task::{Context, Poll, Waker},
};
use alloc::boxed::Box;
use alloc::sync::Arc;
use mammoth::{cap::Capability, sync::Mutex, syscall, zion::ZError};
use super::ahci_command::{HostToDeviceRegisterFis, SataCommand};
pub enum CommandStatus {
Empty,
NotSent,
Pending(Waker),
Complete,
}
pub struct CommandFuture {
status: Arc<Mutex<CommandStatus>>,
trigger: Box<dyn Fn() + Sync + Send>,
}
impl CommandFuture {
pub fn new(status: Arc<Mutex<CommandStatus>>, trigger: Box<dyn Fn() + Sync + Send>) -> Self {
Self { status, trigger }
}
}
impl Drop for CommandFuture {
fn drop(&mut self) {
*self.status.lock() = CommandStatus::Empty;
}
}
impl Future for CommandFuture {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let s = self.deref_mut();
let mut status = s.status.lock();
match status.deref() {
CommandStatus::NotSent => {
*status = CommandStatus::Pending(cx.waker().clone());
(s.trigger)();
Poll::Pending
}
CommandStatus::Pending(_) => Poll::Pending,
CommandStatus::Complete => Poll::Ready(()),
CommandStatus::Empty => panic!("Polling empty command slot"),
}
}
}
pub struct Command {
pub command: SataCommand,
pub lba: u64,
pub sector_cnt: u16,
pub paddr: u64,
memory_region: Option<Capability>,
}
impl Command {
pub fn identify() -> Result<Self, ZError> {
let (memory_region, paddr) = syscall::memory_object_contiguous_physical(512)?;
Ok(Self {
command: SataCommand::IdentifyDevice,
lba: 0,
sector_cnt: 1,
paddr,
memory_region: Some(memory_region),
})
}
pub fn read(lba: u64, lba_count: u16) -> Result<Self, ZError> {
let (memory_region, paddr) =
syscall::memory_object_contiguous_physical(512 * (lba_count as u64))?;
Ok(Self {
command: SataCommand::DmaReadExt,
lba,
sector_cnt: lba_count,
paddr,
memory_region: Some(memory_region),
})
}
pub fn read_manual(lba: u64, lba_count: u16, paddr: u64) -> Self {
Self {
command: SataCommand::DmaReadExt,
lba,
sector_cnt: lba_count,
paddr: paddr,
memory_region: None,
}
}
pub fn release_mem_cap(&mut self) -> u64 {
self.memory_region.take().unwrap().release()
}
}
impl From<&Command> for HostToDeviceRegisterFis {
fn from(val: &Command) -> Self {
HostToDeviceRegisterFis::new_command(val.command, val.lba, val.sector_cnt)
}
}

View File

@ -9,7 +9,7 @@ use mammoth::{
use crate::ahci::{
port::{AhciDeviceDetection, AhciInterfacePowerManagement},
port_controller::Command,
Command,
};
use super::{hba::AhciHba, port::AhciPortHba, port_controller::PortController};

View File

@ -1,10 +1,11 @@
mod ahci_command;
mod command;
mod controller;
mod hba;
mod port;
mod port_controller;
pub use command::Command;
pub use controller::identify_ports;
pub use controller::spawn_irq_thread;
pub use controller::AhciController;
pub use port_controller::Command;

View File

@ -1,124 +1,18 @@
use core::{
array,
future::Future,
ops::Deref,
ops::DerefMut,
pin::Pin,
task::{Context, Poll, Waker},
};
use core::array;
use core::ops::Deref;
use alloc::boxed::Box;
use alloc::sync::Arc;
use mammoth::{cap::Capability, mem, sync::Mutex, syscall, zion::ZError};
use alloc::{boxed::Box, sync::Arc};
use mammoth::{mem, sync::Mutex, zion::ZError};
use crate::ahci::port::AhciPortInterruptStatus;
use super::{
ahci_command::{
CommandList, CommandTable, FisType, HostToDeviceRegisterFis, ReceivedFis, SataCommand,
},
ahci_command::{CommandList, CommandTable, FisType, HostToDeviceRegisterFis, ReceivedFis},
command::{CommandFuture, CommandStatus},
port::AhciPortHba,
Command,
};
enum CommandStatus {
Empty,
NotSent,
Pending(Waker),
Complete,
}
pub struct CommandFuture {
status: Arc<Mutex<CommandStatus>>,
trigger: Box<dyn Fn() + Sync + Send>,
}
impl CommandFuture {
fn new(status: Arc<Mutex<CommandStatus>>, trigger: Box<dyn Fn() + Sync + Send>) -> Self {
Self { status, trigger }
}
}
impl Drop for CommandFuture {
fn drop(&mut self) {
*self.status.lock() = CommandStatus::Empty;
}
}
impl Future for CommandFuture {
type Output = ();
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let s = self.deref_mut();
let mut status = s.status.lock();
match status.deref() {
CommandStatus::NotSent => {
*status = CommandStatus::Pending(cx.waker().clone());
(s.trigger)();
Poll::Pending
}
CommandStatus::Pending(_) => Poll::Pending,
CommandStatus::Complete => Poll::Ready(()),
CommandStatus::Empty => panic!("Polling empty command slot"),
}
}
}
pub struct Command {
command: SataCommand,
lba: u64,
sector_cnt: u16,
paddr: u64,
memory_region: Option<Capability>,
}
impl Command {
pub fn identify() -> Result<Self, ZError> {
let (memory_region, paddr) = syscall::memory_object_contiguous_physical(512)?;
Ok(Self {
command: SataCommand::IdentifyDevice,
lba: 0,
sector_cnt: 1,
paddr,
memory_region: Some(memory_region),
})
}
pub fn read(lba: u64, lba_count: u16) -> Result<Self, ZError> {
let (memory_region, paddr) =
syscall::memory_object_contiguous_physical(512 * (lba_count as u64))?;
Ok(Self {
command: SataCommand::DmaReadExt,
lba,
sector_cnt: lba_count,
paddr,
memory_region: Some(memory_region),
})
}
pub fn read_manual(lba: u64, lba_count: u16, paddr: u64) -> Self {
Self {
command: SataCommand::DmaReadExt,
lba,
sector_cnt: lba_count,
paddr: paddr,
memory_region: None,
}
}
pub fn release_mem_cap(&mut self) -> u64 {
self.memory_region.take().unwrap().release()
}
}
impl From<&Command> for HostToDeviceRegisterFis {
fn from(val: &Command) -> Self {
HostToDeviceRegisterFis::new_command(val.command, val.lba, val.sector_cnt)
}
}
struct CommandStructures {
command_list: &'static mut CommandList,
received_fis: &'static mut ReceivedFis,