static int xhci_wait_for_command(xhci_t *const xhci, const trb_t *const cmd_trb, const int clear_event) { int cc; cc = xhci_wait_for_command_done(xhci, cmd_trb, clear_event); if (cc != TIMEOUT) return cc; /* Abort command on timeout */ xhci_debug("Aborting command (@%p), CRCR: 0x%"PRIx32"\n", cmd_trb, xhci->opreg->crcr_lo); xhci->opreg->crcr_lo |= CRCR_CS | CRCR_CA; xhci->opreg->crcr_hi = 0; cc = xhci_wait_for_command_aborted(xhci, cmd_trb); if (xhci->opreg->crcr_lo & CRCR_CRR) fatal("xhci_wait_for_command: Command ring still running\n"); return cc; }
static void xhci_reinit (hci_t *controller) { xhci_t *const xhci = XHCI_INST(controller); if (xhci_wait_ready(xhci)) return; /* Enable all available slots */ xhci->opreg->config = xhci->max_slots_en; /* Set DCBAA */ xhci->opreg->dcbaap_lo = virt_to_phys(xhci->dcbaa); xhci->opreg->dcbaap_hi = 0; /* Initialize command ring */ xhci_init_cycle_ring(&xhci->cr, COMMAND_RING_SIZE); xhci_debug("command ring @%p (0x%08x)\n", xhci->cr.ring, virt_to_phys(xhci->cr.ring)); xhci->opreg->crcr_lo = virt_to_phys(xhci->cr.ring) | CRCR_RCS; xhci->opreg->crcr_hi = 0; /* Make sure interrupts are disabled */ xhci->opreg->usbcmd &= ~USBCMD_INTE; /* Initialize event ring */ xhci_reset_event_ring(&xhci->er); xhci_debug("event ring @%p (0x%08x)\n", xhci->er.ring, virt_to_phys(xhci->er.ring)); xhci_debug("ERST Max: 0x%lx -> 0x%lx entries\n", xhci->capreg->ERST_Max, 1 << xhci->capreg->ERST_Max); memset((void*)xhci->ev_ring_table, 0x00, sizeof(erst_entry_t)); xhci->ev_ring_table[0].seg_base_lo = virt_to_phys(xhci->er.ring); xhci->ev_ring_table[0].seg_base_hi = 0; xhci->ev_ring_table[0].seg_size = EVENT_RING_SIZE; /* Initialize primary interrupter */ xhci->hcrreg->intrrs[0].erstsz = 1; xhci_update_event_dq(xhci); /* erstba has to be written at last */ xhci->hcrreg->intrrs[0].erstba_lo = virt_to_phys(xhci->ev_ring_table); xhci->hcrreg->intrrs[0].erstba_hi = 0; xhci_start(controller); #ifdef USB_DEBUG int i; for (i = 0; i < 32; ++i) { xhci_debug("NOOP run #%d\n", i); trb_t *const cmd = xhci_next_command_trb(xhci); TRB_SET(TT, cmd, TRB_CMD_NOOP); xhci_post_command(xhci); /* Wait for result in event ring */ xhci_wait_for_command_done(xhci, cmd, 1); xhci_debug("Command ring is %srunning\n", (xhci->opreg->crcr_lo & CRCR_CRR) ? "" : "not "); } #endif }