Add write support
This commit is contained in:
parent
ac68c7e932
commit
5f95c802c5
82
Cargo.lock
generated
82
Cargo.lock
generated
@ -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",
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
18
src/main.rs
18
src/main.rs
@ -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> {
|
||||
|
61
src/port.rs
61
src/port.rs
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user