Changeset c7dd69d in mainline for uspace/drv/uhci-hcd/hc.c


Ignore:
Timestamp:
2011-04-15T13:19:59Z (13 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
da1dd48
Parents:
e3b5129 (diff), 8fd4ba0 (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:

Development changes

File:
1 edited

Legend:

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

    re3b5129 rc7dd69d  
    6666static int hc_interrupt_emulator(void *arg);
    6767static int hc_debug_checker(void *arg);
    68 #if 0
    69 static bool usb_is_allowed(
    70     bool low_speed, usb_transfer_type_t transfer, size_t size);
    71 #endif
    7268/*----------------------------------------------------------------------------*/
    7369/** Initialize UHCI hcd driver structure
     
    8985        int ret;
    9086
    91 #define CHECK_RET_DEST_FUN_RETURN(ret, message...) \
     87#define CHECK_RET_RETURN(ret, message...) \
    9288        if (ret != EOK) { \
    9389                usb_log_error(message); \
    94                 if (instance->ddf_instance) \
    95                         ddf_fun_destroy(instance->ddf_instance); \
    9690                return ret; \
    9791        } else (void) 0
     
    9993        instance->hw_interrupts = interrupts;
    10094        instance->hw_failures = 0;
    101 
    102         /* Setup UHCI function. */
    103         instance->ddf_instance = fun;
    10495
    10596        /* allow access to hc control registers */
    10697        regs_t *io;
    10798        ret = pio_enable(regs, reg_size, (void**)&io);
    108         CHECK_RET_DEST_FUN_RETURN(ret,
     99        CHECK_RET_RETURN(ret,
    109100            "Failed(%d) to gain access to registers at %p: %s.\n",
    110             ret, str_error(ret), io);
     101            ret, io, str_error(ret));
    111102        instance->registers = io;
    112103        usb_log_debug("Device registers at %p(%u) accessible.\n",
     
    114105
    115106        ret = hc_init_mem_structures(instance);
    116         CHECK_RET_DEST_FUN_RETURN(ret,
    117             "Failed to initialize UHCI memory structures.\n");
     107        CHECK_RET_RETURN(ret,
     108            "Failed(%d) to initialize UHCI memory structures: %s.\n",
     109            ret, str_error(ret));
    118110
    119111        hc_init_hw(instance);
    120112        if (!interrupts) {
    121                 instance->cleaner =
     113                instance->interrupt_emulator =
    122114                    fibril_create(hc_interrupt_emulator, instance);
    123                 fibril_add_ready(instance->cleaner);
    124         } else {
    125                 /* TODO: enable interrupts here */
    126         }
    127 
    128         instance->debug_checker =
    129             fibril_create(hc_debug_checker, instance);
    130 //      fibril_add_ready(instance->debug_checker);
     115                fibril_add_ready(instance->interrupt_emulator);
     116        }
     117        (void)hc_debug_checker;
    131118
    132119        return EOK;
     
    228215        /* Set all frames to point to the first queue head */
    229216        const uint32_t queue =
    230           instance->transfers_interrupt.queue_head_pa
    231           | LINK_POINTER_QUEUE_HEAD_FLAG;
     217            LINK_POINTER_QH(addr_to_phys(
     218                instance->transfers_interrupt.queue_head));
    232219
    233220        unsigned i = 0;
     
    236223        }
    237224
    238         /* Init device keeper*/
     225        /* Init device keeper */
    239226        usb_device_keeper_init(&instance->manager);
    240227        usb_log_debug("Initialized device manager.\n");
     
    260247{
    261248        assert(instance);
    262 #define CHECK_RET_CLEAR_RETURN(ret, message...) \
     249#define SETUP_TRANSFER_LIST(type, name) \
     250do { \
     251        int ret = transfer_list_init(&instance->transfers_##type, name); \
    263252        if (ret != EOK) { \
    264                 usb_log_error(message); \
     253                usb_log_error("Failed(%d) to setup %s transfer list: %s.\n", \
     254                    ret, name, str_error(ret)); \
    265255                transfer_list_fini(&instance->transfers_bulk_full); \
    266256                transfer_list_fini(&instance->transfers_control_full); \
     
    268258                transfer_list_fini(&instance->transfers_interrupt); \
    269259                return ret; \
    270         } else (void) 0
    271 
    272         /* initialize TODO: check errors */
    273         int ret;
    274         ret = transfer_list_init(&instance->transfers_bulk_full, "BULK_FULL");
    275         CHECK_RET_CLEAR_RETURN(ret, "Failed to init BULK list.");
    276 
    277         ret = transfer_list_init(
    278             &instance->transfers_control_full, "CONTROL_FULL");
    279         CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL FULL list.");
    280 
    281         ret = transfer_list_init(
    282             &instance->transfers_control_slow, "CONTROL_SLOW");
    283         CHECK_RET_CLEAR_RETURN(ret, "Failed to init CONTROL SLOW list.");
    284 
    285         ret = transfer_list_init(&instance->transfers_interrupt, "INTERRUPT");
    286         CHECK_RET_CLEAR_RETURN(ret, "Failed to init INTERRUPT list.");
    287 
     260        } \
     261} while (0)
     262
     263        SETUP_TRANSFER_LIST(bulk_full, "BULK FULL");
     264        SETUP_TRANSFER_LIST(control_full, "CONTROL FULL");
     265        SETUP_TRANSFER_LIST(control_slow, "CONTROL LOW");
     266        SETUP_TRANSFER_LIST(interrupt, "INTERRUPT");
     267#undef SETUP_TRANSFER_LIST
     268        /* Connect lists into one schedule */
    288269        transfer_list_set_next(&instance->transfers_control_full,
    289270                &instance->transfers_bulk_full);
     
    329310
    330311        transfer_list_t *list =
    331             instance->transfers[batch->speed][batch->transfer_type];
     312            instance->transfers[batch->ep->speed][batch->ep->transfer_type];
    332313        assert(list);
    333314        transfer_list_add_batch(list, batch);
     
    350331        assert(instance);
    351332//      status |= 1; //Uncomment to work around qemu hang
    352         /* TODO: Resume interrupts are not supported */
    353333        /* Lower 2 bits are transaction error and transaction complete */
    354         if (status & 0x3) {
     334        if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
    355335                LIST_INITIALIZE(done);
    356336                transfer_list_remove_finished(
     
    371351                }
    372352        }
    373         /* bits 4 and 5 indicate hc error */
    374         if (status & 0x18) {
     353        /* Resume interrupts are not supported */
     354
     355        /* Bits 4 and 5 indicate hc error */
     356        if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) {
    375357                usb_log_error("UHCI hardware failure!.\n");
    376358                ++instance->hw_failures;
     
    402384
    403385        while (1) {
    404                 /* read and ack interrupts */
     386                /* Readd and clear status register */
    405387                uint16_t status = pio_read_16(&instance->registers->usbsts);
    406                 pio_write_16(&instance->registers->usbsts, 0x1f);
     388                pio_write_16(&instance->registers->usbsts, status);
    407389                if (status != 0)
    408390                        usb_log_debug2("UHCI status: %x.\n", status);
    409391                hc_interrupt(instance, status);
    410                 async_usleep(UHCI_CLEANER_TIMEOUT);
     392                async_usleep(UHCI_INT_EMULATOR_TIMEOUT);
    411393        }
    412394        return EOK;
     
    479461#undef QH
    480462}
    481 /*----------------------------------------------------------------------------*/
    482 /** Check transfers for USB validity
    483  *
    484  * @param[in] low_speed Transfer speed.
    485  * @param[in] transfer Transer type
    486  * @param[in] size Size of data packets
    487  * @return True if transaction is allowed by USB specs, false otherwise
    488  */
    489 #if 0
    490 bool usb_is_allowed(
    491     bool low_speed, usb_transfer_type_t transfer, size_t size)
    492 {
    493         /* see USB specification chapter 5.5-5.8 for magic numbers used here */
    494         switch(transfer)
    495         {
    496         case USB_TRANSFER_ISOCHRONOUS:
    497                 return (!low_speed && size < 1024);
    498         case USB_TRANSFER_INTERRUPT:
    499                 return size <= (low_speed ? 8 : 64);
    500         case USB_TRANSFER_CONTROL: /* device specifies its own max size */
    501                 return (size <= (low_speed ? 8 : 64));
    502         case USB_TRANSFER_BULK: /* device specifies its own max size */
    503                 return (!low_speed && size <= 64);
    504         }
    505         return false;
    506 }
    507 #endif
    508463/**
    509464 * @}
Note: See TracChangeset for help on using the changeset viewer.