Ignore:
File:
1 edited

Legend:

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

    rd57122c r65eac7b  
    4747    (I_SO | I_WDH | I_UE | I_RHSC)
    4848
    49 static const irq_pio_range_t ohci_pio_ranges[] = {
    50         {
    51                 .base = 0,      /* filled later */
    52                 .size = sizeof(ohci_regs_t)
    53         }
    54 };
    55 
    56 static 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 },
     49static 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*/},
    5953        { .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },
    60         { .cmd = CMD_PIO_WRITE_A_32, .srcarg = 1, .addr = NULL /* filled later */ },
     54        { .cmd = CMD_MEM_WRITE_A_32, .srcarg = 1, .addr = NULL /*filled later*/ },
    6155        { .cmd = CMD_ACCEPT },
    6256};
     
    6963static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    7064/*----------------------------------------------------------------------------*/
    71 /** Get number of PIO ranges used in IRQ code.
    72  * @return Number of ranges.
    73  */
    74 size_t hc_irq_pio_range_count(void)
    75 {
    76         return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t);
    77 }
    78 /*----------------------------------------------------------------------------*/
    79 /*----------------------------------------------------------------------------*/
    8065/** Get number of commands used in IRQ code.
    8166 * @return Number of commands.
     
    8671}
    8772/*----------------------------------------------------------------------------*/
    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).
     73/** Generate IRQ code commands.
     74 * @param[out] cmds Place to store the commands.
     75 * @param[in] cmd_size Size of the place (bytes).
    9376 * @param[in] regs Physical address of device's registers.
    9477 * @param[in] reg_size Size of the register area (bytes).
     
    9679 * @return Error code.
    9780 */
    98 int
    99 hc_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)))
     81int 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))
    10586                return EOVERFLOW;
    10687
    107         memcpy(ranges, ohci_pio_ranges, sizeof(ohci_pio_ranges));
    108         ranges[0].base = regs;
     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;
    109109
    110110        memcpy(cmds, ohci_irq_commands, sizeof(ohci_irq_commands));
    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 
     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;
    115116        return EOK;
    116117}
     
    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;
     259                OHCI_SET(instance->registers->control, C_PLE | C_IE);
    258260                break;
    259261        }
     
    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:
     
    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:
     
    342346void hc_interrupt(hc_t *instance, uint32_t status)
    343347{
     348        status = ohci_reg2host(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);
     
    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);
     
    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);
     537            OHCI_RD(instance->registers->control));
    533538}
    534539/*----------------------------------------------------------------------------*/
     
    591596
    592597        for (unsigned i = 0; i < 32; ++i) {
    593                 instance->hcca->int_ep[i] =
    594                     instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
     598                OHCI_WR(instance->hcca->int_ep[i],
     599                    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
    595600        }
    596601        usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
Note: See TracChangeset for help on using the changeset viewer.