Add a driver interface accessible to class drivers.

This commit is contained in:
4lDO2
2020-02-06 21:45:44 +01:00
parent ae0d43c12a
commit 1b74f335b0
19 changed files with 839 additions and 471 deletions
+2
View File
@@ -1,5 +1,7 @@
use std::env;
pub mod protocol;
fn main() {
let mut args = env::args().skip(1);
+47
View File
@@ -0,0 +1,47 @@
use super::Protocol;
pub const CBW_SIGNATURE: u32 = 0x43425355;
/// 0 means host to dev, 1 means dev to host
pub const CBW_FLAGS_DIRECTION_BIT: u8 = 1 << CBW_FLAGS_DIRECTION_SHIFT;
pub const CBW_FLAGS_DIRECTION_SHIFT: u8 = 7;
#[repr(packed)]
pub struct CommandBlockWrapper {
pub signature: u32,
pub tag: u32,
pub data_transfer_len: u32,
pub flags: u8, // upper nibble reserved
pub lun: u8, // bits 7:5 reserved
pub cb_len: u8,
pub command_block: [u8; 16],
}
pub const CSW_SIGNATURE: u32 = 0x53425355;
#[repr(u8)]
pub enum CswStatus {
Passed = 0,
Failed = 1,
PhaseError = 2,
// the rest are reserved
}
#[repr(packed)]
pub struct CommandStatusWrapper {
pub signature: u32,
pub tag: u32,
pub data_residue: u32,
pub status: u8,
}
pub struct BulkOnlyTransport;
impl Protocol for BulkOnlyTransport {
fn send_command_block(&mut self, cb: &[u8]) {
todo!()
}
fn recv_command_block(&mut self, cb: &mut [u8]) {
todo!()
}
}
+12
View File
@@ -0,0 +1,12 @@
pub trait Protocol {
fn send_command_block(&mut self, cb: &[u8]);
fn recv_command_block(&mut self, cb: &mut [u8]);
}
/// Bulk-only transport
pub mod bot;
/// Control-Bulk-Interface transpoint
mod cbi {
// TODO
}
+8
View File
@@ -3,6 +3,14 @@ name = "xhcid"
version = "0.1.0"
edition = "2018"
[[bin]]
name = "xhcid"
path = "src/main.rs"
[lib]
name = "xhcid_interface"
path = "src/lib.rs"
[dependencies]
bitflags = "1"
plain = "0.2"
+1 -1
View File
@@ -2,4 +2,4 @@
name = "SCSI over USB"
class = 8 # Mass Storage class
subclass = 6 # SCSI transparent command set
command = ["usbscsid", "$SCHEME", "$PORT", "$IF_PROTO"]
command = ["/bin/usbscsid", "$SCHEME", "$PORT", "$IF_PROTO"]
+135
View File
@@ -0,0 +1,135 @@
pub extern crate serde;
pub extern crate smallvec;
use serde::{Deserialize, Serialize};
use smallvec::SmallVec;
use syscall::{Error, Result, EINVAL};
pub use crate::usb::{EndpointTy, ENDP_ATTR_TY_MASK};
#[derive(Serialize, Deserialize)]
pub struct ConfigureEndpointsReq {
/// Index into the configuration descriptors of the device descriptor.
pub config_desc: usize,
// TODO: Support multiple alternate interfaces as well.
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct DevDesc {
pub kind: u8,
pub usb: u16,
pub class: u8,
pub sub_class: u8,
pub protocol: u8,
pub packet_size: u8,
pub vendor: u16,
pub product: u16,
pub release: u16,
pub manufacturer_str: Option<String>,
pub product_str: Option<String>,
pub serial_str: Option<String>,
pub config_descs: SmallVec<[ConfDesc; 1]>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ConfDesc {
pub kind: u8,
pub configuration_value: u8,
pub configuration: Option<String>,
pub attributes: u8,
pub max_power: u8,
pub interface_descs: SmallVec<[IfDesc; 1]>,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct EndpDesc {
pub kind: u8,
pub address: u8,
pub attributes: u8,
pub max_packet_size: u16,
pub interval: u8,
pub ssc: Option<SuperSpeedCmp>,
}
pub enum EndpDirection {
Out,
In,
Bidirectional,
}
impl EndpDesc {
pub fn ty(self) -> EndpointTy {
match self.attributes & ENDP_ATTR_TY_MASK {
0 => EndpointTy::Ctrl,
1 => EndpointTy::Interrupt,
2 => EndpointTy::Bulk,
3 => EndpointTy::Isoch,
_ => unreachable!(),
}
}
pub fn is_control(&self) -> bool {
self.ty() == EndpointTy::Ctrl
}
pub fn is_interrupt(&self) -> bool {
self.ty() == EndpointTy::Interrupt
}
pub fn is_bulk(&self) -> bool {
self.ty() == EndpointTy::Bulk
}
pub fn is_isoch(&self) -> bool {
self.ty() == EndpointTy::Isoch
}
pub fn direction(&self) -> EndpDirection {
if self.is_control() {
return EndpDirection::Bidirectional;
}
if self.address & 0x80 != 0 {
EndpDirection::In
} else {
EndpDirection::Out
}
}
pub fn xhci_ep_type(&self) -> Result<u8> {
Ok(match self.direction() {
EndpDirection::Out if self.is_isoch() => 1,
EndpDirection::Out if self.is_bulk() => 2,
EndpDirection::Out if self.is_interrupt() => 3,
EndpDirection::Bidirectional if self.is_control() => 4,
EndpDirection::In if self.is_isoch() => 5,
EndpDirection::In if self.is_bulk() => 6,
EndpDirection::In if self.is_interrupt() => 7,
_ => return Err(Error::new(EINVAL)),
})
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct IfDesc {
pub kind: u8,
pub number: u8,
pub alternate_setting: u8,
pub class: u8,
pub sub_class: u8,
pub protocol: u8,
pub interface_str: Option<String>,
pub endpoints: SmallVec<[EndpDesc; 4]>,
pub hid_descs: SmallVec<[HidDesc; 1]>,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct SuperSpeedCmp {
pub kind: u8,
pub max_burst: u8,
pub attributes: u8,
pub bytes_per_interval: u16,
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
pub struct HidDesc {
pub kind: u8,
pub hid_spec_release: u16,
pub country: u8,
pub desc_count: u8,
pub desc_ty: u8,
pub desc_len: u16,
pub optional_desc_ty: u8,
pub optional_desc_len: u16,
}
+4
View File
@@ -0,0 +1,4 @@
mod driver_interface;
mod usb;
pub use driver_interface::*;
+75 -53
View File
@@ -6,18 +6,19 @@ extern crate syscall;
use event::{Event, EventQueue};
use std::cell::RefCell;
use std::{io, env};
use std::fs::File;
use std::io::{Result, Read, Write};
use std::io::{Read, Result, Write};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::sync::Arc;
use std::{env, io};
use syscall::data::Packet;
use syscall::flag::{CloneFlags, PHYSMAP_NO_CACHE, PHYSMAP_WRITE};
use syscall::error::EWOULDBLOCK;
use syscall::flag::{CloneFlags, PHYSMAP_NO_CACHE, PHYSMAP_WRITE};
use syscall::scheme::SchemeMut;
use crate::xhci::Xhci;
mod driver_interface;
mod usb;
mod xhci;
@@ -33,22 +34,38 @@ fn main() {
let irq_str = args.next().expect("xhcid: no IRQ provided");
let irq = irq_str.parse::<u8>().expect("xhcid: failed to parse irq");
print!("{}", format!(" + XHCI {} on: {:X} IRQ: {}\n", name, bar, irq));
print!(
"{}",
format!(" + XHCI {} on: {:X} IRQ: {}\n", name, bar, irq)
);
// Daemonize
if unsafe { syscall::clone(CloneFlags::empty()).unwrap() } == 0 {
let socket_fd = syscall::open(format!(":usb/{}", name), syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK).expect("xhcid: failed to create usb scheme");
let socket = Arc::new(RefCell::new(unsafe { File::from_raw_fd(socket_fd as RawFd) }));
let socket_fd = syscall::open(
format!(":usb/{}", name),
syscall::O_RDWR | syscall::O_CREAT | syscall::O_NONBLOCK,
)
.expect("xhcid: failed to create usb scheme");
let socket = Arc::new(RefCell::new(unsafe {
File::from_raw_fd(socket_fd as RawFd)
}));
let mut irq_file = File::open(format!("irq:{}", irq)).expect("xhcid: failed to open IRQ file");
let mut irq_file =
File::open(format!("irq:{}", irq)).expect("xhcid: failed to open IRQ file");
let address = unsafe { syscall::physmap(bar, 65536, PHYSMAP_WRITE | PHYSMAP_NO_CACHE).expect("xhcid: failed to map address") };
let address = unsafe {
syscall::physmap(bar, 65536, PHYSMAP_WRITE | PHYSMAP_NO_CACHE)
.expect("xhcid: failed to map address")
};
{
let hci = Arc::new(RefCell::new(Xhci::new(name, address).expect("xhcid: failed to allocate device")));
let hci = Arc::new(RefCell::new(
Xhci::new(name, address).expect("xhcid: failed to allocate device"),
));
hci.borrow_mut().probe().expect("xhcid: failed to probe");
let mut event_queue = EventQueue::<()>::new().expect("xhcid: failed to create event queue");
let mut event_queue =
EventQueue::<()>::new().expect("xhcid: failed to create event queue");
syscall::setrens(0, 0).expect("xhcid: failed to enter null namespace");
@@ -57,62 +74,67 @@ fn main() {
let hci_irq = hci.clone();
let socket_irq = socket.clone();
let todo_irq = todo.clone();
event_queue.add(irq_file.as_raw_fd(), move |_| -> Result<Option<()>> {
let mut irq = [0; 8];
irq_file.read(&mut irq)?;
event_queue
.add(irq_file.as_raw_fd(), move |_| -> Result<Option<()>> {
let mut irq = [0; 8];
irq_file.read(&mut irq)?;
if hci_irq.borrow_mut().trigger_irq() {
irq_file.write(&mut irq)?;
if hci_irq.borrow_mut().trigger_irq() {
irq_file.write(&mut irq)?;
let mut todo = todo_irq.borrow_mut();
let mut i = 0;
while i < todo.len() {
let a = todo[i].a;
hci_irq.borrow_mut().handle(&mut todo[i]);
if todo[i].a == (-EWOULDBLOCK) as usize {
todo[i].a = a;
i += 1;
} else {
socket_irq.borrow_mut().write(&mut todo[i])?;
todo.remove(i);
let mut todo = todo_irq.borrow_mut();
let mut i = 0;
while i < todo.len() {
let a = todo[i].a;
hci_irq.borrow_mut().handle(&mut todo[i]);
if todo[i].a == (-EWOULDBLOCK) as usize {
todo[i].a = a;
i += 1;
} else {
socket_irq.borrow_mut().write(&mut todo[i])?;
todo.remove(i);
}
}
}
}
Ok(None)
}).expect("xhcid: failed to catch events on IRQ file");
Ok(None)
})
.expect("xhcid: failed to catch events on IRQ file");
let socket_fd = socket.borrow().as_raw_fd();
let socket_packet = socket.clone();
event_queue.add(socket_fd, move |_| -> Result<Option<()>> {
loop {
let mut packet = Packet::default();
match socket_packet.borrow_mut().read(&mut packet) {
Ok(0) => break,
Err(err) if err.kind() == io::ErrorKind::WouldBlock => break,
Ok(_) => (),
Err(err) => return Err(err),
}
event_queue
.add(socket_fd, move |_| -> Result<Option<()>> {
loop {
let mut packet = Packet::default();
match socket_packet.borrow_mut().read(&mut packet) {
Ok(0) => break,
Err(err) if err.kind() == io::ErrorKind::WouldBlock => break,
Ok(_) => (),
Err(err) => return Err(err),
}
let a = packet.a;
hci.borrow_mut().handle(&mut packet);
if packet.a == (-EWOULDBLOCK) as usize {
packet.a = a;
todo.borrow_mut().push(packet);
} else {
socket_packet.borrow_mut().write(&mut packet)?;
let a = packet.a;
hci.borrow_mut().handle(&mut packet);
if packet.a == (-EWOULDBLOCK) as usize {
packet.a = a;
todo.borrow_mut().push(packet);
} else {
socket_packet.borrow_mut().write(&mut packet)?;
}
}
}
Ok(None)
}).expect("xhcid: failed to catch events on scheme file");
Ok(None)
})
.expect("xhcid: failed to catch events on scheme file");
event_queue.trigger_all(Event {
fd: 0,
flags: 0
}).expect("xhcid: failed to trigger events");
event_queue
.trigger_all(Event { fd: 0, flags: 0 })
.expect("xhcid: failed to trigger events");
event_queue.run().expect("xhcid: failed to handle events");
}
unsafe { let _ = syscall::physunmap(address); }
unsafe {
let _ = syscall::physunmap(address);
}
}
}
+10 -6
View File
@@ -57,9 +57,7 @@ pub struct BosDevDescIter<'a> {
}
impl<'a> BosDevDescIter<'a> {
pub fn new(bytes: &'a [u8]) -> Self {
Self {
bytes,
}
Self { bytes }
}
}
impl<'a> From<&'a [u8]> for BosDevDescIter<'a> {
@@ -72,7 +70,9 @@ impl<'a> Iterator for BosDevDescIter<'a> {
fn next(&mut self) -> Option<Self::Item> {
if let Some(desc) = plain::from_bytes::<BosDevDescriptorBase>(self.bytes).ok() {
if desc.len as usize > self.bytes.len() { return None };
if desc.len as usize > self.bytes.len() {
return None;
};
let bytes_ret = &self.bytes[..desc.len as usize];
self.bytes = &self.bytes[desc.len as usize..];
Some((*desc, bytes_ret))
@@ -129,6 +129,10 @@ impl<'a> Iterator for BosAnyDevDescIter<'a> {
}
}
pub fn bos_capability_descs<'a>(desc: BosDescriptor, data: &'a [u8]) -> impl Iterator<Item = BosAnyDevDesc> + 'a {
BosAnyDevDescIter::from(&data[..desc.total_len as usize - std::mem::size_of_val(&desc)]).take(desc.cap_count as usize)
pub fn bos_capability_descs<'a>(
desc: BosDescriptor,
data: &'a [u8],
) -> impl Iterator<Item = BosAnyDevDesc> + 'a {
BosAnyDevDescIter::from(&data[..desc.total_len as usize - std::mem::size_of_val(&desc)])
.take(desc.cap_count as usize)
}
+4 -2
View File
@@ -1,7 +1,9 @@
pub use self::bos::{BosDescriptor, BosAnyDevDesc, BosSuperSpeedDesc, bos_capability_descs};
pub use self::bos::{bos_capability_descs, BosAnyDevDesc, BosDescriptor, BosSuperSpeedDesc};
pub use self::config::ConfigDescriptor;
pub use self::device::DeviceDescriptor;
pub use self::endpoint::{EndpointDescriptor, HidDescriptor, SuperSpeedCompanionDescriptor, EndpointTy, ENDP_ATTR_TY_MASK};
pub use self::endpoint::{
EndpointDescriptor, EndpointTy, HidDescriptor, SuperSpeedCompanionDescriptor, ENDP_ATTR_TY_MASK,
};
pub use self::interface::InterfaceDescriptor;
pub use self::setup::Setup;
+6 -1
View File
@@ -108,7 +108,12 @@ impl Setup {
}
}
pub const fn get_descriptor(kind: DescriptorKind, index: u8, language: u16, length: u16) -> Self {
pub const fn get_descriptor(
kind: DescriptorKind,
index: u8,
language: u16,
length: u16,
) -> Self {
Self {
kind: 0b1000_0000,
request: 0x06,
+3 -2
View File
@@ -11,7 +11,7 @@ pub struct CapabilityRegs {
pub hcc_params1: Mmio<u32>,
pub db_offset: Mmio<u32>,
pub rts_offset: Mmio<u32>,
pub hcc_params2: Mmio<u32>
pub hcc_params2: Mmio<u32>,
}
pub const HCC_PARAMS1_MAXPSASIZE_MASK: u32 = 0xF000; // 15:12
@@ -28,6 +28,7 @@ impl CapabilityRegs {
self.hcc_params2.readf(HCC_PARAMS2_CIC_BIT)
}
pub fn max_psa_size(&self) -> u8 {
((self.hcc_params1.read() & HCC_PARAMS1_MAXPSASIZE_MASK) >> HCC_PARAMS1_MAXPSASIZE_SHIFT) as u8
((self.hcc_params1.read() & HCC_PARAMS1_MAXPSASIZE_MASK) >> HCC_PARAMS1_MAXPSASIZE_SHIFT)
as u8
}
}
-1
View File
@@ -1,6 +1,5 @@
use syscall::error::Result;
use super::event::EventRing;
use super::ring::Ring;
use super::trb::Trb;
+13 -3
View File
@@ -1,5 +1,5 @@
use syscall::error::Result;
use syscall::io::{Dma, Mmio, Io};
use syscall::io::{Dma, Io, Mmio};
#[repr(packed)]
pub struct SlotContext {
@@ -55,7 +55,17 @@ pub struct InputContext {
}
impl InputContext {
pub fn dump_control(&self) {
println!("INPUT CONTEXT: {} {} [{} {} {} {} {}] {}", self.drop_context.read(), self.add_context.read(), self._rsvd[0].read(), self._rsvd[1].read(), self._rsvd[2].read(), self._rsvd[3].read(), self._rsvd[4].read(), self.control.read());
println!(
"INPUT CONTEXT: {} {} [{} {} {} {} {}] {}",
self.drop_context.read(),
self.add_context.read(),
self._rsvd[0].read(),
self._rsvd[1].read(),
self._rsvd[2].read(),
self._rsvd[3].read(),
self._rsvd[4].read(),
self.control.read()
);
}
}
@@ -78,7 +88,7 @@ impl DeviceContextList {
Ok(DeviceContextList {
dcbaa: dcbaa,
contexts: contexts
contexts: contexts,
})
}
+76 -49
View File
@@ -1,11 +1,11 @@
use std::{mem, slice, process, sync::atomic, task};
use std::collections::BTreeMap;
use std::ffi::OsStr;
use std::pin::Pin;
use std::sync::{Arc, Mutex, Weak, atomic::AtomicBool};
use std::sync::{atomic::AtomicBool, Arc, Mutex, Weak};
use std::{mem, process, slice, sync::atomic, task};
use serde::Deserialize;
use syscall::error::{EBADF, EBADMSG, ENOENT, Error, Result};
use syscall::error::{Error, Result, EBADF, EBADMSG, ENOENT};
use syscall::io::{Dma, Io};
use crate::usb;
@@ -17,8 +17,8 @@ mod doorbell;
mod event;
mod operational;
mod port;
mod runtime;
mod ring;
mod runtime;
mod scheme;
mod trb;
@@ -29,9 +29,11 @@ use self::doorbell::Doorbell;
use self::operational::OperationalRegs;
use self::port::Port;
use self::ring::Ring;
use self::runtime::{RuntimeRegs, Interrupter};
use self::runtime::{Interrupter, RuntimeRegs};
use self::trb::{TransferKind, TrbCompletionCode, TrbType};
use crate::driver_interface::*;
struct Device<'a> {
ring: &'a mut Ring,
cmd: &'a mut CommandRing,
@@ -47,7 +49,8 @@ impl<'a> Device<'a> {
let (cmd, cycle) = self.ring.next();
cmd.setup(
usb::Setup::get_descriptor(kind, index, 0, len as u16),
TransferKind::In, cycle
TransferKind::In,
cycle,
);
}
@@ -75,45 +78,29 @@ impl<'a> Device<'a> {
fn get_device(&mut self) -> Result<usb::DeviceDescriptor> {
let mut desc = Dma::<usb::DeviceDescriptor>::zeroed()?;
self.get_desc(
usb::DescriptorKind::Device,
0,
&mut desc
);
self.get_desc(usb::DescriptorKind::Device, 0, &mut desc);
Ok(*desc)
}
fn get_config(&mut self, config: u8) -> Result<(usb::ConfigDescriptor, [u8; 4087])> {
let mut desc = Dma::<(usb::ConfigDescriptor, [u8; 4087])>::zeroed()?;
self.get_desc(
usb::DescriptorKind::Configuration,
config,
&mut desc
);
self.get_desc(usb::DescriptorKind::Configuration, config, &mut desc);
Ok(*desc)
}
fn get_bos(&mut self) -> Result<(usb::BosDescriptor, [u8; 4087])> {
let mut desc = Dma::<(usb::BosDescriptor, [u8; 4087])>::zeroed()?;
self.get_desc(
usb::DescriptorKind::BinaryObjectStorage,
0,
&mut desc,
);
self.get_desc(usb::DescriptorKind::BinaryObjectStorage, 0, &mut desc);
Ok(*desc)
}
fn get_string(&mut self, index: u8) -> Result<String> {
let mut sdesc = Dma::<(u8, u8, [u16; 127])>::zeroed()?;
self.get_desc(
usb::DescriptorKind::String,
index,
&mut sdesc
);
self.get_desc(usb::DescriptorKind::String, index, &mut sdesc);
let len = sdesc.0 as usize;
if len > 2 {
Ok(String::from_utf16(&sdesc.2[.. (len - 2)/2]).unwrap_or(String::new()))
Ok(String::from_utf16(&sdesc.2[..(len - 2) / 2]).unwrap_or(String::new()))
} else {
Ok(String::new())
}
@@ -150,7 +137,7 @@ pub struct Xhci {
struct PortState {
slot: u8,
input_context: Dma<InputContext>,
dev_desc: scheme::DevDesc,
dev_desc: DevDesc,
endpoint_states: BTreeMap<u8, EndpointState>,
}
@@ -197,7 +184,7 @@ impl Xhci {
println!(" - Wait for not running");
// Wait until controller not running
while ! op.usb_sts.readf(1) {
while !op.usb_sts.readf(1) {
println!(" - Waiting for XHCI stopped");
}
@@ -217,7 +204,8 @@ impl Xhci {
}
let port_base = op_base + 0x400;
let ports = unsafe { slice::from_raw_parts_mut(port_base as *mut Port, max_ports as usize) };
let ports =
unsafe { slice::from_raw_parts_mut(port_base as *mut Port, max_ports as usize) };
println!(" - PORT {:X}", port_base);
let db_base = address + cap.db_offset.read() as usize;
@@ -331,14 +319,12 @@ impl Xhci {
for i in 0..self.ports.len() {
let (data, state, speed, flags) = {
let port = &self.ports[i];
(
port.read(),
port.state(),
port.speed(),
port.flags(),
)
(port.read(), port.state(), port.speed(), port.flags())
};
println!(" + XHCI Port {}: {:X}, State {}, Speed {}, Flags {:?}", i, data, state, speed, flags);
println!(
" + XHCI Port {}: {:X}, State {}, Speed {}, Flags {:?}",
i, data, state, speed, flags
);
if flags.contains(port::PortFlags::PORT_CCS) {
//TODO: Link TRB when running to the end of the ring buffer
@@ -362,7 +348,9 @@ impl Xhci {
input.device.slot.b.write(((i as u32 + 1) & 0xFF) << 16);
// control endpoint?
input.device.endpoints[0].b.write(4096 << 16 | 4 << 3 | 3 << 1); // packet size | control endpoint | allowed error count
input.device.endpoints[0]
.b
.write(4096 << 16 | 4 << 3 | 3 << 1); // packet size | control endpoint | allowed error count
let tr = ring.register();
input.device.endpoints[0].trh.write((tr >> 32) as u32);
input.device.endpoints[0].trl.write(tr as u32);
@@ -379,7 +367,9 @@ impl Xhci {
println!(" - Waiting for event");
}
if event.completion_code() != TrbCompletionCode::Success as u8 || event.trb_type() != TrbType::CommandCompletion as u8 {
if event.completion_code() != TrbCompletionCode::Success as u8
|| event.trb_type() != TrbType::CommandCompletion as u8
{
panic!("ADDRESS DEVICE FAILED");
}
@@ -387,14 +377,24 @@ impl Xhci {
event.reserved(false);
}
let dev_desc = Self::get_dev_desc_raw(&mut self.ports, &mut self.run, &mut self.cmd, &mut self.dbs, i, slot, &mut ring)?;
let dev_desc = Self::get_dev_desc_raw(
&mut self.ports,
&mut self.run,
&mut self.cmd,
&mut self.dbs,
i,
slot,
&mut ring,
)?;
let mut port_state = PortState {
slot,
input_context: input,
dev_desc,
endpoint_states: std::iter::once((0, EndpointState::Ready(
RingOrStreams::Ring(ring),
))).collect::<BTreeMap<_, _>>(),
endpoint_states: std::iter::once((
0,
EndpointState::Ready(RingOrStreams::Ring(ring)),
))
.collect::<BTreeMap<_, _>>(),
};
match self.spawn_drivers(i, &mut port_state) {
@@ -431,7 +431,7 @@ impl Xhci {
}
pub(crate) fn irq(&self) -> IrqFuture {
IrqFuture {
state: IrqFutureState::Pending(Arc::downgrade(&self.irq_state))
state: IrqFutureState::Pending(Arc::downgrade(&self.irq_state)),
}
}
fn spawn_drivers(&mut self, port: usize, ps: &mut PortState) -> Result<()> {
@@ -440,16 +440,39 @@ impl Xhci {
// TODO: Now that there are some good error crates, I don't think errno.h error codes are
// suitable here.
let ifdesc = &ps.dev_desc.config_descs.first().ok_or(Error::new(EBADF))?.interface_descs.first().ok_or(Error::new(EBADF))?;
let ifdesc = &ps
.dev_desc
.config_descs
.first()
.ok_or(Error::new(EBADF))?
.interface_descs
.first()
.ok_or(Error::new(EBADF))?;
let drivers_usercfg: &DriversConfig = &DRIVERS_CONFIG;
if let Some(driver) = drivers_usercfg.drivers.iter().find(|driver| driver.class == ifdesc.class && driver.subclass == ifdesc.sub_class) {
if let Some(driver) = drivers_usercfg
.drivers
.iter()
.find(|driver| driver.class == ifdesc.class && driver.subclass == ifdesc.sub_class)
{
println!("Loading driver \"{}\"", driver.name);
let (command, args) = driver.command.split_first().ok_or(Error::new(EBADMSG))?;
let if_proto = ifdesc.protocol;
let process = process::Command::new(command).args(args.into_iter().map(|arg| arg.replace("$SCHEME", &self.scheme_name).replace("$PORT", &format!("{}", port)).replace("$IF_PROTO", &format!("{}", if_proto))).collect::<Vec<_>>()).stdin(process::Stdio::null()).spawn().or(Err(Error::new(ENOENT)))?;
let process = process::Command::new(command)
.args(
args.into_iter()
.map(|arg| {
arg.replace("$SCHEME", &self.scheme_name)
.replace("$PORT", &format!("{}", port))
.replace("$IF_PROTO", &format!("{}", if_proto))
})
.collect::<Vec<_>>(),
)
.stdin(process::Stdio::null())
.spawn()
.or(Err(Error::new(ENOENT)))?;
self.drivers.insert(port, process);
} else {
return Err(Error::new(ENOENT));
@@ -481,7 +504,9 @@ lazy_static! {
};
}
pub(crate) struct IrqFuture { state: IrqFutureState }
pub(crate) struct IrqFuture {
state: IrqFutureState,
}
struct IrqState {
triggered: AtomicBool,
@@ -503,7 +528,9 @@ impl std::future::Future for IrqFuture {
match &mut this.state {
// TODO: Ordering?
IrqFutureState::Pending(state_weak) => {
let state = state_weak.upgrade().expect("IRQ futures keep getting polled even after the driver has been deinitialized");
let state = state_weak.upgrade().expect(
"IRQ futures keep getting polled even after the driver has been deinitialized",
);
if state.triggered.load(atomic::Ordering::SeqCst) {
this.state = IrqFutureState::Finished;
+1 -1
View File
@@ -1,4 +1,4 @@
use syscall::io::{Mmio, Io};
use syscall::io::{Io, Mmio};
#[repr(packed)]
pub struct OperationalRegs {
+4 -4
View File
@@ -28,10 +28,10 @@ bitflags! {
#[repr(packed)]
pub struct Port {
pub portsc : Mmio<u32>,
pub portpmsc : Mmio<u32>,
pub portli : Mmio<u32>,
pub porthlpmc : Mmio<u32>,
pub portsc: Mmio<u32>,
pub portpmsc: Mmio<u32>,
pub portli: Mmio<u32>,
pub porthlpmc: Mmio<u32>,
}
impl Port {
+399 -307
View File
File diff suppressed because it is too large Load Diff
+39 -41
View File
@@ -1,6 +1,6 @@
use crate::usb;
use std::{fmt, mem};
use syscall::io::{Io, Mmio};
use crate::usb;
#[repr(u8)]
pub enum TrbType {
@@ -127,12 +127,7 @@ impl Trb {
}
pub fn reserved(&mut self, cycle: bool) {
self.set(
0,
0,
((TrbType::Reserved as u32) << 10) |
(cycle as u32)
);
self.set(0, 0, ((TrbType::Reserved as u32) << 10) | (cycle as u32));
}
pub fn completion_code(&self) -> u8 {
@@ -149,28 +144,21 @@ impl Trb {
self.set(
address as u64,
0,
((TrbType::Link as u32) << 10) |
((toggle as u32) << 1) |
(cycle as u32)
((TrbType::Link as u32) << 10) | ((toggle as u32) << 1) | (cycle as u32),
);
}
pub fn no_op_cmd(&mut self, cycle: bool) {
self.set(
0,
0,
((TrbType::NoOpCmd as u32) << 10) |
(cycle as u32)
);
self.set(0, 0, ((TrbType::NoOpCmd as u32) << 10) | (cycle as u32));
}
pub fn enable_slot(&mut self, slot_type: u8, cycle: bool) {
self.set(
0,
0,
(((slot_type as u32) & 0x1F) << 16) |
((TrbType::EnableSlot as u32) << 10) |
(cycle as u32)
(((slot_type as u32) & 0x1F) << 16)
| ((TrbType::EnableSlot as u32) << 10)
| (cycle as u32),
);
}
@@ -178,21 +166,23 @@ impl Trb {
self.set(
input as u64,
0,
((slot_id as u32) << 24) |
((TrbType::AddressDevice as u32) << 10) |
(cycle as u32)
((slot_id as u32) << 24) | ((TrbType::AddressDevice as u32) << 10) | (cycle as u32),
);
}
// Synchronizes the input context endpoints with the device context endpoints, I think.
pub fn configure_endpoint(&mut self, slot_id: u8, input_ctx_ptr: usize, cycle: bool) {
assert_eq!(input_ctx_ptr & 0xFFFF_FFFF_FFFF_FF80, input_ctx_ptr, "unaligned input context ptr");
assert_eq!(
input_ctx_ptr & 0xFFFF_FFFF_FFFF_FF80,
input_ctx_ptr,
"unaligned input context ptr"
);
self.set(
input_ctx_ptr as u64,
0,
(u32::from(slot_id) << 24) |
((TrbType::ConfigureEndpoint as u32) << 10) |
(cycle as u32),
(u32::from(slot_id) << 24)
| ((TrbType::ConfigureEndpoint as u32) << 10)
| (cycle as u32),
)
}
@@ -200,10 +190,10 @@ impl Trb {
self.set(
unsafe { mem::transmute(setup) },
8,
((transfer as u32) << 16) |
((TrbType::SetupStage as u32) << 10) |
(1 << 6) |
(cycle as u32)
((transfer as u32) << 16)
| ((TrbType::SetupStage as u32) << 10)
| (1 << 6)
| (cycle as u32),
);
}
@@ -211,9 +201,7 @@ impl Trb {
self.set(
buffer as u64,
length as u32,
((input as u32) << 16) |
((TrbType::DataStage as u32) << 10) |
(cycle as u32)
((input as u32) << 16) | ((TrbType::DataStage as u32) << 10) | (cycle as u32),
);
}
@@ -221,24 +209,34 @@ impl Trb {
self.set(
0,
0,
((input as u32) << 16) |
((TrbType::StatusStage as u32) << 10) |
(1 << 5) |
(cycle as u32)
((input as u32) << 16)
| ((TrbType::StatusStage as u32) << 10)
| (1 << 5)
| (cycle as u32),
);
}
}
impl fmt::Debug for Trb {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Trb {{ data: {:>016X}, status: {:>08X}, control: {:>08X} }}",
self.data.read(), self.status.read(), self.control.read())
write!(
f,
"Trb {{ data: {:>016X}, status: {:>08X}, control: {:>08X} }}",
self.data.read(),
self.status.read(),
self.control.read()
)
}
}
impl fmt::Display for Trb {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({:>016X}, {:>08X}, {:>08X})",
self.data.read(), self.status.read(), self.control.read())
write!(
f,
"({:>016X}, {:>08X}, {:>08X})",
self.data.read(),
self.status.read(),
self.control.read()
)
}
}