From b5c65e3022f285d389759bb699a9cefee79c5fd0 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Wed, 8 Jan 2025 22:00:42 -0500 Subject: kernel: xhci: Add xHC interrupt management Signed-off-by: Ian Moffett --- sys/dev/usb/xhci.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) (limited to 'sys/dev/usb/xhci.c') 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. @@ -214,6 +220,19 @@ xhci_alloc_dcbaa(struct xhci_hc *hc) return VIRT_TO_PHYS(hc->dcbaap); } +/* + * 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. */ @@ -312,6 +331,27 @@ xhci_reset(struct xhci_hc *hc) return 0; } +/* + * 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; } -- cgit v1.2.3