Move Ahci Port Controller to hold raw references.
This commit is contained in:
parent
0024e38412
commit
04effd44f8
|
@ -152,3 +152,10 @@ where
|
||||||
write!(f, "{:?}", self.read())
|
write!(f, "{:?}", self.read())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn map_physical_and_leak(size: u64) -> (u64, u64) {
|
||||||
|
let (mem_cap, paddr) = syscall::memory_object_contiguous_physical(size).unwrap();
|
||||||
|
let vaddr = syscall::address_space_map(&mem_cap).unwrap();
|
||||||
|
mem_cap.release();
|
||||||
|
(vaddr, paddr)
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ use core::ops::DerefMut;
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use mammoth::sync::Mutex;
|
use mammoth::sync::Mutex;
|
||||||
use mammoth::thread;
|
use mammoth::{mem, thread};
|
||||||
|
|
||||||
use mammoth::{mem::MemoryRegion, zion::ZError};
|
use mammoth::{mem::MemoryRegion, zion::ZError};
|
||||||
|
|
||||||
|
@ -15,10 +15,7 @@ use crate::ahci::port::{
|
||||||
use super::command::{
|
use super::command::{
|
||||||
CommandList, CommandTable, HostToDeviceRegisterFis, ReceivedFis, SataCommand,
|
CommandList, CommandTable, HostToDeviceRegisterFis, ReceivedFis, SataCommand,
|
||||||
};
|
};
|
||||||
use super::{
|
use super::{hba::AhciHba, port::AhciPortHba};
|
||||||
hba::AhciHba,
|
|
||||||
port::{AhciPortHba, AhciPortInterruptEnable, AhciSataError},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[repr(C, packed)]
|
#[repr(C, packed)]
|
||||||
|
@ -51,7 +48,7 @@ pub struct PciDeviceHeader {
|
||||||
pub struct AhciController {
|
pub struct AhciController {
|
||||||
pci_memory: MemoryRegion,
|
pci_memory: MemoryRegion,
|
||||||
hba_memory: MemoryRegion,
|
hba_memory: MemoryRegion,
|
||||||
ports: [Option<PortController<'static>>; 32],
|
ports: [Option<PortController>; 32],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AhciController {
|
impl AhciController {
|
||||||
|
@ -140,7 +137,7 @@ impl AhciController {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.ports[i] = Some(PortController::new(port)?);
|
self.ports[i] = Some(PortController::new(port));
|
||||||
self.ports[i].as_mut().unwrap().identify()?;
|
self.ports[i].as_mut().unwrap().identify()?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -226,36 +223,51 @@ impl From<&Command> for HostToDeviceRegisterFis {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PortController<'a> {
|
struct PortController {
|
||||||
ahci_port_hba: &'a mut AhciPortHba,
|
ahci_port_hba: &'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: [Option<Arc<Command>>; 32],
|
||||||
command_structures: MemoryRegion,
|
|
||||||
|
|
||||||
// FIXME: These should probably be something like a OnceCell (or OnceLock).
|
// FIXME: These should probably be something like a OnceCell (or OnceLock).
|
||||||
sector_size: Arc<Mutex<Option<u64>>>,
|
sector_size: Arc<Mutex<Option<u64>>>,
|
||||||
sector_cnt: Arc<Mutex<Option<u64>>>,
|
sector_cnt: Arc<Mutex<Option<u64>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> PortController<'a> {
|
impl PortController {
|
||||||
fn new(ahci_port_hba: &'a mut AhciPortHba) -> Result<Self, ZError> {
|
fn new(ahci_port_hba: &'static mut AhciPortHba) -> Self {
|
||||||
let (command_structures, command_paddr) = MemoryRegion::contiguous_physical(0x2500)?;
|
let (command_vaddr, command_paddr) = mem::map_physical_and_leak(0x2500);
|
||||||
ahci_port_hba.init(command_paddr, command_paddr + 0x400);
|
ahci_port_hba.init(command_paddr, command_paddr + 0x400);
|
||||||
|
|
||||||
let mut controller = Self {
|
let command_list = unsafe { (command_vaddr as *mut CommandList).as_mut().unwrap() };
|
||||||
ahci_port_hba,
|
let received_fis = unsafe {
|
||||||
command_slots: [const { None }; 32],
|
((command_vaddr + 0x400) as *mut ReceivedFis)
|
||||||
command_structures,
|
.as_mut()
|
||||||
sector_size: Arc::new(Mutex::new(None)),
|
.unwrap()
|
||||||
sector_cnt: Arc::new(Mutex::new(None)),
|
};
|
||||||
|
let command_tables = unsafe {
|
||||||
|
((command_vaddr + 0x500) as *mut [CommandTable; 32])
|
||||||
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
// This leaves space for 8 prdt entries.
|
// This leaves space for 8 prdt entries.
|
||||||
for i in 0..32 {
|
for i in 0..32 {
|
||||||
controller.command_list()[i].command_table_base_addr =
|
command_list[i].command_table_base_addr =
|
||||||
(command_paddr + 0x500) + (0x100 * (i as u64));
|
(command_paddr + 0x500) + (0x100 * (i as u64));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(controller)
|
Self {
|
||||||
|
ahci_port_hba,
|
||||||
|
command_list,
|
||||||
|
received_fis,
|
||||||
|
command_tables,
|
||||||
|
command_slots: [const { None }; 32],
|
||||||
|
sector_size: Arc::new(Mutex::new(None)),
|
||||||
|
sector_cnt: Arc::new(Mutex::new(None)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn identify(&mut self) -> Result<(), ZError> {
|
pub fn identify(&mut self) -> Result<(), ZError> {
|
||||||
|
@ -300,16 +312,15 @@ impl<'a> PortController<'a> {
|
||||||
let slot = self.select_slot()?;
|
let slot = self.select_slot()?;
|
||||||
self.command_slots[slot] = Some(command.clone());
|
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].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].region_address = command.paddr;
|
||||||
self.command_tables()[slot].prdt[0].byte_count = 512 * (command.sector_cnt as u32);
|
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].prd_table_length = 1;
|
||||||
|
|
||||||
self.command_list()[slot].command =
|
self.command_list[slot].command = (size_of::<HostToDeviceRegisterFis>() as u16 / 4) & 0x1F;
|
||||||
(size_of::<HostToDeviceRegisterFis>() as u16 / 4) & 0x1F;
|
self.command_list[slot].command |= 1 << 7;
|
||||||
self.command_list()[slot].command |= 1 << 7;
|
|
||||||
self.ahci_port_hba.issue_command(slot);
|
self.ahci_port_hba.issue_command(slot);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -324,53 +335,22 @@ impl<'a> PortController<'a> {
|
||||||
return Err(ZError::EXHAUSTED);
|
return Err(ZError::EXHAUSTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_list(&mut self) -> &mut CommandList {
|
|
||||||
unsafe {
|
|
||||||
self.command_structures
|
|
||||||
.mut_slice::<u8>()
|
|
||||||
.as_mut_ptr()
|
|
||||||
.cast::<CommandList>()
|
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn recieved_fis(&mut self) -> &mut ReceivedFis {
|
|
||||||
unsafe {
|
|
||||||
self.command_structures.mut_slice::<u8>()[0x400..]
|
|
||||||
.as_mut_ptr()
|
|
||||||
.cast::<ReceivedFis>()
|
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn command_tables(&mut self) -> &mut [CommandTable; 32] {
|
|
||||||
unsafe {
|
|
||||||
self.command_structures.mut_slice::<u8>()[0x500..]
|
|
||||||
.as_mut_ptr()
|
|
||||||
.cast::<[CommandTable; 32]>()
|
|
||||||
.as_mut()
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_interrupt(&mut self) {
|
fn handle_interrupt(&mut self) {
|
||||||
let int_status = self.ahci_port_hba.interrupt_status.read();
|
let int_status = self.ahci_port_hba.interrupt_status.read();
|
||||||
if int_status.device_to_host_register_fis_interrupt() {
|
if int_status.device_to_host_register_fis_interrupt() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
self.recieved_fis().device_to_host_register_fis.fis_type as u8,
|
self.received_fis.device_to_host_register_fis.fis_type as u8,
|
||||||
FisType::RegisterDeviceToHost as u8
|
FisType::RegisterDeviceToHost as u8
|
||||||
);
|
);
|
||||||
if self.recieved_fis().device_to_host_register_fis.error != 0 {
|
if self.received_fis.device_to_host_register_fis.error != 0 {
|
||||||
mammoth::debug!(
|
mammoth::debug!(
|
||||||
"D2H err: {:#0x}",
|
"D2H err: {:#0x}",
|
||||||
self.recieved_fis().device_to_host_register_fis.error
|
self.received_fis.device_to_host_register_fis.error
|
||||||
);
|
);
|
||||||
|
|
||||||
mammoth::debug!(
|
mammoth::debug!(
|
||||||
"Status: {:#0x}",
|
"Status: {:#0x}",
|
||||||
self.recieved_fis().device_to_host_register_fis.status
|
self.received_fis.device_to_host_register_fis.status
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue