Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/bus/usb/uhci/hc.c

    rf3ae58b r68e5406  
    5050#include <usb/usb.h>
    5151#include <usb/host/utils/malloc32.h>
    52 #include <usb/host/bandwidth.h>
    53 #include <usb/host/utility.h>
    5452
    5553#include "uhci_batch.h"
    56 #include "transfer_list.h"
    5754#include "hc.h"
    5855
     
    106103 * @param[out] code IRQ code structure.
    107104 * @param[in] hw_res Device's resources.
     105 * @param[out] irq
    108106 *
    109107 * @return Error code.
    110108 */
    111 int hc_gen_irq_code(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
     109int uhci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res, int *irq)
    112110{
    113111        assert(code);
     
    142140        code->cmds[3].addr = (void*)&registers->usbsts;
    143141
    144         usb_log_debug("I/O regs at %p (size %zu), IRQ %d.",
     142        usb_log_debug("I/O regs at %p (size %zu), IRQ %d.\n",
    145143            RNGABSPTR(regs), RNGSZ(regs), hw_res->irqs.irqs[0]);
    146144
    147         return hw_res->irqs.irqs[0];
     145        *irq = hw_res->irqs.irqs[0];
     146        return EOK;
    148147}
    149148
     
    158157 * - resume from suspend state (not implemented)
    159158 */
    160 static void hc_interrupt(bus_t *bus, uint32_t status)
    161 {
    162         hc_t *instance = bus_to_hc(bus);
    163 
     159void uhci_hc_interrupt(hcd_t *hcd, uint32_t status)
     160{
     161        assert(hcd);
     162        hc_t *instance = hcd_get_driver_data(hcd);
     163        assert(instance);
    164164        /* Lower 2 bits are transaction error and transaction complete */
    165165        if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
    166                 transfer_list_check_finished(&instance->transfers_interrupt);
    167                 transfer_list_check_finished(&instance->transfers_control_slow);
    168                 transfer_list_check_finished(&instance->transfers_control_full);
    169                 transfer_list_check_finished(&instance->transfers_bulk_full);
    170         }
    171 
     166                LIST_INITIALIZE(done);
     167                transfer_list_remove_finished(
     168                    &instance->transfers_interrupt, &done);
     169                transfer_list_remove_finished(
     170                    &instance->transfers_control_slow, &done);
     171                transfer_list_remove_finished(
     172                    &instance->transfers_control_full, &done);
     173                transfer_list_remove_finished(
     174                    &instance->transfers_bulk_full, &done);
     175
     176                list_foreach_safe(done, current, next) {
     177                        list_remove(current);
     178                        uhci_transfer_batch_t *batch =
     179                            uhci_transfer_batch_from_link(current);
     180                        uhci_transfer_batch_finish_dispose(batch);
     181                }
     182        }
    172183        /* Resume interrupts are not supported */
    173184        if (status & UHCI_STATUS_RESUME) {
    174                 usb_log_error("Resume interrupt!");
     185                usb_log_error("Resume interrupt!\n");
    175186        }
    176187
    177188        /* Bits 4 and 5 indicate hc error */
    178189        if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) {
    179                 usb_log_error("UHCI hardware failure!.");
     190                usb_log_error("UHCI hardware failure!.\n");
    180191                ++instance->hw_failures;
    181192                transfer_list_abort_all(&instance->transfers_interrupt);
     
    188199                        hc_init_hw(instance);
    189200                } else {
    190                         usb_log_fatal("Too many UHCI hardware failures!.");
    191                         hc_gone(&instance->base);
     201                        usb_log_fatal("Too many UHCI hardware failures!.\n");
     202                        hc_fini(instance);
    192203                }
    193204        }
     
    205216 * interrupt fibrils.
    206217 */
    207 int hc_add(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
    208 {
    209         hc_t *instance = hcd_to_hc(hcd);
     218int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts)
     219{
     220        assert(instance);
    210221        assert(hw_res);
    211222        if (hw_res->io_ranges.count != 1 ||
     
    213224            return EINVAL;
    214225
     226        instance->hw_interrupts = interrupts;
    215227        instance->hw_failures = 0;
    216228
     
    219231            (void **) &instance->registers);
    220232        if (ret != EOK) {
    221                 usb_log_error("Failed to gain access to registers: %s.",
     233                usb_log_error("Failed to gain access to registers: %s.\n",
    222234                    str_error(ret));
    223235                return ret;
    224236        }
    225237
    226         usb_log_debug("Device registers at %" PRIx64 " (%zuB) accessible.",
     238        usb_log_debug("Device registers at %" PRIx64 " (%zuB) accessible.\n",
    227239            hw_res->io_ranges.ranges[0].address.absolute,
    228240            hw_res->io_ranges.ranges[0].size);
     
    230242        ret = hc_init_mem_structures(instance);
    231243        if (ret != EOK) {
    232                 usb_log_error("Failed to init UHCI memory structures: %s.",
     244                usb_log_error("Failed to init UHCI memory structures: %s.\n",
    233245                    str_error(ret));
    234246                // TODO: we should disable pio here
     
    236248        }
    237249
    238         return EOK;
    239 }
    240 
    241 int hc_start(hc_device_t *hcd)
    242 {
    243         hc_t *instance = hcd_to_hc(hcd);
    244250        hc_init_hw(instance);
    245251        (void)hc_debug_checker;
    246252
    247         return uhci_rh_init(&instance->rh, instance->registers->ports, "uhci");
    248 }
    249 
    250 int hc_setup_roothub(hc_device_t *hcd)
    251 {
    252         return hc_setup_virtual_root_hub(hcd, USB_SPEED_FULL);
     253        uhci_rh_init(&instance->rh, instance->registers->ports, "uhci");
     254
     255        return EOK;
    253256}
    254257
     
    257260 * @param[in] instance Host controller structure to use.
    258261 */
    259 int hc_gone(hc_device_t *instance)
     262void hc_fini(hc_t *instance)
    260263{
    261264        assert(instance);
    262265        //TODO Implement
    263         return ENOTSUP;
    264266}
    265267
     
    291293        pio_write_32(&registers->flbaseadd, pa);
    292294
    293         if (instance->base.irq_cap >= 0) {
     295        if (instance->hw_interrupts) {
    294296                /* Enable all interrupts, but resume interrupt */
    295297                pio_write_16(&instance->registers->usbintr,
     
    299301        const uint16_t cmd = pio_read_16(&registers->usbcmd);
    300302        if (cmd != 0)
    301                 usb_log_warning("Previous command value: %x.", cmd);
     303                usb_log_warning("Previous command value: %x.\n", cmd);
    302304
    303305        /* Start the hc with large(64B) packet FSBR */
     
    306308}
    307309
    308 static usb_transfer_batch_t *create_transfer_batch(endpoint_t *ep)
    309 {
    310         uhci_transfer_batch_t *batch = uhci_transfer_batch_create(ep);
    311         return &batch->base;
    312 }
    313 
    314 static void destroy_transfer_batch(usb_transfer_batch_t *batch)
    315 {
    316         uhci_transfer_batch_destroy(uhci_transfer_batch_get(batch));
    317 }
    318 
    319 static endpoint_t *endpoint_create(device_t *device, const usb_endpoint_descriptors_t *desc)
    320 {
    321         endpoint_t *ep = calloc(1, sizeof(uhci_endpoint_t));
    322         if (ep)
    323                 endpoint_init(ep, device, desc);
    324         return ep;
    325 }
    326 
    327 static int endpoint_register(endpoint_t *ep)
    328 {
    329         hc_t * const hc = bus_to_hc(endpoint_get_bus(ep));
    330 
    331         const int err = usb2_bus_endpoint_register(&hc->bus_helper, ep);
    332         if (err)
    333                 return err;
    334 
    335         transfer_list_t *list = hc->transfers[ep->device->speed][ep->transfer_type];
    336         if (!list)
    337                 /*
    338                  * We don't support this combination (e.g. isochronous). Do not
    339                  * fail early, because that would block any device with these
    340                  * endpoints from connecting. Instead, make sure these transfers
    341                  * are denied soon enough with ENOTSUP not to fail on asserts.
    342                  */
    343                 return EOK;
    344 
    345         endpoint_set_online(ep, &list->guard);
    346         return EOK;
    347 }
    348 
    349 static void endpoint_unregister(endpoint_t *ep)
    350 {
    351         hc_t * const hc = bus_to_hc(endpoint_get_bus(ep));
    352         usb2_bus_endpoint_unregister(&hc->bus_helper, ep);
    353 
    354         // Check for the roothub, as it does not schedule into lists
    355         if (ep->device->address == uhci_rh_get_address(&hc->rh)) {
    356                 // FIXME: We shall check the roothub for active transfer. But
    357                 // as it is polling, there is no way to make it stop doing so.
    358                 // Return after rewriting uhci rh.
    359                 return;
    360         }
    361 
    362         transfer_list_t *list = hc->transfers[ep->device->speed][ep->transfer_type];
    363         if (!list)
    364                 /*
    365                  * We don't support this combination (e.g. isochronous),
    366                  * so no transfer can be active.
    367                  */
    368                 return;
    369 
    370         fibril_mutex_lock(&list->guard);
    371 
    372         endpoint_set_offline_locked(ep);
    373         /* From now on, no other transfer will be scheduled. */
    374 
    375         if (!ep->active_batch) {
    376                 fibril_mutex_unlock(&list->guard);
    377                 return;
    378         }
    379 
    380         /* First, offer the batch a short chance to be finished. */
    381         endpoint_wait_timeout_locked(ep, 10000);
    382 
    383         if (!ep->active_batch) {
    384                 fibril_mutex_unlock(&list->guard);
    385                 return;
    386         }
    387 
    388         uhci_transfer_batch_t * const batch =
    389                 uhci_transfer_batch_get(ep->active_batch);
    390 
    391         /* Remove the batch from the schedule to stop it from being finished. */
    392         endpoint_deactivate_locked(ep);
    393         transfer_list_remove_batch(list, batch);
    394 
    395         fibril_mutex_unlock(&list->guard);
    396 
    397         /*
    398          * We removed the batch from software schedule only, it's still possible
    399          * that HC has it in its caches. Better wait a while before we release
    400          * the buffers.
    401          */
    402         async_usleep(20000);
    403         batch->base.error = EINTR;
    404         batch->base.transferred_size = 0;
    405         usb_transfer_batch_finish(&batch->base);
    406 }
    407 
    408 static int device_enumerate(device_t *dev)
    409 {
    410         hc_t * const hc = bus_to_hc(dev->bus);
    411         return usb2_bus_device_enumerate(&hc->bus_helper, dev);
    412 }
    413 
    414 static void device_gone(device_t *dev)
    415 {
    416         hc_t * const hc = bus_to_hc(dev->bus);
    417         usb2_bus_device_gone(&hc->bus_helper, dev);
    418 }
    419 
    420 static int hc_status(bus_t *, uint32_t *);
    421 static int hc_schedule(usb_transfer_batch_t *);
    422 
    423 static const bus_ops_t uhci_bus_ops = {
    424         .interrupt = hc_interrupt,
    425         .status = hc_status,
    426 
    427         .device_enumerate = device_enumerate,
    428         .device_gone = device_gone,
    429 
    430         .endpoint_create = endpoint_create,
    431         .endpoint_register = endpoint_register,
    432         .endpoint_unregister = endpoint_unregister,
    433 
    434         .batch_create = create_transfer_batch,
    435         .batch_schedule = hc_schedule,
    436         .batch_destroy = destroy_transfer_batch,
    437 };
    438 
    439310/** Initialize UHCI hc memory structures.
    440311 *
     
    450321{
    451322        assert(instance);
    452 
    453         usb2_bus_helper_init(&instance->bus_helper, &bandwidth_accounting_usb11);
    454 
    455         bus_init(&instance->bus, sizeof(device_t));
    456         instance->bus.ops = &uhci_bus_ops;
    457 
    458         hc_device_setup(&instance->base, &instance->bus);
    459323
    460324        /* Init USB frame list page */
     
    463327                return ENOMEM;
    464328        }
    465         usb_log_debug("Initialized frame list at %p.", instance->frame_list);
     329        usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
    466330
    467331        /* Init transfer lists */
    468332        int ret = hc_init_transfer_lists(instance);
    469333        if (ret != EOK) {
    470                 usb_log_error("Failed to initialize transfer lists.");
     334                usb_log_error("Failed to initialize transfer lists.\n");
    471335                return_page(instance->frame_list);
    472336                return ENOMEM;
    473337        }
    474         list_initialize(&instance->pending_endpoints);
    475         usb_log_debug("Initialized transfer lists.");
     338        usb_log_debug("Initialized transfer lists.\n");
    476339
    477340
     
    503366        int ret = transfer_list_init(&instance->transfers_##type, name); \
    504367        if (ret != EOK) { \
    505                 usb_log_error("Failed to setup %s transfer list: %s.", \
     368                usb_log_error("Failed to setup %s transfer list: %s.\n", \
    506369                    name, str_error(ret)); \
    507370                transfer_list_fini(&instance->transfers_bulk_full); \
     
    548411}
    549412
    550 static int hc_status(bus_t *bus, uint32_t *status)
    551 {
    552         hc_t *instance = bus_to_hc(bus);
     413int uhci_hc_status(hcd_t *hcd, uint32_t *status)
     414{
     415        assert(hcd);
    553416        assert(status);
     417        hc_t *instance = hcd_get_driver_data(hcd);
     418        assert(instance);
    554419
    555420        *status = 0;
     
    562427}
    563428
    564 /**
    565  * Schedule batch for execution.
     429/** Schedule batch for execution.
    566430 *
    567431 * @param[in] instance UHCI structure to use.
    568432 * @param[in] batch Transfer batch to schedule.
    569433 * @return Error code
    570  */
    571 static int hc_schedule(usb_transfer_batch_t *batch)
    572 {
     434 *
     435 * Checks for bandwidth availability and appends the batch to the proper queue.
     436 */
     437int uhci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
     438{
     439        assert(hcd);
     440        hc_t *instance = hcd_get_driver_data(hcd);
     441        assert(instance);
     442        assert(batch);
     443
     444        if (batch->ep->address == uhci_rh_get_address(&instance->rh))
     445                return uhci_rh_schedule(&instance->rh, batch);
     446
    573447        uhci_transfer_batch_t *uhci_batch = uhci_transfer_batch_get(batch);
    574         endpoint_t *ep = batch->ep;
    575         hc_t *hc = bus_to_hc(endpoint_get_bus(ep));
    576 
    577         if (batch->target.address == uhci_rh_get_address(&hc->rh))
    578                 return uhci_rh_schedule(&hc->rh, batch);
    579 
    580         transfer_list_t * const list =
    581             hc->transfers[ep->device->speed][ep->transfer_type];
    582 
    583         if (!list)
    584                 return ENOTSUP;
    585 
    586         int err;
    587         if ((err = uhci_transfer_batch_prepare(uhci_batch)))
    588                 return err;
    589 
    590         return transfer_list_add_batch(list, uhci_batch);
     448        if (!uhci_batch) {
     449                usb_log_error("Failed to create UHCI transfer structures.\n");
     450                return ENOMEM;
     451        }
     452
     453        transfer_list_t *list =
     454            instance->transfers[batch->ep->speed][batch->ep->transfer_type];
     455        assert(list);
     456        transfer_list_add_batch(list, uhci_batch);
     457
     458        return EOK;
    591459}
    592460
     
    611479
    612480                if (((cmd & UHCI_CMD_RUN_STOP) != 1) || (sts != 0)) {
    613                         usb_log_debug2("Command: %X Status: %X Intr: %x",
     481                        usb_log_debug2("Command: %X Status: %X Intr: %x\n",
    614482                            cmd, sts, intr);
    615483                }
     
    618486                    pio_read_32(&instance->registers->flbaseadd) & ~0xfff;
    619487                if (frame_list != addr_to_phys(instance->frame_list)) {
    620                         usb_log_debug("Framelist address: %p vs. %p.",
     488                        usb_log_debug("Framelist address: %p vs. %p.\n",
    621489                            (void *) frame_list,
    622490                            (void *) addr_to_phys(instance->frame_list));
     
    629497                uintptr_t real_pa = addr_to_phys(QH(interrupt));
    630498                if (expected_pa != real_pa) {
    631                         usb_log_debug("Interrupt QH: %p (frame %d) vs. %p.",
     499                        usb_log_debug("Interrupt QH: %p (frame %d) vs. %p.\n",
    632500                            (void *) expected_pa, frnum, (void *) real_pa);
    633501                }
     
    636504                real_pa = addr_to_phys(QH(control_slow));
    637505                if (expected_pa != real_pa) {
    638                         usb_log_debug("Control Slow QH: %p vs. %p.",
     506                        usb_log_debug("Control Slow QH: %p vs. %p.\n",
    639507                            (void *) expected_pa, (void *) real_pa);
    640508                }
     
    643511                real_pa = addr_to_phys(QH(control_full));
    644512                if (expected_pa != real_pa) {
    645                         usb_log_debug("Control Full QH: %p vs. %p.",
     513                        usb_log_debug("Control Full QH: %p vs. %p.\n",
    646514                            (void *) expected_pa, (void *) real_pa);
    647515                }
     
    650518                real_pa = addr_to_phys(QH(bulk_full));
    651519                if (expected_pa != real_pa ) {
    652                         usb_log_debug("Bulk QH: %p vs. %p.",
     520                        usb_log_debug("Bulk QH: %p vs. %p.\n",
    653521                            (void *) expected_pa, (void *) real_pa);
    654522                }
Note: See TracChangeset for help on using the changeset viewer.