Ignore:
File:
1 edited

Legend:

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

    r8486c07 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 = 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         }
     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.
     
    135115        return EOK;
    136116}
    137 
     117/*----------------------------------------------------------------------------*/
    138118/** Announce OHCI root hub to the DDF
    139119 *
     
    194174#undef CHECK_RET_RELEASE
    195175}
    196 
     176/*----------------------------------------------------------------------------*/
    197177/** Initialize OHCI hc driver structure
    198178 *
     
    247227        return EOK;
    248228}
    249 
     229/*----------------------------------------------------------------------------*/
    250230void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep)
    251231{
     
    261241        switch (ep->transfer_type) {
    262242        case USB_TRANSFER_CONTROL:
    263                 OHCI_CLR(instance->registers->control, C_CLE);
     243                instance->registers->control &= ~C_CLE;
    264244                endpoint_list_add_ep(list, ohci_ep);
    265                 OHCI_WR(instance->registers->control_current, 0);
    266                 OHCI_SET(instance->registers->control, C_CLE);
     245                instance->registers->control_current = 0;
     246                instance->registers->control |= C_CLE;
    267247                break;
    268248        case USB_TRANSFER_BULK:
    269                 OHCI_CLR(instance->registers->control, C_BLE);
     249                instance->registers->control &= ~C_BLE;
    270250                endpoint_list_add_ep(list, ohci_ep);
    271                 OHCI_WR(instance->registers->bulk_current, 0);
    272                 OHCI_SET(instance->registers->control, C_BLE);
     251                instance->registers->control |= C_BLE;
    273252                break;
    274253        case USB_TRANSFER_ISOCHRONOUS:
    275254        case USB_TRANSFER_INTERRUPT:
    276                 OHCI_CLR(instance->registers->control, C_PLE | C_IE);
     255                instance->registers->control &= (~C_PLE & ~C_IE);
    277256                endpoint_list_add_ep(list, ohci_ep);
    278                 OHCI_SET(instance->registers->control, C_PLE | C_IE);
    279                 break;
    280         }
    281 }
    282 
     257                instance->registers->control |= C_PLE | C_IE;
     258                break;
     259        }
     260}
     261/*----------------------------------------------------------------------------*/
    283262void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep)
    284263{
     
    294273        switch (ep->transfer_type) {
    295274        case USB_TRANSFER_CONTROL:
    296                 OHCI_CLR(instance->registers->control, C_CLE);
     275                instance->registers->control &= ~C_CLE;
    297276                endpoint_list_remove_ep(list, ohci_ep);
    298                 OHCI_WR(instance->registers->control_current, 0);
    299                 OHCI_SET(instance->registers->control, C_CLE);
     277                instance->registers->control_current = 0;
     278                instance->registers->control |= C_CLE;
    300279                break;
    301280        case USB_TRANSFER_BULK:
    302                 OHCI_CLR(instance->registers->control, C_BLE);
     281                instance->registers->control &= ~C_BLE;
    303282                endpoint_list_remove_ep(list, ohci_ep);
    304                 OHCI_WR(instance->registers->bulk_current, 0);
    305                 OHCI_SET(instance->registers->control, C_BLE);
     283                instance->registers->control |= C_BLE;
    306284                break;
    307285        case USB_TRANSFER_ISOCHRONOUS:
    308286        case USB_TRANSFER_INTERRUPT:
    309                 OHCI_CLR(instance->registers->control, C_PLE | C_IE);
     287                instance->registers->control &= (~C_PLE & ~C_IE);
    310288                endpoint_list_remove_ep(list, ohci_ep);
    311                 OHCI_SET(instance->registers->control, C_PLE | C_IE);
     289                instance->registers->control |= C_PLE | C_IE;
    312290                break;
    313291        default:
     
    315293        }
    316294}
    317 
     295/*----------------------------------------------------------------------------*/
    318296/** Add USB transfer to the schedule.
    319297 *
     
    330308        /* Check for root hub communication */
    331309        if (batch->ep->address == instance->rh.address) {
    332                 usb_log_debug("OHCI root hub request.\n");
    333310                rh_request(&instance->rh, batch);
    334311                return EOK;
     
    346323        {
    347324        case USB_TRANSFER_CONTROL:
    348                 OHCI_SET(instance->registers->command_status, CS_CLF);
     325                instance->registers->command_status |= CS_CLF;
    349326                break;
    350327        case USB_TRANSFER_BULK:
    351                 OHCI_SET(instance->registers->command_status, CS_BLF);
     328                instance->registers->command_status |= CS_BLF;
    352329                break;
    353330        default:
     
    357334        return EOK;
    358335}
    359 
     336/*----------------------------------------------------------------------------*/
    360337/** Interrupt handling routine
    361338 *
     
    365342void hc_interrupt(hc_t *instance, uint32_t status)
    366343{
    367         status = OHCI_RD(status);
    368344        assert(instance);
    369345        if ((status & ~I_SF) == 0) /* ignore sof status */
     
    376352                fibril_mutex_lock(&instance->guard);
    377353                usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,
    378                     OHCI_RD(instance->registers->hcca),
     354                    instance->registers->hcca,
    379355                    (void *) addr_to_phys(instance->hcca));
    380356                usb_log_debug2("Periodic current: %#" PRIx32 ".\n",
    381                     OHCI_RD(instance->registers->periodic_current));
     357                    instance->registers->periodic_current);
    382358
    383359                link_t *current = list_first(&instance->pending_batches);
     
    403379
    404380}
    405 
     381/*----------------------------------------------------------------------------*/
    406382/** Check status register regularly
    407383 *
     
    421397        return EOK;
    422398}
    423 
     399/*----------------------------------------------------------------------------*/
    424400/** Turn off any (BIOS)driver that might be in control of the device.
    425401 *
     
    434410
    435411        usb_log_debug("Requesting OHCI control.\n");
    436         if (OHCI_RD(instance->registers->revision) & R_LEGACY_FLAG) {
     412        if (instance->registers->revision & R_LEGACY_FLAG) {
    437413                /* Turn off legacy emulation, it should be enough to zero
    438414                 * the lowest bit, but it caused problems. Thus clear all
     
    443419                (uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET);
    444420                usb_log_debug("OHCI legacy register %p: %x.\n",
    445                     ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
     421                    ohci_emulation_reg, *ohci_emulation_reg);
    446422                /* Zero everything but A20State */
    447                 OHCI_CLR(*ohci_emulation_reg, ~0x100);
     423                *ohci_emulation_reg &= 0x100;
    448424                usb_log_debug(
    449425                    "OHCI legacy register (should be 0 or 0x100) %p: %x.\n",
    450                     ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
     426                    ohci_emulation_reg, *ohci_emulation_reg);
    451427        }
    452428
    453429        /* Interrupt routing enabled => smm driver is active */
    454         if (OHCI_RD(instance->registers->control) & C_IR) {
     430        if (instance->registers->control & C_IR) {
    455431                usb_log_debug("SMM driver: request ownership change.\n");
    456                 OHCI_SET(instance->registers->command_status, CS_OCR);
     432                instance->registers->command_status |= CS_OCR;
    457433                /* Hope that SMM actually knows its stuff or we can hang here */
    458                 while (OHCI_RD(instance->registers->control & C_IR)) {
     434                while (instance->registers->control & C_IR) {
    459435                        async_usleep(1000);
    460436                }
     
    473449                        return;
    474450                }
    475                 /* HC is suspended assert resume for 20ms */
     451                /* HC is suspended assert resume for 20ms, */
    476452                C_HCFS_SET(instance->registers->control, C_HCFS_RESUME);
    477453                async_usleep(20000);
     
    485461        async_usleep(50000);
    486462}
    487 
     463/*----------------------------------------------------------------------------*/
    488464/** OHCI hw initialization routine.
    489465 *
     
    497473
    498474        /* Save contents of fm_interval register */
    499         const uint32_t fm_interval = OHCI_RD(instance->registers->fm_interval);
     475        const uint32_t fm_interval = instance->registers->fm_interval;
    500476        usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
    501477
     
    503479        usb_log_debug2("HC reset.\n");
    504480        size_t time = 0;
    505         OHCI_WR(instance->registers->command_status, CS_HCR);
    506         while (OHCI_RD(instance->registers->command_status) & CS_HCR) {
     481        instance->registers->command_status = CS_HCR;
     482        while (instance->registers->command_status & CS_HCR) {
    507483                async_usleep(10);
    508484                time += 10;
     
    511487
    512488        /* Restore fm_interval */
    513         OHCI_WR(instance->registers->fm_interval, fm_interval);
    514         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);
    515491
    516492        /* hc is now in suspend state */
    517493        usb_log_debug2("HC should be in suspend state(%x).\n",
    518             OHCI_RD(instance->registers->control));
     494            instance->registers->control);
    519495
    520496        /* Use HCCA */
    521         OHCI_WR(instance->registers->hcca, addr_to_phys(instance->hcca));
     497        instance->registers->hcca = addr_to_phys(instance->hcca);
    522498
    523499        /* Use queues */
    524         OHCI_WR(instance->registers->bulk_head,
    525             instance->lists[USB_TRANSFER_BULK].list_head_pa);
     500        instance->registers->bulk_head =
     501            instance->lists[USB_TRANSFER_BULK].list_head_pa;
    526502        usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n",
    527503            instance->lists[USB_TRANSFER_BULK].list_head,
    528504            instance->lists[USB_TRANSFER_BULK].list_head_pa);
    529505
    530         OHCI_WR(instance->registers->control_head,
    531             instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
     506        instance->registers->control_head =
     507            instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
    532508        usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n",
    533509            instance->lists[USB_TRANSFER_CONTROL].list_head,
     
    535511
    536512        /* Enable queues */
    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));
     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);
    540516
    541517        /* Enable interrupts */
    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);
     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;
    546522
    547523        /* Set periodic start to 90% */
    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);
     524        uint32_t frame_length = ((fm_interval >> FMI_FI_SHIFT) & FMI_FI_MASK);
     525        instance->registers->periodic_start = (frame_length / 10) * 9;
    552526        usb_log_debug2("All periodic start set to: %x(%u - 90%% of %d).\n",
    553             OHCI_RD(instance->registers->periodic_start),
    554             OHCI_RD(instance->registers->periodic_start), frame_length);
     527            instance->registers->periodic_start,
     528            instance->registers->periodic_start, frame_length);
     529
    555530        C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL);
    556531        usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n",
    557             OHCI_RD(instance->registers->control));
    558 }
    559 
     532            instance->registers->control);
     533}
     534/*----------------------------------------------------------------------------*/
    560535/** Initialize schedule queues
    561536 *
     
    591566        return EOK;
    592567}
    593 
     568/*----------------------------------------------------------------------------*/
    594569/** Initialize memory structures used by the OHCI hcd.
    595570 *
     
    612587        if (instance->hcca == NULL)
    613588                return ENOMEM;
     589        bzero(instance->hcca, sizeof(hcca_t));
    614590        usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
    615591
    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);
     592        for (unsigned i = 0; i < 32; ++i) {
     593                instance->hcca->int_ep[i] =
     594                    instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
    619595        }
    620596        usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
Note: See TracChangeset for help on using the changeset viewer.