xhci: route driver chatter through log_message(), silence at default log level
Build / build-amd64-iso (push) Waiting to run
Build / build-aarch64-iso (push) Waiting to run
Build / build-riscv64-img (push) Waiting to run

xhci.c and repl.c's USB attach/detach path printed every xHCI command
submission, completion, and BOT transfer step unconditionally via
console_println()/console_puts() -- floods the serial log on every boot,
regardless of whether anyone is debugging the USB stack.

Converted every "xhci:"-prefixed line to log_message() with a level
chosen by what it reports, not blanket debug:
- LOG_ERROR: allocation/mapping failures, timeouts, command failures,
  CSW signature/tag mismatches, CSW FAILED/PHASE ERROR, "not implemented"
  refusals, every "deferred ... setup failed" path
- LOG_WARN: dropped/skipped conditions (command ring busy, tracked-port
  range exceeded), unrecognized media (bad version/CRC), TUR retry
- LOG_DEBUG: routine progress (command submitted, succeeded, transfer
  completed, port connected) and expected outcomes (recognized/blank
  media)

Default log level is LOG_INFO, so the LOG_DEBUG chatter that was the
actual complaint is now silent by default and re-enabled with
--log-level=debug; LOG_ERROR/LOG_WARN stay visible so real faults aren't
buried.

xhci_log_hex32() now routes through log_message(LOG_DEBUG, ...) instead
of console_puts()/console_println() directly -- kept its own zero-padded
8-digit hex formatting rather than switching to log_message()'s %x
(which has no width control), since register values lining up in the
log is the reason this helper exists. console.h dropped from xhci.c,
no longer used directly.

Verified functionally unchanged, not just "still boots": all three
architectures reach zuse)ok>, log_message()-instrumented lines are gone
from the default-level log (grep -c xhci == 0 on all three, versus dozens
before), and the USB thumbdrive path still works end to end --
"Zuse: identity confirmed from attached thumbdrive" appears on all three
boots exactly as before.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YcT3H2PQeyujrzjqS3Var
This commit is contained in:
Robert Allan James
2026-09-05 01:25:50 -04:00
co-authored by Claude Sonnet 5
parent 1bd041e84d
commit dbaead0af2
10 changed files with 27067 additions and 118 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
# Capsule Block Manifest — Auto-generated
<!-- Generated by mkcapsule --manifest 2026-09-05T05:04:34Z -->
<!-- Generated by mkcapsule --manifest 2026-09-05T05:24:05Z -->
<!-- DO NOT EDIT — re-run mkcapsule --manifest to refresh. -->
<!-- Hand-written justifications and immutability notes live -->
<!-- in MANIFEST.md alongside this auto-generated index. -->
BIN
View File
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+7 -6
View File
@@ -30,6 +30,7 @@
#include "starkernel/repl.h"
#include "console.h"
#include "log.h"
#include "vm.h"
#include "version.h"
#include "starkernel/timer.h"
@@ -224,22 +225,22 @@ static void sk_repl_idle(VM *active_vm)
homeblocks_sig_check(&usb_blk_dev, HOMEBLOCKS_SIG_START_FBLOCK, &sig);
switch (sig_rc) {
case HOMEBLOCKS_SIG_OK:
console_println("xhci: USB drive recognized as a home-blocks drive");
log_message(LOG_DEBUG, "xhci: USB drive recognized as a home-blocks drive");
g_homeblocks_dev = &usb_blk_dev;
g_homeblocks_sig = sig;
g_homeblocks_sig_valid = 1;
break;
case HOMEBLOCKS_SIG_BLANK:
console_println("xhci: USB drive not recognized (blank or foreign media) -- read-only general use only");
log_message(LOG_DEBUG, "xhci: USB drive not recognized (blank or foreign media) -- read-only general use only");
break;
case HOMEBLOCKS_SIG_BAD_VERSION:
console_println("xhci: USB drive has a home-blocks header of an unrecognized version -- read-only general use only");
log_message(LOG_WARN, "xhci: USB drive has a home-blocks header of an unrecognized version -- read-only general use only");
break;
case HOMEBLOCKS_SIG_BAD_CRC:
console_println("xhci: USB drive has a home-blocks header that fails its checksum (corrupt or tampered) -- read-only general use only");
log_message(LOG_WARN, "xhci: USB drive has a home-blocks header that fails its checksum (corrupt or tampered) -- read-only general use only");
break;
case HOMEBLOCKS_SIG_READ_ERROR:
console_println("xhci: USB drive signature check failed to read the device -- read-only general use only");
log_message(LOG_ERROR, "xhci: USB drive signature check failed to read the device -- read-only general use only");
break;
}
@@ -269,7 +270,7 @@ static void sk_repl_idle(VM *active_vm)
xdev->bot_msc_attached = 1;
g_attached_blk_dev = &usb_blk_dev;
} else {
console_println("xhci: USB MSC block-subsystem attach failed");
log_message(LOG_ERROR, "xhci: USB MSC block-subsystem attach failed");
}
}
+113 -111
View File
@@ -24,7 +24,7 @@
#include "starkernel/xhci_driver.h"
#include "starkernel/kmalloc.h"
#include "starkernel/timer.h"
#include "console.h"
#include "log.h"
/* Conservative fixed BAR0 mapping size. xHCI has no self-describing
* capability-region length the way virtio PCI capabilities do (that's
@@ -41,7 +41,7 @@ int xhci_find_and_map(xhci_dev_t *dev)
if (!dev) return -1;
if (pci_find_first(XHCI_PCI_VENDOR_ID, XHCI_PCI_DEVICE_ID, &dev->pci) != 0) {
console_println("xhci: no controller found on PCI bus 0");
log_message(LOG_DEBUG, "xhci: no controller found on PCI bus 0");
return -1;
}
@@ -49,12 +49,12 @@ int xhci_find_and_map(xhci_dev_t *dev)
dev->bar0_phys = pci_bar(&dev->pci, 0);
if (!dev->bar0_phys) {
console_println("xhci: BAR0 read failed (zero or I/O BAR)");
log_message(LOG_ERROR, "xhci: BAR0 read failed (zero or I/O BAR)");
return -1;
}
if (pci_map_bar(dev->bar0_phys, XHCI_BAR0_MAP_SIZE) != 0) {
console_println("xhci: BAR0 mapping failed");
log_message(LOG_ERROR, "xhci: BAR0 mapping failed");
return -2;
}
@@ -71,7 +71,7 @@ int xhci_find_and_map(xhci_dev_t *dev)
dev->max_ports = XHCI_HCSPARAMS1_MAX_PORTS(hcs1);
dev->max_scratchpad_bufs = XHCI_HCSPARAMS2_MAX_SCRATCHPAD_BUFS(dev->cap->hcs_params2);
console_println("xhci: controller found, BAR0 mapped");
log_message(LOG_DEBUG, "xhci: controller found, BAR0 mapped");
return 0;
}
@@ -95,12 +95,15 @@ static int xhci_wait_bit(volatile uint32_t *reg, uint32_t mask, int want_set,
}
}
/* console_println() only takes a string literal -- no formatted print
* exists on this driver's console path. Matches the established pattern
* elsewhere in this kernel (e.g. src/starkernel/vm/parity.c's
* print_hex64()) rather than adding one: a small static hex-dump helper,
* "label: 0xXXXXXXXX". Debugging register values without this is
* guesswork. */
/* log_message()'s own %x has no zero-padding/width control (starkernel/
* log.h's kvsnprintf() is a minimal freestanding formatter), so this
* small hex-dump helper is kept for its fixed 8-digit "0xXXXXXXXX" width
* -- register values line up in the log this way. Routed through
* log_message(LOG_DEBUG, ...) rather than console_puts()/console_println()
* directly (was the reason this helper existed at all, before log.h's
* formatted print was available to this driver) so every xHCI register
* dump is silenced at the default LOG_INFO level, same as the rest of
* this file's routine chatter -- re-enable with --log-level=debug. */
static void xhci_log_hex32(const char *label, uint32_t val)
{
char buf[11];
@@ -112,8 +115,7 @@ static void xhci_log_hex32(const char *label, uint32_t val)
val >>= 4;
}
buf[10] = '\0';
console_puts(label);
console_println(buf);
log_message(LOG_DEBUG, "%s%s", label, buf);
}
/* Only one controller is supported (matches xhci_dev_t's own doc comment);
@@ -165,7 +167,7 @@ int xhci_bringup(xhci_dev_t *dev)
if (dev->op->usb_cmd & XHCI_USBCMD_RUN) {
dev->op->usb_cmd &= ~XHCI_USBCMD_RUN;
if (xhci_wait_bit(&dev->op->usb_sts, XHCI_USBSTS_HCH, 1, 10000) != 0) {
console_println("xhci: timeout waiting for halt before reset");
log_message(LOG_ERROR, "xhci: timeout waiting for halt before reset");
return -1;
}
}
@@ -175,11 +177,11 @@ int xhci_bringup(xhci_dev_t *dev)
* register. */
dev->op->usb_cmd |= XHCI_USBCMD_HCRST;
if (xhci_wait_bit(&dev->op->usb_cmd, XHCI_USBCMD_HCRST, 0, 10000) != 0) {
console_println("xhci: timeout waiting for HCRST to self-clear");
log_message(LOG_ERROR, "xhci: timeout waiting for HCRST to self-clear");
return -1;
}
if (xhci_wait_bit(&dev->op->usb_sts, XHCI_USBSTS_CNR, 0, 10000) != 0) {
console_println("xhci: timeout waiting for CNR to clear");
log_message(LOG_ERROR, "xhci: timeout waiting for CNR to clear");
return -1;
}
@@ -189,7 +191,7 @@ int xhci_bringup(xhci_dev_t *dev)
size_t dcbaa_bytes = (size_t)(dev->max_slots + 1) * sizeof(uint64_t);
dev->dcbaa = kmalloc_aligned(dcbaa_bytes, 64);
if (!dev->dcbaa) {
console_println("xhci: DCBAA allocation failed");
log_message(LOG_ERROR, "xhci: DCBAA allocation failed");
return -2;
}
for (size_t i = 0; i < dcbaa_bytes / sizeof(uint64_t); i++) {
@@ -209,13 +211,13 @@ int xhci_bringup(xhci_dev_t *dev)
size_t arr_bytes = (size_t)dev->max_scratchpad_bufs * sizeof(uint64_t);
dev->scratchpad_arr = kmalloc_aligned(arr_bytes, 64);
if (!dev->scratchpad_arr) {
console_println("xhci: scratchpad array allocation failed");
log_message(LOG_ERROR, "xhci: scratchpad array allocation failed");
return -2;
}
for (uint32_t i = 0; i < dev->max_scratchpad_bufs; i++) {
void *buf = kmalloc_aligned(page_bytes, page_bytes);
if (!buf) {
console_println("xhci: scratchpad buffer allocation failed");
log_message(LOG_ERROR, "xhci: scratchpad buffer allocation failed");
return -2;
}
((uint64_t *)dev->scratchpad_arr)[i] = (uint64_t)(uintptr_t)buf;
@@ -231,7 +233,7 @@ int xhci_bringup(xhci_dev_t *dev)
* is consumed). CRCR low bits carry RCS, not the TRBs themselves. */
dev->cmd_ring = (xhci_trb_t *)kmalloc_aligned(XHCI_RING_BYTES, 64);
if (!dev->cmd_ring) {
console_println("xhci: command ring allocation failed");
log_message(LOG_ERROR, "xhci: command ring allocation failed");
return -2;
}
for (uint32_t i = 0; i < XHCI_RING_TRB_COUNT; i++) {
@@ -264,7 +266,7 @@ int xhci_bringup(xhci_dev_t *dev)
* (single-interrupter design decided in 2a). */
dev->evt_ring = (xhci_trb_t *)kmalloc_aligned(XHCI_RING_BYTES, 64);
if (!dev->evt_ring) {
console_println("xhci: event ring allocation failed");
log_message(LOG_ERROR, "xhci: event ring allocation failed");
return -2;
}
for (uint32_t i = 0; i < XHCI_RING_TRB_COUNT; i++) {
@@ -279,7 +281,7 @@ int xhci_bringup(xhci_dev_t *dev)
* reserved = 16 bytes. One segment is enough (ERST Max >= 1 always). */
dev->evt_ring_seg_table = kmalloc_aligned(16, 64);
if (!dev->evt_ring_seg_table) {
console_println("xhci: event ring segment table allocation failed");
log_message(LOG_ERROR, "xhci: event ring segment table allocation failed");
return -2;
}
uint64_t *erst = (uint64_t *)dev->evt_ring_seg_table;
@@ -298,7 +300,7 @@ int xhci_bringup(xhci_dev_t *dev)
dev->op->usb_cmd |= XHCI_USBCMD_RUN;
if (xhci_wait_bit(&dev->op->usb_sts, XHCI_USBSTS_HCH, 0, 10000) != 0) {
console_println("xhci: controller did not leave halted state after RUN");
log_message(LOG_ERROR, "xhci: controller did not leave halted state after RUN");
return -3;
}
@@ -349,12 +351,12 @@ int xhci_bringup(xhci_dev_t *dev)
dev->next_action_length = 0;
dev->next_action_config_value = 0;
console_println("xhci: controller running");
log_message(LOG_DEBUG, "xhci: controller running");
/* Milestone 2e prep: HCCPARAMS1.CSZ decides 32- vs 64-byte Slot/
* Endpoint/Input Context layout for Address Device -- must be read
* live, not assumed, before any context structure is designed. */
xhci_log_hex32("xhci: hcc_params1=", dev->cap->hcc_params1);
console_println(XHCI_HCCPARAMS1_CSZ(dev->cap->hcc_params1)
log_message(LOG_DEBUG, XHCI_HCCPARAMS1_CSZ(dev->cap->hcc_params1)
? "xhci: context size = 64 bytes"
: "xhci: context size = 32 bytes");
@@ -420,7 +422,7 @@ int xhci_cmd_enable_slot(xhci_dev_t *dev)
{
if (!dev || !dev->cmd_ring) return -1;
xhci_submit_command(dev, 0, 0, XHCI_TRB_TYPE_ENABLE_SLOT_CMD, 0);
console_println("xhci: enable slot command submitted");
log_message(LOG_DEBUG, "xhci: enable slot command submitted");
return 0;
}
@@ -430,7 +432,7 @@ int xhci_cmd_disable_slot(xhci_dev_t *dev, uint32_t slot_id)
/* Slot ID goes in control[31:24], same field Address Device uses --
* no parameter/status payload needed, this command just names a slot. */
xhci_submit_command(dev, 0, 0, XHCI_TRB_TYPE_DISABLE_SLOT_CMD, slot_id << 24);
console_println("xhci: disable slot command submitted");
log_message(LOG_DEBUG, "xhci: disable slot command submitted");
return 0;
}
@@ -454,7 +456,7 @@ int xhci_cmd_address_device(xhci_dev_t *dev, uint32_t slot_id,
if (!dev || !dev->cmd_ring || !dev->dcbaa) return -1;
if (XHCI_HCCPARAMS1_CSZ(dev->cap->hcc_params1)) {
console_println("xhci: 64-byte contexts required, not implemented -- refusing");
log_message(LOG_ERROR, "xhci: 64-byte contexts required, not implemented -- refusing");
return -2;
}
@@ -529,7 +531,7 @@ int xhci_cmd_address_device(xhci_dev_t *dev, uint32_t slot_id,
xhci_submit_command(dev, (uint64_t)(uintptr_t)dev->input_ctx, 0,
XHCI_TRB_TYPE_ADDRESS_DEVICE_CMD, slot_id << 24);
console_println("xhci: address device command submitted");
log_message(LOG_DEBUG, "xhci: address device command submitted");
return 0;
}
@@ -555,7 +557,7 @@ int xhci_cmd_configure_endpoint(xhci_dev_t *dev, uint32_t slot_id)
if (dev->bulk_in_ep_addr == 0 || dev->bulk_out_ep_addr == 0) return -1;
if (XHCI_HCCPARAMS1_CSZ(dev->cap->hcc_params1)) {
console_println("xhci: 64-byte contexts required, not implemented -- refusing");
log_message(LOG_ERROR, "xhci: 64-byte contexts required, not implemented -- refusing");
return -2;
}
@@ -667,7 +669,7 @@ int xhci_cmd_configure_endpoint(xhci_dev_t *dev, uint32_t slot_id)
xhci_submit_command(dev, (uint64_t)(uintptr_t)dev->input_ctx, 0,
XHCI_TRB_TYPE_CONFIGURE_ENDPOINT_CMD, slot_id << 24);
console_println("xhci: configure endpoint command submitted");
log_message(LOG_DEBUG, "xhci: configure endpoint command submitted");
return 0;
}
@@ -685,7 +687,7 @@ int xhci_cmd_reset_endpoint(xhci_dev_t *dev, uint32_t slot_id, uint32_t ep_id)
if (dci == 0) return -1; /* EP0 (DCI 1) is the only non-bulk case -- refuse */
xhci_submit_command(dev, (uint64_t)dci << 24, 0,
XHCI_TRB_TYPE_RESET_ENDPOINT_CMD, slot_id << 24);
console_println("xhci: reset endpoint command submitted");
log_message(LOG_DEBUG, "xhci: reset endpoint command submitted");
return 0;
}
@@ -712,7 +714,7 @@ int xhci_cmd_set_tr_dequeue_pointer(xhci_dev_t *dev, uint32_t slot_id,
uint64_t param = (new_dequeue & ~0xFULL) | (uint64_t)(dcs ? 1u : 0u);
xhci_submit_command(dev, param, 0,
XHCI_TRB_TYPE_SET_TR_DEQUEUE_POINTER_CMD, slot_id << 24);
console_println("xhci: set TR dequeue pointer command submitted");
log_message(LOG_DEBUG, "xhci: set TR dequeue pointer command submitted");
return 0;
}
@@ -803,7 +805,7 @@ int xhci_bot_send_read10(xhci_dev_t *dev, uint32_t slot_id, uint32_t lba,
USB_BOT_CBW_LENGTH,
(XHCI_TRB_TYPE_NORMAL << XHCI_TRB_CONTROL_TYPE_SHIFT) |
XHCI_TRB_CONTROL_IOC);
console_println("xhci: CBW (READ10) submitted");
log_message(LOG_DEBUG, "xhci: CBW (READ10) submitted");
return 0;
}
@@ -851,7 +853,7 @@ int xhci_bot_send_write10(xhci_dev_t *dev, uint32_t slot_id, uint32_t lba,
USB_BOT_CBW_LENGTH,
(XHCI_TRB_TYPE_NORMAL << XHCI_TRB_CONTROL_TYPE_SHIFT) |
XHCI_TRB_CONTROL_IOC);
console_println("xhci: CBW (WRITE10) submitted");
log_message(LOG_DEBUG, "xhci: CBW (WRITE10) submitted");
return 0;
}
@@ -881,7 +883,7 @@ int xhci_bot_send_test_unit_ready(xhci_dev_t *dev, uint32_t slot_id)
USB_BOT_CBW_LENGTH,
(XHCI_TRB_TYPE_NORMAL << XHCI_TRB_CONTROL_TYPE_SHIFT) |
XHCI_TRB_CONTROL_IOC);
console_println("xhci: CBW (TEST UNIT READY) submitted");
log_message(LOG_DEBUG, "xhci: CBW (TEST UNIT READY) submitted");
return 0;
}
@@ -915,7 +917,7 @@ int xhci_bot_send_read_capacity10(xhci_dev_t *dev, uint32_t slot_id)
USB_BOT_CBW_LENGTH,
(XHCI_TRB_TYPE_NORMAL << XHCI_TRB_CONTROL_TYPE_SHIFT) |
XHCI_TRB_CONTROL_IOC);
console_println("xhci: CBW (READ CAPACITY10) submitted");
log_message(LOG_DEBUG, "xhci: CBW (READ CAPACITY10) submitted");
return 0;
}
@@ -1009,7 +1011,7 @@ int xhci_bot_read_data_in(xhci_dev_t *dev, uint32_t slot_id)
dev->bot_expected_data_len,
(XHCI_TRB_TYPE_NORMAL << XHCI_TRB_CONTROL_TYPE_SHIFT) |
XHCI_TRB_CONTROL_IOC);
console_println("xhci: BOT Data-In read submitted");
log_message(LOG_DEBUG, "xhci: BOT Data-In read submitted");
return 0;
}
@@ -1024,7 +1026,7 @@ int xhci_bot_write_data_out(xhci_dev_t *dev, uint32_t slot_id)
dev->bot_expected_data_len,
(XHCI_TRB_TYPE_NORMAL << XHCI_TRB_CONTROL_TYPE_SHIFT) |
XHCI_TRB_CONTROL_IOC);
console_println("xhci: BOT Data-Out write submitted");
log_message(LOG_DEBUG, "xhci: BOT Data-Out write submitted");
return 0;
}
@@ -1041,7 +1043,7 @@ int xhci_bot_receive_csw(xhci_dev_t *dev, uint32_t slot_id)
USB_BOT_CSW_LENGTH,
(XHCI_TRB_TYPE_NORMAL << XHCI_TRB_CONTROL_TYPE_SHIFT) |
XHCI_TRB_CONTROL_IOC);
console_println("xhci: CSW receive submitted");
log_message(LOG_DEBUG, "xhci: CSW receive submitted");
return 0;
}
@@ -1133,7 +1135,7 @@ int xhci_ep0_get_device_descriptor(xhci_dev_t *dev, uint32_t slot_id)
* 6-25 -- distinct from doorbell[0], which is always the Command
* Ring regardless of slot. */
dev->doorbell[slot_id] = XHCI_DB_TARGET(1);
console_println("xhci: get device descriptor submitted");
log_message(LOG_DEBUG, "xhci: get device descriptor submitted");
return 0;
}
@@ -1158,7 +1160,7 @@ int xhci_ep0_get_config_descriptor(xhci_dev_t *dev, uint32_t slot_id, uint16_t l
dev->pending_transfer_slot_id = slot_id;
dev->doorbell[slot_id] = XHCI_DB_TARGET(1);
console_println("xhci: get config descriptor submitted");
log_message(LOG_DEBUG, "xhci: get config descriptor submitted");
return 0;
}
@@ -1201,7 +1203,7 @@ int xhci_ep0_set_configuration(xhci_dev_t *dev, uint32_t slot_id, uint8_t config
dev->pending_transfer_slot_id = slot_id;
dev->doorbell[slot_id] = XHCI_DB_TARGET(1);
console_println("xhci: set configuration submitted");
log_message(LOG_DEBUG, "xhci: set configuration submitted");
return 0;
}
@@ -1225,7 +1227,7 @@ int xhci_ep0_clear_endpoint_halt(xhci_dev_t *dev, uint32_t slot_id, uint8_t ep_a
dev->pending_transfer_slot_id = slot_id;
dev->doorbell[slot_id] = XHCI_DB_TARGET(1);
console_println("xhci: clear endpoint halt submitted");
log_message(LOG_DEBUG, "xhci: clear endpoint halt submitted");
return 0;
}
@@ -1263,7 +1265,7 @@ int xhci_ep0_bot_mass_storage_reset(xhci_dev_t *dev, uint32_t slot_id)
dev->transfer_purpose = XHCI_XFER_BOT_RESET;
dev->pending_transfer_slot_id = slot_id;
dev->doorbell[slot_id] = XHCI_DB_TARGET(1);
console_println("xhci: BOT mass storage reset submitted");
log_message(LOG_DEBUG, "xhci: BOT mass storage reset submitted");
return 0;
}
@@ -1297,14 +1299,14 @@ static xhci_port_regs_t *xhci_port_regs(xhci_dev_t *dev, uint32_t port_id)
* controller bring-up, not just one detected via a later hotplug event. */
static void xhci_handle_port_connected(xhci_dev_t *dev, uint32_t port_id, uint32_t portsc)
{
console_println("xhci: port status change -- device connected");
log_message(LOG_DEBUG, "xhci: port status change -- device connected");
/* Milestone 2e prep: Address Device requires the port in Default
* state. USB3 links train and enable themselves; USB2 needs software
* to drive PORTSC.PR and wait for PRC/PED before the device will
* respond to addressing -- not yet known which this driver's ports
* need, so log raw PORTSC and PED rather than assume. */
xhci_log_hex32("xhci: portsc=", portsc);
console_println((portsc & XHCI_PORTSC_PED)
log_message(LOG_DEBUG, (portsc & XHCI_PORTSC_PED)
? "xhci: port enabled (PED set)"
: "xhci: port not yet enabled (PED clear)");
/* Only one Enable Slot in flight at a time (see xhci_dev_t's doc
@@ -1313,14 +1315,14 @@ static void xhci_handle_port_connected(xhci_dev_t *dev, uint32_t port_id, uint32
* milestone's single-device testing scope; revisit if multi-port
* simultaneous connects become a real scenario. */
if (port_id > XHCI_MAX_TRACKED_PORTS) {
console_println("xhci: port beyond tracked range -- enable slot skipped");
log_message(LOG_WARN, "xhci: port beyond tracked range -- enable slot skipped");
} else if (dev->connect_state == XHCI_CONN_IDLE) {
dev->pending_connect_port_id = port_id;
dev->pending_connect_speed = XHCI_PORTSC_SPEED(portsc);
dev->connect_state = XHCI_CONN_AWAIT_ENABLE_SLOT;
xhci_cmd_enable_slot(dev);
} else {
console_println("xhci: enable slot already pending -- dropped");
log_message(LOG_WARN, "xhci: enable slot already pending -- dropped");
}
}
@@ -1349,7 +1351,7 @@ static void xhci_scan_ports_for_already_connected(xhci_dev_t *dev)
uint32_t portsc = port->portsc;
if (!(portsc & XHCI_PORTSC_CCS)) continue;
console_println("xhci: device already connected at bring-up");
log_message(LOG_DEBUG, "xhci: device already connected at bring-up");
xhci_handle_port_connected(dev, port_id, portsc);
/* Acknowledge CSC the same way xhci_poll_events() does, in case
* the controller latched it during reset -- harmless if it was
@@ -1368,7 +1370,7 @@ static void xhci_scan_ports_for_already_connected(xhci_dev_t *dev)
* pre-G.1 un-recovered stall did. */
static void xhci_stall_fail(xhci_dev_t *dev)
{
console_println("xhci: stall recovery exhausted -- failing command cleanly");
log_message(LOG_ERROR, "xhci: stall recovery exhausted -- failing command cleanly");
dev->bot_last_status = BOT_STATUS_FAILED;
dev->bot_cmd_kind = BOT_CMD_NONE;
dev->stall_retry_action = XHCI_NEXT_ACTION_NONE;
@@ -1453,7 +1455,7 @@ static void xhci_handle_bulk_stall(xhci_dev_t *dev, uint32_t slot_id,
}
dev->bot_stall_recoveries++;
console_println("xhci: bulk endpoint STALL -- starting recovery");
log_message(LOG_WARN, "xhci: bulk endpoint STALL -- starting recovery");
if (dev->bot_stall_recoveries == 1) {
/* First recovery: the basic xHCI-level Reset Endpoint sequence
* (commands are submitted synchronously -- they ring doorbell 0,
@@ -1461,7 +1463,7 @@ static void xhci_handle_bulk_stall(xhci_dev_t *dev, uint32_t slot_id,
* doorbells are deferred). */
dev->connect_state = XHCI_CONN_AWAIT_RESET_ENDPOINT;
if (xhci_cmd_reset_endpoint(dev, slot_id, dev->stall_ep_addr) != 0) {
console_println("xhci: reset endpoint submit failed -- stalling out clean");
log_message(LOG_ERROR, "xhci: reset endpoint submit failed -- stalling out clean");
dev->connect_state = XHCI_CONN_IDLE;
xhci_stall_fail(dev);
}
@@ -1496,14 +1498,14 @@ void xhci_poll_events(void)
uint32_t port_id = XHCI_PSC_EVT_PORT_ID(trb->parameter);
xhci_port_regs_t *port = xhci_port_regs(dev, port_id);
if (!port) {
console_println("xhci: port status change event (bad port id)");
log_message(LOG_WARN, "xhci: port status change event (bad port id)");
break;
}
uint32_t portsc = port->portsc;
if (portsc & XHCI_PORTSC_CCS) {
xhci_handle_port_connected(dev, port_id, portsc);
} else {
console_println("xhci: port status change -- device disconnected");
log_message(LOG_DEBUG, "xhci: port status change -- device disconnected");
if (port_id >= 1 && port_id <= XHCI_MAX_TRACKED_PORTS &&
dev->port_slot_id[port_id - 1] != 0) {
uint32_t disconnecting_slot_id = dev->port_slot_id[port_id - 1];
@@ -1534,7 +1536,7 @@ void xhci_poll_events(void)
* no longer references it, and a genuinely
* concurrent connect/disconnect pair isn't
* this driver's current scope). */
console_println("xhci: disable slot skipped -- command ring busy");
log_message(LOG_WARN, "xhci: disable slot skipped -- command ring busy");
}
}
}
@@ -1563,22 +1565,22 @@ void xhci_poll_events(void)
port_id >= 1 && port_id <= XHCI_MAX_TRACKED_PORTS) {
dev->port_slot_id[port_id - 1] = slot_id;
dev->pending_connect_slot_id = slot_id;
console_println("xhci: enable slot succeeded");
log_message(LOG_DEBUG, "xhci: enable slot succeeded");
dev->connect_state = XHCI_CONN_AWAIT_ADDRESS_DEVICE;
if (xhci_cmd_address_device(dev, slot_id, port_id,
dev->pending_connect_speed) != 0) {
console_println("xhci: address device setup failed");
log_message(LOG_ERROR, "xhci: address device setup failed");
dev->connect_state = XHCI_CONN_IDLE;
dev->pending_connect_port_id = 0;
}
} else {
console_println("xhci: enable slot failed");
log_message(LOG_ERROR, "xhci: enable slot failed");
dev->connect_state = XHCI_CONN_IDLE;
dev->pending_connect_port_id = 0;
}
} else if (dev->connect_state == XHCI_CONN_AWAIT_ADDRESS_DEVICE) {
if (code == XHCI_COMPLETION_CODE_SUCCESS) {
console_println("xhci: address device succeeded");
log_message(LOG_DEBUG, "xhci: address device succeeded");
/* Milestone 2f: enumeration starts here -- the
* device now has a USB address and EP0 is
* usable for control transfers. Deferred (see
@@ -1587,7 +1589,7 @@ void xhci_poll_events(void)
dev->next_action = XHCI_NEXT_ACTION_GET_DEVICE_DESC;
dev->next_action_slot_id = dev->pending_connect_slot_id;
} else {
console_println("xhci: address device failed");
log_message(LOG_ERROR, "xhci: address device failed");
}
dev->connect_state = XHCI_CONN_IDLE;
dev->pending_connect_port_id = 0;
@@ -1601,15 +1603,15 @@ void xhci_poll_events(void)
* references this slot either way, so nothing
* else in this driver will look at it again. */
((uint64_t *)dev->dcbaa)[dev->pending_disable_slot_id] = 0;
console_println("xhci: disable slot succeeded");
log_message(LOG_DEBUG, "xhci: disable slot succeeded");
} else {
console_println("xhci: disable slot failed");
log_message(LOG_ERROR, "xhci: disable slot failed");
}
dev->connect_state = XHCI_CONN_IDLE;
dev->pending_disable_slot_id = 0;
} else if (dev->connect_state == XHCI_CONN_AWAIT_CONFIGURE_ENDPOINT) {
if (code == XHCI_COMPLETION_CODE_SUCCESS) {
console_println("xhci: configure endpoint succeeded");
log_message(LOG_DEBUG, "xhci: configure endpoint succeeded");
/* Chain into SET_CONFIGURATION -- next_action_
* slot_id/next_action_config_value are still the
* values staged when this Configure Endpoint was
@@ -1619,7 +1621,7 @@ void xhci_poll_events(void)
* fields, so they're still valid to reuse here. */
dev->next_action = XHCI_NEXT_ACTION_SET_CONFIG;
} else {
console_println("xhci: configure endpoint failed");
log_message(LOG_ERROR, "xhci: configure endpoint failed");
}
dev->connect_state = XHCI_CONN_IDLE;
} else if (dev->connect_state == XHCI_CONN_AWAIT_RESET_ENDPOINT) {
@@ -1633,7 +1635,7 @@ void xhci_poll_events(void)
* enqueued retry TRB is consumed cleanly. stall_dci
* tells which ring. */
if (code == XHCI_COMPLETION_CODE_SUCCESS) {
console_println("xhci: reset endpoint succeeded");
log_message(LOG_DEBUG, "xhci: reset endpoint succeeded");
uintptr_t new_dequeue;
uint32_t dcs;
if (dev->stall_ep_addr & USB_EP_ADDR_DIR_MASK) {
@@ -1647,7 +1649,7 @@ void xhci_poll_events(void)
if (xhci_cmd_set_tr_dequeue_pointer(dev, slot_id,
dev->stall_ep_addr,
new_dequeue, dcs) != 0) {
console_println("xhci: set tr dequeue pointer submit failed");
log_message(LOG_ERROR, "xhci: set tr dequeue pointer submit failed");
dev->connect_state = XHCI_CONN_IDLE;
/* Recovery couldn't even be issued -- clean
* terminal failure so the synchronous waiter
@@ -1655,7 +1657,7 @@ void xhci_poll_events(void)
xhci_stall_fail(dev);
}
} else {
console_println("xhci: reset endpoint failed -- stalling out clean");
log_message(LOG_ERROR, "xhci: reset endpoint failed -- stalling out clean");
dev->connect_state = XHCI_CONN_IDLE;
xhci_stall_fail(dev);
}
@@ -1666,9 +1668,9 @@ void xhci_poll_events(void)
* halt cleared via control transfer, so chain into the
* deferred CLEAR_FEATURE(ENDPOINT_HALT). */
if (code == XHCI_COMPLETION_CODE_SUCCESS) {
console_println("xhci: set TR dequeue pointer succeeded");
log_message(LOG_DEBUG, "xhci: set TR dequeue pointer succeeded");
} else {
console_println("xhci: set TR dequeue pointer failed -- stalling out clean");
log_message(LOG_ERROR, "xhci: set TR dequeue pointer failed -- stalling out clean");
xhci_stall_fail(dev);
}
dev->connect_state = XHCI_CONN_IDLE;
@@ -1678,7 +1680,7 @@ void xhci_poll_events(void)
dev->next_action_slot_id = slot_id;
}
} else {
console_println("xhci: command completion event");
log_message(LOG_DEBUG, "xhci: command completion event");
}
break;
}
@@ -1702,14 +1704,14 @@ void xhci_poll_events(void)
xhci_bulk_purpose_stalled(dev, purpose)) {
xhci_handle_bulk_stall(dev, xfer_slot_id, purpose);
} else {
console_println("xhci: control transfer failed");
log_message(LOG_ERROR, "xhci: control transfer failed");
}
break;
}
switch (purpose) {
case XHCI_XFER_DEVICE_DESC: {
console_println("xhci: device descriptor received");
log_message(LOG_DEBUG, "xhci: device descriptor received");
/* USB 2.0 spec table 9-8 layout. Logged --
* 2f's own punch list asked whether vendor/
* product IDs are even needed, or class-only
@@ -1748,7 +1750,7 @@ void xhci_poll_events(void)
break;
}
case XHCI_XFER_CONFIG_DESC_FULL: {
console_println("xhci: full config descriptor received");
log_message(LOG_DEBUG, "xhci: full config descriptor received");
/* Walk the concatenated descriptor stream
* (Config + Interface + Endpoint descriptors
* back to back) looking for the Interface
@@ -1774,7 +1776,7 @@ void xhci_poll_events(void)
if (iface_class == USB_CLASS_MASS_STORAGE &&
iface_subclass == USB_SUBCLASS_SCSI &&
iface_protocol == USB_PROTOCOL_BOT) {
console_println("xhci: confirmed Mass Storage / SCSI / BOT device");
log_message(LOG_DEBUG, "xhci: confirmed Mass Storage / SCSI / BOT device");
/* Walk the Endpoint descriptors that
* follow this Interface descriptor,
* stopping at the next Interface
@@ -1832,14 +1834,14 @@ void xhci_poll_events(void)
* separate rather than
* failing enumeration
* outright). */
console_println("xhci: warning -- BOT device missing a bulk IN or OUT endpoint, skipping configure endpoint");
log_message(LOG_WARN, "xhci: warning -- BOT device missing a bulk IN or OUT endpoint, skipping configure endpoint");
dev->next_action = XHCI_NEXT_ACTION_SET_CONFIG;
} else {
dev->next_action = XHCI_NEXT_ACTION_CONFIGURE_ENDPOINT;
}
dev->next_action_slot_id = xfer_slot_id;
} else {
console_println("xhci: not a Mass Storage/SCSI/BOT device -- not usable as a drive");
log_message(LOG_WARN, "xhci: not a Mass Storage/SCSI/BOT device -- not usable as a drive");
}
found = 1;
break;
@@ -1847,12 +1849,12 @@ void xhci_poll_events(void)
off = (uint16_t)(off + desc_len);
}
if (!found) {
console_println("xhci: no Interface descriptor found in config set");
log_message(LOG_WARN, "xhci: no Interface descriptor found in config set");
}
break;
}
case XHCI_XFER_SET_CONFIG: {
console_println("xhci: device configured");
log_message(LOG_DEBUG, "xhci: device configured");
/* Milestone 2h: hand off to sk_repl_idle(),
* the only safe place to run the synchronous
* capacity query + block-subsystem attach --
@@ -1863,7 +1865,7 @@ void xhci_poll_events(void)
break;
}
case XHCI_XFER_CBW_SENT: {
console_println("xhci: CBW send completed");
log_message(LOG_DEBUG, "xhci: CBW send completed");
/* Deferred (see xhci_dev_t's next_action doc
* comment) rather than called directly --
* same doorbell-ordering hazard as every
@@ -1887,13 +1889,13 @@ void xhci_poll_events(void)
break;
}
case XHCI_XFER_BOT_DATA_IN: {
console_println("xhci: BOT Data-In read completed");
log_message(LOG_DEBUG, "xhci: BOT Data-In read completed");
dev->next_action = XHCI_NEXT_ACTION_BOT_CSW_RECEIVE;
dev->next_action_slot_id = xfer_slot_id;
break;
}
case XHCI_XFER_BOT_DATA_OUT: {
console_println("xhci: BOT Data-Out write completed");
log_message(LOG_DEBUG, "xhci: BOT Data-Out write completed");
dev->next_action = XHCI_NEXT_ACTION_BOT_CSW_RECEIVE;
dev->next_action_slot_id = xfer_slot_id;
break;
@@ -1906,12 +1908,12 @@ void xhci_poll_events(void)
* or misaligned CSW read could otherwise be
* misread as a clean pass. */
if (dev->bot_csw.dCSWSignature != USB_BOT_CSW_SIGNATURE) {
console_println("xhci: CSW signature mismatch -- discarding");
log_message(LOG_ERROR, "xhci: CSW signature mismatch -- discarding");
dev->bot_last_status = BOT_STATUS_FAILED;
dev->bot_cmd_kind = BOT_CMD_NONE;
break;
} else if (dev->bot_csw.dCSWTag != dev->bot_last_tag) {
console_println("xhci: CSW tag mismatch -- discarding");
log_message(LOG_ERROR, "xhci: CSW tag mismatch -- discarding");
dev->bot_last_status = BOT_STATUS_FAILED;
dev->bot_cmd_kind = BOT_CMD_NONE;
break;
@@ -1919,11 +1921,11 @@ void xhci_poll_events(void)
int csw_pass = (dev->bot_csw.bCSWStatus == USB_BOT_CSW_STATUS_PASS);
if (csw_pass) {
console_println("xhci: CSW status = PASS");
log_message(LOG_DEBUG, "xhci: CSW status = PASS");
} else if (dev->bot_csw.bCSWStatus == USB_BOT_CSW_STATUS_FAILED) {
console_println("xhci: CSW status = FAILED");
log_message(LOG_ERROR, "xhci: CSW status = FAILED");
} else {
console_println("xhci: CSW status = PHASE ERROR");
log_message(LOG_ERROR, "xhci: CSW status = PHASE ERROR");
}
xhci_log_hex32("xhci: CSW data residue=", dev->bot_csw.dCSWDataResidue);
@@ -1941,23 +1943,23 @@ void xhci_poll_events(void)
if (dev->bot_cmd_kind == BOT_CMD_TEST_UNIT_READY) {
if (csw_pass) {
if (dev->bot_tur_chain_target == BOT_TUR_CHAIN_READ_CAPACITY10) {
console_println("xhci: unit ready -- issuing READ CAPACITY10");
log_message(LOG_DEBUG, "xhci: unit ready -- issuing READ CAPACITY10");
dev->next_action = XHCI_NEXT_ACTION_BOT_SEND_READ_CAPACITY10;
} else if (dev->bot_tur_chain_target == BOT_TUR_CHAIN_WRITE10) {
console_println("xhci: unit ready -- issuing WRITE10");
log_message(LOG_DEBUG, "xhci: unit ready -- issuing WRITE10");
dev->next_action = XHCI_NEXT_ACTION_BOT_SEND_WRITE10;
} else {
console_println("xhci: unit ready -- issuing READ10");
log_message(LOG_DEBUG, "xhci: unit ready -- issuing READ10");
dev->next_action = XHCI_NEXT_ACTION_BOT_SEND_READ10;
}
dev->next_action_slot_id = xfer_slot_id;
} else if (dev->bot_tur_retries < XHCI_BOT_TUR_MAX_RETRIES) {
dev->bot_tur_retries++;
console_println("xhci: unit not ready -- retrying TEST UNIT READY");
log_message(LOG_WARN, "xhci: unit not ready -- retrying TEST UNIT READY");
dev->next_action = XHCI_NEXT_ACTION_BOT_SEND_TUR;
dev->next_action_slot_id = xfer_slot_id;
} else {
console_println("xhci: unit still not ready -- giving up");
log_message(LOG_ERROR, "xhci: unit still not ready -- giving up");
dev->bot_last_status = BOT_STATUS_FAILED;
dev->bot_cmd_kind = BOT_CMD_NONE;
}
@@ -1998,12 +2000,12 @@ void xhci_poll_events(void)
* from §F.14 -- escalate to a full BOT Mass
* Storage Reset. */
if (code != XHCI_COMPLETION_CODE_SUCCESS) {
console_println("xhci: clear endpoint halt failed -- escalating to BOT reset");
log_message(LOG_ERROR, "xhci: clear endpoint halt failed -- escalating to BOT reset");
dev->next_action = XHCI_NEXT_ACTION_BOT_RESET;
dev->next_action_slot_id = xfer_slot_id;
break;
}
console_println("xhci: clear endpoint halt succeeded");
log_message(LOG_DEBUG, "xhci: clear endpoint halt succeeded");
if (dev->bot_reset_clear_remaining > 1) {
dev->bot_reset_clear_remaining--;
/* Flip to the other bulk endpoint for the
@@ -2033,11 +2035,11 @@ void xhci_poll_events(void)
* command is retried; stage that as two
* chained CLEAR_HALT transfers. */
if (code != XHCI_COMPLETION_CODE_SUCCESS) {
console_println("xhci: BOT reset failed -- stalling out clean");
log_message(LOG_ERROR, "xhci: BOT reset failed -- stalling out clean");
xhci_stall_fail(dev);
break;
}
console_println("xhci: BOT reset succeeded -- clearing both endpoints");
log_message(LOG_DEBUG, "xhci: BOT reset succeeded -- clearing both endpoints");
dev->bot_reset_clear_remaining = 2;
dev->stall_ep_addr = dev->bulk_in_ep_addr;
dev->next_action = XHCI_NEXT_ACTION_CLEAR_HALT;
@@ -2045,11 +2047,11 @@ void xhci_poll_events(void)
break;
}
default:
console_println("xhci: transfer event");
log_message(LOG_DEBUG, "xhci: transfer event");
break;
}
} else {
console_println("xhci: transfer event");
log_message(LOG_DEBUG, "xhci: transfer event");
}
break;
}
@@ -2085,21 +2087,21 @@ void xhci_poll_events(void)
uint32_t next_slot_id = dev->next_action_slot_id;
dev->next_action = XHCI_NEXT_ACTION_NONE;
if (xhci_ep0_get_device_descriptor(dev, next_slot_id) != 0) {
console_println("xhci: deferred device descriptor request setup failed");
log_message(LOG_ERROR, "xhci: deferred device descriptor request setup failed");
}
} else if (dev->next_action == XHCI_NEXT_ACTION_GET_CONFIG_DESC) {
uint32_t next_slot_id = dev->next_action_slot_id;
uint16_t next_length = dev->next_action_length;
dev->next_action = XHCI_NEXT_ACTION_NONE;
if (xhci_ep0_get_config_descriptor(dev, next_slot_id, next_length) != 0) {
console_println("xhci: deferred config descriptor request setup failed");
log_message(LOG_ERROR, "xhci: deferred config descriptor request setup failed");
}
} else if (dev->next_action == XHCI_NEXT_ACTION_CONFIGURE_ENDPOINT) {
uint32_t next_slot_id = dev->next_action_slot_id;
dev->next_action = XHCI_NEXT_ACTION_NONE;
dev->connect_state = XHCI_CONN_AWAIT_CONFIGURE_ENDPOINT;
if (xhci_cmd_configure_endpoint(dev, next_slot_id) != 0) {
console_println("xhci: deferred configure endpoint request setup failed");
log_message(LOG_ERROR, "xhci: deferred configure endpoint request setup failed");
dev->connect_state = XHCI_CONN_IDLE;
}
} else if (dev->next_action == XHCI_NEXT_ACTION_SET_CONFIG) {
@@ -2107,31 +2109,31 @@ void xhci_poll_events(void)
uint8_t next_config_value = dev->next_action_config_value;
dev->next_action = XHCI_NEXT_ACTION_NONE;
if (xhci_ep0_set_configuration(dev, next_slot_id, next_config_value) != 0) {
console_println("xhci: deferred set configuration request setup failed");
log_message(LOG_ERROR, "xhci: deferred set configuration request setup failed");
}
} else if (dev->next_action == XHCI_NEXT_ACTION_BOT_DATA_IN) {
uint32_t next_slot_id = dev->next_action_slot_id;
dev->next_action = XHCI_NEXT_ACTION_NONE;
if (xhci_bot_read_data_in(dev, next_slot_id) != 0) {
console_println("xhci: deferred BOT Data-In read setup failed");
log_message(LOG_ERROR, "xhci: deferred BOT Data-In read setup failed");
}
} else if (dev->next_action == XHCI_NEXT_ACTION_BOT_DATA_OUT) {
uint32_t next_slot_id = dev->next_action_slot_id;
dev->next_action = XHCI_NEXT_ACTION_NONE;
if (xhci_bot_write_data_out(dev, next_slot_id) != 0) {
console_println("xhci: deferred BOT Data-Out write setup failed");
log_message(LOG_ERROR, "xhci: deferred BOT Data-Out write setup failed");
}
} else if (dev->next_action == XHCI_NEXT_ACTION_BOT_CSW_RECEIVE) {
uint32_t next_slot_id = dev->next_action_slot_id;
dev->next_action = XHCI_NEXT_ACTION_NONE;
if (xhci_bot_receive_csw(dev, next_slot_id) != 0) {
console_println("xhci: deferred CSW receive setup failed");
log_message(LOG_ERROR, "xhci: deferred CSW receive setup failed");
}
} else if (dev->next_action == XHCI_NEXT_ACTION_BOT_SEND_TUR) {
uint32_t next_slot_id = dev->next_action_slot_id;
dev->next_action = XHCI_NEXT_ACTION_NONE;
if (xhci_bot_send_test_unit_ready(dev, next_slot_id) != 0) {
console_println("xhci: deferred TEST UNIT READY retry setup failed");
log_message(LOG_ERROR, "xhci: deferred TEST UNIT READY retry setup failed");
}
} else if (dev->next_action == XHCI_NEXT_ACTION_BOT_SEND_READ10) {
uint32_t next_slot_id = dev->next_action_slot_id;
@@ -2139,13 +2141,13 @@ void xhci_poll_events(void)
if (xhci_bot_send_read10(dev, next_slot_id, dev->bot_read10_lba,
dev->bot_read10_num_blocks,
dev->bot_read10_block_size) != 0) {
console_println("xhci: deferred READ10 setup failed");
log_message(LOG_ERROR, "xhci: deferred READ10 setup failed");
}
} else if (dev->next_action == XHCI_NEXT_ACTION_BOT_SEND_READ_CAPACITY10) {
uint32_t next_slot_id = dev->next_action_slot_id;
dev->next_action = XHCI_NEXT_ACTION_NONE;
if (xhci_bot_send_read_capacity10(dev, next_slot_id) != 0) {
console_println("xhci: deferred READ CAPACITY10 setup failed");
log_message(LOG_ERROR, "xhci: deferred READ CAPACITY10 setup failed");
}
} else if (dev->next_action == XHCI_NEXT_ACTION_BOT_SEND_WRITE10) {
uint32_t next_slot_id = dev->next_action_slot_id;
@@ -2153,20 +2155,20 @@ void xhci_poll_events(void)
if (xhci_bot_send_write10(dev, next_slot_id, dev->bot_write10_lba,
dev->bot_write10_num_blocks,
dev->bot_write10_block_size) != 0) {
console_println("xhci: deferred WRITE10 setup failed");
log_message(LOG_ERROR, "xhci: deferred WRITE10 setup failed");
}
} else if (dev->next_action == XHCI_NEXT_ACTION_CLEAR_HALT) {
uint32_t next_slot_id = dev->next_action_slot_id;
dev->next_action = XHCI_NEXT_ACTION_NONE;
if (xhci_ep0_clear_endpoint_halt(dev, next_slot_id, dev->stall_ep_addr) != 0) {
console_println("xhci: deferred clear endpoint halt setup failed");
log_message(LOG_ERROR, "xhci: deferred clear endpoint halt setup failed");
xhci_stall_fail(dev);
}
} else if (dev->next_action == XHCI_NEXT_ACTION_BOT_RESET) {
uint32_t next_slot_id = dev->next_action_slot_id;
dev->next_action = XHCI_NEXT_ACTION_NONE;
if (xhci_ep0_bot_mass_storage_reset(dev, next_slot_id) != 0) {
console_println("xhci: deferred BOT mass storage reset setup failed");
log_message(LOG_ERROR, "xhci: deferred BOT mass storage reset setup failed");
xhci_stall_fail(dev);
}
}