XHCI put extended capability parsing into one function, parse USB port info
This commit is contained in:
@@ -91,6 +91,17 @@
|
||||
#define XHCI_TRB_DEV_NOTIF_EVNT 38
|
||||
#define XHCI_TRB_MFINDEX_WRAP 39
|
||||
|
||||
/* extended capabilities */
|
||||
#define XHCI_EXTCAP_USB_LEGACY_SUPPORT 1
|
||||
#define XHCI_EXTCAP_SUPPORTED_PROTOCOL 2
|
||||
#define XHCI_EXTCAP_EXT_POWER_MNGMNT 3
|
||||
#define XHCI_EXTCAP_IO_VIRT 4
|
||||
#define XHCI_EXTCAP_MSG_INTR 5
|
||||
#define XHCI_EXTCAP_LOCAL_MEMORY 6
|
||||
#define XHCI_EXTCAP_USB_DEBUG 7
|
||||
#define XHCI_EXTCAP_EXT_MSG_INTR 8
|
||||
#define XHCI_EXTCAP_VENDOR_DEFINED 9
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
static void xhci_write8 (uintptr_t base, uint32_t reg, uint8_t value) {
|
||||
@@ -235,8 +246,7 @@ void xhci_send_cmd (struct xhci* xhci, uint64_t param, uint32_t status, uint32_t
|
||||
spin_unlock (&xhci->device->lock, fd);
|
||||
}
|
||||
|
||||
/* Make or break on real hardware. We need to take over ownership from the BIOS. */
|
||||
static void xhci_bios_handover (struct xhci* xhci) {
|
||||
static void xhci_parse_ext_cap (struct xhci* xhci) {
|
||||
uint32_t hccparams1 = xhci_read32 (xhci->xhci_mmio_base, XHCI_HCCPARAMS1);
|
||||
uint32_t ext_offset = (hccparams1 >> 16) << 2;
|
||||
|
||||
@@ -247,9 +257,34 @@ static void xhci_bios_handover (struct xhci* xhci) {
|
||||
uintptr_t cap_ptr = xhci->xhci_mmio_base + ext_offset;
|
||||
uint32_t cap = xhci_read32 (cap_ptr, 0);
|
||||
uint8_t cap_id = cap & 0xFF;
|
||||
uint8_t minor = (cap >> 16) & 0xFF;
|
||||
uint8_t major = (cap >> 24) & 0xFF;
|
||||
|
||||
if (cap_id == 1) {
|
||||
DEBUG ("Found USB Legacy Support at offset 0x%x\n", ext_offset);
|
||||
switch (cap_id) {
|
||||
case XHCI_EXTCAP_SUPPORTED_PROTOCOL: {
|
||||
uint32_t dword2 = xhci_read32 (cap_ptr, 8);
|
||||
uint8_t port_off = dword2 & 0xFF;
|
||||
uint8_t port_count = (dword2 >> 8) & 0xFF;
|
||||
|
||||
uint8_t first_port = port_off - 1;
|
||||
uint8_t last_port = first_port + port_count - 1;
|
||||
|
||||
for (uint8_t port = first_port; port <= last_port; port++) {
|
||||
struct xhci_port* xhci_port = malloc (sizeof (*xhci_port));
|
||||
memset (xhci_port, 0, sizeof (*xhci_port));
|
||||
|
||||
if (major == 3)
|
||||
xhci_port->type = XHCI_PORT_USB3;
|
||||
else
|
||||
xhci_port->type = XHCI_PORT_USB2;
|
||||
|
||||
list_append (xhci->xhci_ports, &xhci_port->ports_link);
|
||||
|
||||
DEBUG ("PORT %u: USB %u.%u\n", port, major, minor);
|
||||
}
|
||||
} break;
|
||||
case XHCI_EXTCAP_USB_LEGACY_SUPPORT: {
|
||||
/* Make or break on real hardware. We need to take over ownership from the BIOS. */
|
||||
if (cap & (1 << 16)) {
|
||||
DEBUG ("BIOS owns XHCI, requesting handover!\n");
|
||||
|
||||
@@ -267,6 +302,8 @@ static void xhci_bios_handover (struct xhci* xhci) {
|
||||
|
||||
DEBUG ("XHCI Handover OK\n");
|
||||
}
|
||||
} break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -320,7 +357,7 @@ DEFINE_DEVICE_INIT (xhci_init) {
|
||||
|
||||
stall_ms (1000);
|
||||
|
||||
xhci_bios_handover (xhci);
|
||||
xhci_parse_ext_cap (xhci);
|
||||
|
||||
/* reset controller */
|
||||
usbcmd = xhci_read32 (xhci->xhci_oper_base, XHCI_USBCMD);
|
||||
@@ -434,6 +471,14 @@ DEFINE_DEVICE_FINI (xhci_fini) {
|
||||
pmm_free (xhci->event_ring_phys, 1);
|
||||
pmm_free (xhci->erst_phys, 1);
|
||||
|
||||
struct list_node_link *port_link, *tmp_port_link;
|
||||
list_foreach (xhci->xhci_ports, port_link, tmp_port_link) {
|
||||
struct xhci_port* port = list_entry (port_link, struct xhci_port, ports_link);
|
||||
|
||||
list_remove (xhci->xhci_ports, &port->ports_link);
|
||||
free (port);
|
||||
}
|
||||
|
||||
irq_detach (xhci->irq);
|
||||
|
||||
free (xhci);
|
||||
|
||||
@@ -29,6 +29,14 @@ struct xhci_init {
|
||||
uint8_t irq;
|
||||
};
|
||||
|
||||
#define XHCI_PORT_USB2 0
|
||||
#define XHCI_PORT_USB3 1
|
||||
|
||||
struct xhci_port {
|
||||
struct list_node_link ports_link;
|
||||
int type;
|
||||
};
|
||||
|
||||
struct xhci {
|
||||
struct device* device;
|
||||
|
||||
@@ -65,6 +73,8 @@ struct xhci {
|
||||
uintptr_t erst_phys;
|
||||
|
||||
atomic_bool pending;
|
||||
|
||||
struct list_node_link* xhci_ports;
|
||||
};
|
||||
|
||||
DEFINE_DEVICE_INIT (xhci_init);
|
||||
|
||||
Reference in New Issue
Block a user