pcid: add access file
This commit is contained in:
+68
-5
@@ -1,6 +1,6 @@
|
||||
use std::collections::{BTreeMap, VecDeque};
|
||||
|
||||
use pci_types::PciAddress;
|
||||
use pci_types::{ConfigRegionAccess, PciAddress};
|
||||
use redox_scheme::scheme::SchemeSync;
|
||||
use redox_scheme::{CallerCtx, OpenResult};
|
||||
use syscall::dirent::{DirEntry, DirentBuf, DirentKind};
|
||||
@@ -19,6 +19,7 @@ pub struct PciScheme {
|
||||
}
|
||||
enum Handle {
|
||||
TopLevel { entries: Vec<String> },
|
||||
Access,
|
||||
Device,
|
||||
Channel { addr: PciAddress, st: ChannelState },
|
||||
}
|
||||
@@ -28,14 +29,14 @@ struct HandleWrapper {
|
||||
}
|
||||
impl Handle {
|
||||
fn is_file(&self) -> bool {
|
||||
matches!(self, Self::Channel { .. })
|
||||
matches!(self, Self::Access | Self::Channel { .. })
|
||||
}
|
||||
fn is_dir(&self) -> bool {
|
||||
!self.is_file()
|
||||
}
|
||||
// TODO: capability rather than root
|
||||
fn requires_root(&self) -> bool {
|
||||
matches!(self, Self::Channel { .. })
|
||||
matches!(self, Self::Access | Self::Channel { .. })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +65,8 @@ impl SchemeSync for PciScheme {
|
||||
.map(|(addr, _)| format!("{}", addr).replace(':', "--"))
|
||||
.collect::<Vec<_>>(),
|
||||
}
|
||||
} else if path == "access" {
|
||||
Handle::Access
|
||||
} else {
|
||||
let idx = path.find('/').unwrap_or(path.len());
|
||||
let (addr_str, after) = path.split_at(idx);
|
||||
@@ -104,7 +107,7 @@ impl SchemeSync for PciScheme {
|
||||
let (len, mode) = match handle.inner {
|
||||
Handle::TopLevel { ref entries } => (entries.len(), MODE_DIR | 0o755),
|
||||
Handle::Device => (DEVICE_CONTENTS.len(), MODE_DIR | 0o755),
|
||||
Handle::Channel { .. } => (0, MODE_CHR | 0o600),
|
||||
Handle::Access | Handle::Channel { .. } => (0, MODE_CHR | 0o600),
|
||||
};
|
||||
stat.st_size = len as u64;
|
||||
stat.st_mode = mode;
|
||||
@@ -131,6 +134,7 @@ impl SchemeSync for PciScheme {
|
||||
addr: _,
|
||||
ref mut st,
|
||||
} => Self::read_channel(st, buf),
|
||||
_ => Err(Error::new(EBADF))
|
||||
}
|
||||
}
|
||||
fn getdents<'buf>(
|
||||
@@ -162,7 +166,7 @@ impl SchemeSync for PciScheme {
|
||||
return Ok(buf);
|
||||
}
|
||||
Handle::Device => DEVICE_CONTENTS,
|
||||
Handle::Channel { .. } => return Err(Error::new(ENOTDIR)),
|
||||
Handle::Access | Handle::Channel { .. } => return Err(Error::new(ENOTDIR)),
|
||||
};
|
||||
|
||||
for (i, dent_name) in entries.iter().enumerate().skip(offset) {
|
||||
@@ -198,6 +202,65 @@ impl SchemeSync for PciScheme {
|
||||
_ => Err(Error::new(EBADF)),
|
||||
}
|
||||
}
|
||||
|
||||
fn call(&mut self, id: usize, payload: &mut [u8], metadata: &[u64]) -> Result<usize> {
|
||||
let handle = self.handles.get_mut(&id).ok_or(Error::new(EBADF))?;
|
||||
|
||||
if handle.stat {
|
||||
return Err(Error::new(EBADF));
|
||||
}
|
||||
|
||||
match handle.inner {
|
||||
Handle::Access => {
|
||||
let (addr, offset) = match metadata.get(1) {
|
||||
Some(value) => {
|
||||
// Segment: u16, at 28 bits
|
||||
// Bus: u8, 8 bits, 256 total, at 20 bits
|
||||
// Device: u8, 5 bits, 32 total, at 15 bits
|
||||
// Function: u8, 3 bits, 8 total, at 12 bits
|
||||
// Offset: u16, 12 bits, 4096 total, at 0 bits
|
||||
(
|
||||
PciAddress::new(
|
||||
((value >> 28) & 0xFFFF) as u16,
|
||||
((value >> 20) & 0xFF) as u8,
|
||||
((value >> 15) & 0x1F) as u8,
|
||||
((value >> 12) & 0x7) as u8,
|
||||
),
|
||||
(value & 0xFFF) as u16
|
||||
)
|
||||
}
|
||||
None => return Err(Error::new(EINVAL)),
|
||||
};
|
||||
match metadata.get(0) {
|
||||
Some(1) => {
|
||||
// Read
|
||||
let value = unsafe { self.pcie.read(addr, offset) };
|
||||
let bytes = value.to_le_bytes();
|
||||
let len = payload.len().min(bytes.len());
|
||||
payload.copy_from_slice(&bytes[..len]);
|
||||
Ok(len)
|
||||
}
|
||||
Some(2) => {
|
||||
// Write
|
||||
let len = payload.len().min(4);
|
||||
let mut bytes = if len < 4 {
|
||||
//TODO: any way to do less than dword writes?
|
||||
unsafe { self.pcie.read(addr, offset).to_le_bytes() }
|
||||
} else {
|
||||
[0; 4]
|
||||
};
|
||||
bytes[..len].copy_from_slice(&payload);
|
||||
let value = u32::from_le_bytes(bytes);
|
||||
unsafe { self.pcie.write(addr, offset, value); }
|
||||
Ok(len)
|
||||
}
|
||||
_ => Err(Error::new(EINVAL)),
|
||||
}
|
||||
}
|
||||
|
||||
_ => Err(Error::new(EBADF)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PciScheme {
|
||||
|
||||
Reference in New Issue
Block a user