Ignore:
File:
1 edited

Legend:

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

    r8986412 r4125b7d  
    4444#include "hc.h"
    4545
    46 #define UHCI_INTR_ALLOW_INTERRUPTS \
    47     (UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET)
    48 #define UHCI_STATUS_USED_INTERRUPTS \
    49     (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
    50 
    51 
     46static irq_cmd_t uhci_cmds[] = {
     47        {
     48                .cmd = CMD_PIO_READ_16,
     49                .addr = NULL, /* patched for every instance */
     50                .dstarg = 1
     51        },
     52        {
     53                .cmd = CMD_PIO_WRITE_16,
     54                .addr = NULL, /* pathed for every instance */
     55                .value = 0x1f
     56        },
     57        {
     58                .cmd = CMD_ACCEPT
     59        }
     60};
     61/*----------------------------------------------------------------------------*/
    5262static int hc_init_transfer_lists(hc_t *instance);
    5363static int hc_init_mem_structures(hc_t *instance);
     
    141151                /* Enable all interrupts, but resume interrupt */
    142152                pio_write_16(&instance->registers->usbintr,
    143                     UHCI_INTR_ALLOW_INTERRUPTS);
     153                    UHCI_INTR_CRC | UHCI_INTR_COMPLETE | UHCI_INTR_SHORT_PACKET);
    144154        }
    145155
     
    167177{
    168178        assert(instance);
    169 #define CHECK_RET_RETURN(ret, message...) \
     179#define CHECK_RET_DEST_CMDS_RETURN(ret, message...) \
    170180        if (ret != EOK) { \
    171181                usb_log_error(message); \
     182                if (instance->interrupt_code.cmds != NULL) \
     183                        free(instance->interrupt_code.cmds); \
    172184                return ret; \
    173185        } else (void) 0
    174186
    175187        /* Init interrupt code */
    176         instance->interrupt_code.cmds = instance->interrupt_commands;
     188        instance->interrupt_code.cmds = malloc(sizeof(uhci_cmds));
     189        int ret = (instance->interrupt_code.cmds == NULL) ? ENOMEM : EOK;
     190        CHECK_RET_DEST_CMDS_RETURN(ret,
     191            "Failed to allocate interrupt cmds space.\n");
     192
    177193        {
    178                 /* Read status register */
    179                 instance->interrupt_commands[0].cmd = CMD_PIO_READ_16;
    180                 instance->interrupt_commands[0].dstarg = 1;
    181                 instance->interrupt_commands[0].addr =
    182                     &instance->registers->usbsts;
    183 
    184                 /* Test whether we are the interrupt cause */
    185                 instance->interrupt_commands[1].cmd = CMD_BTEST;
    186                 instance->interrupt_commands[1].value =
    187                     UHCI_STATUS_USED_INTERRUPTS | UHCI_STATUS_NM_INTERRUPTS;
    188                 instance->interrupt_commands[1].srcarg = 1;
    189                 instance->interrupt_commands[1].dstarg = 2;
    190 
    191                 /* Predicate cleaning and accepting */
    192                 instance->interrupt_commands[2].cmd = CMD_PREDICATE;
    193                 instance->interrupt_commands[2].value = 2;
    194                 instance->interrupt_commands[2].srcarg = 2;
    195 
    196                 /* Write clean status register */
    197                 instance->interrupt_commands[3].cmd = CMD_PIO_WRITE_A_16;
    198                 instance->interrupt_commands[3].srcarg = 1;
    199                 instance->interrupt_commands[3].addr =
    200                     &instance->registers->usbsts;
    201 
    202                 /* Accept interrupt */
    203                 instance->interrupt_commands[4].cmd = CMD_ACCEPT;
    204 
    205                 instance->interrupt_code.cmdcount = UHCI_NEEDED_IRQ_COMMANDS;
     194                irq_cmd_t *interrupt_commands = instance->interrupt_code.cmds;
     195                memcpy(interrupt_commands, uhci_cmds, sizeof(uhci_cmds));
     196                interrupt_commands[0].addr =
     197                    (void*)&instance->registers->usbsts;
     198                interrupt_commands[1].addr =
     199                    (void*)&instance->registers->usbsts;
     200                instance->interrupt_code.cmdcount =
     201                    sizeof(uhci_cmds) / sizeof(irq_cmd_t);
    206202        }
    207203
    208204        /* Init transfer lists */
    209         int ret = hc_init_transfer_lists(instance);
    210         CHECK_RET_RETURN(ret, "Failed to init transfer lists.\n");
     205        ret = hc_init_transfer_lists(instance);
     206        CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to init transfer lists.\n");
    211207        usb_log_debug("Initialized transfer lists.\n");
    212208
     
    214210        instance->frame_list = get_page();
    215211        ret = instance ? EOK : ENOMEM;
    216         CHECK_RET_RETURN(ret, "Failed to get frame list page.\n");
     212        CHECK_RET_DEST_CMDS_RETURN(ret, "Failed to get frame list page.\n");
    217213        usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
    218214
    219215        /* Set all frames to point to the first queue head */
    220         const uint32_t queue = LINK_POINTER_QH(
    221                 addr_to_phys(instance->transfers_interrupt.queue_head));
     216        const uint32_t queue =
     217            LINK_POINTER_QH(addr_to_phys(
     218                instance->transfers_interrupt.queue_head));
    222219
    223220        unsigned i = 0;
     
    232229        ret = usb_endpoint_manager_init(&instance->ep_manager,
    233230            BANDWIDTH_AVAILABLE_USB11);
    234         CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
    235             str_error(ret));
    236 
    237         return EOK;
    238 #undef CHECK_RET_RETURN
     231        assert(ret == EOK);
     232
     233        return EOK;
     234#undef CHECK_RET_DEST_CMDS_RETURN
    239235}
    240236/*----------------------------------------------------------------------------*/
     
    281277#ifdef FSBR
    282278        transfer_list_set_next(&instance->transfers_bulk_full,
    283             &instance->transfers_control_full);
     279                &instance->transfers_control_full);
    284280#endif
    285281
     
    334330{
    335331        assert(instance);
     332//      status |= 1; //Uncomment to work around qemu hang
    336333        /* Lower 2 bits are transaction error and transaction complete */
    337334        if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
     
    355352        }
    356353        /* Resume interrupts are not supported */
    357         if (status & UHCI_STATUS_RESUME) {
    358                 usb_log_error("Resume interrupt!\n");
    359         }
    360354
    361355        /* Bits 4 and 5 indicate hc error */
     
    386380{
    387381        usb_log_debug("Started interrupt emulator.\n");
    388         hc_t *instance = arg;
     382        hc_t *instance = (hc_t*)arg;
    389383        assert(instance);
    390384
    391385        while (1) {
    392                 /* Read and clear status register */
     386                /* Readd and clear status register */
    393387                uint16_t status = pio_read_16(&instance->registers->usbsts);
    394388                pio_write_16(&instance->registers->usbsts, status);
    395389                if (status != 0)
    396390                        usb_log_debug2("UHCI status: %x.\n", status);
    397 // Qemu fails to report stalled communication
    398 // see https://bugs.launchpad.net/qemu/+bug/757654
    399 // This is a simple workaround to force queue processing every time
    400         //      status |= 1;
    401391                hc_interrupt(instance, status);
    402392                async_usleep(UHCI_INT_EMULATOR_TIMEOUT);
     
    412402int hc_debug_checker(void *arg)
    413403{
    414         hc_t *instance = arg;
     404        hc_t *instance = (hc_t*)arg;
    415405        assert(instance);
    416406
Note: See TracChangeset for help on using the changeset viewer.