Rust XHCI Data Structure Types.

This commit is contained in:
Drew 2025-12-05 21:15:00 -08:00
parent 2e23e313ac
commit da2eb4fda3
11 changed files with 808 additions and 4 deletions

17
rust/Cargo.lock generated
View file

@ -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",
]

View file

@ -4,5 +4,5 @@ version = "0.1.0"
edition = "2024"
[dependencies]
bitfield-struct = "0.8.0"
bitfield-struct = "0.12"
mammoth = { path = "../../lib/mammoth/" }

View file

@ -0,0 +1,11 @@
use crate::xhci::data_structures::{EndpointContext, SlotContext};
#[repr(C, align(64))]
#[derive(Default)]
pub struct DeviceContext {
slot_context: SlotContext,
endpoint_context_0: EndpointContext,
endpoint_contexts: [EndpointContext; 30],
}
const _: () = assert!(size_of::<DeviceContext>() == 0x400);

View file

@ -0,0 +1,206 @@
use bitfield_struct::{bitenum, bitfield};
#[repr(u8)]
#[bitenum]
#[derive(Debug)]
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,
#[fallback]
Unknown = 5,
}
#[repr(u8)]
#[bitenum]
#[derive(Debug)]
pub enum EndpointType {
#[fallback]
NotValid = 0,
IsochOut = 1,
BulkOut = 2,
InterruptOut = 3,
Control = 4,
IsochIn = 5,
BulkIn = 6,
InterruptIn = 7,
}
#[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 Endpoints 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(&mut self, tr_deque_pointer: u64) {
self.set_tr_deque_pointer(tr_deque_pointer >> 4)
}
pub fn with_pointer(self, tr_deque_pointer: u64) -> Self {
self.with_tr_deque_pointer(tr_deque_pointer >> 4)
}
}
#[bitfield(u64)]
struct AdditionalFields {
/// 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_length: 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,
}
#[repr(C)]
#[derive(Default)]
pub struct EndpointContext {
pub fields: EndpointContextFields,
pub tr_deque_pointer: TRDequeuePointer,
additional_fields: AdditionalFields,
__: u64,
}
const _: () = assert!(size_of::<EndpointContext>() == 0x20);

View file

@ -0,0 +1,67 @@
use core::ops::{Index, IndexMut};
use mammoth::physical_box::PhysicalBox;
use crate::xhci::data_structures::TrbRingSegment;
#[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_ring(&mut self, trb_ring: &TrbRingSegment) {
mammoth::debug!("RSTE: {:0x}", self as *const _ as usize);
self.ring_segment_base_address = trb_ring.physical_address() as u64;
assert!(self.ring_segment_base_address % 64 == 0);
unsafe {
core::ptr::write_volatile(
&mut self.ring_segment_size as *mut u64,
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<usize> for EventRingSegmentTable {
type Output = EventRingSegmentTableEntry;
fn index(&self, index: usize) -> &Self::Output {
&self.0[index]
}
}
impl IndexMut<usize> for EventRingSegmentTable {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
&mut self.0[index]
}
}

View file

@ -0,0 +1,33 @@
use bitfield_struct::bitfield;
use crate::xhci::data_structures::{EndpointContext, SlotContext};
#[bitfield(u32)]
pub struct InputControlContextSettings {
configuration_value: u8,
interface_number: u8,
alternate_setting: u8,
__: u8,
}
#[repr(C)]
#[derive(Default)]
pub struct InputControlContext {
pub drop_context_flags: u32,
pub add_context_flags: u32,
__: [u32; 5],
settings: InputControlContextSettings,
}
const _: () = assert!(size_of::<InputControlContext>() == 0x20);
#[repr(C)]
#[derive(Default)]
pub struct InputContext {
pub input_control_context: InputControlContext,
pub slot_context: SlotContext,
pub endpoint_context_0: EndpointContext,
pub endpoint_contexts: [EndpointContext; 30],
}
const _: () = assert!(size_of::<InputContext>() == 0x420);

View file

@ -0,0 +1,15 @@
mod device_context;
mod endpoint_context;
mod event_ring_segment_table;
mod input_context;
mod slot_context;
mod trb;
mod trb_ring_segment;
pub use device_context::*;
pub use endpoint_context::*;
pub use event_ring_segment_table::*;
pub use input_context::*;
pub use slot_context::*;
pub use trb::*;
pub use trb_ring_segment::*;

View file

@ -0,0 +1,134 @@
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)]
#[derive(Default)]
pub struct SlotContext {
pub fields: SlotContextFields,
__: u128,
}
const _: () = assert!(size_of::<SlotContext>() == 0x20);

View file

@ -0,0 +1,278 @@
use bitfield_struct::{bitenum, bitfield};
#[bitenum]
#[repr(u8)]
#[derive(Debug, Eq, PartialEq)]
pub enum TrbType {
#[fallback]
Reserved = 0,
Normal = 1,
SetupStage = 2,
DataStage = 3,
StatusStage = 4,
Isoch = 5,
Link = 6,
EventData = 7,
NoOp = 8,
EnableSlotCommand = 9,
DisableSlotCommand = 10,
AddressDeviceCommand = 11,
ConfigureEndpointCommand = 12,
EvaluateContextCommand = 13,
ResetEndpointCommand = 14,
StopEndpointCommand = 15,
SetTRDequeuePointerCommand = 16,
ResetDeviceCommand = 17,
ForceEventCommand = 18,
NegotiateBandwidthCommand = 19,
SetLatencyToleranceValueCommand = 20,
GetPortBandwidthCommand = 21,
ForceHeaderCommand = 22,
NoOpCommand = 23,
GetExtendedPropertyCommand = 24,
SetExtendedPropertyCommand = 25,
TransferEvent = 32,
CommandCompletionEvent = 33,
PortStatusChangeEvent = 34,
BandwidthRequestEvent = 35,
DoorbellEvent = 36,
HostControllerEvent = 37,
DeviceNotificationEvent = 38,
MFINDEXWrapEvent = 39,
}
#[bitfield(u128)]
pub struct TransferRequestBlock {
pub parameter: u64,
pub status: u32,
pub 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)]
pub trb_type: TrbType,
control: u16,
}
impl TransferRequestBlock {}
pub trait TypedTrb
where
Self: Into<u128> + From<u128> + Copy,
{
fn from_trb(trb: TransferRequestBlock) -> Self {
trb.into_bits().into()
}
fn to_trb(self) -> TransferRequestBlock {
Into::<u128>::into(self).into()
}
}
#[bitfield(u128)]
pub struct TrbNoOp {
__: u64,
#[bits(22)]
__: u32,
#[bits(10, default = 0)]
interrupter_target: u16,
cycle: bool,
evaluate_next: bool,
__: bool,
__: bool,
chain: bool,
#[bits(default = true)]
interrupt_on_completion: bool,
#[bits(4)]
__: u8,
#[bits(6, default = TrbType::NoOpCommand)]
trb_type: TrbType,
__: u16,
}
impl TypedTrb for TrbNoOp {}
#[bitfield(u128)]
pub struct TrbLink {
/// Ring Segment Pointer Hi and Lo. These fields represent the high order bits of the 64-bit base
/// address of the next Ring Segment.
/// The memory structure referenced by this physical memory pointer shall begin on a 16-byte
/// address boundary.
pub ring_segment_pointer: u64,
#[bits(22)]
__: u32,
/// Interrupter Target. This field defines the index of the Interrupter that will receive Transfer
/// Events generated by this TRB. Valid values are between 0 and MaxIntrs-1.
/// This field is ignored by the xHC on Command Rings.
#[bits(10)]
pub interrupter_target: u16,
/// Cycle bit (C). This bit is used to mark the Enqueue Pointer location of a Transfer or Command
/// Ring.
pub cycle: bool,
/// Toggle Cycle (TC). When set to 1, the xHC shall toggle its interpretation of the Cycle bit. When
/// cleared to 0, the xHC shall continue to the next segment using its current interpretation of the
/// Cycle bit.
pub toggle_cycle: bool,
__: bool,
__: bool,
/// Chain bit (CH). Set to 1 by software to associate this TRB with the next TRB on the Ring. A
/// Transfer Descriptor (TD) is defined as one or more TRBs. The Chain bit is used to identify the
/// TRBs that comprise a TD. Refer to section 4.11.7 for more information on Link TRB placement
/// within a TD. On a Command Ring this bit is ignored by the xHC.
#[bits(default = true)]
chain: bool,
/// Interrupt On Completion (IOC). If this bit is set to 1, it specifies that when this TRB completes,
/// the Host Controller shall notify the system of the completion by placing an Event TRB on the
/// Event ring and sending an interrupt at the next interrupt threshold.
pub interrupt_on_completion: bool,
#[bits(4)]
__: u8,
/// TRB Type. This field is set to Link TRB type. Refer to Table 6-91 for the definition of the Type
/// TRB IDs.
#[bits(6, default = TrbType::Link)]
trb_type: TrbType,
__: u16,
}
impl TypedTrb for TrbLink {}
#[bitfield(u128)]
pub struct TrbTransferEvent {
pub transfer_trb_pointer: u64,
#[bits(24)]
pub trb_transfer_lenght: u32,
/// Completion Code. This field encodes the completion status of the command that generated the
/// event. Refer to the respective command definition for a list of the possible Completion Codes
/// associated with the command. Refer to section 6.4.5 for an enumerated list of possible error
/// conditions.
pub completion_code: u8,
#[bits(10)]
__: u16,
/// TRB Type. This field identifies the type of the TRB. Refer to Table 6-91 for the definition of the
/// Command Completion Event TRB type ID
#[bits(6, default=TrbType::TransferEvent)]
pub trb_type: TrbType,
#[bits(5)]
pub endpoint_id: u8,
#[bits(3)]
__: u8,
pub slot_id: u8,
}
impl TypedTrb for TrbTransferEvent {}
#[bitenum]
#[repr(u8)]
pub enum CommandCompletionCode {
#[fallback]
Invalid = 0,
Success = 1,
}
#[bitfield(u128)]
pub struct TrbCommandCompletion {
/// Command TRB Pointer Hi and Lo. This field represents the high order bits of the 64-bit address
/// of the Command TRB that generated this event. Note that this field is not valid for some
/// Completion Code values. Refer to Table 6-90 for specific cases.
///
/// The memory structure referenced by this physical memory pointer shall be aligned on a 16-byte
/// address boundary.
pub command_trb_pointer: u64,
/// Command Completion Parameter. This field may optionally be set by a command. Refer to
/// section 4.6.6.1 for specific usage. If a command does not utilize this field it shall be treated as
/// RsvdZ.
#[bits(24)]
pub command_completion_parameter: u64,
/// Completion Code. This field encodes the completion status of the command that generated the
/// event. Refer to the respective command definition for a list of the possible Completion Codes
/// associated with the command. Refer to section 6.4.5 for an enumerated list of possible error
/// conditions.
pub completion_code: u8,
/// Cycle bit (C). This bit is used to mark the Dequeue Pointer of an Event Ring
pub cycle_bit: bool,
#[bits(9)]
__: u16,
/// TRB Type. This field identifies the type of the TRB. Refer to Table 6-91 for the definition of the
/// Command Completion Event TRB type ID
#[bits(6, default=TrbType::CommandCompletionEvent)]
pub trb_type: TrbType,
/// VF ID. The ID of the Virtual Function that generated the event. Note that this field is valid only if
/// Virtual Functions are enabled. If they are not enabled this field shall be cleared to 0.
pub vf_id: u8,
/// Slot ID. The Slot ID field shall be updated by the xHC to reflect the slot associated with the
/// command that generated the event, with the following exceptions:
///
/// - The Slot ID shall be cleared to 0 for No Op, Set Latency Tolerance Value, Get Port Bandwidth,
/// and Force Event Commands.
///
/// - The Slot ID shall be set to the ID of the newly allocated Device Slot for the Enable Slot
/// Command.
///
/// - The value of Slot ID shall be vendor defined when generated by a vendor defined command.
///
/// This value is used as an index in the Device Context Base Address Array to select the Device
/// Context of the source device. If this Event is due to a Host Controller Command, then this field
/// shall be cleared to 0.
pub slot_id: u8,
}
impl TypedTrb for TrbCommandCompletion {}
#[bitfield(u128)]
pub struct TrbPortStatusChangeEvent {
#[bits(24)]
__: u32,
pub port_id: u8,
__: u32,
#[bits(24)]
__: u32,
pub completion_code: u8,
#[bits(10)]
__: u16,
#[bits(6, default=TrbType::PortStatusChangeEvent)]
trb_type: TrbType,
__: u16,
}
impl TypedTrb for TrbPortStatusChangeEvent {}
#[bitfield(u128)]
pub struct TrbEnableSlotCommand {
__: u64,
__: u32,
#[bits(10)]
__: u16,
#[bits(6, default=TrbType::EnableSlotCommand)]
trb_type: TrbType,
#[bits(5)]
slot_type: u8,
#[bits(11)]
__: u16,
}
impl TypedTrb for TrbEnableSlotCommand {}
#[bitfield(u128)]
pub struct TrbAddressDeviceCommand {
pub input_context_pointer: u64,
__: u32,
#[bits(9)]
__: u16,
pub block_set_address_request: bool,
#[bits(6, default=TrbType::AddressDeviceCommand)]
trb_typ: TrbType,
__: u8,
pub slot_id: u8,
}
impl TypedTrb for TrbAddressDeviceCommand {}

View file

@ -0,0 +1,48 @@
use core::{
ops::{Index, IndexMut},
slice::SliceIndex,
};
use mammoth::physical_box::PhysicalBox;
use crate::xhci::data_structures::TransferRequestBlock;
#[repr(transparent)]
pub struct TrbRingSegment(PhysicalBox<[TransferRequestBlock]>);
impl TrbRingSegment {
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<I> Index<I> for TrbRingSegment
where
I: SliceIndex<[TransferRequestBlock]>,
{
type Output = I::Output;
fn index(&self, index: I) -> &Self::Output {
&self.0[index]
}
}
impl<I> IndexMut<I> for TrbRingSegment
where
I: SliceIndex<[TransferRequestBlock]>,
{
fn index_mut(&mut self, index: I) -> &mut Self::Output {
&mut self.0[index]
}
}

View file

@ -1 +1,2 @@
pub mod data_structures;
pub mod registers;