Ignore:
File:
1 edited

Legend:

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

    r65eac7b rd57122c  
    4747    (I_SO | I_WDH | I_UE | I_RHSC)
    4848
    49 static const irq_cmd_t ohci_irq_commands[] =
    50 {
    51         { .cmd = CMD_MEM_READ_32, .dstarg = 1, .addr = NULL /*filled later*/ },
    52         { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2, .value = 0 /*filled later*/},
     49static const irq_pio_range_t ohci_pio_ranges[] = {
     50        {
     51                .base = 0,      /* filled later */
     52                .size = sizeof(ohci_regs_t)
     53        }
     54};
     55
     56static 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 },
    5359        { .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },
    54         { .cmd = CMD_MEM_WRITE_A_32, .srcarg = 1, .addr = NULL /*filled later*/ },
     60        { .cmd = CMD_PIO_WRITE_A_32, .srcarg = 1, .addr = NULL /* filled later */ },
    5561        { .cmd = CMD_ACCEPT },
    5662};
     
    6369static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    6470/*----------------------------------------------------------------------------*/
     71/** Get number of PIO ranges used in IRQ code.
     72 * @return Number of ranges.
     73 */
     74size_t hc_irq_pio_range_count(void)
     75{
     76        return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t);
     77}
     78/*----------------------------------------------------------------------------*/
     79/*----------------------------------------------------------------------------*/
    6580/** Get number of commands used in IRQ code.
    6681 * @return Number of commands.
     
    7186}
    7287/*----------------------------------------------------------------------------*/
    73 /** Generate IRQ code commands.
    74  * @param[out] cmds Place to store the commands.
    75  * @param[in] cmd_size Size of the place (bytes).
     88/** Generate IRQ code.
     89 * @param[out] ranges PIO ranges buffer.
     90 * @param[in] ranges_size Size of the ranges buffer (bytes).
     91 * @param[out] cmds Commands buffer.
     92 * @param[in] cmds_size Size of the commands buffer (bytes).
    7693 * @param[in] regs Physical address of device's registers.
    7794 * @param[in] reg_size Size of the register area (bytes).
     
    7996 * @return Error code.
    8097 */
    81 int hc_get_irq_commands(
    82     irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size)
    83 {
    84         if (cmd_size < sizeof(ohci_irq_commands)
    85             || reg_size < sizeof(ohci_regs_t))
     98int
     99hc_get_irq_code(irq_pio_range_t ranges[], size_t ranges_size, irq_cmd_t cmds[],
     100    size_t cmds_size, uintptr_t regs, size_t reg_size)
     101{
     102        if ((ranges_size < sizeof(ohci_pio_ranges)) ||
     103            (cmds_size < sizeof(ohci_irq_commands)) ||
     104            (reg_size < sizeof(ohci_regs_t)))
    86105                return EOVERFLOW;
    87106
    88         /* Create register mapping to use in IRQ handler.
    89          * This mapping should be present in kernel only.
    90          * Remove it from here when kernel knows how to create mappings
    91          * and accepts physical addresses in IRQ code.
    92          * TODO: remove */
    93         ohci_regs_t *registers;
    94         const int ret = pio_enable((void*)regs, reg_size, (void**)&registers);
    95         if (ret != EOK)
    96                 return ret;
    97 
    98         /* Some bogus access to force create mapping. DO NOT remove,
    99          * unless whole virtual addresses in irq is replaced
    100          * NOTE: Compiler won't remove this as ohci_regs_t members
    101          * are declared volatile.
    102          *
    103          * Introducing CMD_MEM set of IRQ code commands broke
    104          * assumption that IRQ code does not cause page faults.
    105          * If this happens during idling (THREAD == NULL)
    106          * it causes kernel panic.
    107          */
    108         registers->revision;
     107        memcpy(ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges));
     108        ranges[0].base = regs;
    109109
    110110        memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands));
    111 
    112         void *address = (void*)&registers->interrupt_status;
    113         cmds[0].addr = address;
    114         cmds[1].value = OHCI_USED_INTERRUPTS;
    115         cmds[3].addr = address;
     111        ohci_regs_t *registers = (ohci_regs_t *) regs;
     112        cmds[0].addr = (void *) &registers->interrupt_status;
     113        cmds[3].addr = (void *) &registers->interrupt_status;
     114
    116115        return EOK;
    117116}
     
    242241        switch (ep->transfer_type) {
    243242        case USB_TRANSFER_CONTROL:
    244                 OHCI_CLR(instance->registers->control, C_CLE);
     243                instance->registers->control &= ~C_CLE;
    245244                endpoint_list_add_ep(list, ohci_ep);
    246                 OHCI_WR(instance->registers->control_current, 0);
    247                 OHCI_SET(instance->registers->control, C_CLE);
     245                instance->registers->control_current = 0;
     246                instance->registers->control |= C_CLE;
    248247                break;
    249248        case USB_TRANSFER_BULK:
    250                 OHCI_CLR(instance->registers->control, C_BLE);
     249                instance->registers->control &= ~C_BLE;
    251250                endpoint_list_add_ep(list, ohci_ep);
    252                 OHCI_WR(instance->registers->bulk_current, 0);
    253                 OHCI_SET(instance->registers->control, C_BLE);
     251                instance->registers->control |= C_BLE;
    254252                break;
    255253        case USB_TRANSFER_ISOCHRONOUS:
    256254        case USB_TRANSFER_INTERRUPT:
    257                 OHCI_CLR(instance->registers->control, C_PLE | C_IE);
     255                instance->registers->control &= (~C_PLE & ~C_IE);
    258256                endpoint_list_add_ep(list, ohci_ep);
    259                 OHCI_SET(instance->registers->control, C_PLE | C_IE);
     257                instance->registers->control |= C_PLE | C_IE;
    260258                break;
    261259        }
     
    275273        switch (ep->transfer_type) {
    276274        case USB_TRANSFER_CONTROL:
    277                 OHCI_CLR(instance->registers->control, C_CLE);
     275                instance->registers->control &= ~C_CLE;
    278276                endpoint_list_remove_ep(list, ohci_ep);
    279                 OHCI_WR(instance->registers->control_current, 0);
    280                 OHCI_SET(instance->registers->control, C_CLE);
     277                instance->registers->control_current = 0;
     278                instance->registers->control |= C_CLE;
    281279                break;
    282280        case USB_TRANSFER_BULK:
    283                 OHCI_CLR(instance->registers->control, C_BLE);
     281                instance->registers->control &= ~C_BLE;
    284282                endpoint_list_remove_ep(list, ohci_ep);
    285                 OHCI_WR(instance->registers->bulk_current, 0);
    286                 OHCI_SET(instance->registers->control, C_BLE);
     283                instance->registers->control |= C_BLE;
    287284                break;
    288285        case USB_TRANSFER_ISOCHRONOUS:
    289286        case USB_TRANSFER_INTERRUPT:
    290                 OHCI_CLR(instance->registers->control, C_PLE | C_IE);
     287                instance->registers->control &= (~C_PLE & ~C_IE);
    291288                endpoint_list_remove_ep(list, ohci_ep);
    292                 OHCI_SET(instance->registers->control, C_PLE | C_IE);
     289                instance->registers->control |= C_PLE | C_IE;
    293290                break;
    294291        default:
     
    311308        /* Check for root hub communication */
    312309        if (batch->ep->address == instance->rh.address) {
    313                 usb_log_debug("OHCI root hub request.\n");
    314310                rh_request(&instance->rh, batch);
    315311                return EOK;
     
    327323        {
    328324        case USB_TRANSFER_CONTROL:
    329                 OHCI_SET(instance->registers->command_status, CS_CLF);
     325                instance->registers->command_status |= CS_CLF;
    330326                break;
    331327        case USB_TRANSFER_BULK:
    332                 OHCI_SET(instance->registers->command_status, CS_BLF);
     328                instance->registers->command_status |= CS_BLF;
    333329                break;
    334330        default:
     
    346342void hc_interrupt(hc_t *instance, uint32_t status)
    347343{
    348         status = ohci_reg2host(status);
    349344        assert(instance);
    350345        if ((status & ~I_SF) == 0) /* ignore sof status */
     
    357352                fibril_mutex_lock(&instance->guard);
    358353                usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,
    359                     OHCI_RD(instance->registers->hcca),
     354                    instance->registers->hcca,
    360355                    (void *) addr_to_phys(instance->hcca));
    361356                usb_log_debug2("Periodic current: %#" PRIx32 ".\n",
    362                     OHCI_RD(instance->registers->periodic_current));
     357                    instance->registers->periodic_current);
    363358
    364359                link_t *current = list_first(&instance->pending_batches);
     
    415410
    416411        usb_log_debug("Requesting OHCI control.\n");
    417         if (OHCI_RD(instance->registers->revision) & R_LEGACY_FLAG) {
     412        if (instance->registers->revision & R_LEGACY_FLAG) {
    418413                /* Turn off legacy emulation, it should be enough to zero
    419414                 * the lowest bit, but it caused problems. Thus clear all
     
    424419                (uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET);
    425420                usb_log_debug("OHCI legacy register %p: %x.\n",
    426                     ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
     421                    ohci_emulation_reg, *ohci_emulation_reg);
    427422                /* Zero everything but A20State */
    428                 OHCI_CLR(*ohci_emulation_reg, ~0x100);
     423                *ohci_emulation_reg &= 0x100;
    429424                usb_log_debug(
    430425                    "OHCI legacy register (should be 0 or 0x100) %p: %x.\n",
    431                     ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
     426                    ohci_emulation_reg, *ohci_emulation_reg);
    432427        }
    433428
    434429        /* Interrupt routing enabled => smm driver is active */
    435         if (OHCI_RD(instance->registers->control) & C_IR) {
     430        if (instance->registers->control & C_IR) {
    436431                usb_log_debug("SMM driver: request ownership change.\n");
    437                 OHCI_SET(instance->registers->command_status, CS_OCR);
     432                instance->registers->command_status |= CS_OCR;
    438433                /* Hope that SMM actually knows its stuff or we can hang here */
    439                 while (OHCI_RD(instance->registers->control & C_IR)) {
     434                while (instance->registers->control & C_IR) {
    440435                        async_usleep(1000);
    441436                }
     
    445440                return;
    446441        }
     442
    447443        const unsigned hc_status = C_HCFS_GET(instance->registers->control);
    448444        /* Interrupt routing disabled && status != USB_RESET => BIOS active */
     
    453449                        return;
    454450                }
    455                 /* HC is suspended assert resume for 20ms */
     451                /* HC is suspended assert resume for 20ms, */
    456452                C_HCFS_SET(instance->registers->control, C_HCFS_RESUME);
    457453                async_usleep(20000);
     
    477473
    478474        /* Save contents of fm_interval register */
    479         const uint32_t fm_interval = OHCI_RD(instance->registers->fm_interval);
     475        const uint32_t fm_interval = instance->registers->fm_interval;
    480476        usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
    481477
     
    483479        usb_log_debug2("HC reset.\n");
    484480        size_t time = 0;
    485         OHCI_WR(instance->registers->command_status, CS_HCR);
    486         while (OHCI_RD(instance->registers->command_status) & CS_HCR) {
     481        instance->registers->command_status = CS_HCR;
     482        while (instance->registers->command_status & CS_HCR) {
    487483                async_usleep(10);
    488484                time += 10;
     
    491487
    492488        /* Restore fm_interval */
    493         OHCI_WR(instance->registers->fm_interval, fm_interval);
    494         assert((OHCI_RD(instance->registers->command_status) & CS_HCR) == 0);
     489        instance->registers->fm_interval = fm_interval;
     490        assert((instance->registers->command_status & CS_HCR) == 0);
    495491
    496492        /* hc is now in suspend state */
    497493        usb_log_debug2("HC should be in suspend state(%x).\n",
    498             OHCI_RD(instance->registers->control));
     494            instance->registers->control);
    499495
    500496        /* Use HCCA */
    501         OHCI_WR(instance->registers->hcca, addr_to_phys(instance->hcca));
     497        instance->registers->hcca = addr_to_phys(instance->hcca);
    502498
    503499        /* Use queues */
    504         OHCI_WR(instance->registers->bulk_head,
    505             instance->lists[USB_TRANSFER_BULK].list_head_pa);
     500        instance->registers->bulk_head =
     501            instance->lists[USB_TRANSFER_BULK].list_head_pa;
    506502        usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n",
    507503            instance->lists[USB_TRANSFER_BULK].list_head,
    508504            instance->lists[USB_TRANSFER_BULK].list_head_pa);
    509505
    510         OHCI_WR(instance->registers->control_head,
    511             instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
     506        instance->registers->control_head =
     507            instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
    512508        usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n",
    513509            instance->lists[USB_TRANSFER_CONTROL].list_head,
     
    515511
    516512        /* Enable queues */
    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));
     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);
    520516
    521517        /* Enable interrupts */
    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);
     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;
    526522
    527523        /* Set periodic start to 90% */
    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);
     524        uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK);
     525        instance->registers->periodic_start = (frame_length / 10) * 9;
    532526        usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n",
    533             OHCI_RD(instance->registers->periodic_start),
    534             OHCI_RD(instance->registers->periodic_start), frame_length);
     527            instance->registers->periodic_start,
     528            instance->registers->periodic_start, frame_length);
     529
    535530        C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL);
    536531        usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n",
    537             OHCI_RD(instance->registers->control));
     532            instance->registers->control);
    538533}
    539534/*----------------------------------------------------------------------------*/
     
    596591
    597592        for (unsigned i = 0; i < 32; ++i) {
    598                 OHCI_WR(instance->hcca->int_ep[i],
    599                     instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
     593                instance->hcca->int_ep[i] =
     594                    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
    600595        }
    601596        usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
Note: See TracChangeset for help on using the changeset viewer.