/* * Some structures must not cross page boundaries. To get this, * we align them by their size (or the next greater power of 2). */ void * xhci_align(const size_t min_align, const size_t size) { size_t align; if (!(size & (size - 1))) align = size; /* It's a power of 2 */ else align = 1 << ((sizeof(unsigned) << 3) - __builtin_clz(size)); if (align < min_align) align = min_align; xhci_spew("Aligning %zu to %zu\n", size, align); return dma_memalign(align, size); }
hci_t * xhci_init (unsigned long physical_bar) { int i; /* First, allocate and initialize static controller structures */ hci_t *const controller = new_controller(); if (!controller) { xhci_debug("Could not create USB controller instance\n"); return controller; } controller->type = XHCI; controller->start = xhci_start; controller->stop = xhci_stop; controller->reset = xhci_reset; controller->init = xhci_reinit; controller->shutdown = xhci_shutdown; controller->bulk = xhci_bulk; controller->control = xhci_control; controller->set_address = xhci_set_address; controller->finish_device_config= xhci_finish_device_config; controller->destroy_device = xhci_destroy_dev; controller->create_intr_queue = xhci_create_intr_queue; controller->destroy_intr_queue = xhci_destroy_intr_queue; controller->poll_intr_queue = xhci_poll_intr_queue; controller->pcidev = 0; for (i = 0; i < 128; ++i) { controller->devices[i] = NULL; } controller->instance = malloc(sizeof(xhci_t)); if (!controller->instance) { xhci_debug("Out of memory creating xHCI controller instance\n"); goto _free_controller; } xhci_t *const xhci = (xhci_t *)controller->instance; memset(xhci, 0x00, sizeof(*xhci)); init_device_entry(controller, 0); xhci->roothub = controller->devices[0]; xhci->cr.ring = xhci_align(64, COMMAND_RING_SIZE * sizeof(trb_t)); xhci->er.ring = xhci_align(64, EVENT_RING_SIZE * sizeof(trb_t)); xhci->ev_ring_table = xhci_align(64, sizeof(erst_entry_t)); if (!xhci->roothub || !xhci->cr.ring || !xhci->er.ring || !xhci->ev_ring_table) { xhci_debug("Out of memory\n"); goto _free_xhci; } xhci->capreg = phys_to_virt(physical_bar); xhci->opreg = ((void *)xhci->capreg) + xhci->capreg->caplength; xhci->hcrreg = ((void *)xhci->capreg) + xhci->capreg->rtsoff; xhci->dbreg = ((void *)xhci->capreg) + xhci->capreg->dboff; xhci_debug("regbase: 0x%"PRIx32"\n", physical_bar); xhci_debug("caplen: 0x%"PRIx32"\n", xhci->capreg->caplength); xhci_debug("rtsoff: 0x%"PRIx32"\n", xhci->capreg->rtsoff); xhci_debug("dboff: 0x%"PRIx32"\n", xhci->capreg->dboff); xhci_debug("hciversion: %"PRIx8".%"PRIx8"\n", xhci->capreg->hciver_hi, xhci->capreg->hciver_lo); if ((xhci->capreg->hciversion < 0x96) || (xhci->capreg->hciversion > 0x100)) { xhci_debug("Unsupported xHCI version\n"); goto _free_xhci; } xhci_debug("context size: %dB\n", CTXSIZE(xhci)); xhci_debug("maxslots: 0x%02lx\n", xhci->capreg->MaxSlots); xhci_debug("maxports: 0x%02lx\n", xhci->capreg->MaxPorts); const unsigned pagesize = xhci->opreg->pagesize << 12; xhci_debug("pagesize: 0x%04x\n", pagesize); /* * We haven't touched the hardware yet. So we allocate all dynamic * structures at first and can still chicken out easily if we run out * of memory. */ xhci->max_slots_en = xhci->capreg->MaxSlots & CONFIG_LP_MASK_MaxSlotsEn; xhci->dcbaa = xhci_align(64, (xhci->max_slots_en + 1) * sizeof(u64)); xhci->dev = malloc((xhci->max_slots_en + 1) * sizeof(*xhci->dev)); if (!xhci->dcbaa || !xhci->dev) { xhci_debug("Out of memory\n"); goto _free_xhci; } memset(xhci->dcbaa, 0x00, (xhci->max_slots_en + 1) * sizeof(u64)); memset(xhci->dev, 0x00, (xhci->max_slots_en + 1) * sizeof(*xhci->dev)); /* * Let dcbaa[0] point to another array of pointers, sp_ptrs. * The pointers therein point to scratchpad buffers (pages). */ const size_t max_sp_bufs = xhci->capreg->Max_Scratchpad_Bufs; xhci_debug("max scratchpad bufs: 0x%zx\n", max_sp_bufs); if (max_sp_bufs) { const size_t sp_ptrs_size = max_sp_bufs * sizeof(u64); xhci->sp_ptrs = xhci_align(64, sp_ptrs_size); if (!xhci->sp_ptrs) { xhci_debug("Out of memory\n"); goto _free_xhci_structs; } memset(xhci->sp_ptrs, 0x00, sp_ptrs_size); for (i = 0; i < max_sp_bufs; ++i) { /* Could use mmap() here if we had it. Maybe there is another way. */ void *const page = memalign(pagesize, pagesize); if (!page) { xhci_debug("Out of memory\n"); goto _free_xhci_structs; } xhci->sp_ptrs[i] = virt_to_phys(page); } xhci->dcbaa[0] = virt_to_phys(xhci->sp_ptrs); } if (dma_initialized()) { xhci->dma_buffer = dma_memalign(64 * 1024, DMA_SIZE); if (!xhci->dma_buffer) { xhci_debug("Not enough memory for DMA bounce buffer\n"); goto _free_xhci_structs; } } /* Now start working on the hardware */ if (xhci_wait_ready(xhci)) goto _free_xhci_structs; /* TODO: Check if BIOS claims ownership (and hand over) */ xhci_reset(controller); xhci_reinit(controller); xhci->roothub->controller = controller; xhci->roothub->init = xhci_rh_init; xhci->roothub->init(xhci->roothub); return controller; _free_xhci_structs: if (xhci->sp_ptrs) { for (i = 0; i < max_sp_bufs; ++i) { if (xhci->sp_ptrs[i]) free(phys_to_virt(xhci->sp_ptrs[i])); } } free(xhci->sp_ptrs); free(xhci->dcbaa); _free_xhci: free((void *)xhci->ev_ring_table); free((void *)xhci->er.ring); free((void *)xhci->cr.ring); free(xhci->roothub); free(xhci->dev); free(xhci); _free_controller: detach_controller(controller); free(controller); return NULL; }
writel(1 << endpoint, &p->opreg->epsetupstat); } static void clear_ep(struct chipidea_pdata *p, int endpoint, int in_dir) { writel(1 << ep_to_bits(endpoint, in_dir), &p->opreg->epcomplete); } static int chipidea_hw_init(struct usbdev_ctrl *this, void *_opreg, const device_descriptor_t *dd) { struct chipidea_opreg *opreg = _opreg; struct chipidea_pdata *p = CI_PDATA(this); p->opreg = phys_to_virt(opreg); p->qhlist = dma_memalign(4096, sizeof(struct qh) * CI_QHELEMENTS); memcpy(&this->device_descriptor, dd, sizeof(*dd)); if (p->qhlist == NULL) die("failed to allocate memory for usb device mode"); memset(p->qhlist, 0, sizeof(struct qh) * CI_QHELEMENTS); SLIST_INIT(&this->configs); int i; for (i = 0; i < 16; i++) { SIMPLEQ_INIT(&p->job_queue[i][0]); SIMPLEQ_INIT(&p->job_queue[i][1]); }