Artemis Milestone 2e: PORTSC connect/disconnect detection, verified live
xhci_poll_events()'s Port Status Change branch now decodes the Port ID from the event TRB (XHCI_PSC_EVT_PORT_ID, new in xhci.h), reads that port's PORTSC.CCS via a new xhci_port_regs() helper, and logs connect vs. disconnect. Acknowledges by writing back only PP (preserved) and CSC (the bit being cleared) -- PED/PR/other _C bits written 0 so nothing is accidentally disabled, reset, or silently cleared, matching the RW1C discipline already used for ERDP.EHB in 2d. Verified with the real target scenario via QMP hotplug on all three architectures: boot with the xHCI controller present but no USB device attached (confirmed zero port activity at ok>), then live attach/detach/re-attach of a virtual USB thumb drive (disk/usb-thumbdrive-test.img via usb-storage on xhci0.0). Full connect->disconnect->connect cycle confirmed clean (no port wedge) on amd64; single connect confirmed on aarch64 and riscv64. Still open: correlating Command Completion Events back to their issuing command, driving Enable Slot/Address Device from this connect path (currently only a boot-time smoke test), and the callback surface into Section U's higher-level code. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HZ8kNoTuP63pbQtro4qvrm
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
bb84eba7e3
commit
dd043bbfeb
@@ -1,8 +1,9 @@
|
||||
/*
|
||||
* xhci.c — xHCI USB host controller driver for StarKernel: PCI discovery
|
||||
* (Milestone 2b), controller bring-up (2c), and polled Event Ring
|
||||
* servicing (2d). Hotplug/enumeration/BOT read-write (2e-2g) follow in
|
||||
* later increments.
|
||||
* (Milestone 2b), controller bring-up (2c), polled Event Ring servicing
|
||||
* (2d), and Command Ring submission + PORTSC connect/disconnect detection
|
||||
* (2e, in progress). Enumeration/BOT read-write (2f-2g) follow in later
|
||||
* increments.
|
||||
*
|
||||
* Memory model: BAR0 is mapped identity (virtual address == physical
|
||||
* address), matching virtio_blk.c's precedent and pci_map_bar()'s own
|
||||
@@ -321,6 +322,17 @@ int xhci_cmd_enable_slot(xhci_dev_t *dev)
|
||||
* out to be simply wrong).
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
/* Port Register Set array lives at Operational base + 0x400 (xhci.h's own
|
||||
* doc comment on xhci_port_regs_t) -- not reachable through xhci_op_regs_t
|
||||
* itself since it isn't a contiguous struct member. port_id is 1-based,
|
||||
* matching XHCI_PSC_EVT_PORT_ID()'s decode and the spec's own numbering. */
|
||||
static xhci_port_regs_t *xhci_port_regs(xhci_dev_t *dev, uint32_t port_id)
|
||||
{
|
||||
if (port_id < 1 || port_id > dev->max_ports) return NULL;
|
||||
return (xhci_port_regs_t *)((uint8_t *)dev->op + XHCI_PORT_REGS_OFFSET +
|
||||
(port_id - 1) * sizeof(xhci_port_regs_t));
|
||||
}
|
||||
|
||||
void xhci_poll_events(void)
|
||||
{
|
||||
xhci_dev_t *dev = g_xhci_dev;
|
||||
@@ -332,13 +344,31 @@ void xhci_poll_events(void)
|
||||
uint32_t type = XHCI_TRB_TYPE(trb->control);
|
||||
|
||||
switch (type) {
|
||||
case XHCI_TRB_TYPE_PORT_STATUS_CHANGE_EVT:
|
||||
/* Hotplug trigger -- full port-read/slot-enable handling is
|
||||
* Milestone 2e's scope, not this one's. Logged so the
|
||||
* event-ring path is visibly exercised before 2e consumes
|
||||
* it for real. */
|
||||
console_println("xhci: port status change event");
|
||||
case XHCI_TRB_TYPE_PORT_STATUS_CHANGE_EVT: {
|
||||
/* Milestone 2e: identify which port changed and whether it
|
||||
* now reads connected or disconnected. Slot allocation/
|
||||
* addressing on connect is the next increment -- this only
|
||||
* detects and acknowledges the change for now. */
|
||||
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)");
|
||||
break;
|
||||
}
|
||||
uint32_t portsc = port->portsc;
|
||||
if (portsc & XHCI_PORTSC_CCS) {
|
||||
console_println("xhci: port status change -- device connected");
|
||||
} else {
|
||||
console_println("xhci: port status change -- device disconnected");
|
||||
}
|
||||
/* Acknowledge only CSC (RW1CS): preserve PP, write 0 for
|
||||
* PED/PR (writing 1 there disables the port / starts a new
|
||||
* reset -- not intended here) and for every other _C bit
|
||||
* (writing 0 leaves them untouched, not cleared) -- the
|
||||
* same discipline this driver already applies to ERDP.EHB. */
|
||||
port->portsc = (portsc & XHCI_PORTSC_PP) | XHCI_PORTSC_CSC;
|
||||
break;
|
||||
}
|
||||
case XHCI_TRB_TYPE_COMMAND_COMPLETION_EVT:
|
||||
/* No commands are issued yet (Milestone 2e is the first
|
||||
* command-ring user) -- logged for the same reason. */
|
||||
|
||||
Reference in New Issue
Block a user