Changeset b828907 in mainline for uspace/drv/bus/usb/ohci/hc.c


Ignore:
Timestamp:
2012-07-20T20:29:54Z (12 years ago)
Author:
Frantisek Princ <frantisek.princ@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
34bc2fe
Parents:
4cdac68 (diff), 6de2d766 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge with mainline

File:
1 edited

Legend:

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

    r4cdac68 rb828907  
    5656static const irq_cmd_t ohci_irq_commands[] = {
    5757        { .cmd = CMD_PIO_READ_32, .dstarg = 1, .addr = NULL /* filled later */ },
    58         { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = OHCI_USED_INTERRUPTS },
     58        { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = 0 /* filled later */ },
    5959        { .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },
    6060        { .cmd = CMD_PIO_WRITE_A_32, .srcarg = 1, .addr = NULL /* filled later */ },
     
    6868static int interrupt_emulator(hc_t *instance);
    6969static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    70 /*----------------------------------------------------------------------------*/
     70
    7171/** Get number of PIO ranges used in IRQ code.
    7272 * @return Number of ranges.
     
    7676        return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t);
    7777}
    78 /*----------------------------------------------------------------------------*/
    79 /*----------------------------------------------------------------------------*/
     78
     79
    8080/** Get number of commands used in IRQ code.
    8181 * @return Number of commands.
     
    8585        return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t);
    8686}
    87 /*----------------------------------------------------------------------------*/
     87
    8888/** Generate IRQ code.
    8989 * @param[out] ranges PIO ranges buffer.
     
    111111        ohci_regs_t *registers = (ohci_regs_t *) regs;
    112112        cmds[0].addr = (void *) &registers->interrupt_status;
     113        cmds[1].value = OHCI_USED_INTERRUPTS;
    113114        cmds[3].addr = (void *) &registers->interrupt_status;
    114115
    115116        return EOK;
    116117}
    117 /*----------------------------------------------------------------------------*/
     118
    118119/** Announce OHCI root hub to the DDF
    119120 *
     
    174175#undef CHECK_RET_RELEASE
    175176}
    176 /*----------------------------------------------------------------------------*/
     177
    177178/** Initialize OHCI hc driver structure
    178179 *
     
    227228        return EOK;
    228229}
    229 /*----------------------------------------------------------------------------*/
     230
    230231void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep)
    231232{
     
    241242        switch (ep->transfer_type) {
    242243        case USB_TRANSFER_CONTROL:
    243                 instance->registers->control &= ~C_CLE;
     244                OHCI_CLR(instance->registers->control, C_CLE);
    244245                endpoint_list_add_ep(list, ohci_ep);
    245                 instance->registers->control_current = 0;
    246                 instance->registers->control |= C_CLE;
     246                OHCI_WR(instance->registers->control_current, 0);
     247                OHCI_SET(instance->registers->control, C_CLE);
    247248                break;
    248249        case USB_TRANSFER_BULK:
    249                 instance->registers->control &= ~C_BLE;
     250                OHCI_CLR(instance->registers->control, C_BLE);
    250251                endpoint_list_add_ep(list, ohci_ep);
    251                 instance->registers->control |= C_BLE;
     252                OHCI_WR(instance->registers->bulk_current, 0);
     253                OHCI_SET(instance->registers->control, C_BLE);
    252254                break;
    253255        case USB_TRANSFER_ISOCHRONOUS:
    254256        case USB_TRANSFER_INTERRUPT:
    255                 instance->registers->control &= (~C_PLE & ~C_IE);
     257                OHCI_CLR(instance->registers->control, C_PLE | C_IE);
    256258                endpoint_list_add_ep(list, ohci_ep);
    257                 instance->registers->control |= C_PLE | C_IE;
    258                 break;
    259         }
    260 }
    261 /*----------------------------------------------------------------------------*/
     259                OHCI_SET(instance->registers->control, C_PLE | C_IE);
     260                break;
     261        }
     262}
     263
    262264void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep)
    263265{
     
    273275        switch (ep->transfer_type) {
    274276        case USB_TRANSFER_CONTROL:
    275                 instance->registers->control &= ~C_CLE;
     277                OHCI_CLR(instance->registers->control, C_CLE);
    276278                endpoint_list_remove_ep(list, ohci_ep);
    277                 instance->registers->control_current = 0;
    278                 instance->registers->control |= C_CLE;
     279                OHCI_WR(instance->registers->control_current, 0);
     280                OHCI_SET(instance->registers->control, C_CLE);
    279281                break;
    280282        case USB_TRANSFER_BULK:
    281                 instance->registers->control &= ~C_BLE;
     283                OHCI_CLR(instance->registers->control, C_BLE);
    282284                endpoint_list_remove_ep(list, ohci_ep);
    283                 instance->registers->control |= C_BLE;
     285                OHCI_WR(instance->registers->bulk_current, 0);
     286                OHCI_SET(instance->registers->control, C_BLE);
    284287                break;
    285288        case USB_TRANSFER_ISOCHRONOUS:
    286289        case USB_TRANSFER_INTERRUPT:
    287                 instance->registers->control &= (~C_PLE & ~C_IE);
     290                OHCI_CLR(instance->registers->control, C_PLE | C_IE);
    288291                endpoint_list_remove_ep(list, ohci_ep);
    289                 instance->registers->control |= C_PLE | C_IE;
     292                OHCI_SET(instance->registers->control, C_PLE | C_IE);
    290293                break;
    291294        default:
     
    293296        }
    294297}
    295 /*----------------------------------------------------------------------------*/
     298
    296299/** Add USB transfer to the schedule.
    297300 *
     
    308311        /* Check for root hub communication */
    309312        if (batch->ep->address == instance->rh.address) {
     313                usb_log_debug("OHCI root hub request.\n");
    310314                rh_request(&instance->rh, batch);
    311315                return EOK;
     
    323327        {
    324328        case USB_TRANSFER_CONTROL:
    325                 instance->registers->command_status |= CS_CLF;
     329                OHCI_SET(instance->registers->command_status, CS_CLF);
    326330                break;
    327331        case USB_TRANSFER_BULK:
    328                 instance->registers->command_status |= CS_BLF;
     332                OHCI_SET(instance->registers->command_status, CS_BLF);
    329333                break;
    330334        default:
     
    334338        return EOK;
    335339}
    336 /*----------------------------------------------------------------------------*/
     340
    337341/** Interrupt handling routine
    338342 *
     
    342346void hc_interrupt(hc_t *instance, uint32_t status)
    343347{
     348        status = OHCI_RD(status);
    344349        assert(instance);
    345350        if ((status & ~I_SF) == 0) /* ignore sof status */
     
    352357                fibril_mutex_lock(&instance->guard);
    353358                usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,
    354                     instance->registers->hcca,
     359                    OHCI_RD(instance->registers->hcca),
    355360                    (void *) addr_to_phys(instance->hcca));
    356361                usb_log_debug2("Periodic current: %#" PRIx32 ".\n",
    357                     instance->registers->periodic_current);
     362                    OHCI_RD(instance->registers->periodic_current));
    358363
    359364                link_t *current = list_first(&instance->pending_batches);
     
    379384
    380385}
    381 /*----------------------------------------------------------------------------*/
     386
    382387/** Check status register regularly
    383388 *
     
    397402        return EOK;
    398403}
    399 /*----------------------------------------------------------------------------*/
     404
    400405/** Turn off any (BIOS)driver that might be in control of the device.
    401406 *
     
    410415
    411416        usb_log_debug("Requesting OHCI control.\n");
    412         if (instance->registers->revision & R_LEGACY_FLAG) {
     417        if (OHCI_RD(instance->registers->revision) & R_LEGACY_FLAG) {
    413418                /* Turn off legacy emulation, it should be enough to zero
    414419                 * the lowest bit, but it caused problems. Thus clear all
     
    419424                (uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET);
    420425                usb_log_debug("OHCI legacy register %p: %x.\n",
    421                     ohci_emulation_reg, *ohci_emulation_reg);
     426                    ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
    422427                /* Zero everything but A20State */
    423                 *ohci_emulation_reg &= 0x100;
     428                OHCI_CLR(*ohci_emulation_reg, ~0x100);
    424429                usb_log_debug(
    425430                    "OHCI legacy register (should be 0 or 0x100) %p: %x.\n",
    426                     ohci_emulation_reg, *ohci_emulation_reg);
     431                    ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
    427432        }
    428433
    429434        /* Interrupt routing enabled => smm driver is active */
    430         if (instance->registers->control & C_IR) {
     435        if (OHCI_RD(instance->registers->control) & C_IR) {
    431436                usb_log_debug("SMM driver: request ownership change.\n");
    432                 instance->registers->command_status |= CS_OCR;
     437                OHCI_SET(instance->registers->command_status, CS_OCR);
    433438                /* Hope that SMM actually knows its stuff or we can hang here */
    434                 while (instance->registers->control & C_IR) {
     439                while (OHCI_RD(instance->registers->control & C_IR)) {
    435440                        async_usleep(1000);
    436441                }
     
    440445                return;
    441446        }
    442 
    443447        const unsigned hc_status = C_HCFS_GET(instance->registers->control);
    444448        /* Interrupt routing disabled && status != USB_RESET => BIOS active */
     
    449453                        return;
    450454                }
    451                 /* HC is suspended assert resume for 20ms, */
     455                /* HC is suspended assert resume for 20ms */
    452456                C_HCFS_SET(instance->registers->control, C_HCFS_RESUME);
    453457                async_usleep(20000);
     
    461465        async_usleep(50000);
    462466}
    463 /*----------------------------------------------------------------------------*/
     467
    464468/** OHCI hw initialization routine.
    465469 *
     
    473477
    474478        /* Save contents of fm_interval register */
    475         const uint32_t fm_interval = instance->registers->fm_interval;
     479        const uint32_t fm_interval = OHCI_RD(instance->registers->fm_interval);
    476480        usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
    477481
     
    479483        usb_log_debug2("HC reset.\n");
    480484        size_t time = 0;
    481         instance->registers->command_status = CS_HCR;
    482         while (instance->registers->command_status & CS_HCR) {
     485        OHCI_WR(instance->registers->command_status, CS_HCR);
     486        while (OHCI_RD(instance->registers->command_status) & CS_HCR) {
    483487                async_usleep(10);
    484488                time += 10;
     
    487491
    488492        /* Restore fm_interval */
    489         instance->registers->fm_interval = fm_interval;
    490         assert((instance->registers->command_status & CS_HCR) == 0);
     493        OHCI_WR(instance->registers->fm_interval, fm_interval);
     494        assert((OHCI_RD(instance->registers->command_status) & CS_HCR) == 0);
    491495
    492496        /* hc is now in suspend state */
    493497        usb_log_debug2("HC should be in suspend state(%x).\n",
    494             instance->registers->control);
     498            OHCI_RD(instance->registers->control));
    495499
    496500        /* Use HCCA */
    497         instance->registers->hcca = addr_to_phys(instance->hcca);
     501        OHCI_WR(instance->registers->hcca, addr_to_phys(instance->hcca));
    498502
    499503        /* Use queues */
    500         instance->registers->bulk_head =
    501             instance->lists[USB_TRANSFER_BULK].list_head_pa;
     504        OHCI_WR(instance->registers->bulk_head,
     505            instance->lists[USB_TRANSFER_BULK].list_head_pa);
    502506        usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n",
    503507            instance->lists[USB_TRANSFER_BULK].list_head,
    504508            instance->lists[USB_TRANSFER_BULK].list_head_pa);
    505509
    506         instance->registers->control_head =
    507             instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
     510        OHCI_WR(instance->registers->control_head,
     511            instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
    508512        usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n",
    509513            instance->lists[USB_TRANSFER_CONTROL].list_head,
     
    511515
    512516        /* Enable queues */
    513         instance->registers->control |= (C_PLE | C_IE | C_CLE | C_BLE);
    514         usb_log_debug2("All queues enabled(%x).\n",
    515             instance->registers->control);
     517        OHCI_SET(instance->registers->control, (C_PLE | C_IE | C_CLE | C_BLE));
     518        usb_log_debug("Queues enabled(%x).\n",
     519            OHCI_RD(instance->registers->control));
    516520
    517521        /* Enable interrupts */
    518         instance->registers->interrupt_enable = OHCI_USED_INTERRUPTS;
    519         usb_log_debug2("Enabled interrupts: %x.\n",
    520             instance->registers->interrupt_enable);
    521         instance->registers->interrupt_enable = I_MI;
     522        OHCI_WR(instance->registers->interrupt_enable, OHCI_USED_INTERRUPTS);
     523        usb_log_debug("Enabled interrupts: %x.\n",
     524            OHCI_RD(instance->registers->interrupt_enable));
     525        OHCI_WR(instance->registers->interrupt_enable, I_MI);
    522526
    523527        /* Set periodic start to 90% */
    524         uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK);
    525         instance->registers->periodic_start = (frame_length / 10) * 9;
     528        const uint32_t frame_length =
     529            (fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK;
     530        OHCI_WR(instance->registers->periodic_start,
     531            ((frame_length / 10) * 9) & PS_MASK << PS_SHIFT);
    526532        usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n",
    527             instance->registers->periodic_start,
    528             instance->registers->periodic_start, frame_length);
    529 
     533            OHCI_RD(instance->registers->periodic_start),
     534            OHCI_RD(instance->registers->periodic_start), frame_length);
    530535        C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL);
    531536        usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n",
    532             instance->registers->control);
    533 }
    534 /*----------------------------------------------------------------------------*/
     537            OHCI_RD(instance->registers->control));
     538}
     539
    535540/** Initialize schedule queues
    536541 *
     
    566571        return EOK;
    567572}
    568 /*----------------------------------------------------------------------------*/
     573
    569574/** Initialize memory structures used by the OHCI hcd.
    570575 *
     
    587592        if (instance->hcca == NULL)
    588593                return ENOMEM;
    589         bzero(instance->hcca, sizeof(hcca_t));
    590594        usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
    591595
    592         for (unsigned i = 0; i < 32; ++i) {
    593                 instance->hcca->int_ep[i] =
    594                     instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
     596        for (unsigned i = 0; i < HCCA_INT_EP_COUNT; ++i) {
     597                hcca_set_int_ep(instance->hcca, i,
     598                    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
    595599        }
    596600        usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
Note: See TracChangeset for help on using the changeset viewer.