mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
xhci: support ehci companions and add more portsc bits
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user