xhcid: improvements based on real hardware testing

This commit is contained in:
Jeremy Soller
2025-09-11 21:06:21 -06:00
parent 69a80a6a13
commit 12e601b336
2 changed files with 21 additions and 16 deletions
+19 -16
View File
@@ -465,12 +465,12 @@ impl Xhci {
pub fn init(&mut self, max_slots: u8) -> Result<()> {
// Set run/stop to 0
debug!("Stopping xHC.");
self.op.get_mut().unwrap().usb_cmd.writef(1, false);
self.op.get_mut().unwrap().usb_cmd.writef(USB_CMD_RS, false);
// Warm reset
debug!("Reset xHC");
self.op.get_mut().unwrap().usb_cmd.writef(1 << 1, true);
while self.op.get_mut().unwrap().usb_cmd.readf(1 << 1) {
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,18 +531,18 @@ impl Xhci {
debug!("Enabling Primary Interrupter.");
int.iman.writef(1 << 1 | 1, true);
}
self.op.get_mut().unwrap().usb_cmd.writef(1 << 2, 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()?;
// Set run/stop to 1
debug!("Starting xHC.");
self.op.get_mut().unwrap().usb_cmd.writef(1, true);
self.op.get_mut().unwrap().usb_cmd.writef(USB_CMD_RS, true);
// Wait until controller is running
debug!("Waiting for start request to complete.");
while self.op.get_mut().unwrap().usb_sts.readf(1) {
while self.op.get_mut().unwrap().usb_sts.readf(USB_STS_HCH) {
trace!("Waiting for XHCI to report running status.");
}
@@ -796,7 +796,7 @@ impl Xhci {
info!("Attempting to address the device");
let mut ring = match self
.address_device(&mut input, port_id, slot_ty, slot, protocol_speed)
.address_device(&mut input, port_id, slot_ty, slot, protocol_speed, speed)
.await
{
Ok(device_ring) => device_ring,
@@ -1012,6 +1012,7 @@ impl Xhci {
slot_ty: u8,
slot: u8,
protocol_speed: &ProtocolSpeed,
speed: u8,
) -> Result<Ring> {
// Collect MTT, parent port number, parent slot ID
let mut mtt = false;
@@ -1057,6 +1058,7 @@ impl Xhci {
assert_eq!(route_string & 0x000F_FFFF, route_string);
slot_ctx.a.write(
route_string
| (u32::from(speed) << 20)
| (u32::from(mtt) << 25)
| (u32::from(hub) << 26)
| (u32::from(context_entries) << 27),
@@ -1087,16 +1089,12 @@ impl Xhci {
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() {
8 // only valid value
} else if protocol_speed.is_fullspeed() {
64 // valid values are 8, 16, 32, 64
let max_packet_size: u32 = if protocol_speed.is_lowspeed() || protocol_speed.is_fullspeed() {
8
} else if protocol_speed.is_highspeed() {
64 // only valid value
} else if protocol_speed.is_superspeed_gen_x() {
512 // only valid value
64
} else {
unreachable!()
512
};
let host_initiate_disable = false; // only applies to streams
let max_burst_size = 0u8; // TODO
@@ -1110,9 +1108,14 @@ impl Xhci {
| (u32::from(max_packet_size) << 16),
);
let dequeue_cycle_state = true;
let tr = ring.register();
endp_ctx.trh.write((tr >> 32) as u32);
endp_ctx.trl.write(tr as u32);
endp_ctx.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));
}
let input_context_physical = input_context.physical();
+2
View File
@@ -80,6 +80,8 @@ pub struct OperationalRegs {
pub const USB_CMD_RS: u32 = 1 << 0;
/// Host controller reset
pub const USB_CMD_HCRST: u32 = 1 << 1;
// Interrupter enable
pub const USB_CMD_INTE: u32 = 1 << 2;
/// Host controller halted
pub const USB_STS_HCH: u32 = 1 << 0;