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

Changeset dfe4955 in mainline


Ignore:
Timestamp:
2011-07-12T18:38:27Z (10 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master
Children:
26858040
Parents:
b4f291d
Message:

UHCI: Mirror OHCI changes to generating irq code, and enabling interrupts.

Rename regs_t ⇒ uhci_regs_t

Location:
uspace/drv/bus/usb
Files:
4 edited

Legend:

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

    rb4f291d rdfe4955  
    202202            hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);
    203203        CHECK_RET_DEST_FREE_RETURN(ret,
    204             "Failed to generate IRQ code: %s.\n", str_error(ret));
     204            "Failed to generate IRQ commands: %s.\n", str_error(ret));
    205205
    206206        irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
     
    217217        if (ret != EOK) {
    218218                usb_log_warning("Failed to enable interrupts: %s."
    219                     "Falling back to polling\n", str_error(ret));
     219                    " Falling back to polling\n", str_error(ret));
    220220                /* We don't need that handler */
    221221                unregister_interrupt_handler(device, irq);
  • uspace/drv/bus/usb/uhci/hc.c

    rb4f291d rdfe4955  
    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);
    86128        CHECK_RET_RETURN(ret,
     
    116158{
    117159        assert(instance);
    118         regs_t *registers = instance->registers;
     160        uhci_regs_t *registers = instance->registers;
    119161
    120162        /* Reset everything, who knows what touched it before us */
  • uspace/drv/bus/usb/uhci/hc.h

    rb4f291d rdfe4955  
    8484        /** SOF modification to match external timers */
    8585        uint8_t sofmod;
    86 } regs_t;
     86} uhci_regs_t;
    8787
    8888#define UHCI_FRAME_LIST_COUNT 1024
     
    100100
    101101        /** Addresses of I/O registers */
    102         regs_t *registers;
     102        uhci_regs_t *registers;
    103103
    104104        /** Frame List contains 1024 link pointers */
     
    132132        unsigned hw_failures;
    133133} hc_t;
    134 
     134size_t hc_irq_cmd_count(void);
     135int hc_get_irq_commands(
     136    irq_cmd_t cmds[], size_t cmd_size, uintptr_t regs, size_t reg_size);
    135137int hc_init(hc_t *instance, void *regs, size_t reg_size, bool interupts);
    136 
    137138int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);
    138 
    139139void hc_interrupt(hc_t *instance, uint16_t status);
    140140
  • uspace/drv/bus/usb/uhci/uhci.c

    rb4f291d rdfe4955  
    6464{
    6565        assert(dev);
    66         assert(dev->driver_data);
    6766        return dev->driver_data;
    6867}
     
    7877        assert(dev);
    7978        uhci_t *uhci = dev_to_uhci(dev);
     79        if (!uhci) {
     80                usb_log_error("Interrupt on not yet initialized device.\n");
     81                return;
     82        }
    8083        hc_t *hc = &uhci->hc;
    8184        const uint16_t status = IPC_GET_ARG1(*call);
    82         assert(hc);
    8385        hc_interrupt(hc, status);
    8486}
     
    192194        } \
    193195        free(instance); \
     196        device->driver_data = NULL; \
    194197        usb_log_error(message); \
    195198        return ret; \
     
    222225        ret = pci_disable_legacy(device);
    223226        CHECK_RET_DEST_FREE_RETURN(ret,
    224             "Failed(%d) to disable legacy USB: %s.\n", ret, str_error(ret));
     227            "Failed to disable legacy USB: %s.\n", str_error(ret));
     228
     229        const size_t cmd_count = hc_irq_cmd_count();
     230        irq_cmd_t irq_cmds[cmd_count];
     231        ret =
     232            hc_get_irq_commands(irq_cmds, sizeof(irq_cmds), reg_base, reg_size);
     233        CHECK_RET_DEST_FREE_RETURN(ret,
     234            "Failed to generate IRQ commands: %s.\n", str_error(ret));
     235
     236        irq_code_t irq_code = { .cmdcount = cmd_count, .cmds = irq_cmds };
     237
     238        /* Register handler to avoid interrupt lockup */
     239        ret = register_interrupt_handler(device, irq, irq_handler, &irq_code);
     240        CHECK_RET_DEST_FREE_RETURN(ret,
     241            "Failed to register interrupt handler: %s.\n", str_error(ret));
    225242
    226243        bool interrupts = false;
    227 #ifdef CONFIG_USBHC_NO_INTERRUPTS
    228         usb_log_warning("Interrupts disabled in OS config, " \
    229             "falling back to polling.\n");
    230 #else
    231244        ret = pci_enable_interrupts(device);
    232245        if (ret != EOK) {
    233                 usb_log_warning("Failed to enable interrupts: %s.\n",
    234                     str_error(ret));
    235                 usb_log_info("HW interrupts not available, " \
    236                     "falling back to polling.\n");
     246                usb_log_warning("Failed to enable interrupts: %s."
     247                    " Falling back to polling.\n", str_error(ret));
    237248        } else {
    238249                usb_log_debug("Hw interrupts enabled.\n");
    239250                interrupts = true;
    240251        }
    241 #endif
    242 
    243252
    244253        ret = hc_init(&instance->hc, (void*)reg_base, reg_size, interrupts);
    245254        CHECK_RET_DEST_FREE_RETURN(ret,
    246255            "Failed(%d) to init uhci_hcd: %s.\n", ret, str_error(ret));
     256
     257        device->driver_data = instance;
    247258
    248259#define CHECK_RET_FINI_RETURN(ret, message...) \
     
    253264} else (void)0
    254265
    255         /* It does no harm if we register this on polling */
    256         ret = register_interrupt_handler(device, irq, irq_handler,
    257             &instance->hc.interrupt_code);
    258         CHECK_RET_FINI_RETURN(ret,
    259             "Failed(%d) to register interrupt handler: %s.\n",
    260             ret, str_error(ret));
    261 
    262266        ret = ddf_fun_bind(instance->hc_fun);
    263267        CHECK_RET_FINI_RETURN(ret,
     
    278282            "Failed(%d) to register UHCI root hub: %s.\n", ret, str_error(ret));
    279283
    280         device->driver_data = instance;
    281284        return EOK;
    282285#undef CHECK_RET_FINI_RETURN
Note: See TracChangeset for help on using the changeset viewer.