feat(usb): every xHCI controller is driven, not only the first

boards/BRINGUP.md A1, FABRIC-3 SXLII.  xhci.c keeps a table of controllers
(up to 8) and services each; kernel_main brings up index 0, 1, ... until
there is none.  repl.c's and blkio_usb.c's per-slot state is per
controller now (a slot ID is a controller's own), and each USB keyboard
keeps its own last report and lights; an unplugged keyboard releases what
it held.

Test first: keyboard and identity on a second controller behind a bridge,
Zuse on the first -- before, only Zuse; after, all three, on all three
ISAs.  Hot-plug and unplug on the second controller.  Acceptance unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-14 14:27:38 -04:00
co-authored by Claude Opus 5.5
parent 739cb9c163
commit e729c64ba3
27 changed files with 81701 additions and 260 deletions
+10 -21
View File
@@ -62,11 +62,8 @@ static const uint8_t modifier_key[8] = { 29, 42, 56, 125, 97, 54, 100, 126 };
#define KBD_EVENTS 64u
static struct { uint16_t keycode; uint8_t pressed; } g_events[KBD_EVENTS];
static uint32_t g_head, g_count;
static uint8_t g_prev[8];
/* Num Lock on to start, matching the console (repl.c); 0xFF = nothing
* sent yet, so a new keyboard is always told. */
/* Num Lock on to start, matching the console (repl.c). */
static uint8_t g_leds_want = USB_KBD_LED_NUM;
static uint8_t g_leds_sent = 0xFFu;
static void push(uint16_t keycode, int pressed)
{
@@ -89,7 +86,7 @@ static int held(const uint8_t *keys, uint32_t n, uint8_t usage)
return 0;
}
void usb_kbd_report(const uint8_t *report, uint32_t len)
void usb_kbd_report(uint8_t prev[8], const uint8_t *report, uint32_t len)
{
uint8_t now[8] = {0};
uint32_t i, n;
@@ -101,34 +98,26 @@ void usb_kbd_report(const uint8_t *report, uint32_t len)
for (i = 0; i < 8; i++) {
uint8_t bit = (uint8_t)(1u << i);
if ((now[0] & bit) != (g_prev[0] & bit)) push(modifier_key[i], (now[0] & bit) != 0);
if ((now[0] & bit) != (prev[0] & bit)) push(modifier_key[i], (now[0] & bit) != 0);
}
n = 6;
for (i = 2; i < 8; i++) /* released first, then pressed */
if (g_prev[i] > 0x01 && !held(now + 2, n, g_prev[i])) push(key_for(g_prev[i]), 0);
if (prev[i] > 0x01 && !held(now + 2, n, prev[i])) push(key_for(prev[i]), 0);
for (i = 2; i < 8; i++)
if (now[i] > 0x01 && !held(g_prev + 2, n, now[i])) push(key_for(now[i]), 1);
if (now[i] > 0x01 && !held(prev + 2, n, now[i])) push(key_for(now[i]), 1);
for (i = 0; i < 8; i++) g_prev[i] = now[i];
for (i = 0; i < 8; i++) prev[i] = now[i];
}
void usb_kbd_reset(void)
void usb_kbd_forget(uint8_t prev[8])
{
uint32_t i;
for (i = 0; i < 8; i++) g_prev[i] = 0;
g_leds_sent = 0xFFu;
static const uint8_t none[8] = {0};
usb_kbd_report(prev, none, 8); /* everything held, released */
}
void usb_kbd_set_leds(uint8_t leds) { g_leds_want = leds; }
int usb_kbd_leds_pending(uint8_t *leds)
{
if (g_leds_want == g_leds_sent) return 0;
*leds = g_leds_want;
return 1;
}
void usb_kbd_leds_sent(uint8_t leds) { g_leds_sent = leds; }
uint8_t usb_kbd_leds_wanted(void) { return g_leds_want; }
int usb_kbd_pop_event(uint16_t *keycode, int *pressed)
{