xhcid: improvements based on real hardware testing
This commit is contained in:
+19
-16
@@ -465,12 +465,12 @@ impl Xhci {
|
|||||||
pub fn init(&mut self, max_slots: u8) -> Result<()> {
|
pub fn init(&mut self, max_slots: u8) -> Result<()> {
|
||||||
// Set run/stop to 0
|
// Set run/stop to 0
|
||||||
debug!("Stopping xHC.");
|
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
|
// Warm reset
|
||||||
debug!("Reset xHC");
|
debug!("Reset xHC");
|
||||||
self.op.get_mut().unwrap().usb_cmd.writef(1 << 1, true);
|
self.op.get_mut().unwrap().usb_cmd.writef(USB_CMD_HCRST, true);
|
||||||
while self.op.get_mut().unwrap().usb_cmd.readf(1 << 1) {
|
while self.op.get_mut().unwrap().usb_cmd.readf(USB_CMD_HCRST) {
|
||||||
thread::yield_now();
|
thread::yield_now();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,18 +531,18 @@ impl Xhci {
|
|||||||
debug!("Enabling Primary Interrupter.");
|
debug!("Enabling Primary Interrupter.");
|
||||||
int.iman.writef(1 << 1 | 1, true);
|
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.
|
// Setup the scratchpad buffers that are required for the xHC to function.
|
||||||
self.setup_scratchpads()?;
|
self.setup_scratchpads()?;
|
||||||
|
|
||||||
// Set run/stop to 1
|
// Set run/stop to 1
|
||||||
debug!("Starting xHC.");
|
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
|
// Wait until controller is running
|
||||||
debug!("Waiting for start request to complete.");
|
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.");
|
trace!("Waiting for XHCI to report running status.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -796,7 +796,7 @@ impl Xhci {
|
|||||||
|
|
||||||
info!("Attempting to address the device");
|
info!("Attempting to address the device");
|
||||||
let mut ring = match self
|
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
|
.await
|
||||||
{
|
{
|
||||||
Ok(device_ring) => device_ring,
|
Ok(device_ring) => device_ring,
|
||||||
@@ -1012,6 +1012,7 @@ impl Xhci {
|
|||||||
slot_ty: u8,
|
slot_ty: u8,
|
||||||
slot: u8,
|
slot: u8,
|
||||||
protocol_speed: &ProtocolSpeed,
|
protocol_speed: &ProtocolSpeed,
|
||||||
|
speed: u8,
|
||||||
) -> Result<Ring> {
|
) -> Result<Ring> {
|
||||||
// Collect MTT, parent port number, parent slot ID
|
// Collect MTT, parent port number, parent slot ID
|
||||||
let mut mtt = false;
|
let mut mtt = false;
|
||||||
@@ -1057,6 +1058,7 @@ impl Xhci {
|
|||||||
assert_eq!(route_string & 0x000F_FFFF, route_string);
|
assert_eq!(route_string & 0x000F_FFFF, route_string);
|
||||||
slot_ctx.a.write(
|
slot_ctx.a.write(
|
||||||
route_string
|
route_string
|
||||||
|
| (u32::from(speed) << 20)
|
||||||
| (u32::from(mtt) << 25)
|
| (u32::from(mtt) << 25)
|
||||||
| (u32::from(hub) << 26)
|
| (u32::from(hub) << 26)
|
||||||
| (u32::from(context_entries) << 27),
|
| (u32::from(context_entries) << 27),
|
||||||
@@ -1087,16 +1089,12 @@ impl Xhci {
|
|||||||
|
|
||||||
let max_error_count = 3u8; // recommended value according to the XHCI spec
|
let max_error_count = 3u8; // recommended value according to the XHCI spec
|
||||||
let ep_ty = 4u8; // control endpoint, bidirectional
|
let ep_ty = 4u8; // control endpoint, bidirectional
|
||||||
let max_packet_size: u32 = if protocol_speed.is_lowspeed() {
|
let max_packet_size: u32 = if protocol_speed.is_lowspeed() || protocol_speed.is_fullspeed() {
|
||||||
8 // only valid value
|
8
|
||||||
} else if protocol_speed.is_fullspeed() {
|
|
||||||
64 // valid values are 8, 16, 32, 64
|
|
||||||
} else if protocol_speed.is_highspeed() {
|
} else if protocol_speed.is_highspeed() {
|
||||||
64 // only valid value
|
64
|
||||||
} else if protocol_speed.is_superspeed_gen_x() {
|
|
||||||
512 // only valid value
|
|
||||||
} else {
|
} else {
|
||||||
unreachable!()
|
512
|
||||||
};
|
};
|
||||||
let host_initiate_disable = false; // only applies to streams
|
let host_initiate_disable = false; // only applies to streams
|
||||||
let max_burst_size = 0u8; // TODO
|
let max_burst_size = 0u8; // TODO
|
||||||
@@ -1110,9 +1108,14 @@ impl Xhci {
|
|||||||
| (u32::from(max_packet_size) << 16),
|
| (u32::from(max_packet_size) << 16),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let dequeue_cycle_state = true;
|
||||||
let tr = ring.register();
|
let tr = ring.register();
|
||||||
endp_ctx.trh.write((tr >> 32) as u32);
|
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();
|
let input_context_physical = input_context.physical();
|
||||||
|
|||||||
@@ -80,6 +80,8 @@ pub struct OperationalRegs {
|
|||||||
pub const USB_CMD_RS: u32 = 1 << 0;
|
pub const USB_CMD_RS: u32 = 1 << 0;
|
||||||
/// Host controller reset
|
/// Host controller reset
|
||||||
pub const USB_CMD_HCRST: u32 = 1 << 1;
|
pub const USB_CMD_HCRST: u32 = 1 << 1;
|
||||||
|
// Interrupter enable
|
||||||
|
pub const USB_CMD_INTE: u32 = 1 << 2;
|
||||||
|
|
||||||
/// Host controller halted
|
/// Host controller halted
|
||||||
pub const USB_STS_HCH: u32 = 1 << 0;
|
pub const USB_STS_HCH: u32 = 1 << 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user