Add write support

This commit is contained in:
pjht 2025-03-07 11:34:34 -06:00
parent ac68c7e932
commit 5f95c802c5
Signed by: pjht
GPG Key ID: CA239FC6934E6F3A
5 changed files with 215 additions and 49 deletions

82
Cargo.lock generated
View File

@ -66,9 +66,9 @@ checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61"
[[package]]
name = "bitflags"
version = "2.6.0"
version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
dependencies = [
"serde",
]
@ -93,9 +93,9 @@ checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
[[package]]
name = "critical-section"
version = "1.1.3"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242"
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
[[package]]
name = "darling"
@ -118,7 +118,7 @@ dependencies = [
"proc-macro2",
"quote",
"strsim",
"syn 2.0.87",
"syn 2.0.99",
]
[[package]]
@ -129,38 +129,38 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core",
"quote",
"syn 2.0.87",
"syn 2.0.99",
]
[[package]]
name = "derive_builder"
version = "0.20.1"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd33f37ee6a119146a1781d3356a7c26028f83d779b2e04ecd45fdc75c76877b"
checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947"
dependencies = [
"derive_builder_macro",
]
[[package]]
name = "derive_builder_core"
version = "0.20.1"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7431fa049613920234f22c47fdc33e6cf3ee83067091ea4277a3f8c4587aae38"
checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.99",
]
[[package]]
name = "derive_builder_macro"
version = "0.20.1"
version = "0.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4abae7035bf79b9877b779505d8cf3749285b80c43941eda66604841889451dc"
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
dependencies = [
"derive_builder_core",
"syn 2.0.87",
"syn 2.0.99",
]
[[package]]
@ -183,9 +183,9 @@ dependencies = [
[[package]]
name = "either"
version = "1.13.0"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "embedded-io"
@ -265,15 +265,15 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.159"
version = "0.2.170"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
[[package]]
name = "libm"
version = "0.2.8"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
[[package]]
name = "lock_api"
@ -318,9 +318,9 @@ dependencies = [
[[package]]
name = "postcard"
version = "1.0.10"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e"
checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8"
dependencies = [
"cobs",
"embedded-io 0.4.0",
@ -343,27 +343,27 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.86"
version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
version = "1.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
checksum = "c1f1914ce909e1658d9907913b4b91947430c7d9be598b15a1912935b8c04801"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.5.7"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1"
dependencies = [
"bitflags",
]
@ -388,9 +388,9 @@ dependencies = [
[[package]]
name = "rustversion"
version = "1.0.17"
version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6"
checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
[[package]]
name = "scopeguard"
@ -400,9 +400,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "semver"
version = "1.0.23"
version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
[[package]]
name = "serde"
@ -417,7 +417,7 @@ version = "1.0.218"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.87",
"syn 2.0.99",
]
[[package]]
@ -431,9 +431,9 @@ dependencies = [
[[package]]
name = "smallvec"
version = "1.13.2"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
[[package]]
name = "spin"
@ -469,9 +469,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.87"
version = "2.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
checksum = "e02e925281e18ffd9d640e234264753c43edc62d64b2d4cf898f1bc5e75f3fc2"
dependencies = [
"proc-macro2",
"quote",
@ -500,9 +500,9 @@ version = "0.6.0"
[[package]]
name = "unicode-ident"
version = "1.0.13"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "volatile"
@ -582,9 +582,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "x86_64"
version = "0.15.1"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bc79523af8abf92fb1a970c3e086c5a343f6bcc1a0eb890f575cbb3b45743df"
checksum = "0f042214de98141e9c8706e8192b73f56494087cc55ebec28ce10f26c5c364ae"
dependencies = [
"bit_field",
"bitflags",

View File

@ -15,6 +15,13 @@ pub trait AtaCommandDataIn {
fn process_data<'a>(&self, data: &'a [u8]) -> Self::ProcessedData<'a>;
}
#[allow(clippy::module_name_repetitions)]
pub trait AtaCommandDataOut {
fn get_fis(&self) -> RegH2DFis;
fn get_data(&self) -> &[u8];
}
pub struct IdentifyCommand;
impl AtaCommandDataIn for IdentifyCommand {
@ -115,3 +122,46 @@ impl AtaCommandDataIn for ReadDmaExtCommand {
data
}
}
pub struct WriteDmaExtCommand<'a> {
lba: u64,
count: u16,
data: &'a [u8],
}
impl<'a> WriteDmaExtCommand<'a> {
pub fn new(lba: u64, count: u16, data: &'a [u8]) -> Self {
Self { lba, count, data }
}
}
impl AtaCommandDataOut for WriteDmaExtCommand<'_> {
fn get_fis(&self) -> RegH2DFis {
let lba_bytes = self.lba.to_le_bytes();
RegH2DFisBuilder::default()
.cmd(true)
.regs(
DeviceRegsWriteBuilder::default()
.commmad(0x35)
.lba(true)
.countl(self.count as u8)
.counth((self.count >> 8) as u8)
.lba0(lba_bytes[0])
.lba1(lba_bytes[1])
.lba2(lba_bytes[2])
.lba3(lba_bytes[3])
.lba4(lba_bytes[4])
.lba5(lba_bytes[5])
.build()
.unwrap(),
)
.build()
.unwrap()
}
fn get_data(&self) -> &[u8] {
self.data
}
}

View File

@ -1,7 +1,7 @@
use std::os::mikros::Errno;
use crate::{
ata_command::ReadDmaExtCommand,
ata_command::{ReadDmaExtCommand, WriteDmaExtCommand},
identify::IdentifyData,
port::{AhciPort, CommandIssueError},
};
@ -19,6 +19,7 @@ pub enum AtaNewError {
DeviceTooBig,
}
#[derive(Debug)]
pub enum AtaReadError {
NotAligned,
@ -46,6 +47,33 @@ impl From<CommandIssueError> for AtaReadError {
}
}
#[derive(Debug)]
pub enum AtaWriteError {
NotAligned,
SizeNotSectMult,
SizeTooBig,
WriteOffEnd,
CommandError(#[allow(unused)] CommandIssueError),
}
impl From<AtaWriteError> for Errno {
fn from(value: AtaWriteError) -> Self {
match value {
AtaWriteError::NotAligned
| AtaWriteError::SizeNotSectMult
| AtaWriteError::SizeTooBig
| AtaWriteError::WriteOffEnd => Self::EINVAL,
AtaWriteError::CommandError(_) => Self::EIO,
}
}
}
impl From<CommandIssueError> for AtaWriteError {
fn from(v: CommandIssueError) -> Self {
Self::CommandError(v)
}
}
impl<'a> AtaDevice<'a> {
pub fn new(port: &'a AhciPort, identify_data: IdentifyData) -> Result<Self, AtaNewError> {
let sect_sz_info_valid = identify_data.phys_log_sect_sz & 0xC000 == 0x4000;
@ -108,6 +136,29 @@ impl<'a> AtaDevice<'a> {
Ok(())
}
pub fn write(&self, offset: usize, data: &[u8]) -> Result<(), AtaWriteError> {
if offset % self.sector_size != 0 {
return Err(AtaWriteError::NotAligned);
};
if data.len() % self.sector_size != 0 {
return Err(AtaWriteError::SizeNotSectMult);
};
if data.len() / self.sector_size > 65536 {
return Err(AtaWriteError::SizeTooBig);
};
if offset + data.len() > self.capacity {
return Err(AtaWriteError::WriteOffEnd);
};
self.port.issue_data_out_command(
&WriteDmaExtCommand::new(
(offset / self.sector_size) as u64,
(data.len() / self.sector_size) as u16,
&data,
),
)?;
Ok(())
}
pub fn capacity(&self) -> usize {
self.capacity
}

View File

@ -29,7 +29,7 @@ mod port;
use std::{
collections::HashMap,
os::mikros::{address_space::ACTIVE_SPACE, ipc, syscalls, Errno, FileOpenMode},
os::mikros::{address_space::ACTIVE_SPACE, ipc, set_serial_output, syscalls, Errno, FileOpenMode},
path::{Path, PathBuf},
sync::Arc,
};
@ -75,8 +75,20 @@ impl file_rpc::Server for AhciState {
Ok(buf.into())
}
fn write(&self, _fd: u64, _data: &[u8]) -> Result<(), Errno> {
todo!()
fn write(&self, fd: u64, data: &[u8]) -> Result<(), Errno> {
let hba = self.hba.lock();
let (port_no, pos) = self.files.read()[fd as usize];
let port = hba.ports().get(port_no).ok_or(Errno::ESTALE)?;
let device = port
.get_device()
.map_err(|_| Errno::ESTALE)?
.ok_or(Errno::ESTALE)?;
let DeviceEnum::Ata(device) = device else {
return Err(Errno::ESTALE);
};
device.write(pos as usize, &data)?;
self.files.write()[fd as usize].1 += data.len() as u64;
Ok(())
}
fn close(&self, _fd: u64) -> Result<(), Errno> {

View File

@ -6,9 +6,9 @@ use volatile::VolatilePtr;
use crate::{
ahci_structs::{
CommandHeader, CommandTableHeader, DeviceRegsRead, FisBuf, PortRegs, Prd, PxCMD, PxIS,
PxSERR, PxSSTS, PxTFD, RegH2DFis,
PxSERR, PxSSTS, PxTFD, RegH2DFis, CH_FLAG_WRITE,
},
ata_command::{AtaCommandDataIn, IdentifyCommand, IdentifyPacketCommand},
ata_command::{AtaCommandDataIn, AtaCommandDataOut, IdentifyCommand, IdentifyPacketCommand},
ata_dev::{AtaDevice, AtaNewError},
atapi_dev::AtapiDevice,
identify::{IdentifyData, IdentifyPacketData},
@ -141,6 +141,7 @@ impl AhciPort {
&self,
fis: &RegH2DFis,
prdt: &[Prd],
flags: u16
) -> Result<(), CommandIssueError> {
if prdt.len() > 65535 {
return Err(CommandIssueError::PrdtTooBig);
@ -170,7 +171,7 @@ impl AhciPort {
let cmd_hdr_ptr = self.cmd_list;
let cmd_hdr = CommandHeader {
flags: (RegH2DFis::BYTE_SIZE / 4) as u16,
flags: (RegH2DFis::BYTE_SIZE / 4) as u16 | flags,
prdtl: prdt.len() as u16,
prdbc: 0,
ctba: buf_phys as u32,
@ -247,7 +248,7 @@ impl AhciPort {
.collect_vec();
unsafe {
self.issue_command_prdt(&command.get_fis(), &prdt)?;
self.issue_command_prdt(&command.get_fis(), &prdt, 0)?;
}
let data_vol = unsafe {
@ -268,6 +269,58 @@ impl AhciPort {
Ok(command.process_data(buf))
}
pub fn issue_data_out_command<'a, T: AtaCommandDataOut>(
&self,
command: &T,
) -> Result<(), CommandIssueError> {
let len = command.get_data().len();
if len > 0x40_0000 * 0xFFFF {
return Err(CommandIssueError::DataTooBig);
}
let (data_buf, data_buf_phys) = ACTIVE_SPACE
.lock()
.unwrap()
.map_free_cont_phys(len.div_ceil(4096))
.unwrap();
let data_vol = unsafe {
VolatilePtr::new(NonNull::slice_from_raw_parts(
NonNull::new(data_buf).unwrap(),
len,
))
};
data_vol.copy_from_slice(command.get_data());
let num_prds = len.div_ceil(0x40_0000);
let prdt = (0..num_prds)
.map(|i| {
let size = if i == num_prds - 1 {
len - (i * 0x40_0000)
} else {
0x40_0000
};
Prd::new(data_buf_phys + (i * 0x40_0000) as u64, size as u32, false).unwrap()
})
.collect_vec();
unsafe {
self.issue_command_prdt(&command.get_fis(), &prdt, CH_FLAG_WRITE)?;
}
ACTIVE_SPACE
.lock()
.unwrap()
.unmap(data_buf, len.div_ceil(4096))
.unwrap();
Ok(())
}
pub fn get_device(&self) -> Result<Option<DeviceEnum>, GetDeviceError> {
if !self.has_device() {
return Ok(None);