From d6968ced27f697b26d7a1d5b44f15eeb300a9fd6 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Fri, 31 Aug 2012 15:30:51 +0200 Subject: [PATCH] xhci: pick target interrupter Pick the correct interrupter when queuing an event. Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 6b3ff16..3b03c6c 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -264,6 +264,10 @@ typedef enum TRBCCode { #define TRB_LK_TC (1<<1) +#define TRB_INTR_SHIFT 22 +#define TRB_INTR_MASK 0x3ff +#define TRB_INTR(t) (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK) + #define EP_TYPE_MASK 0x7 #define EP_TYPE_SHIFT 3 @@ -806,10 +810,16 @@ static void xhci_events_update(XHCIState *xhci, int v) static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v) { - XHCIInterrupter *intr = &xhci->intr[v]; + XHCIInterrupter *intr; dma_addr_t erdp; unsigned int dp_idx; + if (v >= MAXINTRS) { + DPRINTF("intr nr out of range (%d >= %d)\n", v, MAXINTRS); + return; + } + intr = &xhci->intr[v]; + if (intr->er_full) { DPRINTF("xhci_event(): ER full, queueing\n"); if (((intr->ev_buffer_put+1) % EV_QUEUE) == intr->ev_buffer_get) { @@ -1377,7 +1387,7 @@ static void xhci_xfer_report(XHCITransfer *xfer) DPRINTF("xhci_xfer_data: EDTLA=%d\n", event.length); edtla = 0; } - xhci_event(xhci, &event, 0 /* FIXME */); + xhci_event(xhci, &event, TRB_INTR(*trb)); reported = 1; if (xfer->status != CC_SUCCESS) { return; @@ -2253,7 +2263,7 @@ static void xhci_process_commands(XHCIState *xhci) break; } event.slotid = slotid; - xhci_event(xhci, &event, 0 /* FIXME */); + xhci_event(xhci, &event, 0); } } @@ -2283,7 +2293,7 @@ static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach) port->portsc |= PORTSC_CSC; XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, port->portnr << 24}; - xhci_event(xhci, &ev, 0 /* FIXME */); + xhci_event(xhci, &ev, 0); DPRINTF("xhci: port change event for port %d\n", port->portnr); } } @@ -2562,7 +2572,7 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val) if (xhci->crcr_low & (CRCR_CA|CRCR_CS) && (xhci->crcr_low & CRCR_CRR)) { XHCIEvent event = {ER_COMMAND_COMPLETE, CC_COMMAND_RING_STOPPED}; xhci->crcr_low &= ~CRCR_CRR; - xhci_event(xhci, &event, 0 /* FIXME */); + xhci_event(xhci, &event, 0); DPRINTF("xhci: command ring stopped (CRCR=%08x)\n", xhci->crcr_low); } else { dma_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val); @@ -2807,7 +2817,7 @@ static void xhci_wakeup(USBPort *usbport) return; } port->portsc |= PORTSC_PLC; - xhci_event(xhci, &ev, 0 /* FIXME */); + xhci_event(xhci, &ev, 0); } static void xhci_complete(USBPort *port, USBPacket *packet) -- 1.7.12.1