Ignore:
File:
1 edited

Legend:

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

    r26858040 r5203e256  
    4747    (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
    4848
    49 static 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 };
    5849
    5950static int hc_init_transfer_lists(hc_t *instance);
     
    6354static int hc_interrupt_emulator(void *arg);
    6455static int hc_debug_checker(void *arg);
    65 
    66 /*----------------------------------------------------------------------------*/
    67 /** Get number of commands used in IRQ code.
    68  * @return Number of commands.
    69  */
    70 size_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  */
    83 int 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 }
    9856/*----------------------------------------------------------------------------*/
    9957/** Initialize UHCI hc driver structure
     
    11169int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interrupts)
    11270{
    113         assert(reg_size >= sizeof(uhci_regs_t));
     71        assert(reg_size >= sizeof(regs_t));
    11472        int ret;
    11573
     
    12482
    12583        /* allow access to hc control registers */
    126         uhci_regs_t *io;
     84        regs_t *io;
    12785        ret = pio_enable(regs, reg_size, (void **)&io);
    128         CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p: %s.\n",
    129             io, str_error(ret));
     86        CHECK_RET_RETURN(ret,
     87            "Failed(%d) to gain access to registers at %p: %s.\n",
     88            ret, io, str_error(ret));
    13089        instance->registers = io;
    131         usb_log_debug(
    132             "Device registers at %p (%zuB) accessible.\n", io, reg_size);
     90        usb_log_debug("Device registers at %p (%zuB) accessible.\n",
     91            io, reg_size);
    13392
    13493        ret = hc_init_mem_structures(instance);
    13594        CHECK_RET_RETURN(ret,
    136             "Failed to initialize UHCI memory structures: %s.\n",
    137             str_error(ret));
     95            "Failed(%d) to initialize UHCI memory structures: %s.\n",
     96            ret, str_error(ret));
    13897
    13998        hc_init_hw(instance);
     
    157116{
    158117        assert(instance);
    159         uhci_regs_t *registers = instance->registers;
     118        regs_t *registers = instance->registers;
    160119
    161120        /* Reset everything, who knows what touched it before us */
    162121        pio_write_16(&registers->usbcmd, UHCI_CMD_GLOBAL_RESET);
    163         async_usleep(50000); /* 50ms according to USB spec(root hub reset) */
     122        async_usleep(10000); /* 10ms according to USB spec */
    164123        pio_write_16(&registers->usbcmd, 0);
    165124
    166         /* Reset hc, all states and counters. Hope that hw is not broken */
     125        /* Reset hc, all states and counters */
    167126        pio_write_16(&registers->usbcmd, UHCI_CMD_HCRESET);
    168127        do { async_usleep(10); }
     
    182141        }
    183142
    184         const uint16_t cmd = pio_read_16(&registers->usbcmd);
    185         if (cmd != 0)
    186                 usb_log_warning("Previous command value: %x.\n", cmd);
     143        const uint16_t status = pio_read_16(&registers->usbcmd);
     144        if (status != 0)
     145                usb_log_warning("Previous command value: %x.\n", status);
    187146
    188147        /* Start the hc with large(64B) packet FSBR */
     
    211170        } else (void) 0
    212171
     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
    213205        /* Init transfer lists */
    214206        int ret = hc_init_transfer_lists(instance);
    215         CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n");
     207        CHECK_RET_RETURN(ret, "Failed to init transfer lists.\n");
    216208        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        }
    217224
    218225        /* Init device keeper */
    219226        usb_device_keeper_init(&instance->manager);
    220         usb_log_debug("Initialized device keeper.\n");
     227        usb_log_debug("Initialized device manager.\n");
    221228
    222229        ret = usb_endpoint_manager_init(&instance->ep_manager,
     
    225232            str_error(ret));
    226233
    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 
    244234        return EOK;
    245235#undef CHECK_RET_RETURN
     
    262252        int ret = transfer_list_init(&instance->transfers_##type, name); \
    263253        if (ret != EOK) { \
    264                 usb_log_error("Failed to setup %s transfer list: %s.\n", \
    265                     name, str_error(ret)); \
     254                usb_log_error("Failed(%d) to setup %s transfer list: %s.\n", \
     255                    ret, name, str_error(ret)); \
    266256                transfer_list_fini(&instance->transfers_bulk_full); \
    267257                transfer_list_fini(&instance->transfers_control_full); \
Note: See TracChangeset for help on using the changeset viewer.