Ignore:
File:
1 edited

Legend:

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

    r705f83a r68e5406  
    4545
    4646#include <usb/debug.h>
    47 #include <usb/host/utility.h>
    4847#include <usb/usb.h>
    4948
    50 #include "ohci_bus.h"
     49#include "ohci_endpoint.h"
    5150#include "ohci_batch.h"
    5251
     
    9089};
    9190
     91static void hc_gain_control(hc_t *instance);
     92static void hc_start(hc_t *instance);
    9293static int hc_init_transfer_lists(hc_t *instance);
    9394static int hc_init_memory(hc_t *instance);
     
    102103 * @return Error code.
    103104 */
    104 int hc_gen_irq_code(irq_code_t *code, hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
     105int ohci_hc_gen_irq_code(irq_code_t *code, const hw_res_list_parsed_t *hw_res, int *irq)
    105106{
    106107        assert(code);
     
    137138        OHCI_WR(code->cmds[1].value, OHCI_USED_INTERRUPTS);
    138139
    139         usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.",
     140        usb_log_debug("Memory mapped regs at %p (size %zu), IRQ %d.\n",
    140141            RNGABSPTR(regs), RNGSZ(regs), hw_res->irqs.irqs[0]);
    141142
    142         return hw_res->irqs.irqs[0];
     143        *irq = hw_res->irqs.irqs[0];
     144        return EOK;
    143145}
    144146
     
    150152 * @return Error code
    151153 */
    152 int hc_add(hc_device_t *hcd, const hw_res_list_parsed_t *hw_res)
    153 {
    154         hc_t *instance = hcd_to_hc(hcd);
     154int hc_init(hc_t *instance, const hw_res_list_parsed_t *hw_res, bool interrupts)
     155{
     156        assert(instance);
    155157        assert(hw_res);
    156158        if (hw_res->mem_ranges.count != 1 ||
     
    161163            (void **) &instance->registers);
    162164        if (ret != EOK) {
    163                 usb_log_error("Failed to gain access to registers: %s.",
     165                usb_log_error("Failed to gain access to registers: %s.\n",
    164166                    str_error(ret));
    165167                return ret;
    166168        }
    167         usb_log_debug("Device registers at %" PRIx64 " (%zuB) accessible.",
     169        usb_log_debug("Device registers at %" PRIx64 " (%zuB) accessible.\n",
    168170            hw_res->mem_ranges.ranges[0].address.absolute,
    169171            hw_res->mem_ranges.ranges[0].size);
    170172
    171         list_initialize(&instance->pending_endpoints);
     173        list_initialize(&instance->pending_batches);
    172174        fibril_mutex_initialize(&instance->guard);
     175        instance->hw_interrupts = interrupts;
    173176
    174177        ret = hc_init_memory(instance);
    175178        if (ret != EOK) {
    176                 usb_log_error("Failed to create OHCI memory structures: %s.",
     179                usb_log_error("Failed to create OHCI memory structures: %s.\n",
    177180                    str_error(ret));
    178181                // TODO: We should disable pio access here
     
    180183        }
    181184
     185        hc_gain_control(instance);
     186
     187        ohci_rh_init(&instance->rh, instance->registers, "ohci rh");
     188        hc_start(instance);
     189
    182190        return EOK;
    183191}
     
    187195 * @param[in] instance Host controller structure to use.
    188196 */
    189 int hc_gone(hc_device_t *instance)
     197void hc_fini(hc_t *instance)
    190198{
    191199        assert(instance);
    192200        /* TODO: implement*/
    193         return ENOTSUP;
    194 }
     201};
    195202
    196203void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep)
     
    262269}
    263270
    264 int ohci_hc_status(bus_t *bus_base, uint32_t *status)
    265 {
    266         assert(bus_base);
     271int ohci_hc_status(hcd_t *hcd, uint32_t *status)
     272{
     273        assert(hcd);
    267274        assert(status);
    268 
    269         ohci_bus_t *bus = (ohci_bus_t *) bus_base;
    270         hc_t *hc = bus->hc;
    271         assert(hc);
    272 
    273         if (hc->registers){
    274                 *status = OHCI_RD(hc->registers->interrupt_status);
    275                 OHCI_WR(hc->registers->interrupt_status, *status);
     275        hc_t *instance = hcd_get_driver_data(hcd);
     276        assert(instance);
     277
     278        if (instance->registers){
     279                *status = OHCI_RD(instance->registers->interrupt_status);
     280                OHCI_WR(instance->registers->interrupt_status, *status);
    276281        }
    277282        return EOK;
     
    284289 * @return Error code.
    285290 */
    286 int ohci_hc_schedule(usb_transfer_batch_t *batch)
    287 {
    288         assert(batch);
    289 
    290         ohci_bus_t *bus = (ohci_bus_t *) endpoint_get_bus(batch->ep);
    291         hc_t *hc = bus->hc;
    292         assert(hc);
     291int ohci_hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
     292{
     293        assert(hcd);
     294        hc_t *instance = hcd_get_driver_data(hcd);
     295        assert(instance);
    293296
    294297        /* Check for root hub communication */
    295         if (batch->target.address == ohci_rh_get_address(&hc->rh)) {
    296                 usb_log_debug("OHCI root hub request.");
    297                 return ohci_rh_schedule(&hc->rh, batch);
    298         }
    299 
    300         endpoint_t *ep = batch->ep;
    301         ohci_endpoint_t * const ohci_ep = ohci_endpoint_get(ep);
     298        if (batch->ep->address == ohci_rh_get_address(&instance->rh)) {
     299                usb_log_debug("OHCI root hub request.\n");
     300                return ohci_rh_schedule(&instance->rh, batch);
     301        }
    302302        ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch);
    303         int err;
    304 
    305         fibril_mutex_lock(&hc->guard);
    306         if ((err = endpoint_activate_locked(ep, batch))) {
    307                 fibril_mutex_unlock(&hc->guard);
    308                 return err;
    309         }
    310 
    311         if ((err = ohci_transfer_batch_prepare(ohci_batch)))
    312                 return err;
    313 
     303        if (!ohci_batch)
     304                return ENOMEM;
     305
     306        fibril_mutex_lock(&instance->guard);
     307        list_append(&ohci_batch->link, &instance->pending_batches);
    314308        ohci_transfer_batch_commit(ohci_batch);
    315         list_append(&ohci_ep->pending_link, &hc->pending_endpoints);
    316         fibril_mutex_unlock(&hc->guard);
    317309
    318310        /* Control and bulk schedules need a kick to start working */
     
    320312        {
    321313        case USB_TRANSFER_CONTROL:
    322                 OHCI_SET(hc->registers->command_status, CS_CLF);
     314                OHCI_SET(instance->registers->command_status, CS_CLF);
    323315                break;
    324316        case USB_TRANSFER_BULK:
    325                 OHCI_SET(hc->registers->command_status, CS_BLF);
     317                OHCI_SET(instance->registers->command_status, CS_BLF);
    326318                break;
    327319        default:
    328320                break;
    329321        }
    330 
     322        fibril_mutex_unlock(&instance->guard);
    331323        return EOK;
    332324}
     
    337329 * @param[in] status Value of the status register at the time of interrupt.
    338330 */
    339 void ohci_hc_interrupt(bus_t *bus_base, uint32_t status)
    340 {
    341         assert(bus_base);
    342 
    343         ohci_bus_t *bus = (ohci_bus_t *) bus_base;
    344         hc_t *hc = bus->hc;
    345         assert(hc);
    346 
     331void ohci_hc_interrupt(hcd_t *hcd, uint32_t status)
     332{
     333        assert(hcd);
     334        hc_t *instance = hcd_get_driver_data(hcd);
    347335        status = OHCI_RD(status);
    348         assert(hc);
     336        assert(instance);
    349337        if ((status & ~I_SF) == 0) /* ignore sof status */
    350338                return;
    351         usb_log_debug2("OHCI(%p) interrupt: %x.", hc, status);
     339        usb_log_debug2("OHCI(%p) interrupt: %x.\n", instance, status);
    352340        if (status & I_RHSC)
    353                 ohci_rh_interrupt(&hc->rh);
     341                ohci_rh_interrupt(&instance->rh);
    354342
    355343        if (status & I_WDH) {
    356                 fibril_mutex_lock(&hc->guard);
    357                 usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).", hc->hcca,
    358                     OHCI_RD(hc->registers->hcca),
    359                     (void *) addr_to_phys(hc->hcca));
    360                 usb_log_debug2("Periodic current: %#" PRIx32 ".",
    361                     OHCI_RD(hc->registers->periodic_current));
    362 
    363                 list_foreach_safe(hc->pending_endpoints, current, next) {
    364                         ohci_endpoint_t *ep
    365                                 = list_get_instance(current, ohci_endpoint_t, pending_link);
    366 
    367                         ohci_transfer_batch_t *batch
    368                                 = ohci_transfer_batch_get(ep->base.active_batch);
    369                         assert(batch);
    370 
    371                         if (ohci_transfer_batch_check_completed(batch)) {
    372                                 endpoint_deactivate_locked(&ep->base);
     344                fibril_mutex_lock(&instance->guard);
     345                usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,
     346                    OHCI_RD(instance->registers->hcca),
     347                    (void *) addr_to_phys(instance->hcca));
     348                usb_log_debug2("Periodic current: %#" PRIx32 ".\n",
     349                    OHCI_RD(instance->registers->periodic_current));
     350
     351                link_t *current = list_first(&instance->pending_batches);
     352                while (current && current != &instance->pending_batches.head) {
     353                        link_t *next = current->next;
     354                        ohci_transfer_batch_t *batch =
     355                            ohci_transfer_batch_from_link(current);
     356
     357                        if (ohci_transfer_batch_is_complete(batch)) {
    373358                                list_remove(current);
    374                                 hc_reset_toggles(&batch->base, &ohci_ep_toggle_reset);
    375                                 usb_transfer_batch_finish(&batch->base);
     359                                ohci_transfer_batch_finish_dispose(batch);
    376360                        }
     361
     362                        current = next;
    377363                }
    378                 fibril_mutex_unlock(&hc->guard);
     364                fibril_mutex_unlock(&instance->guard);
    379365        }
    380366
    381367        if (status & I_UE) {
    382                 usb_log_fatal("Error like no other!");
    383                 hc_start(&hc->base);
     368                usb_log_fatal("Error like no other!\n");
     369                hc_start(instance);
    384370        }
    385371
     
    393379 * @param[in] instance OHCI hc driver structure.
    394380 */
    395 int hc_gain_control(hc_device_t *hcd)
    396 {
    397         hc_t *instance = hcd_to_hc(hcd);
    398 
    399         usb_log_debug("Requesting OHCI control.");
     381void hc_gain_control(hc_t *instance)
     382{
     383        assert(instance);
     384
     385        usb_log_debug("Requesting OHCI control.\n");
    400386        if (OHCI_RD(instance->registers->revision) & R_LEGACY_FLAG) {
    401387                /* Turn off legacy emulation, it should be enough to zero
     
    406392                volatile uint32_t *ohci_emulation_reg =
    407393                (uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET);
    408                 usb_log_debug("OHCI legacy register %p: %x.",
     394                usb_log_debug("OHCI legacy register %p: %x.\n",
    409395                    ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
    410396                /* Zero everything but A20State */
     
    412398                OHCI_CLR(*ohci_emulation_reg, ~0x100);
    413399                usb_log_debug(
    414                     "OHCI legacy register (should be 0 or 0x100) %p: %x.",
     400                    "OHCI legacy register (should be 0 or 0x100) %p: %x.\n",
    415401                    ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
    416402        }
     
    418404        /* Interrupt routing enabled => smm driver is active */
    419405        if (OHCI_RD(instance->registers->control) & C_IR) {
    420                 usb_log_debug("SMM driver: request ownership change.");
     406                usb_log_debug("SMM driver: request ownership change.\n");
    421407                // TODO: should we ack interrupts before doing this?
    422408                OHCI_SET(instance->registers->command_status, CS_OCR);
     
    425411                        async_usleep(1000);
    426412                }
    427                 usb_log_info("SMM driver: Ownership taken.");
     413                usb_log_info("SMM driver: Ownership taken.\n");
    428414                C_HCFS_SET(instance->registers->control, C_HCFS_RESET);
    429415                async_usleep(50000);
    430                 return EOK;
     416                return;
    431417        }
    432418
     
    434420        /* Interrupt routing disabled && status != USB_RESET => BIOS active */
    435421        if (hc_status != C_HCFS_RESET) {
    436                 usb_log_debug("BIOS driver found.");
     422                usb_log_debug("BIOS driver found.\n");
    437423                if (hc_status == C_HCFS_OPERATIONAL) {
    438                         usb_log_info("BIOS driver: HC operational.");
    439                         return EOK;
     424                        usb_log_info("BIOS driver: HC operational.\n");
     425                        return;
    440426                }
    441427                /* HC is suspended assert resume for 20ms */
    442428                C_HCFS_SET(instance->registers->control, C_HCFS_RESUME);
    443429                async_usleep(20000);
    444                 usb_log_info("BIOS driver: HC resumed.");
    445                 return EOK;
     430                usb_log_info("BIOS driver: HC resumed.\n");
     431                return;
    446432        }
    447433
    448434        /* HC is in reset (hw startup) => no other driver
    449435         * maintain reset for at least the time specified in USB spec (50 ms)*/
    450         usb_log_debug("Host controller found in reset state.");
     436        usb_log_debug("Host controller found in reset state.\n");
    451437        async_usleep(50000);
    452         return EOK;
    453438}
    454439
     
    457442 * @param[in] instance OHCI hc driver structure.
    458443 */
    459 int hc_start(hc_device_t *hcd)
    460 {
    461         hc_t *instance = hcd_to_hc(hcd);
    462         ohci_rh_init(&instance->rh, instance->registers, &instance->guard, "ohci rh");
    463 
     444void hc_start(hc_t *instance)
     445{
    464446        /* OHCI guide page 42 */
    465447        assert(instance);
    466         usb_log_debug2("Started hc initialization routine.");
     448        usb_log_debug2("Started hc initialization routine.\n");
    467449
    468450        /* Save contents of fm_interval register */
    469451        const uint32_t fm_interval = OHCI_RD(instance->registers->fm_interval);
    470         usb_log_debug2("Old value of HcFmInterval: %x.", fm_interval);
     452        usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
    471453
    472454        /* Reset hc */
    473         usb_log_debug2("HC reset.");
     455        usb_log_debug2("HC reset.\n");
    474456        size_t time = 0;
    475457        OHCI_WR(instance->registers->command_status, CS_HCR);
     
    478460                time += 10;
    479461        }
    480         usb_log_debug2("HC reset complete in %zu us.", time);
     462        usb_log_debug2("HC reset complete in %zu us.\n", time);
    481463
    482464        /* Restore fm_interval */
     
    485467
    486468        /* hc is now in suspend state */
    487         usb_log_debug2("HC should be in suspend state(%x).",
     469        usb_log_debug2("HC should be in suspend state(%x).\n",
    488470            OHCI_RD(instance->registers->control));
    489471
     
    494476        OHCI_WR(instance->registers->bulk_head,
    495477            instance->lists[USB_TRANSFER_BULK].list_head_pa);
    496         usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").",
     478        usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n",
    497479            instance->lists[USB_TRANSFER_BULK].list_head,
    498480            instance->lists[USB_TRANSFER_BULK].list_head_pa);
     
    500482        OHCI_WR(instance->registers->control_head,
    501483            instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
    502         usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").",
     484        usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n",
    503485            instance->lists[USB_TRANSFER_CONTROL].list_head,
    504486            instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
     
    506488        /* Enable queues */
    507489        OHCI_SET(instance->registers->control, (C_PLE | C_IE | C_CLE | C_BLE));
    508         usb_log_debug("Queues enabled(%x).",
     490        usb_log_debug("Queues enabled(%x).\n",
    509491            OHCI_RD(instance->registers->control));
    510492
    511493        /* Enable interrupts */
    512         if (instance->base.irq_cap >= 0) {
     494        if (instance->hw_interrupts) {
    513495                OHCI_WR(instance->registers->interrupt_enable,
    514496                    OHCI_USED_INTERRUPTS);
    515                 usb_log_debug("Enabled interrupts: %x.",
     497                usb_log_debug("Enabled interrupts: %x.\n",
    516498                    OHCI_RD(instance->registers->interrupt_enable));
    517499                OHCI_WR(instance->registers->interrupt_enable, I_MI);
     
    523505        OHCI_WR(instance->registers->periodic_start,
    524506            ((frame_length / 10) * 9) & PS_MASK << PS_SHIFT);
    525         usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).",
     507        usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n",
    526508            OHCI_RD(instance->registers->periodic_start),
    527509            OHCI_RD(instance->registers->periodic_start), frame_length);
    528510        C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL);
    529         usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).",
     511        usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n",
    530512            OHCI_RD(instance->registers->control));
    531 
    532         return EOK;
    533 }
    534 
    535 /**
    536  * Setup roothub as a virtual hub.
    537  */
    538 int hc_setup_roothub(hc_device_t *hcd)
    539 {
    540         return hc_setup_virtual_root_hub(hcd, USB_SPEED_FULL);
    541513}
    542514
     
    554526        const int ret = endpoint_list_init(&instance->lists[type], name); \
    555527        if (ret != EOK) { \
    556                 usb_log_error("Failed to setup %s endpoint list: %s.", \
     528                usb_log_error("Failed to setup %s endpoint list: %s.\n", \
    557529                    name, str_error(ret)); \
    558530                endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]);\
     
    586558        memset(&instance->rh, 0, sizeof(instance->rh));
    587559        /* Init queues */
    588         int ret = hc_init_transfer_lists(instance);
     560        const int ret = hc_init_transfer_lists(instance);
    589561        if (ret != EOK) {
    590562                return ret;
     
    595567        if (instance->hcca == NULL)
    596568                return ENOMEM;
    597         usb_log_debug2("OHCI HCCA initialized at %p.", instance->hcca);
     569        usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
    598570
    599571        for (unsigned i = 0; i < HCCA_INT_EP_COUNT; ++i) {
     
    601573                    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
    602574        }
    603         usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").",
     575        usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
    604576            instance->lists[USB_TRANSFER_INTERRUPT].list_head,
    605577            instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
    606578
    607         if ((ret = ohci_bus_init(&instance->bus, instance))) {
    608                 usb_log_error("HC(%p): Failed to setup bus : %s",
    609                     instance, str_error(ret));
    610                 return ret;
    611         }
    612 
    613         hc_device_setup(&instance->base, (bus_t *) &instance->bus);
    614 
    615579        return EOK;
    616580}
Note: See TracChangeset for help on using the changeset viewer.