Changeset 159100a in mainline for uspace/drv/bus/usb/uhci/hc.c


Ignore:
Timestamp:
2011-07-13T22:19:26Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
ef9460b
Parents:
3e5c48c9 (diff), 5d36062 (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 OHCI improvements and fixes.

File:
1 edited

Legend:

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

    r3e5c48c9 r159100a  
    4747    (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
    4848
     49static const irq_cmd_t uhci_irq_commands[] =
     50{
     51        { .cmd = CMD_PIO_READ_16, .dstarg = 1, .addr = NULL/*filled later*/},
     52        { .cmd = CMD_BTEST, .srcarg = 1, .dstarg = 2,
     53          .value = UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS },
     54        { .cmd = CMD_PREDICATE, .srcarg = 2, .value = 2 },
     55        { .cmd = CMD_PIO_WRITE_A_16, .srcarg = 1, .addr = NULL/*filled later*/},
     56        { .cmd = CMD_ACCEPT },
     57};
    4958
    5059static int hc_init_transfer_lists(hc_t *instance);
     
    5463static int hc_interrupt_emulator(void *arg);
    5564static int hc_debug_checker(void *arg);
     65
     66/*----------------------------------------------------------------------------*/
     67/** Get number of commands used in IRQ code.
     68 * @return Number of commands.
     69 */
     70size_t hc_irq_cmd_count(void)
     71{
     72        return sizeof(uhci_irq_commands) / sizeof(irq_cmd_t);
     73}
     74/*----------------------------------------------------------------------------*/
     75/** Generate IRQ code commands.
     76 * @param[out] cmds Place to store the commands.
     77 * @param[in] cmd_size Size of the place (bytes).
     78 * @param[in] regs Physical address of device's registers.
     79 * @param[in] reg_size Size of the register area (bytes).
     80 *
     81 * @return Error code.
     82 */
     83int hc_get_irq_commands(
     84    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size)
     85{
     86        if (cmd_size < sizeof(uhci_irq_commands)
     87            || reg_size < sizeof(uhci_regs_t))
     88                return EOVERFLOW;
     89
     90        uhci_regs_t *registers = (uhci_regs_t*)regs;
     91
     92        memcpy(cmds, uhci_irq_commands, sizeof(uhci_irq_commands));
     93
     94        cmds[0].addr = (void*)&registers->usbsts;
     95        cmds[3].addr = (void*)&registers->usbsts;
     96        return EOK;
     97}
    5698/*----------------------------------------------------------------------------*/
    5799/** Initialize UHCI hc driver structure
     
    69111int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interrupts)
    70112{
    71         assert(reg_size >= sizeof(regs_t));
     113        assert(reg_size >= sizeof(uhci_regs_t));
    72114        int ret;
    73115
     
    82124
    83125        /* allow access to hc control registers */
    84         regs_t *io;
     126        uhci_regs_t *io;
    85127        ret = pio_enable(regs, reg_size, (void **)&io);
    86         CHECK_RET_RETURN(ret,
    87             "Failed(%d) to gain access to registers at %p: %s.\n",
    88             ret, io, str_error(ret));
     128        CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p: %s.\n",
     129            io, str_error(ret));
    89130        instance->registers = io;
    90         usb_log_debug("Device registers at %p (%zuB) accessible.\n",
    91             io, reg_size);
     131        usb_log_debug(
     132            "Device registers at %p (%zuB) accessible.\n", io, reg_size);
    92133
    93134        ret = hc_init_mem_structures(instance);
    94135        CHECK_RET_RETURN(ret,
    95             "Failed(%d) to initialize UHCI memory structures: %s.\n",
    96             ret, str_error(ret));
     136            "Failed to initialize UHCI memory structures: %s.\n",
     137            str_error(ret));
    97138
    98139        hc_init_hw(instance);
     
    116157{
    117158        assert(instance);
    118         regs_t *registers = instance->registers;
     159        uhci_regs_t *registers = instance->registers;
    119160
    120161        /* Reset everything, who knows what touched it before us */
    121162        pio_write_16(&registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
    122         async_usleep(10000); /* 10ms according to USB spec */
     163        async_usleep(50000); /* 50ms according to USB spec(root hub reset) */
    123164        pio_write_16(&registers->usbcmd, 0);
    124165
    125         /* Reset hc, all states and counters */
     166        /* Reset hc, all states and counters. Hope that hw is not broken */
    126167        pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
    127168        do { async_usleep(10); }
     
    141182        }
    142183
    143         const uint16_t status = pio_read_16(&registers->usbcmd);
    144         if (status != 0)
    145                 usb_log_warning("Previous command value: %x.\n", status);
     184        const uint16_t cmd = pio_read_16(&registers->usbcmd);
     185        if (cmd != 0)
     186                usb_log_warning("Previous command value: %x.\n", cmd);
    146187
    147188        /* Start the hc with large(64B) packet FSBR */
     
    170211        } else (void) 0
    171212
    172         /* Init interrupt code */
    173         instance->interrupt_code.cmds = instance->interrupt_commands;
    174         {
    175                 /* Read status register */
    176                 instance->interrupt_commands[0].cmd = CMD_PIO_READ_16;
    177                 instance->interrupt_commands[0].dstarg = 1;
    178                 instance->interrupt_commands[0].addr =
    179                     &instance->registers->usbsts;
    180 
    181                 /* Test whether we are the interrupt cause */
    182                 instance->interrupt_commands[1].cmd = CMD_BTEST;
    183                 instance->interrupt_commands[1].value =
    184                     UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS;
    185                 instance->interrupt_commands[1].srcarg = 1;
    186                 instance->interrupt_commands[1].dstarg = 2;
    187 
    188                 /* Predicate cleaning and accepting */
    189                 instance->interrupt_commands[2].cmd = CMD_PREDICATE;
    190                 instance->interrupt_commands[2].value = 2;
    191                 instance->interrupt_commands[2].srcarg = 2;
    192 
    193                 /* Write clean status register */
    194                 instance->interrupt_commands[3].cmd = CMD_PIO_WRITE_A_16;
    195                 instance->interrupt_commands[3].srcarg = 1;
    196                 instance->interrupt_commands[3].addr =
    197                     &instance->registers->usbsts;
    198 
    199                 /* Accept interrupt */
    200                 instance->interrupt_commands[4].cmd = CMD_ACCEPT;
    201 
    202                 instance->interrupt_code.cmdcount = UHCI_NEEDED_IRQ_COMMANDS;
    203         }
    204 
    205213        /* Init transfer lists */
    206214        int ret = hc_init_transfer_lists(instance);
    207         CHECK_RET_RETURN(ret, "Failed to init transfer lists.\n");
     215        CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n");
    208216        usb_log_debug("Initialized transfer lists.\n");
    209 
    210         /* Init USB frame list page*/
    211         instance->frame_list = get_page();
    212         ret = instance->frame_list ? EOK : ENOMEM;
    213         CHECK_RET_RETURN(ret, "Failed to get frame list page.\n");
    214         usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
    215 
    216         /* Set all frames to point to the first queue head */
    217         const uint32_t queue = LINK_POINTER_QH(
    218                 addr_to_phys(instance->transfers_interrupt.queue_head));
    219 
    220         unsigned i = 0;
    221         for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
    222                 instance->frame_list[i] = queue;
    223         }
    224217
    225218        /* Init device keeper */
    226219        usb_device_keeper_init(&instance->manager);
    227         usb_log_debug("Initialized device manager.\n");
     220        usb_log_debug("Initialized device keeper.\n");
    228221
    229222        ret = usb_endpoint_manager_init(&instance->ep_manager,
     
    232225            str_error(ret));
    233226
     227        /* Init USB frame list page*/
     228        instance->frame_list = get_page();
     229        if (!instance->frame_list) {
     230                usb_log_error("Failed to get frame list page.\n");
     231                usb_endpoint_manager_destroy(&instance->ep_manager);
     232                return ENOMEM;
     233        }
     234        usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
     235
     236        /* Set all frames to point to the first queue head */
     237        const uint32_t queue = LINK_POINTER_QH(
     238                addr_to_phys(instance->transfers_interrupt.queue_head));
     239        unsigned i = 0;
     240        for(; i < UHCI_FRAME_LIST_COUNT; ++i) {
     241                instance->frame_list[i] = queue;
     242        }
     243
    234244        return EOK;
    235245#undef CHECK_RET_RETURN
     
    252262        int ret = transfer_list_init(&instance->transfers_##type, name); \
    253263        if (ret != EOK) { \
    254                 usb_log_error("Failed(%d) to setup %s transfer list: %s.\n", \
    255                     ret, name, str_error(ret)); \
     264                usb_log_error("Failed to setup %s transfer list: %s.\n", \
     265                    name, str_error(ret)); \
    256266                transfer_list_fini(&instance->transfers_bulk_full); \
    257267                transfer_list_fini(&instance->transfers_control_full); \
Note: See TracChangeset for help on using the changeset viewer.