summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorIan Moffett <ian@osmora.org>2025-01-08 22:00:42 -0500
committerIan Moffett <ian@osmora.org>2025-01-08 22:01:34 -0500
commitb5c65e3022f285d389759bb699a9cefee79c5fd0 (patch)
treebe502cdeae88c38fd270bfb2e447295f0ba78517 /sys/dev
parenta5da98ef1f85a78d935a8ba048487eb650b7eb07 (diff)
kernel: xhci: Add xHC interrupt management
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/xhci.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/sys/dev/usb/xhci.c b/sys/dev/usb/xhci.c
index ad99f72..d2c671f 100644
--- a/sys/dev/usb/xhci.c
+++ b/sys/dev/usb/xhci.c
@@ -55,6 +55,12 @@
static struct pci_device *hci_dev;
static struct timer tmr;
+__attribute__((__interrupt__)) static void
+xhci_common_isr(void *sf)
+{
+ pr_trace("Received xHCI interrupt (via PCI MSI-X)\n");
+}
+
/*
* Get port status and control register for a specific
* port.
@@ -215,6 +221,19 @@ xhci_alloc_dcbaa(struct xhci_hc *hc)
}
/*
+ * Initialize MSI-X interrupts.
+ */
+static int
+xhci_init_msix(struct xhci_hc *hc)
+{
+ struct msi_intr intr;
+
+ intr.name = "xHCI MSI-X";
+ intr.handler = xhci_common_isr;
+ return pci_enable_msix(hci_dev, &intr);
+}
+
+/*
* Sets up the event ring.
*/
static void
@@ -313,6 +332,27 @@ xhci_reset(struct xhci_hc *hc)
}
/*
+ * Enable or disable xHC interrupts.
+ */
+static void
+xhci_set_intr(struct xhci_hc *hc, int enable)
+{
+ struct xhci_opregs *opregs = hc->opregs;
+ uint32_t usbcmd;
+
+ enable &= 1;
+ usbcmd = mmio_read32(&opregs->usbcmd);
+
+ if (enable == 1) {
+ usbcmd |= USBCMD_INTE;
+ } else {
+ usbcmd &= ~USBCMD_INTE;
+ }
+
+ mmio_write32(&opregs->usbcmd, usbcmd);
+}
+
+/*
* Start up the host controller and put it into
* a running state. Returns 0 on success.
*/
@@ -419,9 +459,13 @@ xhci_init_hc(struct xhci_hc *hc)
mmio_write64(&opregs->cmd_ring, cmdring);
hc->cr_cycle = 1;
+ xhci_init_msix(hc);
xhci_init_evring(hc);
xhci_parse_ecp(hc);
xhci_start_hc(hc);
+
+ /* Allow the xHC to generate interrupts */
+ xhci_set_intr(hc, 1);
xhci_init_ports(hc);
return 0;
}