xhci: support ehci companions and add more portsc bits

This commit is contained in:
Matheus
2026-05-14 14:44:01 -03:00
parent 04a13539dd
commit bce059a183
3 changed files with 43 additions and 2 deletions
+1
View File
@@ -22,6 +22,7 @@
#define PCI_CONFIG_REVISION 0x8
#define PCI_CONFIG_PROGIF 0x9
#define PCI_PROGIF_STORAGE_SATA_AHCI 0x1
#define PCI_PROGIF_USB_EHCI 0x20
#define PCI_PROGIF_USB_XHCI 0x30
#define PCI_CONFIG_SUBCLASS 0xa
#define PCI_SUBCLASS_STORAGE_NVM 0x8
+7 -1
View File
@@ -200,10 +200,16 @@ _Static_assert(sizeof(xhci_input_ctx_t) == XHCI_CONTEXT_SIZE, "xHCI input contro
#define XHCI_PORTSC_PP (1 << 9) // port power
#define XHCI_PORTSC_CSC (1 << 17) // connect status change
#define XHCI_PORTSC_PEC (1 << 18) // port enabled change
#define XHCI_PORTSC_WRC (1 << 19) // warm reset change
#define XHCI_PORTSC_OCC (1 << 20) // over current change
#define XHCI_PORTSC_PRC (1 << 21) // port reset change
#define XHCI_PORTSC_PLC (1 << 22) // port link state change
#define XHCI_PORTSC_CEC (1 << 23) // config error change
#define XHCI_PORTSC_CAS (1 << 24) // cold attach status
#define XHCI_PORTSC_DR (1 << 30) // device removable
#define XHCI_PORTSC_WPR (1u << 31) // warm port reset
#define XHCI_PORTSC_CHANGE_BITS (XHCI_PORTSC_CSC | XHCI_PORTSC_PEC | XHCI_PORTSC_OCC | XHCI_PORTSC_PRC)
#define XHCI_PORTSC_CHANGE_BITS (XHCI_PORTSC_CSC | XHCI_PORTSC_PEC | XHCI_PORTSC_WRC | XHCI_PORTSC_OCC | XHCI_PORTSC_PRC | XHCI_PORTSC_PLC | XHCI_PORTSC_CEC)
#define XHCI_PORTSC_PRESERVE_BITS XHCI_PORTSC_PP
#define XHCI_TRB_DW2_TR_LEN(LEN) (uint32_t)((LEN) & 0x1ffff)
+35 -1
View File
@@ -398,7 +398,6 @@ static int xhci_run(xhci_ctrl_t *ctrl) {
return 0;
}
static volatile uint32_t *xhci_ext_caps(pcibar_t bar0) {
volatile xhci_caps_t *caps = (xhci_caps_t *)bar0.address;
uint32_t xecp = (caps->hccparams1 >> 16) & 0xffff;
@@ -449,6 +448,39 @@ static int xhci_handoff(pcibar_t bar0) {
return 0;
}
#define XHCI_INTEL_VENDOR_ID 0x8086
#define XHCI_INTEL_XUSB2PR 0xd0
#define XHCI_INTEL_USB2PRM 0xd4
#define XHCI_INTEL_USB3_PSSEN 0xd8
#define XHCI_INTEL_USB3PRM 0xdc
static bool xhci_intel_has_ehci_companion(void) {
return pci_getenum(PCI_CLASS_SERIAL_BUS, PCI_SUBCLASS_SERIAL_BUS_USB, PCI_PROGIF_USB_EHCI, XHCI_INTEL_VENDOR_ID, -1, -1, 0) != NULL;
}
static void xhci_intel_route_ports_to_xhci(pcienum_t *e) {
if (e->vendor != XHCI_INTEL_VENDOR_ID)
return;
if (!xhci_intel_has_ehci_companion())
return;
uint32_t usb2_mask = PCI_READ32(e, XHCI_INTEL_USB2PRM);
uint32_t usb3_mask = PCI_READ32(e, XHCI_INTEL_USB3PRM);
uint32_t usb2_before = PCI_READ32(e, XHCI_INTEL_XUSB2PR);
uint32_t usb3_before = PCI_READ32(e, XHCI_INTEL_USB3_PSSEN);
if (usb3_mask != 0 && usb3_mask != UINT32_MAX)
PCI_WRITE32(e, XHCI_INTEL_USB3_PSSEN, usb3_mask);
if (usb2_mask != 0 && usb2_mask != UINT32_MAX)
PCI_WRITE32(e, XHCI_INTEL_XUSB2PR, usb2_mask);
uint32_t usb2_after = PCI_READ32(e, XHCI_INTEL_XUSB2PR);
uint32_t usb3_after = PCI_READ32(e, XHCI_INTEL_USB3_PSSEN);
printf("xhci: Intel routed ports to xHCI: usb2 %08x->%08x usb3 %08x->%08x\n", usb2_before, usb2_after, usb3_before, usb3_after);
}
static int xhci_ctrl_start(usb_ctrl_t *ctrl) {
int ret = 0;
@@ -689,6 +721,8 @@ static void init_ctrl(pcienum_t *e) {
if (xhci_handoff(bar0) != 0)
return;
xhci_intel_route_ports_to_xhci(e);
pci_setcommand(e, PCI_COMMAND_IO, 0);
pci_setcommand(e, PCI_COMMAND_IRQDISABLE, 1);
pci_setcommand(e, PCI_COMMAND_BUSMASTER, 1);