int xhci_cmd_disable_slot(xhci_t *const xhci, const int slot_id) { trb_t *const cmd = xhci_next_command_trb(xhci); TRB_SET(TT, cmd, TRB_CMD_DISABLE_SLOT); TRB_SET(ID, cmd, slot_id); xhci_post_command(xhci); return xhci_wait_for_command(xhci, cmd, 1); }
int xhci_cmd_stop_endpoint(xhci_t *const xhci, const int slot_id, const int ep) { trb_t *const cmd = xhci_next_command_trb(xhci); TRB_SET(TT, cmd, TRB_CMD_STOP_EP); TRB_SET(ID, cmd, slot_id); TRB_SET(EP, cmd, ep); xhci_post_command(xhci); return xhci_wait_for_command(xhci, cmd, 1); }
int xhci_cmd_set_tr_dq(xhci_t *const xhci, const int slot_id, const int ep, trb_t *const dq_trb, const int dcs) { trb_t *const cmd = xhci_next_command_trb(xhci); TRB_SET(TT, cmd, TRB_CMD_SET_TR_DQ); TRB_SET(ID, cmd, slot_id); TRB_SET(EP, cmd, ep); cmd->ptr_low = virt_to_phys(dq_trb) | dcs; xhci_post_command(xhci); return xhci_wait_for_command(xhci, cmd, 1); }
int xhci_cmd_evaluate_context(xhci_t *const xhci, const int slot_id, inputctx_t *const ic) { trb_t *const cmd = xhci_next_command_trb(xhci); TRB_SET(TT, cmd, TRB_CMD_EVAL_CTX); TRB_SET(ID, cmd, slot_id); cmd->ptr_low = virt_to_phys(ic->raw); xhci_post_command(xhci); return xhci_wait_for_command(xhci, cmd, 1); }
int xhci_cmd_address_device(xhci_t *const xhci, const int slot_id, inputctx_t *const ic) { trb_t *const cmd = xhci_next_command_trb(xhci); TRB_SET(TT, cmd, TRB_CMD_ADDRESS_DEV); TRB_SET(ID, cmd, slot_id); cmd->ptr_low = virt_to_phys(ic->raw); xhci_post_command(xhci); return xhci_wait_for_command(xhci, cmd, 1); }
int xhci_cmd_configure_endpoint(xhci_t *const xhci, const int slot_id, const int config_id, inputctx_t *const ic) { trb_t *const cmd = xhci_next_command_trb(xhci); TRB_SET(TT, cmd, TRB_CMD_CONFIGURE_EP); TRB_SET(ID, cmd, slot_id); cmd->ptr_low = virt_to_phys(ic->raw); if (config_id == 0) TRB_SET(DC, cmd, 1); xhci_post_command(xhci); return xhci_wait_for_command(xhci, cmd, 1); }
int xhci_cmd_enable_slot(xhci_t *const xhci, int *const slot_id) { trb_t *const cmd = xhci_next_command_trb(xhci); TRB_SET(TT, cmd, TRB_CMD_ENABLE_SLOT); xhci_post_command(xhci); int cc = xhci_wait_for_command(xhci, cmd, 0); if (cc >= 0) { if (cc == CC_SUCCESS) { *slot_id = TRB_GET(ID, xhci->er.cur); if (*slot_id > xhci->max_slots_en) cc = CONTROLLER_ERROR; } xhci_advance_event_ring(xhci); xhci_handle_events(xhci); } 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 }