Merge branch 'unify_storage_drivers' into 'master'

Reduce code duplication between disk drivers

See merge request redox-os/drivers!146
This commit is contained in:
Jeremy Soller
2024-03-10 15:12:56 +00:00
24 changed files with 226 additions and 385 deletions
Generated
+13 -12
View File
@@ -42,11 +42,10 @@ name = "ahcid"
version = "0.1.0"
dependencies = [
"bitflags 1.3.2",
"block-io-wrapper",
"byteorder",
"common",
"driver-block",
"log",
"partitionlib",
"pcid",
"redox-daemon",
"redox-log",
@@ -149,10 +148,9 @@ checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
name = "bcm2835-sdhcid"
version = "0.1.0"
dependencies = [
"block-io-wrapper",
"common",
"driver-block",
"fdt",
"partitionlib",
"redox-daemon",
"redox_syscall 0.4.1",
]
@@ -206,10 +204,6 @@ dependencies = [
"wyz",
]
[[package]]
name = "block-io-wrapper"
version = "0.1.0"
[[package]]
name = "bumpalo"
version = "3.13.0"
@@ -350,6 +344,14 @@ dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "driver-block"
version = "0.1.0"
dependencies = [
"partitionlib",
"redox_syscall 0.4.1",
]
[[package]]
name = "driver-network"
version = "0.1.0"
@@ -570,10 +572,9 @@ dependencies = [
name = "ided"
version = "0.1.0"
dependencies = [
"block-io-wrapper",
"common",
"driver-block",
"log",
"partitionlib",
"pcid",
"redox-daemon",
"redox-log",
@@ -758,9 +759,9 @@ version = "0.1.0"
dependencies = [
"arrayvec",
"bitflags 1.3.2",
"block-io-wrapper",
"common",
"crossbeam-channel",
"driver-block",
"futures",
"log",
"partitionlib",
@@ -1591,8 +1592,8 @@ name = "virtio-blkd"
version = "0.1.0"
dependencies = [
"anyhow",
"block-io-wrapper",
"common",
"driver-block",
"futures",
"log",
"partitionlib",
+1 -1
View File
@@ -31,7 +31,7 @@ members = [
"storage/ahcid",
"storage/bcm2835-sdhcid",
"storage/block-io-wrapper",
"storage/driver-block",
"storage/ided",
"storage/lived", # TODO: not really a driver...
"storage/nvmed",
+1 -1
View File
@@ -50,7 +50,7 @@ impl<T: NetworkAdapter> NetworkScheme<T> {
format!(":{scheme_name}"),
syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK,
)
.expect("e1000d: failed to create network scheme");
.expect("failed to create network scheme");
let scheme = unsafe { File::from_raw_fd(scheme_fd as RawFd) };
NetworkScheme {
+1 -2
View File
@@ -7,11 +7,10 @@ edition = "2018"
bitflags = "1.2"
byteorder = "1.2"
log = "0.4"
partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" }
redox-daemon = "0.1"
redox-log = "0.1"
redox_syscall = "0.4"
block-io-wrapper = { path = "../block-io-wrapper" }
common = { path = "../../common" }
driver-block = { path = "../driver-block" }
pcid = { path = "../../pcid" }
+1 -9
View File
@@ -1,6 +1,6 @@
use driver_block::Disk;
use log::{error, info};
use syscall::io::Io;
use syscall::error::Result;
use self::disk_ata::DiskATA;
use self::disk_atapi::DiskATAPI;
@@ -11,14 +11,6 @@ pub mod disk_atapi;
pub mod fis;
pub mod hba;
pub trait Disk {
fn id(&self) -> usize;
fn size(&mut self) -> u64;
fn read(&mut self, block: u64, buffer: &mut [u8]) -> Result<Option<usize>>;
fn write(&mut self, block: u64, buffer: &[u8]) -> Result<Option<usize>>;
fn block_length(&mut self) -> Result<u32>;
}
pub fn disks(base: usize, name: &str) -> (&'static mut HbaMem, Vec<Box<dyn Disk>>) {
let hba_mem = unsafe { &mut *(base as *mut HbaMem) };
hba_mem.init();
+1 -88
View File
@@ -3,19 +3,15 @@ use std::{cmp, str};
use std::convert::{TryFrom};
use std::fmt::Write;
use std::io::prelude::*;
use std::io::SeekFrom;
use std::io;
use driver_block::{Disk, DiskWrapper};
use syscall::{
Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, Result,
Io, SchemeBlockMut, Stat, MODE_DIR, MODE_FILE, O_DIRECTORY,
O_STAT, SEEK_CUR, SEEK_END, SEEK_SET};
use crate::ahci::Disk;
use crate::ahci::hba::HbaMem;
use partitionlib::{LogicalBlockSize, PartitionTable};
#[derive(Clone)]
enum Handle {
List(Vec<u8>, usize), // Dir contents buffer, position
@@ -23,89 +19,6 @@ enum Handle {
Partition(usize, u32, usize), // Disk index, partition index, position
}
pub struct DiskWrapper {
disk: Box<dyn Disk>,
pt: Option<PartitionTable>,
}
impl DiskWrapper {
fn pt(disk: &mut dyn Disk) -> Option<PartitionTable> {
let bs = match disk.block_length() {
Ok(512) => LogicalBlockSize::Lb512,
Ok(4096) => LogicalBlockSize::Lb4096,
_ => return None,
};
struct Device<'a, 'b> { disk: &'a mut dyn Disk, offset: u64, block_bytes: &'b mut [u8] }
impl<'a, 'b> Seek for Device<'a, 'b> {
fn seek(&mut self, from: SeekFrom) -> io::Result<u64> {
let size = i64::try_from(self.disk.size()).or(Err(io::Error::new(io::ErrorKind::Other, "Disk larger than 2^63 - 1 bytes")))?;
self.offset = match from {
SeekFrom::Start(new_pos) => cmp::min(self.disk.size(), new_pos),
SeekFrom::Current(new_pos) => cmp::max(0, cmp::min(size, self.offset as i64 + new_pos)) as u64,
SeekFrom::End(new_pos) => cmp::max(0, cmp::min(size + new_pos, size)) as u64,
};
Ok(self.offset)
}
}
// TODO: Perhaps this impl should be used in the rest of the scheme.
impl<'a, 'b> Read for Device<'a, 'b> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let blksize = self.disk.block_length().map_err(|err| io::Error::from_raw_os_error(err.errno))?;
let size_in_blocks = self.disk.size() / u64::from(blksize);
let disk = &mut self.disk;
let read_block = |block: u64, block_bytes: &mut [u8]| {
if block >= size_in_blocks {
return Err(io::Error::from_raw_os_error(syscall::EOVERFLOW));
}
loop {
match disk.read(block, block_bytes) {
Ok(Some(bytes)) => {
assert_eq!(bytes, block_bytes.len());
assert_eq!(bytes, blksize as usize);
return Ok(());
}
Ok(None) => { std::thread::yield_now(); continue }
Err(err) => return Err(io::Error::from_raw_os_error(err.errno)),
}
}
};
let bytes_read = block_io_wrapper::read(self.offset, blksize, buf, self.block_bytes, read_block)?;
self.offset += bytes_read as u64;
Ok(bytes_read)
}
}
let mut block_bytes = [0u8; 4096];
partitionlib::get_partitions(&mut Device { disk, offset: 0, block_bytes: &mut block_bytes[..bs.into()] }, bs).ok().flatten()
}
fn new(mut disk: Box<dyn Disk>) -> Self {
Self {
pt: Self::pt(&mut *disk),
disk,
}
}
}
impl std::ops::Deref for DiskWrapper {
type Target = dyn Disk;
fn deref(&self) -> &Self::Target {
&*self.disk
}
}
impl std::ops::DerefMut for DiskWrapper {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut *self.disk
}
}
pub struct DiskScheme {
scheme_name: String,
hba_mem: &'static mut HbaMem,
+1 -2
View File
@@ -8,8 +8,7 @@ edition = "2021"
[dependencies]
fdt = "0.1.5"
redox_syscall = "0.4"
partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" }
block-io-wrapper = { path = "../block-io-wrapper" }
common = { path = "../../common" }
driver-block = { path = "../driver-block" }
redox-daemon = "0.1"
+3 -3
View File
@@ -1,15 +1,15 @@
use std::{fs::File, io::{Read, Write}, process};
use driver_block::Disk;
use fdt::{Fdt, node::FdtNode};
use syscall::{Packet, SchemeBlockMut};
use crate::sd::Disk;
use crate::scheme::DiskScheme;
mod sd;
mod scheme;
#[cfg(target_os = "redox")]
#[cfg(target_os = "redox")]
fn get_dtb() -> Vec<u8> {
std::fs::read("kernel.dtb:").unwrap()
}
@@ -48,7 +48,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! {
};
println!("ioremap 0x{:08x} to 0x{:08x} 2222", reg.starting_address as usize, addr);
let mut sdhci = sd::SdHostCtrl::new(addr);
unsafe {
unsafe {
sdhci.init();
/*
let mut buf1 = [0u32; 512];
+1 -88
View File
@@ -3,19 +3,14 @@ use std::{cmp, str};
use std::convert::{TryFrom};
use std::fmt::Write;
use std::io::prelude::*;
use std::io::SeekFrom;
use std::io;
use std::sync::{Arc, Mutex};
use driver_block::{Disk, DiskWrapper};
use syscall::{
Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, Result,
Io, SchemeBlockMut, Stat, MODE_DIR, MODE_FILE, O_DIRECTORY,
O_STAT, SEEK_CUR, SEEK_END, SEEK_SET};
use crate::sd::Disk;
use partitionlib::{LogicalBlockSize, PartitionTable};
#[derive(Clone)]
enum Handle {
List(Vec<u8>, usize), // Dir contents buffer, position
@@ -23,88 +18,6 @@ enum Handle {
Partition(usize, u32, usize), // Disk index, partition index, position
}
pub struct DiskWrapper {
disk: Box<dyn Disk>,
pt: Option<PartitionTable>,
}
impl DiskWrapper {
fn pt(disk: &mut dyn Disk) -> Option<PartitionTable> {
let bs = match disk.block_length() {
Ok(512) => LogicalBlockSize::Lb512,
_ => return None,
};
struct Device<'a, 'b> { disk: &'a mut dyn Disk, offset: u64, block_bytes: &'b mut [u8] }
impl<'a, 'b> Seek for Device<'a, 'b> {
fn seek(&mut self, from: SeekFrom) -> io::Result<u64> {
let size = i64::try_from(self.disk.size()).or(Err(io::Error::new(io::ErrorKind::Other, "Disk larger than 2^63 - 1 bytes")))?;
self.offset = match from {
SeekFrom::Start(new_pos) => cmp::min(self.disk.size(), new_pos),
SeekFrom::Current(new_pos) => cmp::max(0, cmp::min(size, self.offset as i64 + new_pos)) as u64,
SeekFrom::End(new_pos) => cmp::max(0, cmp::min(size + new_pos, size)) as u64,
};
Ok(self.offset)
}
}
// TODO: Perhaps this impl should be used in the rest of the scheme.
impl<'a, 'b> Read for Device<'a, 'b> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let blksize = self.disk.block_length().map_err(|err| io::Error::from_raw_os_error(err.errno))?;
let size_in_blocks = self.disk.size() / u64::from(blksize);
let disk = &mut self.disk;
let read_block = |block: u64, block_bytes: &mut [u8]| {
if block >= size_in_blocks {
return Err(io::Error::from_raw_os_error(syscall::EOVERFLOW));
}
loop {
match disk.read(block, block_bytes) {
Ok(Some(bytes)) => {
assert_eq!(bytes, block_bytes.len());
assert_eq!(bytes, blksize as usize);
return Ok(());
}
Ok(None) => { std::thread::yield_now(); continue }
Err(err) => return Err(io::Error::from_raw_os_error(err.errno)),
}
}
};
let bytes_read = block_io_wrapper::read(self.offset, blksize, buf, self.block_bytes, read_block)?;
self.offset += bytes_read as u64;
Ok(bytes_read)
}
}
let mut block_bytes = [0u8; 4096];
partitionlib::get_partitions(&mut Device { disk, offset: 0, block_bytes: &mut block_bytes[..bs.into()] }, bs).ok().flatten()
}
fn new(mut disk: Box<dyn Disk>) -> Self {
Self {
pt: Self::pt(&mut *disk),
disk,
}
}
}
impl std::ops::Deref for DiskWrapper {
type Target = dyn Disk;
fn deref(&self) -> &Self::Target {
&*self.disk
}
}
impl std::ops::DerefMut for DiskWrapper {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut *self.disk
}
}
pub struct DiskScheme {
scheme_name: String,
disks: Box<[DiskWrapper]>,
+6 -14
View File
@@ -1,6 +1,6 @@
use std::{sync::{Mutex, RwLock}, time::{self, Duration}, thread};
use syscall::{io::Mmio, Io, Error, Result, EINVAL};
use core::ptr::{read_volatile, write_volatile};
use driver_block::Disk;
#[cfg(target_arch = "aarch64")]
#[inline(always)]
@@ -17,7 +17,7 @@ pub(crate) unsafe fn wait_cycles(mut n: usize) {
#[inline(always)]
pub(crate) unsafe fn wait_msec(mut n: usize) {
use core::arch::asm;
let mut f: usize;
let mut t: usize;
let mut r: usize;
@@ -185,7 +185,7 @@ pub struct SdHostCtrl {
impl SdHostCtrl {
pub fn new(address: usize) -> Self {
SdHostCtrl {
regs: RwLock::new(unsafe { &mut *(address as *mut SdHostCtrlRegs)}),
regs: RwLock::new(unsafe { &mut *(address as *mut SdHostCtrlRegs)}),
host_spec_ver: 0,
cid: [0; 4],
csd: [0; 4],
@@ -228,7 +228,7 @@ impl SdHostCtrl {
return ;
}
}
let regs = self.regs.get_mut().unwrap();
regs.irpt_en.write(0xffff_ffff);
regs.irpt_mask.write(0xffff_ffff);
@@ -518,7 +518,7 @@ impl SdHostCtrl {
self.cid[1] = regs.resp1.read();
self.cid[2] = regs.resp2.read();
self.cid[3] = regs.resp3.read();
//FIXME: wrong implement, see CMD_SEND_CSD for detail
return Ok(reg_val);
} else if code == CMD_SEND_CSD {
@@ -526,7 +526,7 @@ impl SdHostCtrl {
let tmp1 = regs.resp1.read();
let tmp2 = regs.resp2.read();
let tmp3 = regs.resp3.read();
self.csd[0] = tmp3 << 8 | tmp2 >> 24;
self.csd[1] = tmp2 << 8 | tmp1 >> 24;
self.csd[2] = tmp1 << 8 | tmp0 >> 24;
@@ -713,14 +713,6 @@ impl SdHostCtrl {
}
}
pub trait Disk {
fn id(&self) -> usize;
fn size(&mut self) -> u64;
fn read(&mut self, block:u64, buffer: &mut [u8]) -> syscall::error::Result<Option<usize>>;
fn write(&mut self, block:u64, buffer: &[u8]) -> syscall::error::Result<Option<usize>>;
fn block_length(&mut self) -> syscall::error::Result<u32>;
}
impl Disk for SdHostCtrl {
fn id(&self) -> usize {
0xdead_dead
-1
View File
@@ -1 +0,0 @@
/target
-9
View File
@@ -1,9 +0,0 @@
[package]
name = "block-io-wrapper"
version = "0.1.0"
authors = ["4lDO2 <4lDO2@protonmail.com>"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-49
View File
@@ -1,49 +0,0 @@
use std::cmp::min;
use std::io::Error;
/// Split the read operation into a series of block reads.
/// `read_fn` will be called with a block number to be read, and a buffer to be filled.
/// The buffer must be large enough to hold `blksize` of data.
/// `read_fn` must return a full block of data.
/// Result will be the number of bytes read.
pub fn read(
offset: u64,
blksize: u32,
buf: &mut [u8],
block_bytes: &mut [u8],
mut read_fn: impl FnMut(u64, &mut [u8]) -> Result<(), Error>,
) -> Result<usize, Error> {
// TODO: Yield sometimes, perhaps after a few blocks or something.
if buf.len() == 0 {
return Ok(0);
}
let to_copy = usize::try_from(
offset.saturating_add(u64::try_from(buf.len()).expect("buf.len() larger than u64"))
- offset,
)
.expect("bytes to copy larger than usize");
let mut curr_buf = &mut buf[..to_copy];
let mut curr_offset = offset;
let blk_size = usize::try_from(blksize).expect("blksize larger than usize");
let mut total_read = 0;
while curr_buf.len() > 0 {
// TODO: Async/await? I mean, shouldn't AHCI be async?
let blk_offset =
usize::try_from(curr_offset % u64::from(blksize)).expect("usize smaller than blksize");
let to_copy = min(curr_buf.len(), blk_size - blk_offset);
assert!(blk_offset + to_copy <= blk_size);
read_fn(curr_offset / u64::from(blksize), block_bytes)?;
let src_buf = &block_bytes[blk_offset..];
curr_buf[..to_copy].copy_from_slice(&src_buf[..to_copy]);
curr_buf = &mut curr_buf[to_copy..];
curr_offset += u64::try_from(to_copy).expect("bytes to copy larger than u64");
total_read += to_copy;
}
Ok(total_read)
}
+9
View File
@@ -0,0 +1,9 @@
[package]
name = "driver-block"
version = "0.1.0"
edition = "2021"
[dependencies]
partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" }
redox_syscall = "0.4"
+175
View File
@@ -0,0 +1,175 @@
use std::cmp;
use std::io::Error;
use std::io::{self, Read, Seek, SeekFrom};
use partitionlib::{LogicalBlockSize, PartitionTable};
/// Split the read operation into a series of block reads.
/// `read_fn` will be called with a block number to be read, and a buffer to be filled.
/// The buffer must be large enough to hold `blksize` of data.
/// `read_fn` must return a full block of data.
/// Result will be the number of bytes read.
// FIXME make private once nvmed uses the DiskWrapper defined in this crate
pub fn block_read(
offset: u64,
blksize: u32,
buf: &mut [u8],
block_bytes: &mut [u8],
mut read_fn: impl FnMut(u64, &mut [u8]) -> Result<(), Error>,
) -> Result<usize, Error> {
// TODO: Yield sometimes, perhaps after a few blocks or something.
if buf.len() == 0 {
return Ok(0);
}
let to_copy = usize::try_from(
offset.saturating_add(u64::try_from(buf.len()).expect("buf.len() larger than u64"))
- offset,
)
.expect("bytes to copy larger than usize");
let mut curr_buf = &mut buf[..to_copy];
let mut curr_offset = offset;
let blk_size = usize::try_from(blksize).expect("blksize larger than usize");
let mut total_read = 0;
while curr_buf.len() > 0 {
// TODO: Async/await? I mean, shouldn't AHCI be async?
let blk_offset =
usize::try_from(curr_offset % u64::from(blksize)).expect("usize smaller than blksize");
let to_copy = cmp::min(curr_buf.len(), blk_size - blk_offset);
assert!(blk_offset + to_copy <= blk_size);
read_fn(curr_offset / u64::from(blksize), block_bytes)?;
let src_buf = &block_bytes[blk_offset..];
curr_buf[..to_copy].copy_from_slice(&src_buf[..to_copy]);
curr_buf = &mut curr_buf[to_copy..];
curr_offset += u64::try_from(to_copy).expect("bytes to copy larger than u64");
total_read += to_copy;
}
Ok(total_read)
}
pub trait Disk {
fn id(&self) -> usize;
fn block_length(&mut self) -> syscall::error::Result<u32>;
fn size(&mut self) -> u64;
fn read(&mut self, block: u64, buffer: &mut [u8]) -> syscall::Result<Option<usize>>;
fn write(&mut self, block: u64, buffer: &[u8]) -> syscall::Result<Option<usize>>;
}
pub struct DiskWrapper {
pub disk: Box<dyn Disk>,
pub pt: Option<PartitionTable>,
}
impl DiskWrapper {
fn pt(disk: &mut dyn Disk) -> Option<PartitionTable> {
let bs = match disk.block_length() {
Ok(512) => LogicalBlockSize::Lb512,
_ => return None,
};
struct Device<'a, 'b> {
disk: &'a mut dyn Disk,
offset: u64,
block_bytes: &'b mut [u8],
}
impl<'a, 'b> Seek for Device<'a, 'b> {
fn seek(&mut self, from: SeekFrom) -> io::Result<u64> {
let size = i64::try_from(self.disk.size()).or(Err(io::Error::new(
io::ErrorKind::Other,
"Disk larger than 2^63 - 1 bytes",
)))?;
self.offset = match from {
SeekFrom::Start(new_pos) => cmp::min(self.disk.size(), new_pos),
SeekFrom::Current(new_pos) => {
cmp::max(0, cmp::min(size, self.offset as i64 + new_pos)) as u64
}
SeekFrom::End(new_pos) => cmp::max(0, cmp::min(size + new_pos, size)) as u64,
};
Ok(self.offset)
}
}
// TODO: Perhaps this impl should be used in the rest of the scheme.
impl<'a, 'b> Read for Device<'a, 'b> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let blksize = self
.disk
.block_length()
.map_err(|err| io::Error::from_raw_os_error(err.errno))?;
let size_in_blocks = self.disk.size() / u64::from(blksize);
let disk = &mut self.disk;
let read_block = |block: u64, block_bytes: &mut [u8]| {
if block >= size_in_blocks {
return Err(io::Error::from_raw_os_error(syscall::EOVERFLOW));
}
loop {
match disk.read(block, block_bytes) {
Ok(Some(bytes)) => {
assert_eq!(bytes, block_bytes.len());
assert_eq!(bytes, blksize as usize);
return Ok(());
}
Ok(None) => {
std::thread::yield_now();
continue;
}
Err(err) => return Err(io::Error::from_raw_os_error(err.errno)),
}
}
};
let bytes_read = block_read(
self.offset,
blksize,
buf,
self.block_bytes,
read_block,
)?;
self.offset += bytes_read as u64;
Ok(bytes_read)
}
}
let mut block_bytes = [0u8; 4096];
partitionlib::get_partitions(
&mut Device {
disk,
offset: 0,
block_bytes: &mut block_bytes[..bs.into()],
},
bs,
)
.ok()
.flatten()
}
pub fn new(mut disk: Box<dyn Disk>) -> Self {
Self {
pt: Self::pt(&mut *disk),
disk,
}
}
}
impl std::ops::Deref for DiskWrapper {
type Target = dyn Disk;
fn deref(&self) -> &Self::Target {
&*self.disk
}
}
impl std::ops::DerefMut for DiskWrapper {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut *self.disk
}
}
+1 -2
View File
@@ -4,10 +4,9 @@ version = "0.1.0"
edition = "2018"
[dependencies]
block-io-wrapper = { path = "../block-io-wrapper" }
common = { path = "../../common" }
driver-block = { path = "../driver-block" }
log = "0.4"
partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" }
pcid = { path = "../../pcid" }
redox-daemon = "0.1"
redox-log = "0.1"
+1 -8
View File
@@ -5,6 +5,7 @@ use std::{
time::{Duration, Instant},
};
use driver_block::Disk;
use syscall::{
error::{Error, Result, EIO},
io::{Io, Pio, ReadOnly, WriteOnly},
@@ -153,14 +154,6 @@ impl Channel {
}
}
pub trait Disk {
fn id(&self) -> usize;
fn size(&mut self) -> u64;
fn read(&mut self, block: u64, buffer: &mut [u8]) -> Result<Option<usize>>;
fn write(&mut self, block: u64, buffer: &[u8]) -> Result<Option<usize>>;
fn block_length(&mut self) -> Result<u32>;
}
pub struct AtaDisk {
pub chan: Arc<Mutex<Channel>>,
pub chan_i: usize,
+2 -1
View File
@@ -1,3 +1,4 @@
use driver_block::Disk;
use log::{error, info};
use pcid_interface::{PciBar, PcidServerHandle};
use redox_log::{OutputBuilder, RedoxLogger};
@@ -18,7 +19,7 @@ use syscall::{
};
use crate::{
ide::{AtaCommand, AtaDisk, Channel, Disk},
ide::{AtaCommand, AtaDisk, Channel},
scheme::DiskScheme,
};
+2 -88
View File
@@ -3,18 +3,15 @@ use std::{cmp, str};
use std::convert::{TryFrom};
use std::fmt::Write;
use std::io::prelude::*;
use std::io::SeekFrom;
use std::io;
use std::sync::{Arc, Mutex};
use driver_block::{Disk, DiskWrapper};
use syscall::{
Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, Result,
Io, SchemeBlockMut, Stat, MODE_DIR, MODE_FILE, O_DIRECTORY,
O_STAT, SEEK_CUR, SEEK_END, SEEK_SET};
use crate::ide::{Channel, Disk};
use partitionlib::{LogicalBlockSize, PartitionTable};
use crate::ide::Channel;
#[derive(Clone)]
enum Handle {
@@ -23,89 +20,6 @@ enum Handle {
Partition(usize, u32, usize), // Disk index, partition index, position
}
pub struct DiskWrapper {
disk: Box<dyn Disk>,
pt: Option<PartitionTable>,
}
impl DiskWrapper {
fn pt(disk: &mut dyn Disk) -> Option<PartitionTable> {
let bs = match disk.block_length() {
Ok(512) => LogicalBlockSize::Lb512,
Ok(4096) => LogicalBlockSize::Lb4096,
_ => return None,
};
struct Device<'a, 'b> { disk: &'a mut dyn Disk, offset: u64, block_bytes: &'b mut [u8] }
impl<'a, 'b> Seek for Device<'a, 'b> {
fn seek(&mut self, from: SeekFrom) -> io::Result<u64> {
let size = i64::try_from(self.disk.size()).or(Err(io::Error::new(io::ErrorKind::Other, "Disk larger than 2^63 - 1 bytes")))?;
self.offset = match from {
SeekFrom::Start(new_pos) => cmp::min(self.disk.size(), new_pos),
SeekFrom::Current(new_pos) => cmp::max(0, cmp::min(size, self.offset as i64 + new_pos)) as u64,
SeekFrom::End(new_pos) => cmp::max(0, cmp::min(size + new_pos, size)) as u64,
};
Ok(self.offset)
}
}
// TODO: Perhaps this impl should be used in the rest of the scheme.
impl<'a, 'b> Read for Device<'a, 'b> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let blksize = self.disk.block_length().map_err(|err| io::Error::from_raw_os_error(err.errno))?;
let size_in_blocks = self.disk.size() / u64::from(blksize);
let disk = &mut self.disk;
let read_block = |block: u64, block_bytes: &mut [u8]| {
if block >= size_in_blocks {
return Err(io::Error::from_raw_os_error(syscall::EOVERFLOW));
}
loop {
match disk.read(block, block_bytes) {
Ok(Some(bytes)) => {
assert_eq!(bytes, block_bytes.len());
assert_eq!(bytes, blksize as usize);
return Ok(());
}
Ok(None) => { std::thread::yield_now(); continue }
Err(err) => return Err(io::Error::from_raw_os_error(err.errno)),
}
}
};
let bytes_read = block_io_wrapper::read(self.offset, blksize, buf, self.block_bytes, read_block)?;
self.offset += bytes_read as u64;
Ok(bytes_read)
}
}
let mut block_bytes = [0u8; 4096];
partitionlib::get_partitions(&mut Device { disk, offset: 0, block_bytes: &mut block_bytes[..bs.into()] }, bs).ok().flatten()
}
fn new(mut disk: Box<dyn Disk>) -> Self {
Self {
pt: Self::pt(&mut *disk),
disk,
}
}
}
impl std::ops::Deref for DiskWrapper {
type Target = dyn Disk;
fn deref(&self) -> &Self::Target {
&*self.disk
}
}
impl std::ops::DerefMut for DiskWrapper {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut *self.disk
}
}
pub struct DiskScheme {
scheme_name: String,
chans: Box<[Arc<Mutex<Channel>>]>,
+1 -1
View File
@@ -15,8 +15,8 @@ redox_syscall = "0.4"
partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" }
smallvec = "1"
block-io-wrapper = { path = "../block-io-wrapper" }
common = { path = "../../common" }
driver-block = { path = "../driver-block" }
pcid = { path = "../../pcid" }
[features]
+1 -1
View File
@@ -96,7 +96,7 @@ impl DiskWrapper {
}
}
};
let bytes_read = block_io_wrapper::read(
let bytes_read = driver_block::block_read(
self.offset,
blksize
.try_into()
+1 -1
View File
@@ -17,7 +17,7 @@ redox-log = "0.1"
redox_syscall = "0.4"
partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" }
block-io-wrapper = { path = "../block-io-wrapper" }
common = { path = "../../common" }
driver-block = { path = "../driver-block" }
pcid = { path = "../../pcid" }
virtio-core = { path = "../../virtio-core" }
+1 -1
View File
@@ -148,7 +148,7 @@ impl<'a> DiskScheme<'a> {
};
let bytes_read =
block_io_wrapper::read(self.offset, 512, buf, self.block_bytes, read_block)
driver_block::block_read(self.offset, 512, buf, self.block_bytes, read_block)
.unwrap();
self.offset += bytes_read as u64;
Ok(bytes_read)
+3 -3
View File
@@ -71,7 +71,7 @@ pub fn probe_device(pcid_handle: &mut PcidServerHandle) -> Result<Device, Error>
let mut notify_addr = None;
let mut device_addr = None;
for capability in pcid_handle
for raw_capability in pcid_handle
.get_capabilities()?
.iter()
.filter_map(|capability| {
@@ -83,7 +83,7 @@ pub fn probe_device(pcid_handle: &mut PcidServerHandle) -> Result<Device, Error>
})
{
// SAFETY: We have verified that the length of the data is correct.
let capability = unsafe { &*(capability.data.as_ptr() as *const PciCapability) };
let capability = unsafe { &*(raw_capability.data.as_ptr() as *const PciCapability) };
match capability.cfg_type {
CfgType::Common | CfgType::Notify | CfgType::Device => {}
@@ -123,7 +123,7 @@ pub fn probe_device(pcid_handle: &mut PcidServerHandle) -> Result<Device, Error>
// SAFETY: The capability type is `Notify`, so its safe to access
// the `notify_multiplier` field.
let multiplier = unsafe {
(&*(capability as *const PciCapability as *const PciCapabilityNotify))
(&*(raw_capability.data.as_ptr() as *const PciCapability as *const PciCapabilityNotify))
.notify_off_multiplier()
};
notify_addr = Some((address, multiplier));