diff --git a/xhcid/src/main.rs b/xhcid/src/main.rs index 7cd01894d7..d85df737d9 100644 --- a/xhcid/src/main.rs +++ b/xhcid/src/main.rs @@ -22,6 +22,9 @@ //! - USB2 - [Universal Serial Bus Specification](https://www.usb.org/document-library/usb-20-specification) //! - USB32 - [Universal Serial Bus 3.2 Specification Revision 1.1](https://usb.org/document-library/usb-32-revision-11-june-2022) //! +#![allow(warnings)] +#![feature(generic_const_exprs)] + #[macro_use] extern crate bitflags; @@ -117,8 +120,11 @@ fn main() { redox_daemon::Daemon::new(daemon).expect("xhcid: failed to daemonize"); } -fn daemon(daemon: redox_daemon::Daemon) -> ! { - let mut pcid_handle = PciFunctionHandle::connect_default(); +//TODO: cleanup CSZ support +fn daemon_with_context_size( + daemon: redox_daemon::Daemon, + mut pcid_handle: PciFunctionHandle, +) -> ! { let pci_config = pcid_handle.config(); let mut name = pci_config.func.name(); @@ -147,7 +153,7 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { daemon.ready().expect("xhcid: failed to notify parent"); let hci = Arc::new( - Xhci::new(scheme_name, address, interrupt_method, pcid_handle) + Xhci::::new(scheme_name, address, interrupt_method, pcid_handle) .expect("xhcid: failed to allocate device"), ); @@ -179,3 +185,14 @@ fn daemon(daemon: redox_daemon::Daemon) -> ! { } } } + +fn daemon(daemon: redox_daemon::Daemon) -> ! { + let mut pcid_handle = PciFunctionHandle::connect_default(); + let address = unsafe { pcid_handle.map_bar(0) }.ptr.as_ptr() as usize; + let cap = unsafe { &mut *(address as *mut xhci::CapabilityRegs) }; + if cap.csz() { + daemon_with_context_size::<{ xhci::CONTEXT_64 }>(daemon, pcid_handle) + } else { + daemon_with_context_size::<{ xhci::CONTEXT_32 }>(daemon, pcid_handle) + } +} diff --git a/xhcid/src/xhci/capability.rs b/xhcid/src/xhci/capability.rs index cc45611c7d..2ad4ad1aa0 100644 --- a/xhcid/src/xhci/capability.rs +++ b/xhcid/src/xhci/capability.rs @@ -120,6 +120,10 @@ pub struct CapabilityRegs { pub const HCC_PARAMS1_AC64_BIT: u32 = 1 << HCC_PARAMS1_AC64_SHIFT; /// The shift to use to get the AC64 bit from HCCParams1. See [CapabilityRegs] pub const HCC_PARAMS1_AC64_SHIFT: u8 = 0; +/// The mask to use to get the CSZ bit from HCCPARAMS1. See [CapabilityRegs] +pub const HCC_PARAMS1_CSZ_BIT: u32 = 1 << HCC_PARAMS1_CSZ_SHIFT; +/// The shift to use to get the CSZ bit from HCCParams1. See [CapabilityRegs] +pub const HCC_PARAMS1_CSZ_SHIFT: u8 = 2; /// The Mask to use to get the MAXPSASIZE value from HCCParams1. See [CapabilityRegs] pub const HCC_PARAMS1_MAXPSASIZE_MASK: u32 = 0xF000; // 15:12 /// The shift to use to get the MAXPSASIZE value from HCCParams1. See [CapabilityRegs] @@ -161,6 +165,11 @@ impl CapabilityRegs { self.hcc_params1.readf(HCC_PARAMS1_AC64_BIT) } + /// Gets the context size (CSZ) bit from HCCParams1. + pub fn csz(&self) -> bool { + self.hcc_params1.readf(HCC_PARAMS1_CSZ_BIT) + } + /// Gets the LEC bit from HCCParams2. pub fn lec(&self) -> bool { self.hcc_params2.readf(HCC_PARAMS2_LEC_BIT) diff --git a/xhcid/src/xhci/context.rs b/xhcid/src/xhci/context.rs index 497a39dafe..b8f2f45a95 100644 --- a/xhcid/src/xhci/context.rs +++ b/xhcid/src/xhci/context.rs @@ -10,24 +10,25 @@ use common::dma::Dma; use super::ring::Ring; use super::Xhci; +pub const CONTEXT_32: usize = 0; +pub const CONTEXT_64: usize = 1; + #[repr(C, packed)] -pub struct SlotContext { +struct Rsvd64([[Mmio; 8]; N]); + +#[repr(C, packed)] +pub struct SlotContext { pub a: Mmio, pub b: Mmio, pub c: Mmio, pub d: Mmio, _rsvd: [Mmio; 4], + _rsvd64: Rsvd64, } pub const SLOT_CONTEXT_STATE_MASK: u32 = 0xF800_0000; pub const SLOT_CONTEXT_STATE_SHIFT: u8 = 27; -impl SlotContext { - pub fn state(&self) -> u8 { - ((self.d.read() & SLOT_CONTEXT_STATE_MASK) >> SLOT_CONTEXT_STATE_SHIFT) as u8 - } -} - #[repr(u8)] pub enum SlotState { EnabledOrDisabled = 0, @@ -37,32 +38,34 @@ pub enum SlotState { } #[repr(C, packed)] -pub struct EndpointContext { +pub struct EndpointContext { pub a: Mmio, pub b: Mmio, pub trl: Mmio, pub trh: Mmio, pub c: Mmio, _rsvd: [Mmio; 3], + _rsvd64: Rsvd64, } pub const ENDPOINT_CONTEXT_STATUS_MASK: u32 = 0x7; #[repr(C, packed)] -pub struct DeviceContext { - pub slot: SlotContext, - pub endpoints: [EndpointContext; 31], +pub struct DeviceContext { + pub slot: SlotContext, + pub endpoints: [EndpointContext; 31], } #[repr(C, packed)] -pub struct InputContext { +pub struct InputContext { pub drop_context: Mmio, pub add_context: Mmio, _rsvd: [Mmio; 5], pub control: Mmio, - pub device: DeviceContext, + _rsvd64: Rsvd64, + pub device: DeviceContext, } -impl InputContext { +impl InputContext { pub fn dump_control(&self) { debug!( "INPUT CONTEXT: {} {} [{} {} {} {} {}] {}", @@ -78,19 +81,19 @@ impl InputContext { } } -pub struct DeviceContextList { +pub struct DeviceContextList { pub dcbaa: Dma<[u64; 256]>, - pub contexts: Box<[Dma]>, + pub contexts: Box<[Dma>]>, } -impl DeviceContextList { - pub fn new(ac64: bool, max_slots: u8) -> Result { - let mut dcbaa = unsafe { Xhci::alloc_dma_zeroed_raw::<[u64; 256]>(ac64)? }; +impl DeviceContextList { + pub fn new(ac64: bool, max_slots: u8) -> Result { + let mut dcbaa = unsafe { Xhci::::alloc_dma_zeroed_raw::<[u64; 256]>(ac64)? }; let mut contexts = vec![]; // Create device context buffers for each slot for i in 0..max_slots as usize { - let context: Dma = unsafe { Xhci::alloc_dma_zeroed_raw(ac64) }?; + let context: Dma> = unsafe { Xhci::::alloc_dma_zeroed_raw(ac64) }?; dcbaa[i] = context.physical() as u64; contexts.push(context); } @@ -134,19 +137,24 @@ pub struct StreamContextArray { } impl StreamContextArray { - pub fn new(ac64: bool, count: usize) -> Result { + pub fn new(ac64: bool, count: usize) -> Result { unsafe { Ok(Self { - contexts: Xhci::alloc_dma_zeroed_unsized_raw(ac64, count)?, + contexts: Xhci::::alloc_dma_zeroed_unsized_raw(ac64, count)?, rings: BTreeMap::new(), }) } } - pub fn add_ring(&mut self, ac64: bool, stream_id: u16, link: bool) -> Result<()> { + pub fn add_ring( + &mut self, + ac64: bool, + stream_id: u16, + link: bool, + ) -> Result<()> { // NOTE: stream_id 0 is reserved assert_ne!(stream_id, 0); - let ring = Ring::new(ac64, 16, link)?; + let ring = Ring::new::(ac64, 16, link)?; let pointer = ring.register(); let sct = StreamContextType::PrimaryRing; @@ -182,8 +190,9 @@ pub struct ScratchpadBufferArray { pub pages: Vec>, } impl ScratchpadBufferArray { - pub fn new(ac64: bool, entries: u16) -> Result { - let mut entries = unsafe { Xhci::alloc_dma_zeroed_unsized_raw(ac64, entries as usize)? }; + pub fn new(ac64: bool, entries: u16) -> Result { + let mut entries = + unsafe { Xhci::::alloc_dma_zeroed_unsized_raw(ac64, entries as usize)? }; let pages = entries .iter_mut() @@ -203,3 +212,17 @@ impl ScratchpadBufferArray { self.entries.physical() } } + +#[cfg(test)] +mod test { + use super::*; + use core::mem; + + #[test] + fn context_size() { + assert_eq!(mem::size_of::>(), 32); + assert_eq!(mem::size_of::>(), 64); + assert_eq!(mem::size_of::>(), 32); + assert_eq!(mem::size_of::>(), 64); + } +} diff --git a/xhcid/src/xhci/device_enumerator.rs b/xhcid/src/xhci/device_enumerator.rs index f33f420c90..a48900c226 100644 --- a/xhcid/src/xhci/device_enumerator.rs +++ b/xhcid/src/xhci/device_enumerator.rs @@ -11,13 +11,13 @@ pub struct DeviceEnumerationRequest { pub port_id: PortId, } -pub struct DeviceEnumerator { - hci: Arc, +pub struct DeviceEnumerator { + hci: Arc>, request_queue: crossbeam_channel::Receiver, } -impl DeviceEnumerator { - pub fn new(hci: Arc) -> Self { +impl DeviceEnumerator { + pub fn new(hci: Arc>) -> Self { let request_queue = hci.device_enumerator_receiver.clone(); DeviceEnumerator { hci, request_queue } } diff --git a/xhcid/src/xhci/event.rs b/xhcid/src/xhci/event.rs index 47c370ccff..83af1209af 100644 --- a/xhcid/src/xhci/event.rs +++ b/xhcid/src/xhci/event.rs @@ -23,10 +23,10 @@ pub struct EventRing { } impl EventRing { - pub fn new(ac64: bool) -> Result { + pub fn new(ac64: bool) -> Result { let mut ring = EventRing { - ste: unsafe { Xhci::alloc_dma_zeroed_unsized_raw(ac64, 1)? }, - ring: Ring::new(ac64, 256, false)?, + ste: unsafe { Xhci::::alloc_dma_zeroed_unsized_raw(ac64, 1)? }, + ring: Ring::new::(ac64, 256, false)?, }; ring.ste[0] diff --git a/xhcid/src/xhci/irq_reactor.rs b/xhcid/src/xhci/irq_reactor.rs index 8215f06034..ac492d5bc1 100644 --- a/xhcid/src/xhci/irq_reactor.rs +++ b/xhcid/src/xhci/irq_reactor.rs @@ -92,8 +92,8 @@ impl StateKind { } } -pub struct IrqReactor { - hci: Arc, +pub struct IrqReactor { + hci: Arc>, irq_file: Option, irq_receiver: Receiver, device_enumerator_sender: Sender, @@ -104,8 +104,8 @@ pub struct IrqReactor { pub type NewPendingTrb = State; -impl IrqReactor { - pub fn new(hci: Arc, irq_file: Option) -> Self { +impl IrqReactor { + pub fn new(hci: Arc>, irq_file: Option) -> Self { let device_enumerator_sender = hci.device_enumerator_sender.clone(); let irq_receiver = hci.irq_reactor_receiver.clone(); @@ -559,7 +559,7 @@ pub struct EventDoorbell { } impl EventDoorbell { - pub fn new(hci: &Xhci, index: usize, data: u32) -> Self { + pub fn new(hci: &Xhci, index: usize, data: u32) -> Self { Self { //TODO: simplify this logic, maybe just use a raw pointer? dbs: hci.dbs.clone(), @@ -625,7 +625,7 @@ impl Future for EventTrbFuture { } } -impl Xhci { +impl Xhci { pub fn get_transfer_trb(&self, paddr: u64, id: RingId) -> Option { self.with_ring(id, |ring| ring.phys_addr_to_entry(self.cap.ac64(), paddr)) .flatten() diff --git a/xhcid/src/xhci/mod.rs b/xhcid/src/xhci/mod.rs index fe633432db..aea7439397 100644 --- a/xhcid/src/xhci/mod.rs +++ b/xhcid/src/xhci/mod.rs @@ -43,8 +43,12 @@ mod runtime; pub mod scheme; mod trb; -use self::capability::CapabilityRegs; -use self::context::{DeviceContextList, InputContext, ScratchpadBufferArray, StreamContextArray}; +pub use self::capability::CapabilityRegs; +use self::context::{ + DeviceContextList, InputContext, ScratchpadBufferArray, StreamContextArray, + SLOT_CONTEXT_STATE_MASK, SLOT_CONTEXT_STATE_SHIFT, +}; +pub use self::context::{CONTEXT_32, CONTEXT_64}; use self::doorbell::Doorbell; use self::event::EventRing; use self::extended::{CapabilityId, ExtendedCapabilitiesIter, ProtocolSpeed, SupportedProtoCap}; @@ -73,7 +77,7 @@ pub enum InterruptMethod { Msi, } -impl Xhci { +impl Xhci { /// Gets descriptors, before the port state is initiated. async fn get_desc_raw( &self, @@ -246,7 +250,7 @@ impl Xhci { } /// The eXtensible Host Controller Interface (XHCI) data structure -pub struct Xhci { +pub struct Xhci { // immutable /// The Host Controller Interface Capability Registers. These read-only registers specify the /// limits and capabilities of the host controller implementation (See XHCI section 5.3) @@ -270,7 +274,7 @@ pub struct Xhci { primary_event_ring: Mutex, // immutable - dev_ctx: DeviceContextList, + dev_ctx: DeviceContextList, scratchpad_buf_arr: Option, // used for the extended capabilities, and so far none of them are mutated, and thus no lock. @@ -278,7 +282,7 @@ pub struct Xhci { handles: CHashMap, next_handle: AtomicUsize, - port_states: CHashMap, + port_states: CHashMap>, drivers: CHashMap>, scheme_name: String, @@ -297,19 +301,19 @@ pub struct Xhci { device_enumerator_receiver: Receiver, } -unsafe impl Send for Xhci {} -unsafe impl Sync for Xhci {} +unsafe impl Send for Xhci {} +unsafe impl Sync for Xhci {} -struct PortState { +struct PortState { slot: u8, protocol_speed: &'static ProtocolSpeed, cfg_idx: Option, - input_context: Mutex>, + input_context: Mutex>>, dev_desc: Option, endpoint_states: BTreeMap, } -impl PortState { +impl PortState { //TODO: fetch using endpoint number instead fn get_endp_desc(&self, endp_idx: u8) -> Option<&EndpDesc> { let cfg_idx = self.cfg_idx?; @@ -350,13 +354,13 @@ impl EndpointState { } } -impl Xhci { +impl Xhci { pub fn new( scheme_name: String, address: usize, interrupt_method: InterruptMethod, pcid_handle: PciFunctionHandle, - ) -> Result { + ) -> Result { //Locate the capability registers from the mapped PCI Bar let cap = unsafe { &mut *(address as *mut CapabilityRegs) }; debug!("CAP REGS BASE {:X}", address); @@ -419,7 +423,7 @@ impl Xhci { // Create the command ring with 4096 / 16 (TRB size) entries, so that it uses all of the // DMA allocation (which is at least a 4k page). let entries_per_page = PAGE_SIZE / mem::size_of::(); - let cmd = Ring::new(cap.ac64(), entries_per_page, true)?; + let cmd = Ring::new::(cap.ac64(), entries_per_page, true)?; let (irq_reactor_sender, irq_reactor_receiver) = crossbeam_channel::unbounded(); @@ -439,7 +443,7 @@ impl Xhci { scratchpad_buf_arr: None, // initialized in init() cmd: Mutex::new(cmd), - primary_event_ring: Mutex::new(EventRing::new(cap.ac64())?), + primary_event_ring: Mutex::new(EventRing::new::(cap.ac64())?), handles: CHashMap::new(), next_handle: AtomicUsize::new(0), port_states: CHashMap::new(), @@ -469,7 +473,11 @@ impl Xhci { // Warm reset debug!("Reset xHC"); - self.op.get_mut().unwrap().usb_cmd.writef(USB_CMD_HCRST, true); + self.op + .get_mut() + .unwrap() + .usb_cmd + .writef(USB_CMD_HCRST, true); while self.op.get_mut().unwrap().usb_cmd.readf(USB_CMD_HCRST) { thread::yield_now(); } @@ -531,7 +539,11 @@ impl Xhci { debug!("Enabling Primary Interrupter."); int.iman.writef(1 << 1 | 1, true); } - self.op.get_mut().unwrap().usb_cmd.writef(USB_CMD_INTE, true); + self.op + .get_mut() + .unwrap() + .usb_cmd + .writef(USB_CMD_INTE, true); // Setup the scratchpad buffers that are required for the xHC to function. self.setup_scratchpads()?; @@ -674,7 +686,7 @@ impl Xhci { if buf_count == 0 { return Ok(()); } - let scratchpad_buf_arr = ScratchpadBufferArray::new(self.cap.ac64(), buf_count)?; + let scratchpad_buf_arr = ScratchpadBufferArray::new::(self.cap.ac64(), buf_count)?; self.dev_ctx.dcbaa[0] = scratchpad_buf_arr.register() as u64; debug!( "Setting up {} scratchpads, at {:#0x}", @@ -733,7 +745,8 @@ impl Xhci { } pub fn slot_state(&self, slot: usize) -> u8 { - self.dev_ctx.contexts[slot].slot.state() + ((self.dev_ctx.contexts[slot].slot.d.read() & SLOT_CONTEXT_STATE_MASK) + >> SLOT_CONTEXT_STATE_SHIFT) as u8 } pub unsafe fn alloc_dma_zeroed_raw(_ac64: bool) -> Result> { // TODO: ac64 @@ -792,7 +805,7 @@ impl Xhci { .lookup_psiv(port_id, speed) .expect("Failed to retrieve speed ID"); - let mut input = unsafe { self.alloc_dma_zeroed::()? }; + let mut input = unsafe { self.alloc_dma_zeroed::>()? }; info!("Attempting to address the device"); let mut ring = match self @@ -940,7 +953,7 @@ impl Xhci { pub async fn update_max_packet_size( &self, - input_context: &mut Dma, + input_context: &mut Dma>, slot_id: u8, dev_desc: usb::DeviceDescriptor8Byte, ) -> Result<()> { @@ -951,11 +964,10 @@ impl Xhci { // For later USB versions, packet_size is the shift 1u32 << dev_desc.packet_size }; - let endp_ctx = &mut input_context.device.endpoints[0]; - let mut b = endp_ctx.b.read(); + let mut b = input_context.device.endpoints[0].b.read(); b &= 0x0000_FFFF; b |= (new_max_packet_size) << 16; - endp_ctx.b.write(b); + input_context.device.endpoints[0].b.write(b); let (event_trb, command_trb) = self .execute_command(|trb, cycle| { @@ -971,7 +983,7 @@ impl Xhci { pub async fn update_default_control_pipe( &self, - input_context: &mut Dma, + input_context: &mut Dma>, slot_id: u8, dev_desc: &DevDesc, ) -> Result<()> { @@ -986,11 +998,10 @@ impl Xhci { // For later USB versions, packet_size is the shift 1u32 << dev_desc.packet_size }; - let endp_ctx = &mut input_context.device.endpoints[0]; - let mut b = endp_ctx.b.read(); + let mut b = input_context.device.endpoints[0].b.read(); b &= 0x0000_FFFF; b |= (new_max_packet_size) << 16; - endp_ctx.b.write(b); + input_context.device.endpoints[0].b.write(b); let (event_trb, command_trb) = self .execute_command(|trb, cycle| { @@ -1007,7 +1018,7 @@ impl Xhci { pub async fn address_device( &self, - input_context: &mut Dma, + input_context: &mut Dma>, port: PortId, slot_ty: u8, slot: u8, @@ -1044,19 +1055,17 @@ impl Xhci { } } - let mut ring = Ring::new(self.cap.ac64(), 16, true)?; + let mut ring = Ring::new::(self.cap.ac64(), 16, true)?; { input_context.add_context.write(1 << 1 | 1); // Enable the slot (zeroth bit) and the control endpoint (first bit). - let slot_ctx = &mut input_context.device.slot; - let route_string = port.route_string; let context_entries = 1u8; let hub = false; assert_eq!(route_string & 0x000F_FFFF, route_string); - slot_ctx.a.write( + input_context.device.slot.a.write( route_string | (u32::from(speed) << 20) | (u32::from(mtt) << 25) @@ -1067,7 +1076,7 @@ impl Xhci { let max_exit_latency = 0u16; let root_hub_port_num = port.root_hub_port_num; let number_of_ports = 0u8; - slot_ctx.b.write( + input_context.device.slot.b.write( u32::from(max_exit_latency) | (u32::from(root_hub_port_num) << 16) | (u32::from(number_of_ports) << 24), @@ -1078,29 +1087,28 @@ impl Xhci { let interrupter = 0u8; assert_eq!(ttt & 0b11, ttt); - slot_ctx.c.write( + input_context.device.slot.c.write( u32::from(parent_hub_slot_id) | (u32::from(parent_port_num) << 8) | (u32::from(ttt) << 16) | (u32::from(interrupter) << 22), ); - let endp_ctx = &mut input_context.device.endpoints[0]; - let max_error_count = 3u8; // recommended value according to the XHCI spec let ep_ty = 4u8; // control endpoint, bidirectional - let max_packet_size: u32 = if protocol_speed.is_lowspeed() || protocol_speed.is_fullspeed() { - 8 - } else if protocol_speed.is_highspeed() { - 64 - } else { - 512 - }; + let max_packet_size: u32 = + if protocol_speed.is_lowspeed() || protocol_speed.is_fullspeed() { + 8 + } else if protocol_speed.is_highspeed() { + 64 + } else { + 512 + }; let host_initiate_disable = false; // only applies to streams let max_burst_size = 0u8; // TODO assert_eq!(max_error_count & 0b11, max_error_count); - endp_ctx.b.write( + input_context.device.endpoints[0].b.write( (u32::from(max_error_count) << 1) | (u32::from(ep_ty) << 3) | (u32::from(host_initiate_disable) << 7) @@ -1110,12 +1118,18 @@ impl Xhci { let dequeue_cycle_state = true; let tr = ring.register(); - endp_ctx.trh.write((tr >> 32) as u32); - endp_ctx.trl.write((tr as u32) | u32::from(dequeue_cycle_state)); + input_context.device.endpoints[0] + .trh + .write((tr >> 32) as u32); + input_context.device.endpoints[0] + .trl + .write((tr as u32) | u32::from(dequeue_cycle_state)); // The default control pipe can always use 8 bytes let avg_trb_len = 8u8; - endp_ctx.c.write(u32::from(avg_trb_len)); + input_context.device.endpoints[0] + .c + .write(u32::from(avg_trb_len)); } let input_context_physical = input_context.physical(); @@ -1394,7 +1408,7 @@ impl Xhci { .find(|speed| speed.psiv() == psiv) } } -pub fn start_irq_reactor(hci: &Arc, irq_file: Option) { +pub fn start_irq_reactor(hci: &Arc>, irq_file: Option) { let hci_clone = Arc::clone(&hci); debug!("About to start IRQ reactor"); @@ -1405,7 +1419,7 @@ pub fn start_irq_reactor(hci: &Arc, irq_file: Option) { })); } -pub fn start_device_enumerator(hci: &Arc) { +pub fn start_device_enumerator(hci: &Arc>) { let hci_clone = Arc::clone(&hci); debug!("About to start Device Enumerator"); diff --git a/xhcid/src/xhci/ring.rs b/xhcid/src/xhci/ring.rs index e0e76d5228..8e187ebea4 100644 --- a/xhcid/src/xhci/ring.rs +++ b/xhcid/src/xhci/ring.rs @@ -15,10 +15,10 @@ pub struct Ring { } impl Ring { - pub fn new(ac64: bool, length: usize, link: bool) -> Result { + pub fn new(ac64: bool, length: usize, link: bool) -> Result { Ok(Ring { link, - trbs: unsafe { Xhci::alloc_dma_zeroed_unsized_raw(ac64, length)? }, + trbs: unsafe { Xhci::::alloc_dma_zeroed_unsized_raw(ac64, length)? }, i: 0, cycle: link, }) diff --git a/xhcid/src/xhci/scheme.rs b/xhcid/src/xhci/scheme.rs index 12d77d39e3..1b92fa51aa 100644 --- a/xhcid/src/xhci/scheme.rs +++ b/xhcid/src/xhci/scheme.rs @@ -40,7 +40,10 @@ use syscall::{ use super::{port, usb}; use super::{EndpointState, PortId, Xhci}; -use super::context::{SlotState, StreamContextArray, StreamContextType}; +use super::context::{ + SlotState, StreamContextArray, StreamContextType, CONTEXT_32, CONTEXT_64, + SLOT_CONTEXT_STATE_MASK, SLOT_CONTEXT_STATE_SHIFT, +}; use super::extended::ProtocolSpeed; use super::irq_reactor::{EventDoorbell, RingId}; use super::ring::Ring; @@ -543,7 +546,7 @@ impl AnyDescriptor { } } -impl Xhci { +impl Xhci { async fn new_if_desc( &self, port_id: PortId, @@ -927,13 +930,13 @@ impl Xhci { fn port_state( &self, port: PortId, - ) -> Result> { + ) -> Result>> { self.port_states.get(&port).ok_or(Error::new(EBADF)) } fn port_state_mut( &self, port: PortId, - ) -> Result> { + ) -> Result>> { self.port_states.get_mut(&port).ok_or(Error::new(EBADF)) } @@ -1103,10 +1106,10 @@ impl Xhci { let ring_ptr = if usb_log_max_streams.is_some() { let mut array = - StreamContextArray::new(self.cap.ac64(), 1 << (primary_streams + 1))?; + StreamContextArray::new::(self.cap.ac64(), 1 << (primary_streams + 1))?; // TODO: Use as many stream rings as needed. - array.add_ring(self.cap.ac64(), 1, true)?; + array.add_ring::(self.cap.ac64(), 1, true)?; let array_ptr = array.register(); assert_eq!( @@ -1124,7 +1127,7 @@ impl Xhci { array_ptr } else { - let ring = Ring::new(self.cap.ac64(), 16, true)?; + let ring = Ring::new::(self.cap.ac64(), 16, true)?; let ring_ptr = ring.register(); assert_eq!( @@ -1146,23 +1149,15 @@ impl Xhci { let mut input_context = port_state.input_context.lock().unwrap(); input_context.add_context.writef(1 << endp_num_xhc, true); - let endp_ctx = input_context - .device - .endpoints - .get_mut(endp_num_xhc as usize - 1) - .ok_or_else(|| { - warn!("failed to find endpoint {}", endp_num_xhc - 1); - Error::new(EIO) - })?; - - endp_ctx.a.write( + let endp_i = endp_num_xhc as usize - 1; + input_context.device.endpoints[endp_i].a.write( u32::from(mult) << 8 | u32::from(primary_streams) << 10 | u32::from(linear_stream_array) << 15 | u32::from(interval) << 16 | u32::from(max_esit_payload_hi) << 24, ); - endp_ctx.b.write( + input_context.device.endpoints[endp_i].b.write( max_error_count << 1 | u32::from(ep_ty) << 3 | u32::from(host_initiate_disable) << 7 @@ -1170,10 +1165,14 @@ impl Xhci { | u32::from(max_packet_size) << 16, ); - endp_ctx.trl.write(ring_ptr as u32); - endp_ctx.trh.write((ring_ptr >> 32) as u32); + input_context.device.endpoints[endp_i] + .trl + .write(ring_ptr as u32); + input_context.device.endpoints[endp_i] + .trh + .write((ring_ptr >> 32) as u32); - endp_ctx + input_context.device.endpoints[endp_i] .c .write(u32::from(avg_trb_len) | (u32::from(max_esit_payload_lo) << 16)); @@ -2099,7 +2098,7 @@ impl Xhci { } } -impl SchemeSync for &Xhci { +impl SchemeSync for &Xhci { fn open(&mut self, path_str: &str, flags: usize, ctx: &CallerCtx) -> Result { if ctx.uid != 0 { return Err(Error::new(EACCES)); @@ -2237,13 +2236,13 @@ impl SchemeSync for &Xhci { }, &mut Handle::PortState(port_num) => { let ps = self.port_states.get(&port_num).ok_or(Error::new(EBADF))?; - let state = self + let ctx = self .dev_ctx .contexts .get(ps.slot as usize) - .ok_or(Error::new(EBADF))? - .slot - .state(); + .ok_or(Error::new(EBADF))?; + let state = ((ctx.slot.d.read() & SLOT_CONTEXT_STATE_MASK) + >> SLOT_CONTEXT_STATE_SHIFT) as u8; let string = match state { 0 => Some(PortState::EnabledOrDisabled), @@ -2257,7 +2256,7 @@ impl SchemeSync for &Xhci { .unwrap_or("unknown") .as_bytes(); - Ok(Xhci::write_dyn_string(string, buf, offset)) + Ok(Xhci::::write_dyn_string(string, buf, offset)) } &mut Handle::PortReq(port_num, ref mut st) => { let state = std::mem::replace(st, PortReqState::Tmp); @@ -2316,7 +2315,7 @@ impl SchemeSync for &Xhci { } } } -impl Xhci { +impl Xhci { pub fn on_close(&self, fd: usize) { self.handles.remove(&fd); } @@ -2351,9 +2350,7 @@ impl Xhci { .contexts .get(slot as usize) .ok_or(Error::new(EBADFD))? - .endpoints - .get(endp_num_xhc as usize - 1) - .ok_or(Error::new(EBADFD))? + .endpoints[endp_num_xhc as usize - 1] .a .read() & super::context::ENDPOINT_CONTEXT_STATUS_MASK;