Ignore:
File:
1 edited

Legend:

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

    r9d58539 r8486c07  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
     28
    2829/** @addtogroup drvusbohcihc
    2930 * @{
     
    3233 * @brief OHCI Host controller driver routines
    3334 */
     35
    3436#include <errno.h>
    3537#include <str_error.h>
     
    4951static const irq_pio_range_t ohci_pio_ranges[] = {
    5052        {
    51                 .base = 0,      /* filled later */
     53                .base = 0,
    5254                .size = sizeof(ohci_regs_t)
    5355        }
     
    5557
    5658static const irq_cmd_t ohci_irq_commands[] = {
    57         { .cmd = CMD_PIO_READ_32, .dstarg = 1, .addr = NULL /* filled later */ },
    58         { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = OHCI_USED_INTERRUPTS },
    59         { .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },
    60         { .cmd = CMD_PIO_WRITE_A_32, .srcarg = 1, .addr = NULL /* filled later */ },
    61         { .cmd = CMD_ACCEPT },
     59        {
     60                .cmd = CMD_PIO_READ_32,
     61                .dstarg = 1,
     62                .addr = NULL
     63        },
     64        {
     65                .cmd = CMD_AND,
     66                .srcarg = 1,
     67                .dstarg = 2,
     68                .value = OHCI_USED_INTERRUPTS
     69        },
     70        {
     71                .cmd = CMD_PREDICATE,
     72                .srcarg = 2,
     73                .value = 2
     74        },
     75        {
     76                .cmd = CMD_PIO_WRITE_A_32,
     77                .srcarg = 1,
     78                .addr = NULL
     79        },
     80        {
     81                .cmd = CMD_ACCEPT
     82        }
    6283};
    6384
     
    6889static int interrupt_emulator(hc_t *instance);
    6990static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    70 /*----------------------------------------------------------------------------*/
     91
    7192/** Get number of PIO ranges used in IRQ code.
    7293 * @return Number of ranges.
     
    7697        return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t);
    7798}
    78 /*----------------------------------------------------------------------------*/
    79 /*----------------------------------------------------------------------------*/
     99
    80100/** Get number of commands used in IRQ code.
    81101 * @return Number of commands.
     
    85105        return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t);
    86106}
    87 /*----------------------------------------------------------------------------*/
     107
    88108/** Generate IRQ code.
    89109 * @param[out] ranges PIO ranges buffer.
     
    115135        return EOK;
    116136}
    117 /*----------------------------------------------------------------------------*/
     137
    118138/** Announce OHCI root hub to the DDF
    119139 *
     
    174194#undef CHECK_RET_RELEASE
    175195}
    176 /*----------------------------------------------------------------------------*/
     196
    177197/** Initialize OHCI hc driver structure
    178198 *
     
    227247        return EOK;
    228248}
    229 /*----------------------------------------------------------------------------*/
     249
    230250void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep)
    231251{
     
    241261        switch (ep->transfer_type) {
    242262        case USB_TRANSFER_CONTROL:
    243                 instance->registers->control &= ~C_CLE;
     263                OHCI_CLR(instance->registers->control, C_CLE);
    244264                endpoint_list_add_ep(list, ohci_ep);
    245                 instance->registers->control_current = 0;
    246                 instance->registers->control |= C_CLE;
     265                OHCI_WR(instance->registers->control_current, 0);
     266                OHCI_SET(instance->registers->control, C_CLE);
    247267                break;
    248268        case USB_TRANSFER_BULK:
    249                 instance->registers->control &= ~C_BLE;
     269                OHCI_CLR(instance->registers->control, C_BLE);
    250270                endpoint_list_add_ep(list, ohci_ep);
    251                 instance->registers->control |= C_BLE;
     271                OHCI_WR(instance->registers->bulk_current, 0);
     272                OHCI_SET(instance->registers->control, C_BLE);
    252273                break;
    253274        case USB_TRANSFER_ISOCHRONOUS:
    254275        case USB_TRANSFER_INTERRUPT:
    255                 instance->registers->control &= (~C_PLE & ~C_IE);
     276                OHCI_CLR(instance->registers->control, C_PLE | C_IE);
    256277                endpoint_list_add_ep(list, ohci_ep);
    257                 instance->registers->control |= C_PLE | C_IE;
    258                 break;
    259         }
    260 }
    261 /*----------------------------------------------------------------------------*/
     278                OHCI_SET(instance->registers->control, C_PLE | C_IE);
     279                break;
     280        }
     281}
     282
    262283void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep)
    263284{
     
    273294        switch (ep->transfer_type) {
    274295        case USB_TRANSFER_CONTROL:
    275                 instance->registers->control &= ~C_CLE;
     296                OHCI_CLR(instance->registers->control, C_CLE);
    276297                endpoint_list_remove_ep(list, ohci_ep);
    277                 instance->registers->control_current = 0;
    278                 instance->registers->control |= C_CLE;
     298                OHCI_WR(instance->registers->control_current, 0);
     299                OHCI_SET(instance->registers->control, C_CLE);
    279300                break;
    280301        case USB_TRANSFER_BULK:
    281                 instance->registers->control &= ~C_BLE;
     302                OHCI_CLR(instance->registers->control, C_BLE);
    282303                endpoint_list_remove_ep(list, ohci_ep);
    283                 instance->registers->control |= C_BLE;
     304                OHCI_WR(instance->registers->bulk_current, 0);
     305                OHCI_SET(instance->registers->control, C_BLE);
    284306                break;
    285307        case USB_TRANSFER_ISOCHRONOUS:
    286308        case USB_TRANSFER_INTERRUPT:
    287                 instance->registers->control &= (~C_PLE & ~C_IE);
     309                OHCI_CLR(instance->registers->control, C_PLE | C_IE);
    288310                endpoint_list_remove_ep(list, ohci_ep);
    289                 instance->registers->control |= C_PLE | C_IE;
     311                OHCI_SET(instance->registers->control, C_PLE | C_IE);
    290312                break;
    291313        default:
     
    293315        }
    294316}
    295 /*----------------------------------------------------------------------------*/
     317
    296318/** Add USB transfer to the schedule.
    297319 *
     
    308330        /* Check for root hub communication */
    309331        if (batch->ep->address == instance->rh.address) {
     332                usb_log_debug("OHCI root hub request.\n");
    310333                rh_request(&instance->rh, batch);
    311334                return EOK;
     
    323346        {
    324347        case USB_TRANSFER_CONTROL:
    325                 instance->registers->command_status |= CS_CLF;
     348                OHCI_SET(instance->registers->command_status, CS_CLF);
    326349                break;
    327350        case USB_TRANSFER_BULK:
    328                 instance->registers->command_status |= CS_BLF;
     351                OHCI_SET(instance->registers->command_status, CS_BLF);
    329352                break;
    330353        default:
     
    334357        return EOK;
    335358}
    336 /*----------------------------------------------------------------------------*/
     359
    337360/** Interrupt handling routine
    338361 *
     
    342365void hc_interrupt(hc_t *instance, uint32_t status)
    343366{
     367        status = OHCI_RD(status);
    344368        assert(instance);
    345369        if ((status & ~I_SF) == 0) /* ignore sof status */
     
    352376                fibril_mutex_lock(&instance->guard);
    353377                usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,
    354                     instance->registers->hcca,
     378                    OHCI_RD(instance->registers->hcca),
    355379                    (void *) addr_to_phys(instance->hcca));
    356380                usb_log_debug2("Periodic current: %#" PRIx32 ".\n",
    357                     instance->registers->periodic_current);
     381                    OHCI_RD(instance->registers->periodic_current));
    358382
    359383                link_t *current = list_first(&instance->pending_batches);
     
    379403
    380404}
    381 /*----------------------------------------------------------------------------*/
     405
    382406/** Check status register regularly
    383407 *
     
    397421        return EOK;
    398422}
    399 /*----------------------------------------------------------------------------*/
     423
    400424/** Turn off any (BIOS)driver that might be in control of the device.
    401425 *
     
    410434
    411435        usb_log_debug("Requesting OHCI control.\n");
    412         if (instance->registers->revision & R_LEGACY_FLAG) {
     436        if (OHCI_RD(instance->registers->revision) & R_LEGACY_FLAG) {
    413437                /* Turn off legacy emulation, it should be enough to zero
    414438                 * the lowest bit, but it caused problems. Thus clear all
     
    419443                (uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET);
    420444                usb_log_debug("OHCI legacy register %p: %x.\n",
    421                     ohci_emulation_reg, *ohci_emulation_reg);
     445                    ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
    422446                /* Zero everything but A20State */
    423                 *ohci_emulation_reg &= 0x100;
     447                OHCI_CLR(*ohci_emulation_reg, ~0x100);
    424448                usb_log_debug(
    425449                    "OHCI legacy register (should be 0 or 0x100) %p: %x.\n",
    426                     ohci_emulation_reg, *ohci_emulation_reg);
     450                    ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
    427451        }
    428452
    429453        /* Interrupt routing enabled => smm driver is active */
    430         if (instance->registers->control & C_IR) {
     454        if (OHCI_RD(instance->registers->control) & C_IR) {
    431455                usb_log_debug("SMM driver: request ownership change.\n");
    432                 instance->registers->command_status |= CS_OCR;
     456                OHCI_SET(instance->registers->command_status, CS_OCR);
    433457                /* Hope that SMM actually knows its stuff or we can hang here */
    434                 while (instance->registers->control & C_IR) {
     458                while (OHCI_RD(instance->registers->control & C_IR)) {
    435459                        async_usleep(1000);
    436460                }
     
    449473                        return;
    450474                }
    451                 /* HC is suspended assert resume for 20ms, */
     475                /* HC is suspended assert resume for 20ms */
    452476                C_HCFS_SET(instance->registers->control, C_HCFS_RESUME);
    453477                async_usleep(20000);
     
    461485        async_usleep(50000);
    462486}
    463 /*----------------------------------------------------------------------------*/
     487
    464488/** OHCI hw initialization routine.
    465489 *
     
    473497
    474498        /* Save contents of fm_interval register */
    475         const uint32_t fm_interval = instance->registers->fm_interval;
     499        const uint32_t fm_interval = OHCI_RD(instance->registers->fm_interval);
    476500        usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
    477501
     
    479503        usb_log_debug2("HC reset.\n");
    480504        size_t time = 0;
    481         instance->registers->command_status = CS_HCR;
    482         while (instance->registers->command_status & CS_HCR) {
     505        OHCI_WR(instance->registers->command_status, CS_HCR);
     506        while (OHCI_RD(instance->registers->command_status) & CS_HCR) {
    483507                async_usleep(10);
    484508                time += 10;
     
    487511
    488512        /* Restore fm_interval */
    489         instance->registers->fm_interval = fm_interval;
    490         assert((instance->registers->command_status & CS_HCR) == 0);
     513        OHCI_WR(instance->registers->fm_interval, fm_interval);
     514        assert((OHCI_RD(instance->registers->command_status) & CS_HCR) == 0);
    491515
    492516        /* hc is now in suspend state */
    493517        usb_log_debug2("HC should be in suspend state(%x).\n",
    494             instance->registers->control);
     518            OHCI_RD(instance->registers->control));
    495519
    496520        /* Use HCCA */
    497         instance->registers->hcca = addr_to_phys(instance->hcca);
     521        OHCI_WR(instance->registers->hcca, addr_to_phys(instance->hcca));
    498522
    499523        /* Use queues */
    500         instance->registers->bulk_head =
    501             instance->lists[USB_TRANSFER_BULK].list_head_pa;
     524        OHCI_WR(instance->registers->bulk_head,
     525            instance->lists[USB_TRANSFER_BULK].list_head_pa);
    502526        usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n",
    503527            instance->lists[USB_TRANSFER_BULK].list_head,
    504528            instance->lists[USB_TRANSFER_BULK].list_head_pa);
    505529
    506         instance->registers->control_head =
    507             instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
     530        OHCI_WR(instance->registers->control_head,
     531            instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
    508532        usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n",
    509533            instance->lists[USB_TRANSFER_CONTROL].list_head,
     
    511535
    512536        /* 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);
     537        OHCI_SET(instance->registers->control, (C_PLE | C_IE | C_CLE | C_BLE));
     538        usb_log_debug("Queues enabled(%x).\n",
     539            OHCI_RD(instance->registers->control));
    516540
    517541        /* 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;
     542        OHCI_WR(instance->registers->interrupt_enable, OHCI_USED_INTERRUPTS);
     543        usb_log_debug("Enabled interrupts: %x.\n",
     544            OHCI_RD(instance->registers->interrupt_enable));
     545        OHCI_WR(instance->registers->interrupt_enable, I_MI);
    522546
    523547        /* 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;
     548        const uint32_t frame_length =
     549            (fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK;
     550        OHCI_WR(instance->registers->periodic_start,
     551            ((frame_length / 10) * 9) & PS_MASK << PS_SHIFT);
    526552        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 
     553            OHCI_RD(instance->registers->periodic_start),
     554            OHCI_RD(instance->registers->periodic_start), frame_length);
    530555        C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL);
    531556        usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n",
    532             instance->registers->control);
    533 }
    534 /*----------------------------------------------------------------------------*/
     557            OHCI_RD(instance->registers->control));
     558}
     559
    535560/** Initialize schedule queues
    536561 *
     
    566591        return EOK;
    567592}
    568 /*----------------------------------------------------------------------------*/
     593
    569594/** Initialize memory structures used by the OHCI hcd.
    570595 *
     
    587612        if (instance->hcca == NULL)
    588613                return ENOMEM;
    589         bzero(instance->hcca, sizeof(hcca_t));
    590614        usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
    591615
    592         for (unsigned i = 0; i < 32; ++i) {
    593                 instance->hcca->int_ep[i] =
    594                     instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
     616        for (unsigned i = 0; i < HCCA_INT_EP_COUNT; ++i) {
     617                hcca_set_int_ep(instance->hcca, i,
     618                    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
    595619        }
    596620        usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
Note: See TracChangeset for help on using the changeset viewer.