Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset d1e580a in mainline for uspace/drv/bus/usb/ohci/hc.c


Ignore:
Timestamp:
2012-07-29T03:07:52Z (9 years ago)
Author:
Sean Bartell <wingedtachikoma@…>
Branches:
lfn, master
Children:
10334c2e
Parents:
d7c8e39f (diff), b2ba418 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes

File:
1 edited

Legend:

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

    rd7c8e39f rd1e580a  
    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 = 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        }
    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.
     
    112132        cmds[0].addr = (void *) &registers->interrupt_status;
    113133        cmds[3].addr = (void *) &registers->interrupt_status;
     134        OHCI_WR(cmds[1].value, OHCI_USED_INTERRUPTS);
    114135
    115136        return EOK;
    116137}
    117 /*----------------------------------------------------------------------------*/
     138
    118139/** Announce OHCI root hub to the DDF
    119140 *
     
    174195#undef CHECK_RET_RELEASE
    175196}
    176 /*----------------------------------------------------------------------------*/
     197
    177198/** Initialize OHCI hc driver structure
    178199 *
     
    227248        return EOK;
    228249}
    229 /*----------------------------------------------------------------------------*/
     250
    230251void hc_enqueue_endpoint(hc_t *instance, const endpoint_t *ep)
    231252{
     
    241262        switch (ep->transfer_type) {
    242263        case USB_TRANSFER_CONTROL:
    243                 instance->registers->control &= ~C_CLE;
     264                OHCI_CLR(instance->registers->control, C_CLE);
    244265                endpoint_list_add_ep(list, ohci_ep);
    245                 instance->registers->control_current = 0;
    246                 instance->registers->control |= C_CLE;
     266                OHCI_WR(instance->registers->control_current, 0);
     267                OHCI_SET(instance->registers->control, C_CLE);
    247268                break;
    248269        case USB_TRANSFER_BULK:
    249                 instance->registers->control &= ~C_BLE;
     270                OHCI_CLR(instance->registers->control, C_BLE);
    250271                endpoint_list_add_ep(list, ohci_ep);
    251                 instance->registers->control |= C_BLE;
     272                OHCI_WR(instance->registers->bulk_current, 0);
     273                OHCI_SET(instance->registers->control, C_BLE);
    252274                break;
    253275        case USB_TRANSFER_ISOCHRONOUS:
    254276        case USB_TRANSFER_INTERRUPT:
    255                 instance->registers->control &= (~C_PLE & ~C_IE);
     277                OHCI_CLR(instance->registers->control, C_PLE | C_IE);
    256278                endpoint_list_add_ep(list, ohci_ep);
    257                 instance->registers->control |= C_PLE | C_IE;
    258                 break;
    259         }
    260 }
    261 /*----------------------------------------------------------------------------*/
     279                OHCI_SET(instance->registers->control, C_PLE | C_IE);
     280                break;
     281        }
     282}
     283
    262284void hc_dequeue_endpoint(hc_t *instance, const endpoint_t *ep)
    263285{
     
    273295        switch (ep->transfer_type) {
    274296        case USB_TRANSFER_CONTROL:
    275                 instance->registers->control &= ~C_CLE;
     297                OHCI_CLR(instance->registers->control, C_CLE);
    276298                endpoint_list_remove_ep(list, ohci_ep);
    277                 instance->registers->control_current = 0;
    278                 instance->registers->control |= C_CLE;
     299                OHCI_WR(instance->registers->control_current, 0);
     300                OHCI_SET(instance->registers->control, C_CLE);
    279301                break;
    280302        case USB_TRANSFER_BULK:
    281                 instance->registers->control &= ~C_BLE;
     303                OHCI_CLR(instance->registers->control, C_BLE);
    282304                endpoint_list_remove_ep(list, ohci_ep);
    283                 instance->registers->control |= C_BLE;
     305                OHCI_WR(instance->registers->bulk_current, 0);
     306                OHCI_SET(instance->registers->control, C_BLE);
    284307                break;
    285308        case USB_TRANSFER_ISOCHRONOUS:
    286309        case USB_TRANSFER_INTERRUPT:
    287                 instance->registers->control &= (~C_PLE & ~C_IE);
     310                OHCI_CLR(instance->registers->control, C_PLE | C_IE);
    288311                endpoint_list_remove_ep(list, ohci_ep);
    289                 instance->registers->control |= C_PLE | C_IE;
     312                OHCI_SET(instance->registers->control, C_PLE | C_IE);
    290313                break;
    291314        default:
     
    293316        }
    294317}
    295 /*----------------------------------------------------------------------------*/
     318
    296319/** Add USB transfer to the schedule.
    297320 *
     
    308331        /* Check for root hub communication */
    309332        if (batch->ep->address == instance->rh.address) {
     333                usb_log_debug("OHCI root hub request.\n");
    310334                rh_request(&instance->rh, batch);
    311335                return EOK;
     
    323347        {
    324348        case USB_TRANSFER_CONTROL:
    325                 instance->registers->command_status |= CS_CLF;
     349                OHCI_SET(instance->registers->command_status, CS_CLF);
    326350                break;
    327351        case USB_TRANSFER_BULK:
    328                 instance->registers->command_status |= CS_BLF;
     352                OHCI_SET(instance->registers->command_status, CS_BLF);
    329353                break;
    330354        default:
     
    334358        return EOK;
    335359}
    336 /*----------------------------------------------------------------------------*/
     360
    337361/** Interrupt handling routine
    338362 *
     
    342366void hc_interrupt(hc_t *instance, uint32_t status)
    343367{
     368        status = OHCI_RD(status);
    344369        assert(instance);
    345370        if ((status & ~I_SF) == 0) /* ignore sof status */
     
    352377                fibril_mutex_lock(&instance->guard);
    353378                usb_log_debug2("HCCA: %p-%#" PRIx32 " (%p).\n", instance->hcca,
    354                     instance->registers->hcca,
     379                    OHCI_RD(instance->registers->hcca),
    355380                    (void *) addr_to_phys(instance->hcca));
    356381                usb_log_debug2("Periodic current: %#" PRIx32 ".\n",
    357                     instance->registers->periodic_current);
     382                    OHCI_RD(instance->registers->periodic_current));
    358383
    359384                link_t *current = list_first(&instance->pending_batches);
     
    379404
    380405}
    381 /*----------------------------------------------------------------------------*/
     406
    382407/** Check status register regularly
    383408 *
     
    397422        return EOK;
    398423}
    399 /*----------------------------------------------------------------------------*/
     424
    400425/** Turn off any (BIOS)driver that might be in control of the device.
    401426 *
     
    410435
    411436        usb_log_debug("Requesting OHCI control.\n");
    412         if (instance->registers->revision & R_LEGACY_FLAG) {
     437        if (OHCI_RD(instance->registers->revision) & R_LEGACY_FLAG) {
    413438                /* Turn off legacy emulation, it should be enough to zero
    414439                 * the lowest bit, but it caused problems. Thus clear all
     
    419444                (uint32_t*)((char*)instance->registers + LEGACY_REGS_OFFSET);
    420445                usb_log_debug("OHCI legacy register %p: %x.\n",
    421                     ohci_emulation_reg, *ohci_emulation_reg);
     446                    ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
    422447                /* Zero everything but A20State */
    423                 *ohci_emulation_reg &= 0x100;
     448                OHCI_CLR(*ohci_emulation_reg, ~0x100);
    424449                usb_log_debug(
    425450                    "OHCI legacy register (should be 0 or 0x100) %p: %x.\n",
    426                     ohci_emulation_reg, *ohci_emulation_reg);
     451                    ohci_emulation_reg, OHCI_RD(*ohci_emulation_reg));
    427452        }
    428453
    429454        /* Interrupt routing enabled => smm driver is active */
    430         if (instance->registers->control & C_IR) {
     455        if (OHCI_RD(instance->registers->control) & C_IR) {
    431456                usb_log_debug("SMM driver: request ownership change.\n");
    432                 instance->registers->command_status |= CS_OCR;
     457                OHCI_SET(instance->registers->command_status, CS_OCR);
    433458                /* Hope that SMM actually knows its stuff or we can hang here */
    434                 while (instance->registers->control & C_IR) {
     459                while (OHCI_RD(instance->registers->control & C_IR)) {
    435460                        async_usleep(1000);
    436461                }
     
    449474                        return;
    450475                }
    451                 /* HC is suspended assert resume for 20ms, */
     476                /* HC is suspended assert resume for 20ms */
    452477                C_HCFS_SET(instance->registers->control, C_HCFS_RESUME);
    453478                async_usleep(20000);
     
    461486        async_usleep(50000);
    462487}
    463 /*----------------------------------------------------------------------------*/
     488
    464489/** OHCI hw initialization routine.
    465490 *
     
    473498
    474499        /* Save contents of fm_interval register */
    475         const uint32_t fm_interval = instance->registers->fm_interval;
     500        const uint32_t fm_interval = OHCI_RD(instance->registers->fm_interval);
    476501        usb_log_debug2("Old value of HcFmInterval: %x.\n", fm_interval);
    477502
     
    479504        usb_log_debug2("HC reset.\n");
    480505        size_t time = 0;
    481         instance->registers->command_status = CS_HCR;
    482         while (instance->registers->command_status & CS_HCR) {
     506        OHCI_WR(instance->registers->command_status, CS_HCR);
     507        while (OHCI_RD(instance->registers->command_status) & CS_HCR) {
    483508                async_usleep(10);
    484509                time += 10;
     
    487512
    488513        /* Restore fm_interval */
    489         instance->registers->fm_interval = fm_interval;
    490         assert((instance->registers->command_status & CS_HCR) == 0);
     514        OHCI_WR(instance->registers->fm_interval, fm_interval);
     515        assert((OHCI_RD(instance->registers->command_status) & CS_HCR) == 0);
    491516
    492517        /* hc is now in suspend state */
    493518        usb_log_debug2("HC should be in suspend state(%x).\n",
    494             instance->registers->control);
     519            OHCI_RD(instance->registers->control));
    495520
    496521        /* Use HCCA */
    497         instance->registers->hcca = addr_to_phys(instance->hcca);
     522        OHCI_WR(instance->registers->hcca, addr_to_phys(instance->hcca));
    498523
    499524        /* Use queues */
    500         instance->registers->bulk_head =
    501             instance->lists[USB_TRANSFER_BULK].list_head_pa;
     525        OHCI_WR(instance->registers->bulk_head,
     526            instance->lists[USB_TRANSFER_BULK].list_head_pa);
    502527        usb_log_debug2("Bulk HEAD set to: %p (%#" PRIx32 ").\n",
    503528            instance->lists[USB_TRANSFER_BULK].list_head,
    504529            instance->lists[USB_TRANSFER_BULK].list_head_pa);
    505530
    506         instance->registers->control_head =
    507             instance->lists[USB_TRANSFER_CONTROL].list_head_pa;
     531        OHCI_WR(instance->registers->control_head,
     532            instance->lists[USB_TRANSFER_CONTROL].list_head_pa);
    508533        usb_log_debug2("Control HEAD set to: %p (%#" PRIx32 ").\n",
    509534            instance->lists[USB_TRANSFER_CONTROL].list_head,
     
    511536
    512537        /* 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);
     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));
    516541
    517542        /* 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;
     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);
    522547
    523548        /* 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;
     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);
    526553        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 
     554            OHCI_RD(instance->registers->periodic_start),
     555            OHCI_RD(instance->registers->periodic_start), frame_length);
    530556        C_HCFS_SET(instance->registers->control, C_HCFS_OPERATIONAL);
    531557        usb_log_debug("OHCI HC up and running (ctl_reg=0x%x).\n",
    532             instance->registers->control);
    533 }
    534 /*----------------------------------------------------------------------------*/
     558            OHCI_RD(instance->registers->control));
     559}
     560
    535561/** Initialize schedule queues
    536562 *
     
    566592        return EOK;
    567593}
    568 /*----------------------------------------------------------------------------*/
     594
    569595/** Initialize memory structures used by the OHCI hcd.
    570596 *
     
    587613        if (instance->hcca == NULL)
    588614                return ENOMEM;
    589         bzero(instance->hcca, sizeof(hcca_t));
    590615        usb_log_debug2("OHCI HCCA initialized at %p.\n", instance->hcca);
    591616
    592         for (unsigned i = 0; i < 32; ++i) {
    593                 instance->hcca->int_ep[i] =
    594                     instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa;
     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);
    595620        }
    596621        usb_log_debug2("Interrupt HEADs set to: %p (%#" PRIx32 ").\n",
Note: See TracChangeset for help on using the changeset viewer.