Ignore:
File:
1 edited

Legend:

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

    rea8b91d r9d58539  
    2626 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    2727 */
    28 
    2928/** @addtogroup drvusbohcihc
    3029 * @{
     
    3332 * @brief OHCI Host controller driver routines
    3433 */
    35 
    3634#include <errno.h>
    3735#include <str_error.h>
     
    5149static const irq_pio_range_t ohci_pio_ranges[] = {
    5250        {
    53                 .base = 0,
     51                .base = 0,      /* filled later */
    5452                .size = sizeof(ohci_regs_t)
    5553        }
     
    5755
    5856static const irq_cmd_t ohci_irq_commands[] = {
    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 = 0
    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         }
     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 },
    8362};
    8463
     
    8968static int interrupt_emulator(hc_t *instance);
    9069static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    91 
     70/*----------------------------------------------------------------------------*/
    9271/** Get number of PIO ranges used in IRQ code.
    9372 * @return Number of ranges.
     
    9776        return sizeof(ohci_pio_ranges) / sizeof(irq_pio_range_t);
    9877}
    99 
     78/*----------------------------------------------------------------------------*/
     79/*----------------------------------------------------------------------------*/
    10080/** Get number of commands used in IRQ code.
    10181 * @return Number of commands.
     
    10585        return sizeof(ohci_irq_commands) / sizeof(irq_cmd_t);
    10686}
    107 
     87/*----------------------------------------------------------------------------*/
    10888/** Generate IRQ code.
    10989 * @param[out] ranges PIO ranges buffer.
     
    132112        cmds[0].addr = (void *) &registers->interrupt_status;
    133113        cmds[3].addr = (void *) &registers->interrupt_status;
    134         OHCI_WR(cmds[1].value, OHCI_USED_INTERRUPTS);
    135114
    136115        return EOK;
    137116}
    138 
     117/*----------------------------------------------------------------------------*/
    139118/** Announce OHCI root hub to the DDF
    140119 *
     
    195174#undef CHECK_RET_RELEASE
    196175}
    197 
     176/*----------------------------------------------------------------------------*/
    198177/** Initialize OHCI hc driver structure
    199178 *
     
    248227        return EOK;
    249228}
    250 
     229/*----------------------------------------------------------------------------*/
    251230void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep)
    252231{
     
    262241        switch (ep->transfer_type) {
    263242        case USB_TRANSFER_CONTROL:
    264                 OHCI_CLR(instance->registers->control, C_CLE);
     243                instance->registers->control &= ~C_CLE;
    265244                endpoint_list_add_ep(list, ohci_ep);
    266                 OHCI_WR(instance->registers->control_current, 0);
    267                 OHCI_SET(instance->registers->control, C_CLE);
     245                instance->registers->control_current = 0;
     246                instance->registers->control |= C_CLE;
    268247                break;
    269248        case USB_TRANSFER_BULK:
    270                 OHCI_CLR(instance->registers->control, C_BLE);
     249                instance->registers->control &= ~C_BLE;
    271250                endpoint_list_add_ep(list, ohci_ep);
    272                 OHCI_WR(instance->registers->bulk_current, 0);
    273                 OHCI_SET(instance->registers->control, C_BLE);
     251                instance->registers->control |= C_BLE;
    274252                break;
    275253        case USB_TRANSFER_ISOCHRONOUS:
    276254        case USB_TRANSFER_INTERRUPT:
    277                 OHCI_CLR(instance->registers->control, C_PLE | C_IE);
     255                instance->registers->control &= (~C_PLE & ~C_IE);
    278256                endpoint_list_add_ep(list, ohci_ep);
    279                 OHCI_SET(instance->registers->control, C_PLE | C_IE);
    280                 break;
    281         }
    282 }
    283 
     257                instance->registers->control |= C_PLE | C_IE;
     258                break;
     259        }
     260}
     261/*----------------------------------------------------------------------------*/
    284262void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep)
    285263{
     
    295273        switch (ep->transfer_type) {
    296274        case USB_TRANSFER_CONTROL:
    297                 OHCI_CLR(instance->registers->control, C_CLE);
     275                instance->registers->control &= ~C_CLE;
    298276                endpoint_list_remove_ep(list, ohci_ep);
    299                 OHCI_WR(instance->registers->control_current, 0);
    300                 OHCI_SET(instance->registers->control, C_CLE);
     277                instance->registers->control_current = 0;
     278                instance->registers->control |= C_CLE;
    301279                break;
    302280        case USB_TRANSFER_BULK:
    303                 OHCI_CLR(instance->registers->control, C_BLE);
     281                instance->registers->control &= ~C_BLE;
    304282                endpoint_list_remove_ep(list, ohci_ep);
    305                 OHCI_WR(instance->registers->bulk_current, 0);
    306                 OHCI_SET(instance->registers->control, C_BLE);
     283                instance->registers->control |= C_BLE;
    307284                break;
    308285        case USB_TRANSFER_ISOCHRONOUS:
    309286        case USB_TRANSFER_INTERRUPT:
    310                 OHCI_CLR(instance->registers->control, C_PLE | C_IE);
     287                instance->registers->control &= (~C_PLE & ~C_IE);
    311288                endpoint_list_remove_ep(list, ohci_ep);
    312                 OHCI_SET(instance->registers->control, C_PLE | C_IE);
     289                instance->registers->control |= C_PLE | C_IE;
    313290                break;
    314291        default:
     
    316293        }
    317294}
    318 
     295/*----------------------------------------------------------------------------*/
    319296/** Add USB transfer to the schedule.
    320297 *
     
    331308        /* Check for root hub communication */
    332309        if (batch->ep->address == instance->rh.address) {
    333                 usb_log_debug("OHCI root hub request.\n");
    334310                rh_request(&instance->rh, batch);
    335311                return EOK;
     
    347323        {
    348324        case USB_TRANSFER_CONTROL:
    349                 OHCI_SET(instance->registers->command_status, CS_CLF);
     325                instance->registers->command_status |= CS_CLF;
    350326                break;
    351327        case USB_TRANSFER_BULK:
    352                 OHCI_SET(instance->registers->command_status, CS_BLF);
     328                instance->registers->command_status |= CS_BLF;
    353329                break;
    354330        default:
     
    358334        return EOK;
    359335}
    360 
     336/*----------------------------------------------------------------------------*/
    361337/** Interrupt handling routine
    362338 *
     
    366342void hc_interrupt(hc_t *instance, uint32_t status)
    367343{
    368         status = OHCI_RD(status);
    369344        assert(instance);
    370345        if ((status & ~I_SF) == 0) /* ignore sof status */
     
    377352                fibril_mutex_lock(&instance->guard);
    378353                usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,
    379                     OHCI_RD(instance->registers->hcca),
     354                    instance->registers->hcca,
    380355                    (void *) addr_to_phys(instance->hcca));
    381356                usb_log_debug2("Periodic current: %#" PRIx32 ".\n",
    382                     OHCI_RD(instance->registers->periodic_current));
     357                    instance->registers->periodic_current);
    383358
    384359                link_t *current = list_first(&instance->pending_batches);
     
    404379
    405380}
    406 
     381/*----------------------------------------------------------------------------*/
    407382/** Check status register regularly
    408383 *
     
    422397        return EOK;
    423398}
    424 
     399/*----------------------------------------------------------------------------*/
    425400/** Turn off any (BIOS)driver that might be in control of the device.
    426401 *
     
    435410
    436411        usb_log_debug("Requesting OHCI control.\n");
    437         if (OHCI_RD(instance->registers->revision) & R_LEGACY_FLAG) {
     412        if (instance->registers->revision & R_LEGACY_FLAG) {
    438413                /* Turn off legacy emulation, it should be enough to zero
    439414                 * the lowest bit, but it caused problems. Thus clear all
     
    444419                (uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET);
    445420                usb_log_debug("OHCI legacy register %p: %x.\n",
    446                     ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
     421                    ohci_emulation_reg, *ohci_emulation_reg);
    447422                /* Zero everything but A20State */
    448                 OHCI_CLR(*ohci_emulation_reg, ~0x100);
     423                *ohci_emulation_reg &= 0x100;
    449424                usb_log_debug(
    450425                    "OHCI legacy register (should be 0 or 0x100) %p: %x.\n",
    451                     ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
     426                    ohci_emulation_reg, *ohci_emulation_reg);
    452427        }
    453428
    454429        /* Interrupt routing enabled => smm driver is active */
    455         if (OHCI_RD(instance->registers->control) & C_IR) {
     430        if (instance->registers->control & C_IR) {
    456431                usb_log_debug("SMM driver: request ownership change.\n");
    457                 OHCI_SET(instance->registers->command_status, CS_OCR);
     432                instance->registers->command_status |= CS_OCR;
    458433                /* Hope that SMM actually knows its stuff or we can hang here */
    459                 while (OHCI_RD(instance->registers->control & C_IR)) {
     434                while (instance->registers->control & C_IR) {
    460435                        async_usleep(1000);
    461436                }
     
    474449                        return;
    475450                }
    476                 /* HC is suspended assert resume for 20ms */
     451                /* HC is suspended assert resume for 20ms, */
    477452                C_HCFS_SET(instance->registers->control, C_HCFS_RESUME);
    478453                async_usleep(20000);
     
    486461        async_usleep(50000);
    487462}
    488 
     463/*----------------------------------------------------------------------------*/
    489464/** OHCI hw initialization routine.
    490465 *
     
    498473
    499474        /* Save contents of fm_interval register */
    500         const uint32_t fm_interval = OHCI_RD(instance->registers->fm_interval);
     475        const uint32_t fm_interval = instance->registers->fm_interval;
    501476        usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
    502477
     
    504479        usb_log_debug2("HC reset.\n");
    505480        size_t time = 0;
    506         OHCI_WR(instance->registers->command_status, CS_HCR);
    507         while (OHCI_RD(instance->registers->command_status) & CS_HCR) {
     481        instance->registers->command_status = CS_HCR;
     482        while (instance->registers->command_status & CS_HCR) {
    508483                async_usleep(10);
    509484                time += 10;
     
    512487
    513488        /* Restore fm_interval */
    514         OHCI_WR(instance->registers->fm_interval, fm_interval);
    515         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);
    516491
    517492        /* hc is now in suspend state */
    518493        usb_log_debug2("HC should be in suspend state(%x).\n",
    519             OHCI_RD(instance->registers->control));
     494            instance->registers->control);
    520495
    521496        /* Use HCCA */
    522         OHCI_WR(instance->registers->hcca, addr_to_phys(instance->hcca));
     497        instance->registers->hcca = addr_to_phys(instance->hcca);
    523498
    524499        /* Use queues */
    525         OHCI_WR(instance->registers->bulk_head,
    526             instance->lists[USB_TRANSFER_BULK].list_head_pa);
     500        instance->registers->bulk_head =
     501            instance->lists[USB_TRANSFER_BULK].list_head_pa;
    527502        usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n",
    528503            instance->lists[USB_TRANSFER_BULK].list_head,
    529504            instance->lists[USB_TRANSFER_BULK].list_head_pa);
    530505
    531         OHCI_WR(instance->registers->control_head,
    532             instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
     506        instance->registers->control_head =
     507            instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
    533508        usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n",
    534509            instance->lists[USB_TRANSFER_CONTROL].list_head,
     
    536511
    537512        /* Enable queues */
    538         OHCI_SET(instance->registers->control, (C_PLE | C_IE | C_CLE | C_BLE));
    539         usb_log_debug("Queues enabled(%x).\n",
    540             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);
    541516
    542517        /* Enable interrupts */
    543         OHCI_WR(instance->registers->interrupt_enable, OHCI_USED_INTERRUPTS);
    544         usb_log_debug("Enabled interrupts: %x.\n",
    545             OHCI_RD(instance->registers->interrupt_enable));
    546         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;
    547522
    548523        /* Set periodic start to 90% */
    549         const uint32_t frame_length =
    550             (fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK;
    551         OHCI_WR(instance->registers->periodic_start,
    552             ((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;
    553526        usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n",
    554             OHCI_RD(instance->registers->periodic_start),
    555             OHCI_RD(instance->registers->periodic_start), frame_length);
     527            instance->registers->periodic_start,
     528            instance->registers->periodic_start, frame_length);
     529
    556530        C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL);
    557531        usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n",
    558             OHCI_RD(instance->registers->control));
    559 }
    560 
     532            instance->registers->control);
     533}
     534/*----------------------------------------------------------------------------*/
    561535/** Initialize schedule queues
    562536 *
     
    592566        return EOK;
    593567}
    594 
     568/*----------------------------------------------------------------------------*/
    595569/** Initialize memory structures used by the OHCI hcd.
    596570 *
     
    613587        if (instance->hcca == NULL)
    614588                return ENOMEM;
     589        bzero(instance->hcca, sizeof(hcca_t));
    615590        usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
    616591
    617         for (unsigned i = 0; i < HCCA_INT_EP_COUNT; ++i) {
    618                 hcca_set_int_ep(instance->hcca, i,
    619                     instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa);
     592        for (unsigned i = 0; i < 32; ++i) {
     593                instance->hcca->int_ep[i] =
     594                    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
    620595        }
    621596        usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
Note: See TracChangeset for help on using the changeset viewer.