Changeset 423e8c81 in mainline for uspace/drv/uhci-hcd/uhci.c


Ignore:
Timestamp:
2011-02-19T23:41:38Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
063ead6f, 41e645c, 62066b4
Parents:
374552ef (diff), fb78ae72 (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:

Use hardware interrupts instead of polling

NOTE: hw interrupt enabling is implemented in pciintel driver,
it's probably not done ddf-way, but it works and can be used by other drivers too.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/uhci-hcd/uhci.c

    r374552ef r423e8c81  
    3939
    4040#include "uhci.h"
     41static irq_cmd_t uhci_cmds[] = {
     42        {
     43                .cmd = CMD_PIO_READ_16,
     44                .addr = (void*)0xc022,
     45                .dstarg = 1
     46        },
     47        {
     48                .cmd = CMD_PIO_WRITE_16,
     49                .addr = (void*)0xc022,
     50                .value = 0x1f
     51        },
     52        {
     53                .cmd = CMD_ACCEPT
     54        }
     55};
    4156
    4257static int uhci_init_transfer_lists(uhci_t *instance);
    43 static int uhci_clean_finished(void *arg);
     58static int uhci_init_mem_structures(uhci_t *instance);
     59static void uhci_init_hw(uhci_t *instance);
     60
     61static int uhci_interrupt_emulator(void *arg);
    4462static int uhci_debug_checker(void *arg);
     63
    4564static bool allowed_usb_packet(
    4665        bool low_speed, usb_transfer_type_t, size_t size);
    4766
    48 int uhci_init(uhci_t *instance, void *regs, size_t reg_size)
    49 {
    50 #define CHECK_RET_RETURN(message...) \
     67#define CHECK_RET_RETURN(ret, message...) \
    5168        if (ret != EOK) { \
    5269                usb_log_error(message); \
     
    5471        } else (void) 0
    5572
    56         /* init address keeper(libusb) */
    57         usb_address_keeping_init(&instance->address_manager, USB11_ADDRESS_MAX);
    58         usb_log_debug("Initialized address manager.\n");
     73int uhci_init(uhci_t *instance, void *regs, size_t reg_size)
     74{
     75        assert(reg_size >= sizeof(regs_t));
    5976
    6077        /* allow access to hc control registers */
    6178        regs_t *io;
    62         assert(reg_size >= sizeof(regs_t));
    6379        int ret = pio_enable(regs, reg_size, (void**)&io);
    64         CHECK_RET_RETURN("Failed to gain access to registers at %p.\n", io);
     80        CHECK_RET_RETURN(ret, "Failed to gain access to registers at %p.\n", io);
    6581        instance->registers = io;
    6682        usb_log_debug("Device registers accessible.\n");
    6783
     84        ret = uhci_init_mem_structures(instance);
     85        CHECK_RET_RETURN(ret, "Failed to initialize memory structures.\n");
     86
     87        uhci_init_hw(instance);
     88
     89        instance->cleaner = fibril_create(uhci_interrupt_emulator, instance);
     90//      fibril_add_ready(instance->cleaner);
     91
     92        instance->debug_checker = fibril_create(uhci_debug_checker, instance);
     93        fibril_add_ready(instance->debug_checker);
     94
     95        return EOK;
     96}
     97/*----------------------------------------------------------------------------*/
     98void uhci_init_hw(uhci_t *instance)
     99{
     100
     101        /* set framelist pointer */
     102        const uint32_t pa = addr_to_phys(instance->frame_list);
     103        pio_write_32(&instance->registers->flbaseadd, pa);
     104
     105        /* enable all interrupts, but resume interrupt */
     106        pio_write_16(&instance->registers->usbintr,
     107                  UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
     108
     109        /* Start the hc with large(64B) packet FSBR */
     110        pio_write_16(&instance->registers->usbcmd,
     111            UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET | UHCI_CMD_CONFIGURE);
     112        usb_log_debug("Started UHCI HC.\n");
     113}
     114/*----------------------------------------------------------------------------*/
     115int uhci_init_mem_structures(uhci_t *instance)
     116{
     117        assert(instance);
     118
     119        /* init interrupt code */
     120        irq_cmd_t *interrupt_commands = malloc(sizeof(uhci_cmds));
     121        if (interrupt_commands == NULL) {
     122                return ENOMEM;
     123        }
     124        memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
     125        interrupt_commands[0].addr = (void*)&instance->registers->usbsts;
     126        interrupt_commands[1].addr = (void*)&instance->registers->usbsts;
     127        instance->interrupt_code.cmds = interrupt_commands;
     128        instance->interrupt_code.cmdcount =
     129            sizeof(uhci_cmds) / sizeof(irq_cmd_t);
     130
    68131        /* init transfer lists */
    69         ret = uhci_init_transfer_lists(instance);
    70         CHECK_RET_RETURN("Failed to initialize transfer lists.\n");
    71         usb_log_debug("Transfer lists initialized.\n");
    72 
    73 
    74         usb_log_debug("Initializing frame list.\n");
     132        int ret = uhci_init_transfer_lists(instance);
     133        CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n");
     134        usb_log_debug("Initialized transfer lists.\n");
     135
     136        /* frame list initialization */
    75137        instance->frame_list = get_page();
    76138        ret = instance ? EOK : ENOMEM;
    77         CHECK_RET_RETURN("Failed to get frame list page.\n");
     139        CHECK_RET_RETURN(ret, "Failed to get frame list page.\n");
     140        usb_log_debug("Initialized frame list.\n");
    78141
    79142        /* initialize all frames to point to the first queue head */
     
    86149        }
    87150
    88         const uintptr_t pa = (uintptr_t)addr_to_phys(instance->frame_list);
    89         pio_write_32(&instance->registers->flbaseadd, (uint32_t)pa);
    90 
    91         list_initialize(&instance->batch_list);
    92         fibril_mutex_initialize(&instance->batch_list_mutex);
    93 
    94         instance->cleaner = fibril_create(uhci_clean_finished, instance);
    95         fibril_add_ready(instance->cleaner);
    96 
    97         instance->debug_checker = fibril_create(uhci_debug_checker, instance);
    98         fibril_add_ready(instance->debug_checker);
    99 
    100         /* Start the hc with large(64B) packet FSBR */
    101         pio_write_16(&instance->registers->usbcmd,
    102             UHCI_CMD_RUN_STOP | UHCI_CMD_MAX_PACKET);
    103         usb_log_debug("Started UHCI HC.\n");
    104 
    105         uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
    106         cmd |= UHCI_CMD_DEBUG;
    107         pio_write_16(&instance->registers->usbcmd, cmd);
     151        /* init address keeper(libusb) */
     152        usb_address_keeping_init(&instance->address_manager, USB11_ADDRESS_MAX);
     153        usb_log_debug("Initialized address manager.\n");
    108154
    109155        return EOK;
     
    114160        assert(instance);
    115161
    116         /* initialize */
     162        /* initialize TODO: check errors */
    117163        int ret;
    118164        ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
     
    146192        instance->transfers[1][USB_TRANSFER_CONTROL] =
    147193          &instance->transfers_control_slow;
    148         instance->transfers[0][USB_TRANSFER_CONTROL] =
    149           &instance->transfers_control_full;
     194        instance->transfers[0][USB_TRANSFER_BULK] =
     195          &instance->transfers_bulk_full;
    150196
    151197        return EOK;
     
    174220}
    175221/*----------------------------------------------------------------------------*/
    176 int uhci_clean_finished(void* arg)
    177 {
    178         usb_log_debug("Started cleaning fibril.\n");
     222void uhci_interrupt(uhci_t *instance, uint16_t status)
     223{
     224        assert(instance);
     225        if ((status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) == 0)
     226                return;
     227        usb_log_debug("UHCI interrupt: %X.\n", status);
     228        transfer_list_check(&instance->transfers_interrupt);
     229        transfer_list_check(&instance->transfers_control_slow);
     230        transfer_list_check(&instance->transfers_control_full);
     231        transfer_list_check(&instance->transfers_bulk_full);
     232}
     233/*----------------------------------------------------------------------------*/
     234int uhci_interrupt_emulator(void* arg)
     235{
     236        usb_log_debug("Started interrupt emulator.\n");
    179237        uhci_t *instance = (uhci_t*)arg;
    180238        assert(instance);
    181239
    182240        while(1) {
    183                 transfer_list_check(&instance->transfers_interrupt);
    184                 transfer_list_check(&instance->transfers_control_slow);
    185                 transfer_list_check(&instance->transfers_control_full);
    186                 transfer_list_check(&instance->transfers_bulk_full);
     241                uint16_t status = pio_read_16(&instance->registers->usbsts);
     242                uhci_interrupt(instance, status);
    187243                async_usleep(UHCI_CLEANER_TIMEOUT);
    188244        }
     
    195251        assert(instance);
    196252        while (1) {
    197                 uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
    198                 uint16_t sts = pio_read_16(&instance->registers->usbsts);
    199                 usb_log_debug("Command register: %X Status register: %X\n", cmd, sts);
     253                const uint16_t cmd = pio_read_16(&instance->registers->usbcmd);
     254                const uint16_t sts = pio_read_16(&instance->registers->usbsts);
     255                const uint16_t intr = pio_read_16(&instance->registers->usbintr);
     256                usb_log_debug("Command: %X Status: %X Interrupts: %x\n",
     257                    cmd, sts, intr);
    200258
    201259                uintptr_t frame_list = pio_read_32(&instance->registers->flbaseadd);
    202                 if (frame_list != (uintptr_t)addr_to_phys(instance->frame_list)) {
     260                if (frame_list != addr_to_phys(instance->frame_list)) {
    203261                        usb_log_debug("Framelist address: %p vs. %p.\n",
    204262                                frame_list, addr_to_phys(instance->frame_list));
Note: See TracChangeset for help on using the changeset viewer.