From 0b950987484c39d44e144b9c20765fd5cea6114a Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Fri, 5 Dec 2025 21:15:00 -0800 Subject: [PATCH] Rust XHCI Data Structure Types. --- rust/Cargo.lock | 17 +- rust/sys/voyageurs/Cargo.toml | 2 +- .../xhci/data_structures/endpoint_context.rs | 228 ++++++++++++++++++ .../event_ring_segment_table.rs | 62 +++++ .../voyageurs/src/xhci/data_structures/mod.rs | 8 + .../src/xhci/data_structures/slot_context.rs | 133 ++++++++++ .../src/xhci/data_structures/trb_ring.rs | 113 +++++++++ rust/sys/voyageurs/src/xhci/mod.rs | 1 + 8 files changed, 560 insertions(+), 4 deletions(-) create mode 100644 rust/sys/voyageurs/src/xhci/data_structures/endpoint_context.rs create mode 100644 rust/sys/voyageurs/src/xhci/data_structures/event_ring_segment_table.rs create mode 100644 rust/sys/voyageurs/src/xhci/data_structures/mod.rs create mode 100644 rust/sys/voyageurs/src/xhci/data_structures/slot_context.rs create mode 100644 rust/sys/voyageurs/src/xhci/data_structures/trb_ring.rs diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 35fccae..aec4469 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -19,6 +19,17 @@ dependencies = [ "syn", ] +[[package]] +name = "bitfield-struct" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8769c4854c5ada2852ddf6fd09d15cf43d4c2aaeccb4de6432f5402f08a6003b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "convert_case" version = "0.6.0" @@ -32,7 +43,7 @@ dependencies = [ name = "denali" version = "0.1.0" dependencies = [ - "bitfield-struct", + "bitfield-struct 0.8.0", "mammoth", "pci", "yellowstone-yunq", @@ -88,7 +99,7 @@ dependencies = [ name = "pci" version = "0.1.0" dependencies = [ - "bitfield-struct", + "bitfield-struct 0.8.0", "mammoth", ] @@ -193,7 +204,7 @@ dependencies = [ name = "voyageurs" version = "0.1.0" dependencies = [ - "bitfield-struct", + "bitfield-struct 0.12.1", "mammoth", ] diff --git a/rust/sys/voyageurs/Cargo.toml b/rust/sys/voyageurs/Cargo.toml index 492a285..084d083 100644 --- a/rust/sys/voyageurs/Cargo.toml +++ b/rust/sys/voyageurs/Cargo.toml @@ -4,5 +4,5 @@ version = "0.1.0" edition = "2024" [dependencies] -bitfield-struct = "0.8.0" +bitfield-struct = "0.12" mammoth = { path = "../../lib/mammoth/" } diff --git a/rust/sys/voyageurs/src/xhci/data_structures/endpoint_context.rs b/rust/sys/voyageurs/src/xhci/data_structures/endpoint_context.rs new file mode 100644 index 0000000..0c62428 --- /dev/null +++ b/rust/sys/voyageurs/src/xhci/data_structures/endpoint_context.rs @@ -0,0 +1,228 @@ +use bitfield_struct::bitfield; + +#[derive(Debug)] +#[repr(u8)] +pub enum EndpointState { + /// The endpoint is not operationa. + Disabled = 0, + /// The endpoint is operational, either waiting for a doorbell ring or processing TDs. + Running = 1, + /// The endpoint is halted due to a Halt condition detected on the USB. SW shall issue + /// Reset Endpoint Command to recover from the Halt condition and transition to the Stopped + /// state. SW may manipulate the Transfer Ring while in this state + Halted = 2, + /// The endpoint is not running due to a Stop Endpoint Command or recovering + /// from a Halt condition. SW may manipulate the Transfer Ring while in this state. + Stopped = 3, + /// The endpoint is not running due to a TRB Error. SW may manipulate the Transfer + /// Ring while in this state. + Error = 4, + Unknown = 5, +} + +impl EndpointState { + const fn from_bits(value: u8) -> Self { + match value { + 0 => Self::Disabled, + 1 => Self::Running, + 2 => Self::Halted, + 3 => Self::Stopped, + 4 => Self::Error, + _ => Self::Unknown, + } + } + + const fn into_bits(self) -> u8 { + self as u8 + } +} + +#[derive(Debug)] +#[repr(u8)] +pub enum EndpointType { + NotValid = 0, + IsochOut = 1, + BulkOut = 2, + InterruptOut = 3, + Control = 4, + IsochIn = 5, + BulkIn = 6, + InterruptIn = 7, +} + +impl EndpointType { + const fn from_bits(value: u8) -> Self { + match value { + 0 => Self::NotValid, + 1 => Self::IsochOut, + 2 => Self::BulkOut, + 3 => Self::InterruptOut, + 4 => Self::Control, + 5 => Self::IsochIn, + 6 => Self::BulkIn, + 7 => Self::InterruptIn, + _ => Self::NotValid, + } + } + + const fn into_bits(self) -> u8 { + self as u8 + } +} + +#[bitfield(u64)] +pub struct EndpointContextFields { + /// Endpoint State (EP State). The Endpoint State identifies the current operational state of the + /// endpoint. + /// + /// As Output, a Running to Halted transition is forced by the xHC if a STALL condition is detected + /// on the endpoint. A Running to Error transition is forced by the xHC if a TRB Error condition is + /// detected. + /// + /// As Input, this field is initialized to ‘0’ by software. + /// + /// Refer to section 4.8.3 for more information on Endpoint State. + #[bits(3)] + pub endpoint_state: EndpointState, + #[bits(5)] + __: u8, + /// Mult. If LEC = ‘0’, then this field indicates the maximum number of bursts within an Interval that + /// this endpoint supports. Mult is a “zero-based” value, where 0 to 3 represents 1 to 4 bursts, + /// respectively. The valid range of values is ‘0’ to ‘2’.111 This field shall be ‘0’ for all endpoint types + /// except for SS Isochronous. + /// + /// If LEC = ‘1’, then this field shall be RsvdZ and Mult is calculated as: + /// ROUNDUP(Max ESIT Payload / Max Packet Size / (Max Burst Size + 1)) - 1 + #[bits(2)] + pub mult: u8, + /// Max Primary Streams (MaxPStreams). This field identifies the maximum number of Primary + /// Stream IDs this endpoint supports. Valid values are defined below. If the value of this field is ‘0’, + /// then the TR Dequeue Pointer field shall point to a Transfer Ring. If this field is > '0' then the TR + /// Dequeue Pointer field shall point to a Primary Stream Context Array. Refer to section 4.12 for + /// more information. + /// + /// A value of ‘0’ indicates that Streams are not supported by this endpoint and the Endpoint + /// Context TR Dequeue Pointer field references a Transfer Ring. + /// + /// A value of ‘1’ to ‘15’ indicates that the Primary Stream ID Width is MaxPstreams+1 and the + /// Primary Stream Array contains 2MaxPStreams+1 entries. + /// + /// For SS Bulk endpoints, the range of valid values for this field is defined by the MaxPSASize field + /// in the HCCPARAMS1 register (refer to Table 5-13). + /// + /// This field shall be '0' for all SS Control, Isoch, and Interrupt endpoints, and for all non-SS + /// endpoints. + #[bits(5)] + pub max_primary_streams: u8, + /// Linear Stream Array (LSA). This field identifies how a Stream ID shall be interpreted. + /// Setting this bit to a value of ‘1’ shall disable Secondary Stream Arrays and a Stream ID shall be + /// interpreted as a linear index into the Primary Stream Array, where valid values for MaxPStreams + /// are ‘1’ to ‘15’. + /// + /// A value of ‘0’ shall enable Secondary Stream Arrays, where the low order (MaxPStreams+1) bits + /// of a Stream ID shall be interpreted as a linear index into the Primary Stream Array, where valid + /// values for MaxPStreams are ‘1’ to ‘7’. And the high order bits of a Stream ID shall be interpreted + /// as a linear index into the Secondary Stream Array. + /// + /// If MaxPStreams = ‘0’, this field RsvdZ. + /// + /// Refer to section 4.12.2 for more information + pub linear_stream_array: bool, + /// Interval. The period between consecutive requests to a USB endpoint to send or receive data. + /// Expressed in 125 μs. increments. The period is calculated as 125 μs. * 2Interval; e.g., an Interval + /// value of 0 means a period of 125 μs. (20 = 1 * 125 μs.), a value of 1 means a period of 250 μs. (21 + /// = 2 * 125 μs.), a value of 4 means a period of 2 ms. (24 = 16 * 125 μs.), etc. Refer to Table 6-12 + /// for legal Interval field values. See further discussion of this field below. Refer to section 6.2.3.6 + /// for more information. + pub interval: u8, + /// Max Endpoint Service Time Interval Payload High (Max ESIT Payload Hi). If LEC = '1', then this + /// field indicates the high order 8 bits of the Max ESIT Payload value. If LEC = '0', then this field + /// shall be RsvdZ. Refer to section 6.2.3.8 for more information. + pub max_esit_payload_hi: u8, + __: bool, + /// Error Count (CErr)112. This field defines a 2-bit down count, which identifies the number of + /// consecutive USB Bus Errors allowed while executing a TD. If this field is programmed with a + /// non-zero value when the Endpoint Context is initialized, the xHC loads this value into an internal + /// Bus Error Counter before executing a USB transaction and decrements it if the transaction fails. + /// If the Bus Error Counter counts from ‘1’ to ‘0’, the xHC ceases execution of the TRB, sets the + /// endpoint to the Halted state, and generates a USB Transaction Error Event for the TRB that + /// caused the internal Bus Error Counter to decrement to ‘0’. If system software programs this field + /// to ‘0’, the xHC shall not count errors for TRBs on the Endpoint’s Transfer Ring and there shall be + /// no limit on the number of TRB retries. Refer to section 4.10.2.7 for more information on the + /// operation of the Bus Error Counter. + /// + /// Note: CErr does not apply to Isoch endpoints and shall be set to ‘0’ if EP Type = Isoch Out ('1') or + /// Isoch In ('5'). + #[bits(2)] + pub error_count: u8, + /// Endpoint Type (EP Type). This field identifies whether an Endpoint Context is Valid, and if so, + /// what type of endpoint the context defines. + #[bits(3)] + pub endpoint_type: EndpointType, + __: bool, + /// Host Initiate Disable (HID). This field affects Stream enabled endpoints, allowing the Host + /// Initiated Stream selection feature to be disabled for the endpoint. Setting this bit to a value of + /// ‘1’ shall disable the Host Initiated Stream selection feature. A value of ‘0’ will enable normal + /// Stream operation. Refer to section 4.12.1.1 for more information. + pub host_initiate_disable: bool, + /// Max Burst Size. This field indicates to the xHC the maximum number of consecutive USB + /// transactions that should be executed per scheduling opportunity. This is a “zero-based” value, + /// where 0 to 15 represents burst sizes of 1 to 16, respectively. Refer to section 6.2.3.4 for more + /// information. + pub max_burst_size: u8, + /// Max Packet Size. This field indicates the maximum packet size in bytes that this endpoint is + /// capable of sending or receiving when configured. Refer to section 6.2.3.5 for more information + pub max_packet_size: u16, +} + +#[bitfield(u64)] +pub struct TRDequeuePointer { + /// Dequeue Cycle State (DCS). This bit identifies the value of the xHC Consumer Cycle State (CCS) + /// flag for the TRB referenced by the TR Dequeue Pointer. Refer to section 4.9.2 for more + /// information. This field shall be ‘0’ if MaxPStreams > ‘0’ + pub dequeue_cycle_state: bool, + #[bits(3)] + __: u8, + /// TR Dequeue Pointer. As Input, this field represents the high order bits of the 64-bit base + /// address of a Transfer Ring or a Stream Context Array associated with this endpoint. If + /// MaxPStreams = '0' then this field shall point to a Transfer Ring. If MaxPStreams > '0' then this + /// field shall point to a Stream Context Array. + /// + /// As Output, if MaxPStreams = ‘0’ this field shall be used by the xHC to store the value of the + /// Dequeue Pointer when the endpoint enters the Halted or Stopped states, and the value of the + /// this field shall be undefined when the endpoint is not in the Halted or Stopped states. if + /// MaxPStreams > ‘0’ then this field shall point to a Stream Context Array. + /// The memory structure referenced by this physical memory pointer shall be aligned to a 16-byte + /// boundary. + #[bits(60)] + tr_deque_pointer: u64, +} + +impl TRDequeuePointer { + pub fn pointer(self) -> u64 { + self.tr_deque_pointer() << 4 + } + + pub fn set_pointer(self, tr_deque_pointer: u64) -> TRDequeuePointer { + self.with_tr_deque_pointer(tr_deque_pointer >> 4) + } +} + +#[repr(C, packed)] +pub struct EndpointContext { + pub fields: u64, + pub tr_deque_pointer: TRDequeuePointer, + /// Average TRB Length. This field represents the average Length of the TRBs executed by this + /// endpoint. The value of this field shall be greater than ‘0’. Refer to section 4.14.1.1 and the + /// implementation note TRB Lengths and System Bus Bandwidth for more information. + /// The xHC shall use this parameter to calculate system bus bandwidth requirements + pub average_trb_lenght: u16, + /// Max Endpoint Service Time Interval Payload Low (Max ESIT Payload Lo). This field indicates + /// the low order 16 bits of the Max ESIT Payload. The Max ESIT Payload represents the total + /// number of bytes this endpoint will transfer during an ESIT. This field is only valid for periodic + /// endpoints. Refer to section 6.2.3.8 for more information. + pub max_esit_payload_lo: u16, + __: [u32; 3], +} + +const _: () = assert!(size_of::() == 0x20); diff --git a/rust/sys/voyageurs/src/xhci/data_structures/event_ring_segment_table.rs b/rust/sys/voyageurs/src/xhci/data_structures/event_ring_segment_table.rs new file mode 100644 index 0000000..89ce405 --- /dev/null +++ b/rust/sys/voyageurs/src/xhci/data_structures/event_ring_segment_table.rs @@ -0,0 +1,62 @@ +use core::ops::{Index, IndexMut}; + +use alloc::{boxed::Box, vec}; +use mammoth::physical_box::PhysicalBox; + +use crate::xhci::data_structures::TrbRing; + +#[repr(align(64))] +#[derive(Default, Clone)] +pub struct EventRingSegmentTableEntry { + /// Ring Segment Base Address Hi and Lo. These fields represent the high order bits of the 64-bit + /// base address of the Event Ring Segment. + /// The memory structure referenced by this physical memory pointer shall begin on a 64-byte + /// address boundary. + pub ring_segment_base_address: u64, + /// Ring Segment Size. This field defines the number of TRBs supported by the ring segment, Valid + /// values for this field are 16 to 4096, i.e. an Event Ring segment shall contain at least 16 entries + pub ring_segment_size: u64, +} + +impl EventRingSegmentTableEntry { + pub fn from_trb_fing(&mut self, trb_ring: &TrbRing) { + self.ring_segment_base_address = trb_ring.physical_address() as u64; + assert!(self.ring_segment_base_address % 64 == 0); + self.ring_segment_size = trb_ring.len() as u64; + assert!(self.ring_segment_size >= 16); + assert!(self.ring_segment_size <= 4096); + } +} + +pub struct EventRingSegmentTable(PhysicalBox<[EventRingSegmentTableEntry]>); + +impl EventRingSegmentTable { + pub fn new(size: usize) -> Self { + Self(PhysicalBox::default_with_count( + EventRingSegmentTableEntry::default(), + size, + )) + } + + pub fn physical_address(&self) -> usize { + self.0.physical_address() + } + + pub fn len(&self) -> usize { + self.0.len() + } +} + +impl Index for EventRingSegmentTable { + type Output = EventRingSegmentTableEntry; + + fn index(&self, index: usize) -> &Self::Output { + &self.0[index] + } +} + +impl IndexMut for EventRingSegmentTable { + fn index_mut(&mut self, index: usize) -> &mut Self::Output { + &mut self.0[index] + } +} diff --git a/rust/sys/voyageurs/src/xhci/data_structures/mod.rs b/rust/sys/voyageurs/src/xhci/data_structures/mod.rs new file mode 100644 index 0000000..781cbc1 --- /dev/null +++ b/rust/sys/voyageurs/src/xhci/data_structures/mod.rs @@ -0,0 +1,8 @@ +mod endpoint_context; +mod event_ring_segment_table; +mod slot_context; +mod trb_ring; + +pub use event_ring_segment_table::*; +pub use slot_context::*; +pub use trb_ring::*; diff --git a/rust/sys/voyageurs/src/xhci/data_structures/slot_context.rs b/rust/sys/voyageurs/src/xhci/data_structures/slot_context.rs new file mode 100644 index 0000000..ab6df95 --- /dev/null +++ b/rust/sys/voyageurs/src/xhci/data_structures/slot_context.rs @@ -0,0 +1,133 @@ +use bitfield_struct::bitfield; + +#[bitfield(u128)] +pub struct SlotContextFields { + /// Route String. This field is used by hubs to route packets to the correct downstream port. The + /// format of the Route String is defined in section 8.9 the USB3 specification. + /// As Input, this field shall be set for all USB devices, irrespective of their speed, to indicate their + /// location in the USB topology. + #[bits(20)] + pub route_string: u32, + /// Speed. This field is deprecated in this version of the specification and shall be Reserved. + /// This field indicates the speed of the device. Refer to the PORTSC Port Speed field in Table 5-27 + /// for the definition of the valid values + #[bits(4)] + pub speed: u8, + __: bool, + /// Multi-TT (MTT). This flag is set to '1' by software if this is a High-speed hub that supports + /// Multiple TTs and the Multiple TT Interface has been enabled by software, or if this is a Low- + /// /Full-speed device or Full-speed hub and connected to the xHC through a parent108 High-speed + /// hub that supports Multiple TTs and the Multiple TT Interface of the parent hub has been + /// enabled by software, or ‘0’ if not. + pub multi_tt: bool, + /// Hub. This flag is set to '1' by software if this device is a USB hub, or '0' if it is a USB function + pub hub: bool, + /// Context Entries. This field identifies the index of the last valid Endpoint Context within this + /// Device Context structure. The value of ‘0’ is Reserved and is not a valid entry for this field. Valid + /// entries for this field shall be in the range of 1-31. This field indicates the size of the Device + /// Context structure. For example, ((Context Entries+1) * 32 bytes) = Total bytes for this structure. + /// + /// Note, Output Context Entries values are written by the xHC, and Input Context Entries values are + /// written by software. + #[bits(5)] + pub context_entries: u8, + /// Max Exit Latency. The Maximum Exit Latency is in microseconds, and indicates the worst case + /// time it takes to wake up all the links in the path to the device, given the current USB link level + /// power management settings. + /// + /// Refer to section 4.23.5.2 for more information on the use of this field. + pub max_exit_latency: u16, + /// Root Hub Port Number. This field identifies the Root Hub Port Number used to access the USB + /// device. Refer to section 4.19.7 for port numbering information. + /// + /// Note: Ports are numbered from 1 to MaxPorts + pub root_hub_port_number: u8, + /// Number of Ports. If this device is a hub (Hub = ‘1’), then this field is set by software to identify + /// the number of downstream facing ports supported by the hub. Refer to the bNbrPorts field + /// description in the Hub Descriptor (Table 11-13) of the USB2 spec. If this device is not a hub (Hub + /// = ‘0’), then this field shall be ‘0 + pub number_of_ports: u8, + /// Parent Hub Slot ID. If this device is Low-/Full-speed and connected through a High-speed hub, + /// then this field shall contain the Slot ID of the parent High-speed hub109. + /// + /// For SS and SSP bus instance, if this device is connected through a higher rank hub110 then this + /// field shall contain the Slot ID of the parent hub. For example, a Gen1 x1 connected behind a + /// Gen1 x2 hub, or Gen1 x2 device connected behind Gen2 x2 hub. + /// + /// This field shall be ‘0’ if any of the following are true: + /// Device is attached to a Root Hub port + /// Device is a High-Speed device + /// Device is the highest rank SS/SSP device supported by xHCI + pub parent_hub_slot_id: u8, + /// Parent Port Number. If this device is Low-/Full-speed and connected through a High-speed + /// hub, then this field shall contain the number of the downstream facing port of the parent High- + /// speed hub109. + /// For SS and SSP bus instance, if this device is connected through a higher rank hub110 then this + /// field shall contain the number of the downstream facing port of the parent hub. For example, a + /// Gen1 x1 connected behind a Gen1 x2 hub, or Gen1 x2 device connected behind Gen2 x2 hub. + /// This field shall be ‘0’ if any of the following are true: + /// Device is attached to a Root Hub port + /// Device is a High-Speed device + /// Device is the highest rank SS/SSP device supported by xH + pub parent_port_number: u8, + /// TT Think Time (TTT). If this is a High-speed hub (Hub = ‘1’ and Speed = High-Speed), then this + /// field shall be set by software to identify the time the TT of the hub requires to proceed to the + /// next full-/low-speed transaction. + /// Value Think Time + /// 0 TT requires at most 8 FS bit times of inter-transaction gap on a full-/low-speed + /// downstream bus. + /// 1 TT requires at most 16 FS bit times. + /// 2 TT requires at most 24 FS bit times. + /// 3 TT requires at most 32 FS bit times. + /// Refer to the TT Think Time sub-field of the wHubCharacteristics field description in the Hub + /// Descriptor (Table 11-13) and section 11.18.2 of the USB2 spec for more information on TT + /// Think Time. If this device is not a High-speed hub (Hub = ‘0’ or Speed != High-speed), then this + /// field shall be ‘0’. + #[bits(2)] + pub tt_think_time: u8, + #[bits(4)] + __: u8, + /// Interrupter Target. This field defines the index of the Interrupter that will receive Bandwidth + /// Request Events and Device Notification Events generated by this slot, or when a Ring Underrun + /// or Ring Overrun condition is reported (refer to section 4.10.3.1). Valid values are between 0 and + /// MaxIntrs-1 + #[bits(10)] + pub interrupter_target: u16, + /// USB Device Address. This field identifies the address assigned to the USB device by the xHC, + /// and is set upon the successful completion of a Set Address Command. Refer to the USB2 spec + /// for a more detailed description. + /// + /// As Output, this field is invalid if the Slot State = Disabled or Default. + /// As Input, software shall initialize the field to ‘0’. + pub usb_device_address: u8, + + #[bits(19)] + __: u32, + + /// Slot State. This field is updated by the xHC when a Device Slot transitions from one state to + /// another. + /// Value Slot State + /// 0 Disabled/Enabled + /// 1 Default + /// 2 Addressed + /// 3 Configured + /// 31-4 Reserved + /// + /// Slot States are defined in section 4.5.3. + /// + /// As Output, since software initializes all fields of the Device Context data structure to ‘0’, this field + /// shall initially indicate the Disabled state. + /// + /// As Input, software shall initialize the field to ‘0’. + /// Refer to section 4.5.3 for more information on Slot State. + #[bits(5)] + pub slot_state: u8, +} + +#[repr(C)] +pub struct SlotContext { + pub fields: SlotContextFields, + __: u128, +} + +const _: () = assert!(size_of::() == 0x20); diff --git a/rust/sys/voyageurs/src/xhci/data_structures/trb_ring.rs b/rust/sys/voyageurs/src/xhci/data_structures/trb_ring.rs new file mode 100644 index 0000000..2ded382 --- /dev/null +++ b/rust/sys/voyageurs/src/xhci/data_structures/trb_ring.rs @@ -0,0 +1,113 @@ +use core::{ + ops::{Index, IndexMut}, + slice::SliceIndex, +}; + +use bitfield_struct::{bitenum, bitfield}; +use mammoth::physical_box::PhysicalBox; + +#[bitenum] +#[repr(u8)] +#[derive(Debug)] +pub enum TrbType { + #[fallback] + Reserved = 0, + NoOp = 8, +} + +#[bitfield(u128)] +pub struct TransferRequestBlock { + parameter: u64, + status: u32, + cycle: bool, + evaluate_next: bool, + flag_2: bool, + flag_3: bool, + flag_4: bool, + flag_5: bool, + flag_6: bool, + flag_7: bool, + flag_8: bool, + flag_9: bool, + #[bits(6)] + trb_type: u8, + control: u16, +} + +impl TransferRequestBlock {} + +trait TypedTrb { + fn from_trb(trb: TransferRequestBlock) -> Self + where + Self: From, + { + trb.into_bits().into() + } + + fn to_trb(self) -> TransferRequestBlock + where + Self: Into, + { + Into::::into(self).into() + } +} + +#[bitfield(u128)] +pub struct TrbNoOp { + __: u64, + __: u32, + cycle: bool, + evaluate_next: bool, + __: bool, + __: bool, + chain: bool, + #[bits(default = true)] + interrupt_on_completion: bool, + #[bits(4)] + __: u8, + #[bits(6, default = TrbType::NoOp)] + trb_type: TrbType, + __: u16, +} + +impl TypedTrb for TrbNoOp {} + +#[repr(transparent)] +pub struct TrbRing(PhysicalBox<[TransferRequestBlock]>); + +impl TrbRing { + pub fn new(size: usize) -> Self { + Self(PhysicalBox::default_with_count( + TransferRequestBlock::default(), + size, + )) + } + + pub fn len(&self) -> usize { + self.0.len() + } + + pub fn physical_address(&self) -> usize { + self.0.physical_address() + } +} + +impl Index for TrbRing +where + I: SliceIndex<[TransferRequestBlock]>, +{ + type Output = I::Output; + + fn index(&self, index: I) -> &Self::Output { + &self.0[index] + } +} + +impl IndexMut for TrbRing +where + I: SliceIndex<[TransferRequestBlock]>, +{ + fn index_mut(&mut self, index: I) -> &mut Self::Output { + &mut self.0[index] + } +} diff --git a/rust/sys/voyageurs/src/xhci/mod.rs b/rust/sys/voyageurs/src/xhci/mod.rs index 8993d24..008e36e 100644 --- a/rust/sys/voyageurs/src/xhci/mod.rs +++ b/rust/sys/voyageurs/src/xhci/mod.rs @@ -1 +1,2 @@ +pub mod data_structures; pub mod registers;