Changeset 3afb758 in mainline for uspace/drv/bus/usb/uhci/hc.c


Ignore:
Timestamp:
2011-08-24T15:23:46Z (13 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1a02517
Parents:
5fe0a69
Message:

UHCI: Remove old code

Add support for hcd_t destruction.

File:
1 edited

Legend:

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

    r5fe0a69 r3afb758  
    4848    (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)
    4949
    50 static int schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
    51 {
    52         assert(hcd);
    53         return hc_schedule(hcd->private_data, batch);
    54 }
    5550
    5651static const irq_cmd_t uhci_irq_commands[] =
     
    6459};
    6560
     61static void hc_init_hw(const hc_t *instance);
     62static int hc_init_mem_structures(hc_t *instance);
    6663static int hc_init_transfer_lists(hc_t *instance);
    67 static int hc_init_mem_structures(hc_t *instance);
    68 static void hc_init_hw(hc_t *instance);
     64static int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch);
    6965
    7066static int hc_interrupt_emulator(void *arg);
     
    10298        cmds[3].addr = (void*)&registers->usbsts;
    10399        return EOK;
     100}
     101/*----------------------------------------------------------------------------*/
     102/** Take action based on the interrupt cause.
     103 *
     104 * @param[in] instance UHCI structure to use.
     105 * @param[in] status Value of the status register at the time of interrupt.
     106 *
     107 * Interrupt might indicate:
     108 * - transaction completed, either by triggering IOC, SPD, or an error
     109 * - some kind of device error
     110 * - resume from suspend state (not implemented)
     111 */
     112void hc_interrupt(hc_t *instance, uint16_t status)
     113{
     114        assert(instance);
     115        /* Lower 2 bits are transaction error and transaction complete */
     116        if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
     117                LIST_INITIALIZE(done);
     118                transfer_list_remove_finished(
     119                    &instance->transfers_interrupt, &done);
     120                transfer_list_remove_finished(
     121                    &instance->transfers_control_slow, &done);
     122                transfer_list_remove_finished(
     123                    &instance->transfers_control_full, &done);
     124                transfer_list_remove_finished(
     125                    &instance->transfers_bulk_full, &done);
     126
     127                while (!list_empty(&done)) {
     128                        link_t *item = list_first(&done);
     129                        list_remove(item);
     130                        usb_transfer_batch_t *batch =
     131                            list_get_instance(item, usb_transfer_batch_t, link);
     132                        usb_transfer_batch_finish(batch);
     133                }
     134        }
     135        /* Resume interrupts are not supported */
     136        if (status & UHCI_STATUS_RESUME) {
     137                usb_log_error("Resume interrupt!\n");
     138        }
     139
     140        /* Bits 4 and 5 indicate hc error */
     141        if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) {
     142                usb_log_error("UHCI hardware failure!.\n");
     143                ++instance->hw_failures;
     144                transfer_list_abort_all(&instance->transfers_interrupt);
     145                transfer_list_abort_all(&instance->transfers_control_slow);
     146                transfer_list_abort_all(&instance->transfers_control_full);
     147                transfer_list_abort_all(&instance->transfers_bulk_full);
     148
     149                if (instance->hw_failures < UHCI_ALLOWED_HW_FAIL) {
     150                        /* reinitialize hw, this triggers virtual disconnect*/
     151                        hc_init_hw(instance);
     152                } else {
     153                        usb_log_fatal("Too many UHCI hardware failures!.\n");
     154                        hc_fini(instance);
     155                }
     156        }
    104157}
    105158/*----------------------------------------------------------------------------*/
     
    138191        usb_log_debug(
    139192            "Device registers at %p (%zuB) accessible.\n", io, reg_size);
    140         hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11);
     193
     194        ret = hcd_init(&instance->generic, BANDWIDTH_AVAILABLE_USB11);
     195        CHECK_RET_RETURN(ret, "Failed to initialize HCD generic driver: %s.\n",
     196            str_error(ret));
     197
    141198        instance->generic.private_data = instance;
    142         instance->generic.schedule = schedule;
     199        instance->generic.schedule = hc_schedule;
    143200        instance->generic.batch_private_ctor = uhci_transfer_batch_create;
    144201        instance->generic.batch_private_dtor = uhci_transfer_batch_dispose;
     202#undef CHECK_RET_DEST_FUN_RETURN
    145203
    146204        ret = hc_init_mem_structures(instance);
    147         CHECK_RET_RETURN(ret,
    148             "Failed to initialize UHCI memory structures: %s.\n",
    149             str_error(ret));
     205        if (ret != EOK) {
     206                usb_log_error(
     207                    "Failed to initialize UHCI memory structures: %s.\n",
     208                    str_error(ret));
     209                hcd_destroy(&instance->generic);
     210                return ret;
     211        }
    150212
    151213        hc_init_hw(instance);
     
    158220
    159221        return EOK;
    160 #undef CHECK_RET_DEST_FUN_RETURN
    161222}
    162223/*----------------------------------------------------------------------------*/
     
    166227 * For magic values see UHCI Design Guide
    167228 */
    168 void hc_init_hw(hc_t *instance)
     229void hc_init_hw(const hc_t *instance)
    169230{
    170231        assert(instance);
     
    210271 *
    211272 * Structures:
    212  *  - interrupt code (I/O addressses are customized per instance)
    213273 *  - transfer lists (queue heads need to be accessible by the hw)
    214274 *  - frame list page (needs to be one UHCI hw accessible 4K page)
     
    217277{
    218278        assert(instance);
    219 #define CHECK_RET_RETURN(ret, message...) \
    220         if (ret != EOK) { \
    221                 usb_log_error(message); \
    222                 return ret; \
    223         } else (void) 0
     279
     280        /* Init USB frame list page */
     281        instance->frame_list = get_page();
     282        if (!instance->frame_list) {
     283                return ENOMEM;
     284        }
     285        usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
    224286
    225287        /* Init transfer lists */
    226288        int ret = hc_init_transfer_lists(instance);
    227         CHECK_RET_RETURN(ret, "Failed to initialize transfer lists.\n");
     289        if (ret != EOK) {
     290                usb_log_error("Failed to initialize transfer lists.\n");
     291                return_page(instance->frame_list);
     292                return ENOMEM;
     293        }
    228294        usb_log_debug("Initialized transfer lists.\n");
    229295
    230         /* Init device keeper */
    231         usb_device_keeper_init(&instance->manager);
    232         usb_log_debug("Initialized device keeper.\n");
    233 
    234         ret = usb_endpoint_manager_init(&instance->ep_manager,
    235             BANDWIDTH_AVAILABLE_USB11);
    236         CHECK_RET_RETURN(ret, "Failed to initialize endpoint manager: %s.\n",
    237             str_error(ret));
    238 
    239         /* Init USB frame list page*/
    240         instance->frame_list = get_page();
    241         if (!instance->frame_list) {
    242                 usb_log_error("Failed to get frame list page.\n");
    243                 usb_endpoint_manager_destroy(&instance->ep_manager);
    244                 return ENOMEM;
    245         }
    246         usb_log_debug("Initialized frame list at %p.\n", instance->frame_list);
    247296
    248297        /* Set all frames to point to the first queue head */
     
    255304
    256305        return EOK;
    257 #undef CHECK_RET_RETURN
    258306}
    259307/*----------------------------------------------------------------------------*/
     
    328376 * Checks for bandwidth availability and appends the batch to the proper queue.
    329377 */
    330 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch)
    331 {
     378int hc_schedule(hcd_t *hcd, usb_transfer_batch_t *batch)
     379{
     380        assert(hcd);
     381        hc_t *instance = hcd->private_data;
    332382        assert(instance);
    333383        assert(batch);
     
    339389
    340390        return EOK;
    341 }
    342 /*----------------------------------------------------------------------------*/
    343 /** Take action based on the interrupt cause.
    344  *
    345  * @param[in] instance UHCI structure to use.
    346  * @param[in] status Value of the status register at the time of interrupt.
    347  *
    348  * Interrupt might indicate:
    349  * - transaction completed, either by triggering IOC, SPD, or an error
    350  * - some kind of device error
    351  * - resume from suspend state (not implemented)
    352  */
    353 void hc_interrupt(hc_t *instance, uint16_t status)
    354 {
    355         assert(instance);
    356         /* Lower 2 bits are transaction error and transaction complete */
    357         if (status & (UHCI_STATUS_INTERRUPT | UHCI_STATUS_ERROR_INTERRUPT)) {
    358                 LIST_INITIALIZE(done);
    359                 transfer_list_remove_finished(
    360                     &instance->transfers_interrupt, &done);
    361                 transfer_list_remove_finished(
    362                     &instance->transfers_control_slow, &done);
    363                 transfer_list_remove_finished(
    364                     &instance->transfers_control_full, &done);
    365                 transfer_list_remove_finished(
    366                     &instance->transfers_bulk_full, &done);
    367 
    368                 while (!list_empty(&done)) {
    369                         link_t *item = list_first(&done);
    370                         list_remove(item);
    371                         usb_transfer_batch_t *batch =
    372                             list_get_instance(item, usb_transfer_batch_t, link);
    373                         usb_transfer_batch_finish(batch);
    374                 }
    375         }
    376         /* Resume interrupts are not supported */
    377         if (status & UHCI_STATUS_RESUME) {
    378                 usb_log_error("Resume interrupt!\n");
    379         }
    380 
    381         /* Bits 4 and 5 indicate hc error */
    382         if (status & (UHCI_STATUS_PROCESS_ERROR | UHCI_STATUS_SYSTEM_ERROR)) {
    383                 usb_log_error("UHCI hardware failure!.\n");
    384                 ++instance->hw_failures;
    385                 transfer_list_abort_all(&instance->transfers_interrupt);
    386                 transfer_list_abort_all(&instance->transfers_control_slow);
    387                 transfer_list_abort_all(&instance->transfers_control_full);
    388                 transfer_list_abort_all(&instance->transfers_bulk_full);
    389 
    390                 if (instance->hw_failures < UHCI_ALLOWED_HW_FAIL) {
    391                         /* reinitialize hw, this triggers virtual disconnect*/
    392                         hc_init_hw(instance);
    393                 } else {
    394                         usb_log_fatal("Too many UHCI hardware failures!.\n");
    395                         hc_fini(instance);
    396                 }
    397         }
    398391}
    399392/*----------------------------------------------------------------------------*/
     
    415408                if (status != 0)
    416409                        usb_log_debug2("UHCI status: %x.\n", status);
    417 // Qemu fails to report stalled communication
    418 // see https://bugs.launchpad.net/qemu/+bug/757654
    419 // This is a simple workaround to force queue processing every time
    420         //      status |= 1;
    421410                hc_interrupt(instance, status);
    422411                async_usleep(UHCI_INT_EMULATOR_TIMEOUT);
     
    424413        return EOK;
    425414}
    426 /*---------------------------------------------------------------------------*/
     415/*----------------------------------------------------------------------------*/
    427416/** Debug function, checks consistency of memory structures.
    428417 *
Note: See TracChangeset for help on using the changeset viewer.