Changeset d8b275d in mainline for uspace/drv/uhci-hcd


Ignore:
Timestamp:
2011-04-14T08:24:29Z (15 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5e07e2b5
Parents:
3f2af64 (diff), 34e8bab (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:

Merge development/ changes

Location:
uspace/drv/uhci-hcd
Files:
16 edited

Legend:

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

    r3f2af64 rd8b275d  
    3030 */
    3131/** @file
    32  * @brief UHCI driver USB transaction structure
     32 * @brief UHCI driver USB transfer structure
    3333 */
    3434#include <errno.h>
     
    4545#define DEFAULT_ERROR_COUNT 3
    4646
    47 typedef struct uhci_batch {
     47typedef struct uhci_transfer_batch {
    4848        qh_t *qh;
    4949        td_t *tds;
    50         size_t transfers;
    51 } uhci_batch_t;
     50        void *device_buffer;
     51        size_t td_count;
     52} uhci_transfer_batch_t;
     53/*----------------------------------------------------------------------------*/
     54static void uhci_transfer_batch_dispose(void *uhci_batch)
     55{
     56        uhci_transfer_batch_t *instance = uhci_batch;
     57        assert(instance);
     58        free32(instance->device_buffer);
     59        free(instance);
     60}
     61/*----------------------------------------------------------------------------*/
    5262
    5363static void batch_control(usb_transfer_batch_t *instance,
    5464    usb_packet_id data_stage, usb_packet_id status_stage);
    5565static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid);
    56 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance);
    57 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance);
    58 
    5966
    6067/** Allocate memory and initialize internal data structure.
    6168 *
    6269 * @param[in] fun DDF function to pass to callback.
    63  * @param[in] target Device and endpoint target of the transaction.
    64  * @param[in] transfer_type Interrupt, Control or Bulk.
    65  * @param[in] max_packet_size maximum allowed size of data transfers.
    66  * @param[in] speed Speed of the transaction.
     70 * @param[in] ep Communication target
    6771 * @param[in] buffer Data source/destination.
    6872 * @param[in] size Size of the buffer.
    6973 * @param[in] setup_buffer Setup data source (if not NULL)
    7074 * @param[in] setup_size Size of setup_buffer (should be always 8)
    71  * @param[in] func_in function to call on inbound transaction completion
    72  * @param[in] func_out function to call on outbound transaction completion
     75 * @param[in] func_in function to call on inbound transfer completion
     76 * @param[in] func_out function to call on outbound transfer completion
    7377 * @param[in] arg additional parameter to func_in or func_out
    74  * @param[in] ep Pointer to endpoint toggle management structure.
    75  * @return Valid pointer if all substructures were successfully created,
     78 * @return Valid pointer if all structures were successfully created,
    7679 * NULL otherwise.
    7780 *
    78  * Determines the number of needed transfers (TDs). Prepares a transport buffer
    79  * (that is accessible by the hardware). Initializes parameters needed for the
    80  * transaction and callback.
     81 * Determines the number of needed transfer descriptors (TDs).
     82 * Prepares a transport buffer (that is accessible by the hardware).
     83 * Initializes parameters needed for the transfer and callback.
    8184 */
    8285usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep,
     
    9295        if (ptr == NULL) { \
    9396                usb_log_error(message); \
    94                 if (instance) { \
    95                         batch_dispose(instance); \
     97                if (uhci_data) { \
     98                        uhci_transfer_batch_dispose(uhci_data); \
    9699                } \
    97100                return NULL; \
    98101        } else (void)0
    99102
     103        uhci_transfer_batch_t *uhci_data =
     104            malloc(sizeof(uhci_transfer_batch_t));
     105        CHECK_NULL_DISPOSE_RETURN(uhci_data,
     106            "Failed to allocate UHCI batch.\n");
     107        bzero(uhci_data, sizeof(uhci_transfer_batch_t));
     108
     109        uhci_data->td_count =
     110            (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size;
     111        if (ep->transfer_type == USB_TRANSFER_CONTROL) {
     112                uhci_data->td_count += 2;
     113        }
     114
     115        assert((sizeof(td_t) % 16) == 0);
     116        const size_t total_size = (sizeof(td_t) * uhci_data->td_count)
     117            + sizeof(qh_t) + setup_size + buffer_size;
     118        uhci_data->device_buffer = malloc32(total_size);
     119        CHECK_NULL_DISPOSE_RETURN(uhci_data->device_buffer,
     120            "Failed to allocate UHCI buffer.\n");
     121        bzero(uhci_data->device_buffer, total_size);
     122
     123        uhci_data->tds = uhci_data->device_buffer;
     124        uhci_data->qh =
     125            (uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count));
     126
     127        qh_init(uhci_data->qh);
     128        qh_set_element_td(uhci_data->qh, uhci_data->tds);
     129
    100130        usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));
    101131        CHECK_NULL_DISPOSE_RETURN(instance,
    102132            "Failed to allocate batch instance.\n");
     133        void *setup =
     134            uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count)
     135            + sizeof(qh_t);
     136        void *data_buffer = setup + setup_size;
    103137        usb_target_t target =
    104138            { .address = ep->address, .endpoint = ep->endpoint };
    105         usb_transfer_batch_init(instance, target, ep->transfer_type, ep->speed,
    106             ep->max_packet_size, buffer, NULL, buffer_size, NULL, setup_size,
    107             func_in, func_out, arg, fun, ep, NULL);
    108 
    109 
    110         uhci_batch_t *data = malloc(sizeof(uhci_batch_t));
    111         CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n");
    112         bzero(data, sizeof(uhci_batch_t));
    113         instance->private_data = data;
    114 
    115         data->transfers =
    116             (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size;
    117         if (ep->transfer_type == USB_TRANSFER_CONTROL) {
    118                 data->transfers += 2;
    119         }
    120 
    121         data->tds = malloc32(sizeof(td_t) * data->transfers);
    122         CHECK_NULL_DISPOSE_RETURN(
    123             data->tds, "Failed to allocate transfer descriptors.\n");
    124         bzero(data->tds, sizeof(td_t) * data->transfers);
    125 
    126         data->qh = malloc32(sizeof(qh_t));
    127         CHECK_NULL_DISPOSE_RETURN(data->qh,
    128             "Failed to allocate batch queue head.\n");
    129         qh_init(data->qh);
    130         qh_set_element_td(data->qh, addr_to_phys(data->tds));
    131 
    132         if (buffer_size > 0) {
    133                 instance->transport_buffer = malloc32(buffer_size);
    134                 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer,
    135                     "Failed to allocate device accessible buffer.\n");
    136         }
    137 
    138         if (setup_size > 0) {
    139                 instance->setup_buffer = malloc32(setup_size);
    140                 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer,
    141                     "Failed to allocate device accessible setup buffer.\n");
    142                 memcpy(instance->setup_buffer, setup_buffer, setup_size);
    143         }
    144 
     139        usb_transfer_batch_init(instance, ep, buffer, data_buffer, buffer_size,
     140            setup, setup_size, func_in, func_out, arg, fun,
     141            uhci_data, uhci_transfer_batch_dispose);
     142
     143        memcpy(instance->setup_buffer, setup_buffer, setup_size);
    145144        usb_log_debug("Batch(%p) %d:%d memory structures ready.\n",
    146145            instance, target.address, target.endpoint);
     
    154153 *
    155154 * Walk all TDs. Stop with false if there is an active one (it is to be
    156  * processed). Stop with true if an error is found. Return true if the last TS
     155 * processed). Stop with true if an error is found. Return true if the last TD
    157156 * is reached.
    158157 */
     
    160159{
    161160        assert(instance);
    162         uhci_batch_t *data = instance->private_data;
     161        uhci_transfer_batch_t *data = instance->private_data;
    163162        assert(data);
    164163
    165164        usb_log_debug2("Batch(%p) checking %d transfer(s) for completion.\n",
    166             instance, data->transfers);
     165            instance, data->td_count);
    167166        instance->transfered_size = 0;
    168167        size_t i = 0;
    169         for (;i < data->transfers; ++i) {
     168        for (;i < data->td_count; ++i) {
    170169                if (td_is_active(&data->tds[i])) {
    171170                        return false;
     
    177176                            instance, i, data->tds[i].status);
    178177                        td_print_status(&data->tds[i]);
     178
    179179                        assert(instance->ep != NULL);
    180 
    181180                        endpoint_toggle_set(instance->ep,
    182181                            td_toggle(&data->tds[i]));
     
    195194}
    196195/*----------------------------------------------------------------------------*/
    197 /** Prepares control write transaction.
    198  *
    199  * @param[in] instance Batch structure to use.
    200  *
    201  * Uses genercir control function with pids OUT and IN.
     196/** Prepares control write transfer.
     197 *
     198 * @param[in] instance Batch structure to use.
     199 *
     200 * Uses generic control function with pids OUT and IN.
    202201 */
    203202void batch_control_write(usb_transfer_batch_t *instance)
     
    205204        assert(instance);
    206205        /* We are data out, we are supposed to provide data */
    207         memcpy(instance->transport_buffer, instance->buffer,
    208             instance->buffer_size);
     206        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    209207        batch_control(instance, USB_PID_OUT, USB_PID_IN);
    210         instance->next_step = batch_call_out_and_dispose;
     208        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    211209        usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance);
    212210}
    213211/*----------------------------------------------------------------------------*/
    214 /** Prepares control read transaction.
     212/** Prepares control read transfer.
    215213 *
    216214 * @param[in] instance Batch structure to use.
     
    222220        assert(instance);
    223221        batch_control(instance, USB_PID_IN, USB_PID_OUT);
    224         instance->next_step = batch_call_in_and_dispose;
     222        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    225223        usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance);
    226224}
    227225/*----------------------------------------------------------------------------*/
    228 /** Prepare interrupt in transaction.
    229  *
    230  * @param[in] instance Batch structure to use.
    231  *
    232  * Data transaction with PID_IN.
     226/** Prepare interrupt in transfer.
     227 *
     228 * @param[in] instance Batch structure to use.
     229 *
     230 * Data transfer with PID_IN.
    233231 */
    234232void batch_interrupt_in(usb_transfer_batch_t *instance)
    235233{
    236234        assert(instance);
    237         instance->direction = USB_DIRECTION_IN;
    238235        batch_data(instance, USB_PID_IN);
    239         instance->next_step = batch_call_in_and_dispose;
     236        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    240237        usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance);
    241238}
    242239/*----------------------------------------------------------------------------*/
    243 /** Prepare interrupt out transaction.
    244  *
    245  * @param[in] instance Batch structure to use.
    246  *
    247  * Data transaction with PID_OUT.
     240/** Prepare interrupt out transfer.
     241 *
     242 * @param[in] instance Batch structure to use.
     243 *
     244 * Data transfer with PID_OUT.
    248245 */
    249246void batch_interrupt_out(usb_transfer_batch_t *instance)
    250247{
    251248        assert(instance);
    252         instance->direction = USB_DIRECTION_OUT;
    253249        /* We are data out, we are supposed to provide data */
    254         memcpy(instance->transport_buffer, instance->buffer,
    255             instance->buffer_size);
     250        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    256251        batch_data(instance, USB_PID_OUT);
    257         instance->next_step = batch_call_out_and_dispose;
     252        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    258253        usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance);
    259254}
    260255/*----------------------------------------------------------------------------*/
    261 /** Prepare bulk in transaction.
    262  *
    263  * @param[in] instance Batch structure to use.
    264  *
    265  * Data transaction with PID_IN.
     256/** Prepare bulk in transfer.
     257 *
     258 * @param[in] instance Batch structure to use.
     259 *
     260 * Data transfer with PID_IN.
    266261 */
    267262void batch_bulk_in(usb_transfer_batch_t *instance)
     
    269264        assert(instance);
    270265        batch_data(instance, USB_PID_IN);
    271         instance->direction = USB_DIRECTION_IN;
    272         instance->next_step = batch_call_in_and_dispose;
     266        instance->next_step = usb_transfer_batch_call_in_and_dispose;
    273267        usb_log_debug("Batch(%p) BULK IN initialized.\n", instance);
    274268}
    275269/*----------------------------------------------------------------------------*/
    276 /** Prepare bulk out transaction.
    277  *
    278  * @param[in] instance Batch structure to use.
    279  *
    280  * Data transaction with PID_OUT.
     270/** Prepare bulk out transfer.
     271 *
     272 * @param[in] instance Batch structure to use.
     273 *
     274 * Data transfer with PID_OUT.
    281275 */
    282276void batch_bulk_out(usb_transfer_batch_t *instance)
    283277{
    284278        assert(instance);
    285         instance->direction = USB_DIRECTION_OUT;
    286279        /* We are data out, we are supposed to provide data */
    287         memcpy(instance->transport_buffer, instance->buffer,
    288             instance->buffer_size);
     280        memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    289281        batch_data(instance, USB_PID_OUT);
    290         instance->next_step = batch_call_out_and_dispose;
     282        instance->next_step = usb_transfer_batch_call_out_and_dispose;
    291283        usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance);
    292284}
    293285/*----------------------------------------------------------------------------*/
    294 /** Prepare generic data transaction
    295  *
    296  * @param[in] instance Batch structure to use.
    297  * @param[in] pid Pid to use for data transfers.
    298  *
    299  * Packets with alternating toggle bit and supplied pid value.
     286/** Prepare generic data transfer
     287 *
     288 * @param[in] instance Batch structure to use.
     289 * @param[in] pid Pid to use for data transactions.
     290 *
     291 * Transactions with alternating toggle bit and supplied pid value.
    300292 * The last transfer is marked with IOC flag.
    301293 */
     
    303295{
    304296        assert(instance);
    305         uhci_batch_t *data = instance->private_data;
     297        uhci_transfer_batch_t *data = instance->private_data;
    306298        assert(data);
    307299
    308         const bool low_speed = instance->speed == USB_SPEED_LOW;
     300        const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
    309301        int toggle = endpoint_toggle_get(instance->ep);
    310302        assert(toggle == 0 || toggle == 1);
    311303
    312         size_t transfer = 0;
     304        size_t td = 0;
    313305        size_t remain_size = instance->buffer_size;
     306        char *buffer = instance->data_buffer;
    314307        while (remain_size > 0) {
    315                 char *trans_data =
    316                     instance->transport_buffer + instance->buffer_size
    317                     - remain_size;
    318 
    319308                const size_t packet_size =
    320                     (instance->max_packet_size > remain_size) ?
    321                     remain_size : instance->max_packet_size;
    322 
    323                 td_t *next_transfer = (transfer + 1 < data->transfers)
    324                     ? &data->tds[transfer + 1] : NULL;
    325 
    326                 assert(transfer < data->transfers);
     309                    (instance->ep->max_packet_size > remain_size) ?
     310                    remain_size : instance->ep->max_packet_size;
     311
     312                td_t *next_td = (td + 1 < data->td_count)
     313                    ? &data->tds[td + 1] : NULL;
     314
     315
     316                usb_target_t target =
     317                    { instance->ep->address, instance->ep->endpoint };
     318
     319                assert(td < data->td_count);
     320                td_init(
     321                    &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
     322                    toggle, false, low_speed, target, pid, buffer, next_td);
     323
     324                ++td;
     325                toggle = 1 - toggle;
     326                buffer += packet_size;
    327327                assert(packet_size <= remain_size);
    328 
    329                 td_init(
    330                     &data->tds[transfer], DEFAULT_ERROR_COUNT, packet_size,
    331                     toggle, false, low_speed, instance->target, pid, trans_data,
    332                     next_transfer);
    333 
    334 
    335                 toggle = 1 - toggle;
    336328                remain_size -= packet_size;
    337                 ++transfer;
    338329        }
    339         td_set_ioc(&data->tds[transfer - 1]);
     330        td_set_ioc(&data->tds[td - 1]);
    340331        endpoint_toggle_set(instance->ep, toggle);
    341332}
    342333/*----------------------------------------------------------------------------*/
    343 /** Prepare generic control transaction
    344  *
    345  * @param[in] instance Batch structure to use.
    346  * @param[in] data_stage Pid to use for data transfers.
    347  * @param[in] status_stage Pid to use for data transfers.
     334/** Prepare generic control transfer
     335 *
     336 * @param[in] instance Batch structure to use.
     337 * @param[in] data_stage Pid to use for data tds.
     338 * @param[in] status_stage Pid to use for data tds.
    348339 *
    349340 * Setup stage with toggle 0 and USB_PID_SETUP.
     
    356347{
    357348        assert(instance);
    358         uhci_batch_t *data = instance->private_data;
     349        uhci_transfer_batch_t *data = instance->private_data;
    359350        assert(data);
    360         assert(data->transfers >= 2);
    361 
    362         const bool low_speed = instance->speed == USB_SPEED_LOW;
    363         int toggle = 0;
     351        assert(data->td_count >= 2);
     352
     353        const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
     354        const usb_target_t target =
     355            { instance->ep->address, instance->ep->endpoint };
     356
    364357        /* setup stage */
    365358        td_init(
    366             data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, toggle, false,
    367             low_speed, instance->target, USB_PID_SETUP, instance->setup_buffer,
     359            data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, 0, false,
     360            low_speed, target, USB_PID_SETUP, instance->setup_buffer,
    368361            &data->tds[1]);
    369362
    370363        /* data stage */
    371         size_t transfer = 1;
     364        size_t td = 1;
     365        unsigned toggle = 1;
    372366        size_t remain_size = instance->buffer_size;
     367        char *buffer = instance->data_buffer;
    373368        while (remain_size > 0) {
    374                 char *control_data =
    375                     instance->transport_buffer + instance->buffer_size
    376                     - remain_size;
    377 
     369                const size_t packet_size =
     370                    (instance->ep->max_packet_size > remain_size) ?
     371                    remain_size : instance->ep->max_packet_size;
     372
     373                td_init(
     374                    &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
     375                    toggle, false, low_speed, target, data_stage,
     376                    buffer, &data->tds[td + 1]);
     377
     378                ++td;
    378379                toggle = 1 - toggle;
    379 
    380                 const size_t packet_size =
    381                     (instance->max_packet_size > remain_size) ?
    382                     remain_size : instance->max_packet_size;
    383 
    384                 td_init(
    385                     &data->tds[transfer], DEFAULT_ERROR_COUNT, packet_size,
    386                     toggle, false, low_speed, instance->target, data_stage,
    387                     control_data, &data->tds[transfer + 1]);
    388 
    389                 ++transfer;
    390                 assert(transfer < data->transfers);
     380                buffer += packet_size;
     381                assert(td < data->td_count);
    391382                assert(packet_size <= remain_size);
    392383                remain_size -= packet_size;
     
    394385
    395386        /* status stage */
    396         assert(transfer == data->transfers - 1);
     387        assert(td == data->td_count - 1);
    397388
    398389        td_init(
    399             &data->tds[transfer], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
    400             instance->target, status_stage, NULL, NULL);
    401         td_set_ioc(&data->tds[transfer]);
     390            &data->tds[td], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
     391            target, status_stage, NULL, NULL);
     392        td_set_ioc(&data->tds[td]);
    402393
    403394        usb_log_debug2("Control last TD status: %x.\n",
    404             data->tds[transfer].status);
    405 }
    406 /*----------------------------------------------------------------------------*/
     395            data->tds[td].status);
     396}
     397/*----------------------------------------------------------------------------*/
     398/** Provides access to QH data structure.
     399 * @param[in] instance Batch pointer to use.
     400 * @return Pointer to the QH used by the batch.
     401 */
    407402qh_t * batch_qh(usb_transfer_batch_t *instance)
    408403{
    409404        assert(instance);
    410         uhci_batch_t *data = instance->private_data;
     405        uhci_transfer_batch_t *data = instance->private_data;
    411406        assert(data);
    412407        return data->qh;
    413408}
    414 /*----------------------------------------------------------------------------*/
    415 /** Helper function calls callback and correctly disposes of batch structure.
    416  *
    417  * @param[in] instance Batch structure to use.
    418  */
    419 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)
    420 {
    421         assert(instance);
    422         usb_transfer_batch_call_in(instance);
    423         batch_dispose(instance);
    424 }
    425 /*----------------------------------------------------------------------------*/
    426 /** Helper function calls callback and correctly disposes of batch structure.
    427  *
    428  * @param[in] instance Batch structure to use.
    429  */
    430 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)
    431 {
    432         assert(instance);
    433         usb_transfer_batch_call_out(instance);
    434         batch_dispose(instance);
    435 }
    436 /*----------------------------------------------------------------------------*/
    437 /** Correctly dispose all used data structures.
    438  *
    439  * @param[in] instance Batch structure to use.
    440  */
    441 void batch_dispose(usb_transfer_batch_t *instance)
    442 {
    443         assert(instance);
    444         uhci_batch_t *data = instance->private_data;
    445         assert(data);
    446         usb_log_debug("Batch(%p) disposing.\n", instance);
    447         /* free32 is NULL safe */
    448         free32(data->tds);
    449         free32(data->qh);
    450         free32(instance->setup_buffer);
    451         free32(instance->transport_buffer);
    452         free(data);
    453         free(instance);
    454 }
    455409/**
    456410 * @}
  • uspace/drv/uhci-hcd/batch.h

    r3f2af64 rd8b275d  
    3030 */
    3131/** @file
    32  * @brief UHCI driver USB transaction structure
     32 * @brief UHCI driver USB tranfer helper functions
    3333 */
    3434#ifndef DRV_UHCI_BATCH_H
  • uspace/drv/uhci-hcd/hc.c

    r3f2af64 rd8b275d  
    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");
     
    329316
    330317        transfer_list_t *list =
    331             instance->transfers[batch->speed][batch->transfer_type];
     318            instance->transfers[batch->ep->speed][batch->ep->transfer_type];
    332319        assert(list);
    333320        transfer_list_add_batch(list, batch);
     
    479466#undef QH
    480467}
    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
    508468/**
    509469 * @}
  • uspace/drv/uhci-hcd/hc.h

    r3f2af64 rd8b275d  
    4848#include "transfer_list.h"
    4949
     50/** UHCI I/O registers layout */
    5051typedef struct uhci_regs {
     52        /** Command register, controls HC behaviour */
    5153        uint16_t usbcmd;
    5254#define UHCI_CMD_MAX_PACKET (1 << 7)
     
    5961#define UHCI_CMD_RUN_STOP  (1 << 0)
    6062
     63        /** Status register, 1 means interrupt is asserted (if enabled) */
    6164        uint16_t usbsts;
    6265#define UHCI_STATUS_HALTED (1 << 5)
     
    6770#define UHCI_STATUS_INTERRUPT (1 << 0)
    6871
     72        /** Interrupt enabled registers */
    6973        uint16_t usbintr;
    7074#define UHCI_INTR_SHORT_PACKET (1 << 3)
     
    7377#define UHCI_INTR_CRC (1 << 0)
    7478
     79        /** Register stores frame number used in SOF packet */
    7580        uint16_t frnum;
     81
     82        /** Pointer(physical) to the Frame List */
    7683        uint32_t flbaseadd;
     84
     85        /** SOF modification to match external timers */
    7786        uint8_t sofmod;
    7887} regs_t;
     
    8392#define UHCI_ALLOWED_HW_FAIL 5
    8493
     94/* Main HC driver structure */
    8595typedef struct hc {
     96        /** USB bus driver, devices and addresses */
    8697        usb_device_keeper_t manager;
     98        /** USB bus driver, endpoints */
    8799        usb_endpoint_manager_t ep_manager;
    88100
     101        /** Addresses of I/O registers */
    89102        regs_t *registers;
    90103
     104        /** Frame List contains 1024 link pointers */
    91105        link_pointer_t *frame_list;
    92106
     107        /** List and queue of interrupt transfers */
     108        transfer_list_t transfers_interrupt;
     109        /** List and queue of low speed control transfers */
     110        transfer_list_t transfers_control_slow;
     111        /** List and queue of full speed bulk transfers */
    93112        transfer_list_t transfers_bulk_full;
     113        /** List and queue of full speed control transfers */
    94114        transfer_list_t transfers_control_full;
    95         transfer_list_t transfers_control_slow;
    96         transfer_list_t transfers_interrupt;
    97115
     116        /** Pointer table to the above lists, helps during scheduling */
    98117        transfer_list_t *transfers[2][4];
    99118
     119        /** Code to be executed in kernel interrupt handler */
    100120        irq_code_t interrupt_code;
    101121
    102         fid_t cleaner;
    103         fid_t debug_checker;
     122        /** Fibril periodically checking status register*/
     123        fid_t interrupt_emulator;
     124
     125        /** Indicator of hw interrupts availability */
    104126        bool hw_interrupts;
     127
     128        /** Number of hw failures detected. */
    105129        unsigned hw_failures;
    106 
    107         ddf_fun_t *ddf_instance;
    108130} hc_t;
    109131
  • uspace/drv/uhci-hcd/hw_struct/queue_head.h

    r3f2af64 rd8b275d  
    3434#ifndef DRV_UHCI_QH_H
    3535#define DRV_UHCI_QH_H
    36 
    37 /* libc */
    3836#include <assert.h>
    3937
    4038#include "link_pointer.h"
     39#include "transfer_descriptor.h"
     40#include "utils/malloc32.h"
    4141
     42/** This structure is defined in UHCI design guide p. 31 */
    4243typedef struct queue_head {
     44        /** Pointer to the next entity (another QH or TD */
    4345        volatile link_pointer_t next;
     46        /** Pointer to the contained entities (execution controlled by vertical flag*/
    4447        volatile link_pointer_t element;
    4548} __attribute__((packed)) qh_t;
     
    6467 * @param[in] pa Physical address of the next queue head.
    6568 *
    66  * Adds proper flag. If the pointer is NULL or terminal, sets next to terminal
    67  * NULL.
     69 * Adds proper flag. If the pointer is NULL, sets next to terminal NULL.
    6870 */
    69 static inline void qh_set_next_qh(qh_t *instance, uint32_t pa)
     71static inline void qh_set_next_qh(qh_t *instance, qh_t *next)
    7072{
    71         /* Address is valid and not terminal */
    72         if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
     73        uint32_t pa = addr_to_phys(next);
     74        if (pa) {
    7375                instance->next = LINK_POINTER_QH(pa);
    7476        } else {
     
    8082 *
    8183 * @param[in] instance qh_t structure to initialize.
    82  * @param[in] pa Physical address of the next queue head.
    83  *
    84  * Adds proper flag. If the pointer is NULL or terminal, sets element
    85  * to terminal NULL.
    86  */
    87 static inline void qh_set_element_qh(qh_t *instance, uint32_t pa)
    88 {
    89         /* Address is valid and not terminal */
    90         if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
    91                 instance->element = LINK_POINTER_QH(pa);
    92         } else {
    93                 instance->element = LINK_POINTER_TERM;
    94         }
    95 }
    96 /*----------------------------------------------------------------------------*/
    97 /** Set queue head element pointer
    98  *
    99  * @param[in] instance qh_t structure to initialize.
    10084 * @param[in] pa Physical address of the TD structure.
    10185 *
    102  * Adds proper flag. If the pointer is NULL or terminal, sets element
    103  * to terminal NULL.
     86 * Adds proper flag. If the pointer is NULL, sets element to terminal NULL.
    10487 */
    105 static inline void qh_set_element_td(qh_t *instance, uint32_t pa)
     88static inline void qh_set_element_td(qh_t *instance, td_t *td)
    10689{
    107         if (pa && ((pa & LINK_POINTER_TERMINATE_FLAG) == 0)) {
     90        uint32_t pa = addr_to_phys(td);
     91        if (pa) {
    10892                instance->element = LINK_POINTER_TD(pa);
    10993        } else {
     
    11195        }
    11296}
    113 
    11497#endif
    11598/**
  • uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.c

    r3f2af64 rd8b275d  
    7777
    7878        instance->status = 0
    79             | ((err_count & TD_STATUS_ERROR_COUNT_MASK) << TD_STATUS_ERROR_COUNT_POS)
     79            | ((err_count & TD_STATUS_ERROR_COUNT_MASK)
     80                << TD_STATUS_ERROR_COUNT_POS)
    8081            | (low_speed ? TD_STATUS_LOW_SPEED_FLAG : 0)
    8182            | (iso ? TD_STATUS_ISOCHRONOUS_FLAG : 0)
     
    8990            | (((size - 1) & TD_DEVICE_MAXLEN_MASK) << TD_DEVICE_MAXLEN_POS)
    9091            | (toggle ? TD_DEVICE_DATA_TOGGLE_ONE_FLAG : 0)
    91             | ((target.address & TD_DEVICE_ADDRESS_MASK) << TD_DEVICE_ADDRESS_POS)
    92             | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK) << TD_DEVICE_ENDPOINT_POS)
     92            | ((target.address & TD_DEVICE_ADDRESS_MASK)
     93                << TD_DEVICE_ADDRESS_POS)
     94            | ((target.endpoint & TD_DEVICE_ENDPOINT_MASK)
     95                << TD_DEVICE_ENDPOINT_POS)
    9396            | ((pid & TD_DEVICE_PID_MASK) << TD_DEVICE_PID_POS);
    9497
     
    114117        assert(instance);
    115118
    116         /* this is hc internal error it should never be reported */
     119        /* This is hc internal error it should never be reported. */
    117120        if ((instance->status & TD_STATUS_ERROR_BIT_STUFF) != 0)
    118121                return EAGAIN;
     
    123126                return EBADCHECKSUM;
    124127
    125         /* hc does not end transaction on these, it should never be reported */
     128        /* HC does not end transactions on these, it should never be reported */
    126129        if ((instance->status & TD_STATUS_ERROR_NAK) != 0)
    127130                return EAGAIN;
    128131
    129         /* buffer overrun or underrun */
     132        /* Buffer overrun or underrun */
    130133        if ((instance->status & TD_STATUS_ERROR_BUFFER) != 0)
    131134                return ERANGE;
    132135
    133         /* device babble is something serious */
     136        /* Device babble is something serious */
    134137        if ((instance->status & TD_STATUS_ERROR_BABBLE) != 0)
    135138                return EIO;
    136139
    137         /* stall might represent err count reaching zero or stall response from
    138          * the device, is err count reached zero, one of the above is reported*/
     140        /* Stall might represent err count reaching zero or stall response from
     141         * the device. If err count reached zero, one of the above is reported*/
    139142        if ((instance->status & TD_STATUS_ERROR_STALLED) != 0)
    140143                return ESTALL;
  • uspace/drv/uhci-hcd/hw_struct/transfer_descriptor.h

    r3f2af64 rd8b275d  
    4040#include "link_pointer.h"
    4141
    42 /** UHCI Transfer Descriptor */
     42/** Transfer Descriptor, defined in UHCI design guide p. 26 */
    4343typedef struct transfer_descriptor {
     44        /** Pointer to the next entity (TD or QH) */
    4445        link_pointer_t next;
    4546
     47        /** Status doubleword */
    4648        volatile uint32_t status;
    4749#define TD_STATUS_RESERVED_MASK 0xc000f800
    48 #define TD_STATUS_SPD_FLAG ( 1 << 29 )
    49 #define TD_STATUS_ERROR_COUNT_POS ( 27 )
    50 #define TD_STATUS_ERROR_COUNT_MASK ( 0x3 )
    51 #define TD_STATUS_LOW_SPEED_FLAG ( 1 << 26 )
    52 #define TD_STATUS_ISOCHRONOUS_FLAG ( 1 << 25 )
    53 #define TD_STATUS_IOC_FLAG ( 1 << 24 )
     50#define TD_STATUS_SPD_FLAG         (1 << 29)
     51#define TD_STATUS_ERROR_COUNT_POS 27
     52#define TD_STATUS_ERROR_COUNT_MASK 0x3
     53#define TD_STATUS_LOW_SPEED_FLAG   (1 << 26)
     54#define TD_STATUS_ISOCHRONOUS_FLAG (1 << 25)
     55#define TD_STATUS_IOC_FLAG         (1 << 24)
    5456
    55 #define TD_STATUS_ERROR_ACTIVE ( 1 << 23 )
    56 #define TD_STATUS_ERROR_STALLED ( 1 << 22 )
    57 #define TD_STATUS_ERROR_BUFFER ( 1 << 21 )
    58 #define TD_STATUS_ERROR_BABBLE ( 1 << 20 )
    59 #define TD_STATUS_ERROR_NAK ( 1 << 19 )
    60 #define TD_STATUS_ERROR_CRC ( 1 << 18 )
    61 #define TD_STATUS_ERROR_BIT_STUFF ( 1 << 17 )
    62 #define TD_STATUS_ERROR_RESERVED ( 1 << 16 )
     57#define TD_STATUS_ERROR_ACTIVE    (1 << 23)
     58#define TD_STATUS_ERROR_STALLED   (1 << 22)
     59#define TD_STATUS_ERROR_BUFFER    (1 << 21)
     60#define TD_STATUS_ERROR_BABBLE    (1 << 20)
     61#define TD_STATUS_ERROR_NAK       (1 << 19)
     62#define TD_STATUS_ERROR_CRC       (1 << 18)
     63#define TD_STATUS_ERROR_BIT_STUFF (1 << 17)
     64#define TD_STATUS_ERROR_RESERVED  (1 << 16)
    6365#define TD_STATUS_ERROR_POS 16
    64 #define TD_STATUS_ERROR_MASK ( 0xff )
     66#define TD_STATUS_ERROR_MASK 0xff
    6567
    6668#define TD_STATUS_ACTLEN_POS 0
    6769#define TD_STATUS_ACTLEN_MASK 0x7ff
    6870
     71        /* double word with USB device specific info */
    6972        volatile uint32_t device;
    7073#define TD_DEVICE_MAXLEN_POS 21
    71 #define TD_DEVICE_MAXLEN_MASK ( 0x7ff )
    72 #define TD_DEVICE_RESERVED_FLAG ( 1 << 20 )
    73 #define TD_DEVICE_DATA_TOGGLE_ONE_FLAG ( 1 << 19 )
     74#define TD_DEVICE_MAXLEN_MASK 0x7ff
     75#define TD_DEVICE_RESERVED_FLAG        (1 << 20)
     76#define TD_DEVICE_DATA_TOGGLE_ONE_FLAG (1 << 19)
    7477#define TD_DEVICE_ENDPOINT_POS 15
    75 #define TD_DEVICE_ENDPOINT_MASK ( 0xf )
     78#define TD_DEVICE_ENDPOINT_MASK 0xf
    7679#define TD_DEVICE_ADDRESS_POS 8
    77 #define TD_DEVICE_ADDRESS_MASK ( 0x7f )
     80#define TD_DEVICE_ADDRESS_MASK 0x7f
    7881#define TD_DEVICE_PID_POS 0
    79 #define TD_DEVICE_PID_MASK ( 0xff )
     82#define TD_DEVICE_PID_MASK 0xff
    8083
     84        /** Pointer(physical) to the beginning of the transaction's buffer */
    8185        volatile uint32_t buffer_ptr;
    8286
    83         /* there is 16 bytes of data available here, according to UHCI
    84          * Design guide, according to linux kernel the hardware does not care,
    85          * it just needs to be aligned, we don't use it anyway
     87        /* According to UHCI design guide, there is 16 bytes of
     88         * data available here.
     89         * According to linux kernel the hardware does not care,
     90         * it just needs to be aligned. We don't use it anyway.
    8691         */
    8792} __attribute__((packed)) td_t;
  • uspace/drv/uhci-hcd/iface.c

    r3f2af64 rd8b275d  
    6363        }
    6464
     65        usb_log_debug("%s %d:%d %zu(%zu).\n",
     66            name, target.address, target.endpoint, size, ep->max_packet_size);
     67
    6568        const size_t bw = bandwidth_count_usb11(
    6669            ep->speed, ep->transfer_type, size, ep->max_packet_size);
     
    6871                usb_log_error("Endpoint(%d:%d) %s needs %zu bw "
    6972                    "but only %zu is reserved.\n",
    70                     name, target.address, target.endpoint, bw, res_bw);
     73                    target.address, target.endpoint, name, bw, res_bw);
    7174                return ENOSPC;
    7275        }
    73         usb_log_debug("%s %d:%d %zu(%zu).\n",
    74             name, target.address, target.endpoint, size, ep->max_packet_size);
    7576
    7677        *batch = batch_get(
     
    146147        hc_t *hc = fun_to_hc(fun);
    147148        assert(hc);
     149        const size_t size = max_packet_size;
    148150        usb_speed_t speed = usb_device_keeper_get_speed(&hc->manager, address);
    149151        if (speed >= USB_SPEED_MAX) {
    150152                speed = ep_speed;
    151153        }
    152         const size_t size =
    153             (transfer_type == USB_TRANSFER_INTERRUPT
    154             || transfer_type == USB_TRANSFER_ISOCHRONOUS) ?
    155             max_packet_size : 0;
    156         int ret;
    157 
    158         endpoint_t *ep = malloc(sizeof(endpoint_t));
    159         if (ep == NULL)
    160                 return ENOMEM;
    161         ret = endpoint_init(ep, address, endpoint, direction,
    162             transfer_type, speed, max_packet_size);
    163         if (ret != EOK) {
    164                 free(ep);
    165                 return ret;
    166         }
    167 
    168154        usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n",
    169155            address, endpoint, usb_str_transfer_type(transfer_type),
    170156            usb_str_speed(speed), direction, size, max_packet_size, interval);
    171157
    172         ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size);
    173         if (ret != EOK) {
    174                 endpoint_destroy(ep);
    175         }
    176         return ret;
     158        return usb_endpoint_manager_add_ep(&hc->ep_manager, address, endpoint,
     159            direction, transfer_type, speed, max_packet_size, size);
    177160}
    178161/*----------------------------------------------------------------------------*/
     
    212195        ret = hc_schedule(hc, batch);
    213196        if (ret != EOK) {
    214                 batch_dispose(batch);
     197                usb_transfer_batch_dispose(batch);
    215198        }
    216199        return ret;
     
    240223        ret = hc_schedule(hc, batch);
    241224        if (ret != EOK) {
    242                 batch_dispose(batch);
     225                usb_transfer_batch_dispose(batch);
    243226        }
    244227        return ret;
     
    268251        ret = hc_schedule(hc, batch);
    269252        if (ret != EOK) {
    270                 batch_dispose(batch);
     253                usb_transfer_batch_dispose(batch);
    271254        }
    272255        return ret;
     
    296279        ret = hc_schedule(hc, batch);
    297280        if (ret != EOK) {
    298                 batch_dispose(batch);
     281                usb_transfer_batch_dispose(batch);
    299282        }
    300283        return ret;
     
    329312        ret = hc_schedule(hc, batch);
    330313        if (ret != EOK) {
    331                 batch_dispose(batch);
     314                usb_transfer_batch_dispose(batch);
    332315        }
    333316        return ret;
     
    361344        ret = hc_schedule(hc, batch);
    362345        if (ret != EOK) {
    363                 batch_dispose(batch);
     346                usb_transfer_batch_dispose(batch);
    364347        }
    365348        return ret;
  • uspace/drv/uhci-hcd/main.c

    r3f2af64 rd8b275d  
    3939#include <usb/debug.h>
    4040
    41 #include "iface.h"
    4241#include "uhci.h"
    4342
     
    6261int uhci_add_device(ddf_dev_t *device)
    6362{
    64         usb_log_debug("uhci_add_device() called\n");
     63        usb_log_debug2("uhci_add_device() called\n");
    6564        assert(device);
     65
    6666        uhci_t *uhci = malloc(sizeof(uhci_t));
    6767        if (uhci == NULL) {
     
    7272        int ret = uhci_init(uhci, device);
    7373        if (ret != EOK) {
    74                 usb_log_error("Failed to initialize UHCI driver: %s.\n",
    75                     str_error(ret));
     74                usb_log_error("Failed(%d) to initialize UHCI driver: %s.\n",
     75                    ret, str_error(ret));
    7676                return ret;
    7777        }
     
    8585/** Initialize global driver structures (NONE).
    8686 *
    87  * @param[in] argc Nmber of arguments in argv vector (ignored).
     87 * @param[in] argc Number of arguments in argv vector (ignored).
    8888 * @param[in] argv Cmdline argument vector (ignored).
    8989 * @return Error code.
     
    9494{
    9595        printf(NAME ": HelenOS UHCI driver.\n");
    96 
    97         sleep(3); /* TODO: remove in final version */
    9896        usb_log_enable(USB_LOG_LEVEL_DEFAULT, NAME);
    9997
  • uspace/drv/uhci-hcd/pci.c

    r3f2af64 rd8b275d  
    4444#include "pci.h"
    4545
    46 /** Get address of registers and IRQ for given device.
     46/** Get I/O address of registers and IRQ for given device.
    4747 *
    4848 * @param[in] dev Device asking for the addresses.
     
    5353 */
    5454int pci_get_my_registers(ddf_dev_t *dev,
    55     uintptr_t *io_reg_address, size_t *io_reg_size,
    56     int *irq_no)
     55    uintptr_t *io_reg_address, size_t *io_reg_size, int *irq_no)
    5756{
    5857        assert(dev != NULL);
    5958
    60         int parent_phone = devman_parent_device_connect(dev->handle,
    61             IPC_FLAG_BLOCKING);
     59        int parent_phone =
     60            devman_parent_device_connect(dev->handle, IPC_FLAG_BLOCKING);
    6261        if (parent_phone < 0) {
    6362                return parent_phone;
    6463        }
    6564
    66         int rc;
    6765        hw_resource_list_t hw_resources;
    68         rc = hw_res_get_resource_list(parent_phone, &hw_resources);
     66        int rc = hw_res_get_resource_list(parent_phone, &hw_resources);
    6967        if (rc != EOK) {
    7068                goto leave;
     
    9593                            res->res.io_range.address, res->res.io_range.size);
    9694                        io_found = true;
     95                        break;
    9796
    9897                default:
     
    113112leave:
    114113        async_hangup(parent_phone);
    115 
    116114        return rc;
    117115}
     
    145143        }
    146144
    147         /* See UHCI design guide for these values,
     145        /* See UHCI design guide for these values p.45,
    148146         * write all WC bits in USB legacy register */
    149147        sysarg_t address = 0xc0;
  • uspace/drv/uhci-hcd/root_hub.c

    r3f2af64 rd8b275d  
    5555        int ret = asprintf(&match_str, "usb&uhci&root-hub");
    5656        if (ret < 0) {
    57                 usb_log_error("Failed to create root hub match string.\n");
    58                 return ENOMEM;
     57                usb_log_error(
     58                    "Failed(%d) to create root hub match string: %s.\n",
     59                    ret, str_error(ret));
     60                return ret;
    5961        }
    6062
    6163        ret = ddf_fun_add_match_id(fun, match_str, 100);
    6264        if (ret != EOK) {
     65                free(match_str);
    6366                usb_log_error("Failed(%d) to add root hub match id: %s\n",
    6467                    ret, str_error(ret));
     
    6669        }
    6770
    68         hw_resource_list_t *resource_list = &instance->resource_list;
    69         resource_list->count = 1;
    70         resource_list->resources = &instance->io_regs;
    71         assert(resource_list->resources);
     71        /* Initialize resource structure */
     72        instance->resource_list.count = 1;
     73        instance->resource_list.resources = &instance->io_regs;
     74
    7275        instance->io_regs.type = IO_RANGE;
    7376        instance->io_regs.res.io_range.address = reg_addr;
  • uspace/drv/uhci-hcd/root_hub.h

    r3f2af64 rd8b275d  
    3939#include <ops/hw_res.h>
    4040
     41/** DDF support structure for uhci-rhd driver, provides I/O resources */
    4142typedef struct rh {
     43        /** List of resources available to the root hub. */
    4244        hw_resource_list_t resource_list;
     45        /** The only resource in the above list */
    4346        hw_resource_t io_regs;
    4447} rh_t;
  • uspace/drv/uhci-hcd/transfer_list.c

    r3f2af64 rd8b275d  
    5757                return ENOMEM;
    5858        }
    59         instance->queue_head_pa = addr_to_phys(instance->queue_head);
     59        uint32_t queue_head_pa = addr_to_phys(instance->queue_head);
    6060        usb_log_debug2("Transfer list %s setup with QH: %p(%p).\n",
    61             name, instance->queue_head, instance->queue_head_pa);
     61            name, instance->queue_head, queue_head_pa);
    6262
    6363        qh_init(instance->queue_head);
     
    6767}
    6868/*----------------------------------------------------------------------------*/
     69/** Dispose transfer list structures.
     70 *
     71 * @param[in] instance Memory place to use.
     72 *
     73 * Frees memory for internal qh_t structure.
     74 */
     75void transfer_list_fini(transfer_list_t *instance)
     76{
     77        assert(instance);
     78        free32(instance->queue_head);
     79}
    6980/** Set the next list in transfer list chain.
    7081 *
     
    8192        if (!instance->queue_head)
    8293                return;
    83         /* Set both queue_head.next to point to the follower */
    84         qh_set_next_qh(instance->queue_head, next->queue_head_pa);
    85 }
    86 /*----------------------------------------------------------------------------*/
    87 /** Submit transfer batch to the list and queue.
     94        /* Set queue_head.next to point to the follower */
     95        qh_set_next_qh(instance->queue_head, next->queue_head);
     96}
     97/*----------------------------------------------------------------------------*/
     98/** Add transfer batch to the list and queue.
    8899 *
    89100 * @param[in] instance List to use.
    90101 * @param[in] batch Transfer batch to submit.
    91  * @return Error code
    92102 *
    93103 * The batch is added to the end of the list and queue.
     
    109119        } else {
    110120                /* There is something scheduled */
    111                 usb_transfer_batch_t *last = list_get_instance(
    112                     instance->batch_list.prev, usb_transfer_batch_t, link);
     121                usb_transfer_batch_t *last =
     122                    usb_transfer_batch_from_link(instance->batch_list.prev);
    113123                last_qh = batch_qh(last);
    114124        }
     
    118128        /* keep link */
    119129        batch_qh(batch)->next = last_qh->next;
    120         qh_set_next_qh(last_qh, pa);
     130        qh_set_next_qh(last_qh, batch_qh(batch));
    121131
    122132        asm volatile ("": : :"memory");
     
    132142}
    133143/*----------------------------------------------------------------------------*/
    134 /** Create list for finished batches.
     144/** Add completed bantches to the provided list.
    135145 *
    136146 * @param[in] instance List to use.
     
    147157                link_t *next = current->next;
    148158                usb_transfer_batch_t *batch =
    149                     list_get_instance(current, usb_transfer_batch_t, link);
     159                    usb_transfer_batch_from_link(current);
    150160
    151161                if (batch_is_complete(batch)) {
    152                         /* Save for post-processing */
     162                        /* Save for processing */
    153163                        transfer_list_remove_batch(instance, batch);
    154164                        list_append(current, done);
     
    159169}
    160170/*----------------------------------------------------------------------------*/
    161 /** Walk the list and abort all batches.
     171/** Walk the list and finish all batches with EINTR.
    162172 *
    163173 * @param[in] instance List to use.
     
    169179                link_t *current = instance->batch_list.next;
    170180                usb_transfer_batch_t *batch =
    171                     list_get_instance(current, usb_transfer_batch_t, link);
     181                    usb_transfer_batch_from_link(current);
    172182                transfer_list_remove_batch(instance, batch);
    173                 usb_transfer_batch_finish_error(batch, EIO);
     183                usb_transfer_batch_finish_error(batch, EINTR);
    174184        }
    175185        fibril_mutex_unlock(&instance->guard);
     
    180190 * @param[in] instance List to use.
    181191 * @param[in] batch Transfer batch to remove.
    182  * @return Error code
    183192 *
    184193 * Does not lock the transfer list, caller is responsible for that.
     
    197206
    198207        const char *qpos = NULL;
     208        qh_t *prev_qh = NULL;
    199209        /* Remove from the hardware queue */
    200210        if (instance->batch_list.next == &batch->link) {
    201211                /* I'm the first one here */
    202                 assert((instance->queue_head->next & LINK_POINTER_ADDRESS_MASK)
    203                     == addr_to_phys(batch_qh(batch)));
    204                 instance->queue_head->next = batch_qh(batch)->next;
     212                prev_qh = instance->queue_head;
    205213                qpos = "FIRST";
    206214        } else {
     215                /* The thing before me is a batch too */
    207216                usb_transfer_batch_t *prev =
    208                     list_get_instance(
    209                         batch->link.prev, usb_transfer_batch_t, link);
    210                 assert((batch_qh(prev)->next & LINK_POINTER_ADDRESS_MASK)
    211                     == addr_to_phys(batch_qh(batch)));
    212                 batch_qh(prev)->next = batch_qh(batch)->next;
     217                    usb_transfer_batch_from_link(batch->link.prev);
     218                prev_qh = batch_qh(prev);
    213219                qpos = "NOT FIRST";
    214220        }
     221        assert((prev_qh->next & LINK_POINTER_ADDRESS_MASK)
     222            == addr_to_phys(batch_qh(batch)));
     223        prev_qh->next = batch_qh(batch)->next;
    215224        asm volatile ("": : :"memory");
    216225        /* Remove from the batch list */
    217226        list_remove(&batch->link);
    218         usb_log_debug("Batch(%p) removed (%s) from %s, next %x.\n",
     227        usb_log_debug("Batch(%p) removed (%s) from %s, next: %x.\n",
    219228            batch, qpos, instance->name, batch_qh(batch)->next);
    220229}
  • uspace/drv/uhci-hcd/transfer_list.h

    r3f2af64 rd8b275d  
    3939#include "batch.h"
    4040#include "hw_struct/queue_head.h"
    41 #include "utils/malloc32.h"
    4241
     42/** Structure maintaining both hw queue and software list
     43 * of currently executed transfers
     44 */
    4345typedef struct transfer_list
    4446{
     47        /** Guard against multiple add/remove races */
    4548        fibril_mutex_t guard;
     49        /** UHCI hw structure represeting this queue */
    4650        qh_t *queue_head;
    47         uint32_t queue_head_pa;
     51        /** Assigned name, for nicer debug output */
    4852        const char *name;
     53        /** List of all batches in this list */
    4954        link_t batch_list;
    5055} transfer_list_t;
    5156
    52 /** Dispose transfer list structures.
    53  *
    54  * @param[in] instance Memory place to use.
    55  *
    56  * Frees memory for internal qh_t structure.
    57  */
    58 static inline void transfer_list_fini(transfer_list_t *instance)
    59 {
    60         assert(instance);
    61         free32(instance->queue_head);
    62 }
    63 
     57void transfer_list_fini(transfer_list_t *instance);
    6458int transfer_list_init(transfer_list_t *instance, const char *name);
    65 
    6659void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
    67 
    68 void transfer_list_add_batch(transfer_list_t *instance, usb_transfer_batch_t *batch);
    69 
     60void transfer_list_add_batch(
     61    transfer_list_t *instance, usb_transfer_batch_t *batch);
    7062void transfer_list_remove_finished(transfer_list_t *instance, link_t *done);
    71 
    7263void transfer_list_abort_all(transfer_list_t *instance);
    7364#endif
  • uspace/drv/uhci-hcd/uhci.c

    r3f2af64 rd8b275d  
    4444#include "pci.h"
    4545
    46 /** IRQ handling callback, identifies device
     46/** IRQ handling callback, forward status from call to diver structure.
    4747 *
    4848 * @param[in] dev DDF instance of the device to use.
    4949 * @param[in] iid (Unused).
    50  * @param[in] call Pointer to the call that represents interrupt.
     50 * @param[in] call Pointer to the call from kernel.
    5151 */
    5252static void irq_handler(ddf_dev_t *dev, ipc_callid_t iid, ipc_call_t *call)
     
    6161/** Get address of the device identified by handle.
    6262 *
    63  * @param[in] dev DDF instance of the device to use.
    64  * @param[in] iid (Unused).
    65  * @param[in] call Pointer to the call that represents interrupt.
     63 * @param[in] fun DDF instance of the function to use.
     64 * @param[in] handle DDF handle of the driver seeking its USB address.
     65 * @param[out] address Found address.
    6666 */
    6767static int usb_iface_get_address(
     
    6969{
    7070        assert(fun);
    71         usb_device_keeper_t *manager = &((uhci_t*)fun->dev->driver_data)->hc.manager;
     71        usb_device_keeper_t *manager =
     72            &((uhci_t*)fun->dev->driver_data)->hc.manager;
    7273
    7374        usb_address_t addr = usb_device_keeper_find(manager, handle);
     
    8384}
    8485/*----------------------------------------------------------------------------*/
    85 /** Gets handle of the respective hc (this or parent device).
    86  *
    87  * @param[in] root_hub_fun Root hub function seeking hc handle.
    88  * @param[out] handle Place to write the handle.
     86/** Gets handle of the respective hc.
     87 *
     88 * @param[in] fun DDF function of uhci device.
     89 * @param[out] handle Host cotnroller handle.
    8990 * @return Error code.
    9091 */
     
    100101}
    101102/*----------------------------------------------------------------------------*/
    102 /** This iface is generic for both RH and HC. */
     103/** USB interface implementation used by RH */
    103104static usb_iface_t usb_iface = {
    104105        .get_hc_handle = usb_iface_get_hc_handle,
     
    106107};
    107108/*----------------------------------------------------------------------------*/
     109/** Operations supported by the HC driver */
    108110static ddf_dev_ops_t hc_ops = {
    109 //      .interfaces[USB_DEV_IFACE] = &usb_iface,
    110111        .interfaces[USBHC_DEV_IFACE] = &hc_iface, /* see iface.h/c */
    111112};
     
    122123}
    123124/*----------------------------------------------------------------------------*/
     125/** Interface to provide the root hub driver with hw info */
    124126static hw_res_ops_t hw_res_iface = {
    125127        .get_resource_list = get_resource_list,
     
    127129};
    128130/*----------------------------------------------------------------------------*/
     131/** RH function support for uhci-rhd */
    129132static ddf_dev_ops_t rh_ops = {
    130133        .interfaces[USB_DEV_IFACE] = &usb_iface,
     
    132135};
    133136/*----------------------------------------------------------------------------*/
    134 /** Initialize hc and rh ddf structures and their respective drivers.
     137/** Initialize hc and rh DDF structures and their respective drivers.
    135138 *
    136139 * @param[in] instance UHCI structure to use.
     
    138141 *
    139142 * This function does all the preparatory work for hc and rh drivers:
    140  *  - gets device hw resources
    141  *  - disables UHCI legacy support
     143 *  - gets device's hw resources
     144 *  - disables UHCI legacy support (PCI config space)
    142145 *  - asks for interrupt
    143146 *  - registers interrupt handler
     
    193196        ret = (instance->hc_fun == NULL) ? ENOMEM : EOK;
    194197        CHECK_RET_DEST_FUN_RETURN(ret,
    195             "Failed(%d) to create HC function.\n", ret);
     198            "Failed(%d) to create HC function: %s.\n", ret, str_error(ret));
    196199
    197200        ret = hc_init(&instance->hc, instance->hc_fun,
    198201            (void*)io_reg_base, io_reg_size, interrupts);
    199         CHECK_RET_DEST_FUN_RETURN(ret, "Failed(%d) to init uhci-hcd.\n", ret);
     202        CHECK_RET_DEST_FUN_RETURN(ret,
     203            "Failed(%d) to init uhci-hcd: %s.\n", ret, str_error(ret));
     204
    200205        instance->hc_fun->ops = &hc_ops;
    201206        instance->hc_fun->driver_data = &instance->hc;
     
    221226            &instance->hc.interrupt_code);
    222227        CHECK_RET_FINI_RETURN(ret,
    223             "Failed(%d) to register interrupt handler.\n", ret);
     228            "Failed(%d) to register interrupt handler: %s.\n",
     229            ret, str_error(ret));
    224230
    225231        instance->rh_fun = ddf_fun_create(device, fun_inner, "uhci-rh");
    226232        ret = (instance->rh_fun == NULL) ? ENOMEM : EOK;
    227233        CHECK_RET_FINI_RETURN(ret,
    228             "Failed(%d) to create root hub function.\n", ret);
     234            "Failed(%d) to create root hub function: %s.\n",
     235            ret, str_error(ret));
    229236
    230237        ret = rh_init(&instance->rh, instance->rh_fun,
    231238            (uintptr_t)instance->hc.registers + 0x10, 4);
    232239        CHECK_RET_FINI_RETURN(ret,
    233             "Failed(%d) to setup UHCI root hub.\n", ret);
     240            "Failed(%d) to setup UHCI root hub: %s.\n", ret, str_error(ret));
    234241
    235242        instance->rh_fun->ops = &rh_ops;
     
    237244        ret = ddf_fun_bind(instance->rh_fun);
    238245        CHECK_RET_FINI_RETURN(ret,
    239             "Failed(%d) to register UHCI root hub.\n", ret);
     246            "Failed(%d) to register UHCI root hub: %s.\n", ret, str_error(ret));
    240247
    241248        return EOK;
  • uspace/drv/uhci-hcd/uhci.h

    r3f2af64 rd8b275d  
    4141#include "root_hub.h"
    4242
     43/** Structure representing both functions of UHCI hc, USB host controller
     44 * and USB root hub */
    4345typedef struct uhci {
     46        /** Pointer to DDF represenation of UHCI host controller */
    4447        ddf_fun_t *hc_fun;
     48        /** Pointer to DDF represenation of UHCI root hub */
    4549        ddf_fun_t *rh_fun;
    4650
     51        /** Internal driver's represenation of UHCI host controller */
    4752        hc_t hc;
     53        /** Internal driver's represenation of UHCI root hub */
    4854        rh_t rh;
    4955} uhci_t;
    5056
    5157int uhci_init(uhci_t *instance, ddf_dev_t *device);
    52 
    5358#endif
    5459/**
Note: See TracChangeset for help on using the changeset viewer.