Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset b991d37 in mainline


Ignore:
Timestamp:
2011-08-31T16:41:11Z (10 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master
Children:
ff6dd73
Parents:
96e2d01
Message:

uhci: use uhci sepcific structure instead of generic library

revert the way uhci_transfer_batch_t and usb_transfer_batch_t are included,
don't use usb_transfer_batch_t:

-private data and data dtor
-next_step pointer
-buffer_data pointer

Location:
uspace/drv/bus/usb/uhci
Files:
5 edited

Legend:

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

    r96e2d01 rb991d37  
    128128                        link_t *item = list_first(&done);
    129129                        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);
     130                        uhci_transfer_batch_t *batch =
     131                            uhci_transfer_batch_from_link(item);
     132                        uhci_transfer_batch_call_dispose(batch);
    133133                }
    134134        }
     
    382382        assert(instance);
    383383        assert(batch);
    384         int ret = batch_init_uhci(batch);
    385         if (ret != EOK) {
    386                 return ret;
     384        uhci_transfer_batch_t *uhci_batch = uhci_transfer_batch_get(batch);
     385        if (!uhci_batch) {
     386                usb_log_error("Failed to create UHCI transfer structures.\n");
     387                return ENOMEM;
    387388        }
    388389
     
    390391            instance->transfers[batch->ep->speed][batch->ep->transfer_type];
    391392        assert(list);
    392         transfer_list_add_batch(list, batch);
     393        transfer_list_add_batch(list, uhci_batch);
    393394
    394395        return EOK;
  • uspace/drv/bus/usb/uhci/transfer_list.c

    r96e2d01 rb991d37  
    3939
    4040#include "transfer_list.h"
    41 #include "uhci_batch.h"
    4241
    4342static void transfer_list_remove_batch(
    44     transfer_list_t *instance, usb_transfer_batch_t *batch);
     43    transfer_list_t *instance, uhci_transfer_batch_t *uhci_batch);
    4544/*----------------------------------------------------------------------------*/
    4645/** Initialize transfer list structures.
     
    107106 */
    108107void transfer_list_add_batch(
    109     transfer_list_t *instance, usb_transfer_batch_t *batch)
    110 {
    111         assert(instance);
    112         assert(batch);
    113         usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);
     108    transfer_list_t *instance, uhci_transfer_batch_t *uhci_batch)
     109{
     110        assert(instance);
     111        assert(uhci_batch);
     112        usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name,
     113            uhci_batch->usb_batch);
    114114
    115115        fibril_mutex_lock(&instance->guard);
    116116
    117         qh_t *last_qh = NULL;
     117        /* Assume there is nothing scheduled */
     118        qh_t *last_qh = instance->queue_head;
     119        /* There is something scheduled */
     120        if (!list_empty(&instance->batch_list)) {
     121                last_qh = uhci_transfer_batch_from_link(
     122                    list_last(&instance->batch_list))->qh;
     123        }
    118124        /* Add to the hardware queue. */
    119         if (list_empty(&instance->batch_list)) {
    120                 /* There is nothing scheduled */
    121                 last_qh = instance->queue_head;
    122         } else {
    123                 /* There is something scheduled */
    124                 usb_transfer_batch_t *last = usb_transfer_batch_from_link(
    125                     list_last(&instance->batch_list));
    126                 last_qh = batch_qh(last);
    127         }
    128         const uint32_t pa = addr_to_phys(batch_qh(batch));
     125        const uint32_t pa = addr_to_phys(uhci_batch->qh);
    129126        assert((pa & LINK_POINTER_ADDRESS_MASK) == pa);
    130127
     
    133130
    134131        /* keep link */
    135         batch_qh(batch)->next = last_qh->next;
    136         qh_set_next_qh(last_qh, batch_qh(batch));
     132        uhci_batch->qh->next = last_qh->next;
     133        qh_set_next_qh(last_qh, uhci_batch->qh);
    137134
    138135        /* Make sure the pointer is updated */
     
    140137
    141138        /* Add to the driver's list */
    142         list_append(&batch->link, &instance->batch_list);
     139        list_append(&uhci_batch->link, &instance->batch_list);
    143140
    144141        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " scheduled in queue %s.\n",
    145             batch, USB_TRANSFER_BATCH_ARGS(*batch), instance->name);
     142            uhci_batch, USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch),
     143            instance->name);
    146144        fibril_mutex_unlock(&instance->guard);
    147145}
     
    158156
    159157        fibril_mutex_lock(&instance->guard);
    160         link_t *current = instance->batch_list.head.next;
    161         while (current != &instance->batch_list.head) {
     158        link_t *current = list_first(&instance->batch_list);
     159        while (current && current != &instance->batch_list.head) {
    162160                link_t * const next = current->next;
    163                 usb_transfer_batch_t *batch =
    164                     usb_transfer_batch_from_link(current);
    165 
    166                 if (batch_is_complete(batch)) {
     161                uhci_transfer_batch_t *batch =
     162                    uhci_transfer_batch_from_link(current);
     163
     164                if (uhci_transfer_batch_is_complete(batch)) {
    167165                        /* Save for processing */
    168166                        transfer_list_remove_batch(instance, batch);
     
    183181        while (!list_empty(&instance->batch_list)) {
    184182                link_t * const current = list_first(&instance->batch_list);
    185                 usb_transfer_batch_t *batch =
    186                     usb_transfer_batch_from_link(current);
     183                uhci_transfer_batch_t *batch =
     184                    uhci_transfer_batch_from_link(current);
    187185                transfer_list_remove_batch(instance, batch);
    188                 usb_transfer_batch_finish_error(batch, EINTR);
     186                batch->usb_batch->error = EINTR;
     187                uhci_transfer_batch_call_dispose(batch);
    189188        }
    190189        fibril_mutex_unlock(&instance->guard);
     
    199198 */
    200199void transfer_list_remove_batch(
    201     transfer_list_t *instance, usb_transfer_batch_t *batch)
     200    transfer_list_t *instance, uhci_transfer_batch_t *uhci_batch)
    202201{
    203202        assert(instance);
    204203        assert(instance->queue_head);
    205         assert(batch);
    206         assert(batch_qh(batch));
     204        assert(uhci_batch);
     205        assert(uhci_batch->qh);
    207206        assert(fibril_mutex_is_locked(&instance->guard));
    208207
    209         usb_log_debug2(
    210             "Queue %s: removing batch(%p).\n", instance->name, batch);
    211 
    212         const char *qpos = NULL;
    213         qh_t *prev_qh = NULL;
     208        usb_log_debug2("Queue %s: removing batch(%p).\n",
     209            instance->name, uhci_batch->usb_batch);
     210
     211        /* Assume I'm the first */
     212        const char *qpos = "FIRST";
     213        qh_t *prev_qh = instance->queue_head;
    214214        /* Remove from the hardware queue */
    215         if (list_first(&instance->batch_list) == &batch->link) {
    216                 /* I'm the first one here */
    217                 prev_qh = instance->queue_head;
    218                 qpos = "FIRST";
    219         } else {
    220                 /* The thing before me is a batch too */
    221                 usb_transfer_batch_t *prev =
    222                     usb_transfer_batch_from_link(batch->link.prev);
    223                 prev_qh = batch_qh(prev);
     215        if (list_first(&instance->batch_list) != &uhci_batch->link) {
     216                /* There is a batch in front of me */
     217                prev_qh =
     218                    uhci_transfer_batch_from_link(uhci_batch->link.prev)->qh;
    224219                qpos = "NOT FIRST";
    225220        }
    226221        assert((prev_qh->next & LINK_POINTER_ADDRESS_MASK)
    227             == addr_to_phys(batch_qh(batch)));
    228         prev_qh->next = batch_qh(batch)->next;
     222            == addr_to_phys(uhci_batch->qh));
     223        prev_qh->next = uhci_batch->qh->next;
    229224
    230225        /* Make sure the pointer is updated */
     
    232227
    233228        /* Remove from the batch list */
    234         list_remove(&batch->link);
     229        list_remove(&uhci_batch->link);
    235230        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT " removed (%s) "
    236231            "from %s, next: %x.\n",
    237             batch, USB_TRANSFER_BATCH_ARGS(*batch),
    238             qpos, instance->name, batch_qh(batch)->next);
     232            uhci_batch, USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch),
     233            qpos, instance->name, uhci_batch->qh->next);
    239234}
    240235/**
  • uspace/drv/bus/usb/uhci/transfer_list.h

    r96e2d01 rb991d37  
    3636
    3737#include <fibril_synch.h>
    38 #include <usb/host/batch.h>
    3938
    4039#include "hw_struct/queue_head.h"
    41 
     40#include "uhci_batch.h"
    4241/** Structure maintaining both hw queue and software list
    4342 * of currently executed transfers
     
    4645        /** Guard against multiple add/remove races */
    4746        fibril_mutex_t guard;
    48         /** UHCI hw structure represeting this queue */
     47        /** UHCI hw structure representing this queue */
    4948        qh_t *queue_head;
    5049        /** Assigned name, for nicer debug output */
     
    5857void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);
    5958void transfer_list_add_batch(
    60     transfer_list_t *instance, usb_transfer_batch_t *batch);
     59    transfer_list_t *instance, uhci_transfer_batch_t *batch);
    6160void transfer_list_remove_finished(transfer_list_t *instance, list_t *done);
    6261void transfer_list_abort_all(transfer_list_t *instance);
  • uspace/drv/bus/usb/uhci/uhci_batch.c

    r96e2d01 rb991d37  
    4444
    4545#define DEFAULT_ERROR_COUNT 3
    46 static void batch_control_write(usb_transfer_batch_t *instance);
    47 static void batch_control_read(usb_transfer_batch_t *instance);
    48 
    49 static void batch_interrupt_in(usb_transfer_batch_t *instance);
    50 static void batch_interrupt_out(usb_transfer_batch_t *instance);
    51 
    52 static void batch_bulk_in(usb_transfer_batch_t *instance);
    53 static void batch_bulk_out(usb_transfer_batch_t *instance);
    54 
    55 static void batch_setup_control(usb_transfer_batch_t *batch)
    56 {
    57         // TODO Find a better way to do this
    58         if (batch->setup_buffer[0] & (1 << 7))
    59                 batch_control_read(batch);
    60         else
    61                 batch_control_write(batch);
    62 }
    63 
    64 void (*batch_setup[4][3])(usb_transfer_batch_t*) =
    65 {
    66         { NULL, NULL, batch_setup_control },
    67         { NULL, NULL, NULL },
    68         { batch_bulk_in, batch_bulk_out, NULL },
    69         { batch_interrupt_in, batch_interrupt_out, NULL },
    70 };
    71  // */
    72 /** UHCI specific data required for USB transfer */
    73 typedef struct uhci_transfer_batch {
    74         /** Queue head
    75          * This QH is used to maintain UHCI schedule structure and the element
    76          * pointer points to the first TD of this batch.
    77          */
    78         qh_t *qh;
    79         /** List of TDs needed for the transfer */
    80         td_t *tds;
    81         /** Number of TDs used by the transfer */
    82         size_t td_count;
    83         /** Data buffer, must be accessible by the UHCI hw */
    84         void *device_buffer;
    85 } uhci_transfer_batch_t;
    86 /*----------------------------------------------------------------------------*/
    87 static void batch_control(usb_transfer_batch_t *instance,
     46
     47static void batch_control(uhci_transfer_batch_t *uhci_batch,
    8848    usb_packet_id data_stage, usb_packet_id status_stage);
    89 static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid);
     49static void batch_data(uhci_transfer_batch_t *uhci_batch, usb_packet_id pid);
     50/*----------------------------------------------------------------------------*/
     51static void uhci_transfer_batch_dispose(uhci_transfer_batch_t *uhci_batch)
     52{
     53        if (uhci_batch) {
     54                usb_transfer_batch_dispose(uhci_batch->usb_batch);
     55                free32(uhci_batch->device_buffer);
     56                free(uhci_batch);
     57        }
     58}
    9059/*----------------------------------------------------------------------------*/
    9160/** Safely destructs uhci_transfer_batch_t structure
     
    9362 * @param[in] uhci_batch Instance to destroy.
    9463 */
    95 static void uhci_transfer_batch_dispose(void *uhci_batch)
    96 {
    97         uhci_transfer_batch_t *instance = uhci_batch;
    98         assert(instance);
    99         free32(instance->device_buffer);
    100         free(instance);
    101 }
     64void uhci_transfer_batch_call_dispose(uhci_transfer_batch_t *uhci_batch)
     65{
     66        assert(uhci_batch);
     67        assert(uhci_batch->usb_batch);
     68        /* Copy data unless we are sure we sent it */
     69        if (uhci_batch->usb_batch->ep->direction != USB_DIRECTION_OUT) {
     70                memcpy(uhci_batch->usb_batch->buffer,
     71                    uhci_transfer_batch_data_buffer(uhci_batch),
     72                    uhci_batch->usb_batch->buffer_size);
     73        }
     74        if (uhci_batch->usb_batch->callback_out)
     75                usb_transfer_batch_call_out(uhci_batch->usb_batch);
     76        if (uhci_batch->usb_batch->callback_in)
     77                usb_transfer_batch_call_in(uhci_batch->usb_batch);
     78        usb_transfer_batch_finish(uhci_batch->usb_batch);
     79        uhci_transfer_batch_dispose(uhci_batch);
     80}
     81/*----------------------------------------------------------------------------*/
     82static void (*batch_setup[4][3])(uhci_transfer_batch_t*);
    10283/*----------------------------------------------------------------------------*/
    10384/** Allocate memory and initialize internal data structure.
     
    119100 * Initializes parameters needed for the transfer and callback.
    120101 */
    121 int batch_init_uhci(usb_transfer_batch_t *batch)
    122 {
     102uhci_transfer_batch_t * uhci_transfer_batch_get(usb_transfer_batch_t *usb_batch)
     103{
     104        assert((sizeof(td_t) % 16) == 0);
    123105#define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \
    124106        if (ptr == NULL) { \
    125107                usb_log_error(message); \
    126                 if (uhci_data) { \
    127                         uhci_transfer_batch_dispose(uhci_data); \
    128                 } \
    129                 return ENOMEM; \
     108                uhci_transfer_batch_dispose(uhci_batch); \
     109                return NULL; \
    130110        } else (void)0
    131111
    132         uhci_transfer_batch_t *uhci_data =
     112        uhci_transfer_batch_t *uhci_batch =
    133113            calloc(1, sizeof(uhci_transfer_batch_t));
    134         CHECK_NULL_DISPOSE_RETURN(uhci_data,
     114        CHECK_NULL_DISPOSE_RETURN(uhci_batch,
    135115            "Failed to allocate UHCI batch.\n");
    136116
    137         uhci_data->td_count =
    138             (batch->buffer_size + batch->ep->max_packet_size - 1)
    139             / batch->ep->max_packet_size;
    140         if (batch->ep->transfer_type == USB_TRANSFER_CONTROL) {
    141                 uhci_data->td_count += 2;
    142         }
    143 
    144         assert((sizeof(td_t) % 16) == 0);
    145         const size_t total_size = (sizeof(td_t) * uhci_data->td_count)
    146             + sizeof(qh_t) + batch->setup_size + batch->buffer_size;
    147         uhci_data->device_buffer = malloc32(total_size);
    148         CHECK_NULL_DISPOSE_RETURN(uhci_data->device_buffer,
     117        uhci_batch->td_count =
     118            (usb_batch->buffer_size + usb_batch->ep->max_packet_size - 1)
     119            / usb_batch->ep->max_packet_size;
     120        if (usb_batch->ep->transfer_type == USB_TRANSFER_CONTROL) {
     121                uhci_batch->td_count += 2;
     122        }
     123
     124        const size_t total_size = (sizeof(td_t) * uhci_batch->td_count)
     125            + sizeof(qh_t) + usb_batch->setup_size + usb_batch->buffer_size;
     126        uhci_batch->device_buffer = malloc32(total_size);
     127        CHECK_NULL_DISPOSE_RETURN(uhci_batch->device_buffer,
    149128            "Failed to allocate UHCI buffer.\n");
    150         bzero(uhci_data->device_buffer, total_size);
    151 
    152         uhci_data->tds = uhci_data->device_buffer;
    153         uhci_data->qh =
    154             (uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count));
    155 
    156         qh_init(uhci_data->qh);
    157         qh_set_element_td(uhci_data->qh, uhci_data->tds);
    158 
    159         void *setup =
    160             uhci_data->device_buffer + (sizeof(td_t) * uhci_data->td_count)
     129        bzero(uhci_batch->device_buffer, total_size);
     130
     131        uhci_batch->tds = uhci_batch->device_buffer;
     132        uhci_batch->qh =
     133            (uhci_batch->device_buffer + (sizeof(td_t) * uhci_batch->td_count));
     134
     135        qh_init(uhci_batch->qh);
     136        qh_set_element_td(uhci_batch->qh, &uhci_batch->tds[0]);
     137
     138        void *dest =
     139            uhci_batch->device_buffer + (sizeof(td_t) * uhci_batch->td_count)
    161140            + sizeof(qh_t);
    162         /* Copy SETUP packet data to device buffer */
    163         memcpy(setup, batch->setup_buffer, batch->setup_size);
    164         /* Set generic data buffer pointer */
    165         batch->data_buffer = setup + batch->setup_size;
    166         batch->private_data_dtor = uhci_transfer_batch_dispose;
    167         batch->private_data = uhci_data;
     141        /* Copy SETUP packet data to the device buffer */
     142        memcpy(dest, usb_batch->setup_buffer, usb_batch->setup_size);
     143        dest += usb_batch->setup_size;
     144        /* Copy generic data if unless they are provided by the device */
     145        if (usb_batch->ep->direction != USB_DIRECTION_IN) {
     146                memcpy(dest, usb_batch->buffer, usb_batch->buffer_size);
     147        }
     148        uhci_batch->usb_batch = usb_batch;
    168149        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT
    169             " memory structures ready.\n", batch,
    170             USB_TRANSFER_BATCH_ARGS(*batch));
    171         assert(batch_setup[batch->ep->transfer_type][batch->ep->direction]);
    172         batch_setup[batch->ep->transfer_type][batch->ep->direction](batch);
    173 
    174         return EOK;
     150            " memory structures ready.\n", usb_batch,
     151            USB_TRANSFER_BATCH_ARGS(*usb_batch));
     152        assert(
     153            batch_setup[usb_batch->ep->transfer_type][usb_batch->ep->direction]);
     154        batch_setup[usb_batch->ep->transfer_type][usb_batch->ep->direction](
     155            uhci_batch);
     156
     157        return uhci_batch;
    175158}
    176159/*----------------------------------------------------------------------------*/
     
    184167 * is reached.
    185168 */
    186 bool batch_is_complete(usb_transfer_batch_t *instance)
    187 {
    188         assert(instance);
    189         uhci_transfer_batch_t *data = instance->private_data;
    190         assert(data);
    191 
    192         usb_log_debug2("Batch(%p) checking %zu transfer(s) for completion.\n",
    193             instance, data->td_count);
    194         instance->transfered_size = 0;
     169bool uhci_transfer_batch_is_complete(uhci_transfer_batch_t *uhci_batch)
     170{
     171        assert(uhci_batch);
     172        assert(uhci_batch->usb_batch);
     173
     174        usb_log_debug2("Batch %p " USB_TRANSFER_BATCH_FMT
     175            " checking %zu transfer(s) for completion.\n",
     176            uhci_batch->usb_batch,
     177            USB_TRANSFER_BATCH_ARGS(*uhci_batch->usb_batch),
     178            uhci_batch->td_count);
     179        uhci_batch->usb_batch->transfered_size = 0;
    195180        size_t i = 0;
    196         for (;i < data->td_count; ++i) {
    197                 if (td_is_active(&data->tds[i])) {
     181        for (;i < uhci_batch->td_count; ++i) {
     182                if (td_is_active(&uhci_batch->tds[i])) {
    198183                        return false;
    199184                }
    200185
    201                 instance->error = td_status(&data->tds[i]);
    202                 if (instance->error != EOK) {
     186                uhci_batch->usb_batch->error = td_status(&uhci_batch->tds[i]);
     187                if (uhci_batch->usb_batch->error != EOK) {
     188                        assert(uhci_batch->usb_batch->ep != NULL);
     189
    203190                        usb_log_debug("Batch(%p) found error TD(%zu):%"
    204                             PRIx32 ".\n", instance, i, data->tds[i].status);
    205                         td_print_status(&data->tds[i]);
    206 
    207                         assert(instance->ep != NULL);
    208                         endpoint_toggle_set(instance->ep,
    209                             td_toggle(&data->tds[i]));
     191                            PRIx32 ".\n", uhci_batch->usb_batch, i,
     192                            uhci_batch->tds[i].status);
     193                        td_print_status(&uhci_batch->tds[i]);
     194
     195                        endpoint_toggle_set(uhci_batch->usb_batch->ep,
     196                            td_toggle(&uhci_batch->tds[i]));
    210197                        if (i > 0)
    211198                                goto substract_ret;
     
    213200                }
    214201
    215                 instance->transfered_size += td_act_size(&data->tds[i]);
    216                 if (td_is_short(&data->tds[i]))
     202                uhci_batch->usb_batch->transfered_size
     203                    += td_act_size(&uhci_batch->tds[i]);
     204                if (td_is_short(&uhci_batch->tds[i]))
    217205                        goto substract_ret;
    218206        }
    219207substract_ret:
    220         instance->transfered_size -= instance->setup_size;
     208        uhci_batch->usb_batch->transfered_size
     209            -= uhci_batch->usb_batch->setup_size;
    221210        return true;
    222211}
     
    233222 * Uses generic control function with pids OUT and IN.
    234223 */
    235 static void batch_control_write(usb_transfer_batch_t *instance)
    236 {
    237         assert(instance);
    238         /* We are data out, we are supposed to provide data */
    239         memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    240         batch_control(instance, USB_PID_OUT, USB_PID_IN);
    241         instance->next_step = usb_transfer_batch_call_out_and_dispose;
    242         LOG_BATCH_INITIALIZED(instance, "control write");
     224static void control_write(uhci_transfer_batch_t *uhci_batch)
     225{
     226        batch_control(uhci_batch, USB_PID_OUT, USB_PID_IN);
     227        LOG_BATCH_INITIALIZED(uhci_batch->usb_batch, "control write");
    243228}
    244229/*----------------------------------------------------------------------------*/
     
    249234 * Uses generic control with pids IN and OUT.
    250235 */
    251 static void batch_control_read(usb_transfer_batch_t *instance)
    252 {
    253         assert(instance);
    254         batch_control(instance, USB_PID_IN, USB_PID_OUT);
    255         instance->next_step = usb_transfer_batch_call_in_and_dispose;
    256         LOG_BATCH_INITIALIZED(instance, "control read");
     236static void control_read(uhci_transfer_batch_t *uhci_batch)
     237{
     238        batch_control(uhci_batch, USB_PID_IN, USB_PID_OUT);
     239        LOG_BATCH_INITIALIZED(uhci_batch->usb_batch, "control read");
    257240}
    258241/*----------------------------------------------------------------------------*/
     
    263246 * Data transfer with PID_IN.
    264247 */
    265 static void batch_interrupt_in(usb_transfer_batch_t *instance)
    266 {
    267         assert(instance);
    268         batch_data(instance, USB_PID_IN);
    269         instance->next_step = usb_transfer_batch_call_in_and_dispose;
    270         LOG_BATCH_INITIALIZED(instance, "interrupt in");
     248static void interrupt_in(uhci_transfer_batch_t *uhci_batch)
     249{
     250        batch_data(uhci_batch, USB_PID_IN);
     251        LOG_BATCH_INITIALIZED(uhci_batch->usb_batch, "interrupt in");
    271252}
    272253/*----------------------------------------------------------------------------*/
     
    277258 * Data transfer with PID_OUT.
    278259 */
    279 static void batch_interrupt_out(usb_transfer_batch_t *instance)
    280 {
    281         assert(instance);
    282         /* We are data out, we are supposed to provide data */
    283         memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    284         batch_data(instance, USB_PID_OUT);
    285         instance->next_step = usb_transfer_batch_call_out_and_dispose;
    286         LOG_BATCH_INITIALIZED(instance, "interrupt out");
     260static void interrupt_out(uhci_transfer_batch_t *uhci_batch)
     261{
     262        batch_data(uhci_batch, USB_PID_OUT);
     263        LOG_BATCH_INITIALIZED(uhci_batch->usb_batch, "interrupt out");
    287264}
    288265/*----------------------------------------------------------------------------*/
     
    293270 * Data transfer with PID_IN.
    294271 */
    295 static void batch_bulk_in(usb_transfer_batch_t *instance)
    296 {
    297         assert(instance);
    298         batch_data(instance, USB_PID_IN);
    299         instance->next_step = usb_transfer_batch_call_in_and_dispose;
    300         LOG_BATCH_INITIALIZED(instance, "bulk in");
     272static void bulk_in(uhci_transfer_batch_t *uhci_batch)
     273{
     274        batch_data(uhci_batch, USB_PID_IN);
     275        LOG_BATCH_INITIALIZED(uhci_batch->usb_batch, "bulk in");
    301276}
    302277/*----------------------------------------------------------------------------*/
     
    307282 * Data transfer with PID_OUT.
    308283 */
    309 static void batch_bulk_out(usb_transfer_batch_t *instance)
    310 {
    311         assert(instance);
    312         /* We are data out, we are supposed to provide data */
    313         memcpy(instance->data_buffer, instance->buffer, instance->buffer_size);
    314         batch_data(instance, USB_PID_OUT);
    315         instance->next_step = usb_transfer_batch_call_out_and_dispose;
    316         LOG_BATCH_INITIALIZED(instance, "bulk out");
     284static void bulk_out(uhci_transfer_batch_t *uhci_batch)
     285{
     286        batch_data(uhci_batch, USB_PID_OUT);
     287        LOG_BATCH_INITIALIZED(uhci_batch->usb_batch, "bulk out");
    317288}
    318289/*----------------------------------------------------------------------------*/
     
    325296 * The last transfer is marked with IOC flag.
    326297 */
    327 static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid)
    328 {
    329         assert(instance);
    330         uhci_transfer_batch_t *data = instance->private_data;
    331         assert(data);
    332 
    333         const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
    334         int toggle = endpoint_toggle_get(instance->ep);
     298static void batch_data(uhci_transfer_batch_t *uhci_batch, usb_packet_id pid)
     299{
     300        assert(uhci_batch);
     301        assert(uhci_batch->usb_batch);
     302
     303        const bool low_speed =
     304            uhci_batch->usb_batch->ep->speed == USB_SPEED_LOW;
     305        const size_t mps = uhci_batch->usb_batch->ep->max_packet_size;
     306        const usb_target_t target = {
     307            uhci_batch->usb_batch->ep->address,
     308            uhci_batch->usb_batch->ep->endpoint };
     309
     310        int toggle = endpoint_toggle_get(uhci_batch->usb_batch->ep);
    335311        assert(toggle == 0 || toggle == 1);
    336312
    337313        size_t td = 0;
    338         size_t remain_size = instance->buffer_size;
    339         char *buffer = instance->data_buffer;
     314        size_t remain_size = uhci_batch->usb_batch->buffer_size;
     315        char *buffer = uhci_transfer_batch_data_buffer(uhci_batch);
     316
    340317        while (remain_size > 0) {
    341318                const size_t packet_size =
    342                     (instance->ep->max_packet_size > remain_size) ?
    343                     remain_size : instance->ep->max_packet_size;
    344 
    345                 td_t *next_td = (td + 1 < data->td_count)
    346                     ? &data->tds[td + 1] : NULL;
    347 
    348 
    349                 usb_target_t target =
    350                     { instance->ep->address, instance->ep->endpoint };
    351 
    352                 assert(td < data->td_count);
     319                    (remain_size < mps) ? remain_size : mps;
     320
     321                const td_t *next_td = (td + 1 < uhci_batch->td_count)
     322                    ? &uhci_batch->tds[td + 1] : NULL;
     323
     324                assert(td < uhci_batch->td_count);
    353325                td_init(
    354                     &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
     326                    &uhci_batch->tds[td], DEFAULT_ERROR_COUNT, packet_size,
    355327                    toggle, false, low_speed, target, pid, buffer, next_td);
    356328
     
    358330                toggle = 1 - toggle;
    359331                buffer += packet_size;
    360                 assert(packet_size <= remain_size);
    361332                remain_size -= packet_size;
    362333        }
    363         td_set_ioc(&data->tds[td - 1]);
    364         endpoint_toggle_set(instance->ep, toggle);
     334        td_set_ioc(&uhci_batch->tds[td - 1]);
     335        endpoint_toggle_set(uhci_batch->usb_batch->ep, toggle);
    365336}
    366337/*----------------------------------------------------------------------------*/
     
    376347 * The last transfer is marked with IOC.
    377348 */
    378 static void batch_control(usb_transfer_batch_t *instance,
    379    usb_packet_id data_stage, usb_packet_id status_stage)
    380 {
    381         assert(instance);
    382         uhci_transfer_batch_t *data = instance->private_data;
    383         assert(data);
    384         assert(data->td_count >= 2);
    385 
    386         const bool low_speed = instance->ep->speed == USB_SPEED_LOW;
    387         const usb_target_t target =
    388             { instance->ep->address, instance->ep->endpoint };
     349static void batch_control(uhci_transfer_batch_t *uhci_batch,
     350   usb_packet_id data_stage_pid, usb_packet_id status_stage_pid)
     351{
     352        assert(uhci_batch);
     353        assert(uhci_batch->usb_batch);
     354        assert(uhci_batch->usb_batch->ep);
     355        assert(uhci_batch->td_count >= 2);
     356
     357        const bool low_speed =
     358            uhci_batch->usb_batch->ep->speed == USB_SPEED_LOW;
     359        const size_t mps = uhci_batch->usb_batch->ep->max_packet_size;
     360        const usb_target_t target = {
     361            uhci_batch->usb_batch->ep->address,
     362            uhci_batch->usb_batch->ep->endpoint };
    389363
    390364        /* setup stage */
    391365        td_init(
    392             data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, 0, false,
    393             low_speed, target, USB_PID_SETUP, instance->setup_buffer,
    394             &data->tds[1]);
     366            &uhci_batch->tds[0], DEFAULT_ERROR_COUNT,
     367            uhci_batch->usb_batch->setup_size, 0, false,
     368            low_speed, target, USB_PID_SETUP,
     369            uhci_transfer_batch_setup_buffer(uhci_batch), &uhci_batch->tds[1]);
    395370
    396371        /* data stage */
    397372        size_t td = 1;
    398373        unsigned toggle = 1;
    399         size_t remain_size = instance->buffer_size;
    400         char *buffer = instance->data_buffer;
     374        size_t remain_size = uhci_batch->usb_batch->buffer_size;
     375        char *buffer = uhci_transfer_batch_data_buffer(uhci_batch);
     376
    401377        while (remain_size > 0) {
    402378                const size_t packet_size =
    403                     (instance->ep->max_packet_size > remain_size) ?
    404                     remain_size : instance->ep->max_packet_size;
     379                    (remain_size < mps) ? remain_size : mps;
    405380
    406381                td_init(
    407                     &data->tds[td], DEFAULT_ERROR_COUNT, packet_size,
    408                     toggle, false, low_speed, target, data_stage,
    409                     buffer, &data->tds[td + 1]);
     382                    &uhci_batch->tds[td], DEFAULT_ERROR_COUNT, packet_size,
     383                    toggle, false, low_speed, target, data_stage_pid,
     384                    buffer, &uhci_batch->tds[td + 1]);
    410385
    411386                ++td;
    412387                toggle = 1 - toggle;
    413388                buffer += packet_size;
    414                 assert(td < data->td_count);
    415                 assert(packet_size <= remain_size);
    416389                remain_size -= packet_size;
     390                assert(td < uhci_batch->td_count);
    417391        }
    418392
    419393        /* status stage */
    420         assert(td == data->td_count - 1);
     394        assert(td == uhci_batch->td_count - 1);
    421395
    422396        td_init(
    423             &data->tds[td], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
    424             target, status_stage, NULL, NULL);
    425         td_set_ioc(&data->tds[td]);
     397            &uhci_batch->tds[td], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed,
     398            target, status_stage_pid, NULL, NULL);
     399        td_set_ioc(&uhci_batch->tds[td]);
    426400
    427401        usb_log_debug2("Control last TD status: %x.\n",
    428             data->tds[td].status);
    429 }
    430 /*----------------------------------------------------------------------------*/
    431 /** Provides access to QH data structure.
    432  *
    433  * @param[in] instance Batch pointer to use.
    434  * @return Pointer to the QH used by the batch.
    435  */
    436 qh_t * batch_qh(usb_transfer_batch_t *instance)
    437 {
    438         assert(instance);
    439         uhci_transfer_batch_t *data = instance->private_data;
    440         assert(data);
    441         return data->qh;
    442 }
     402            uhci_batch->tds[td].status);
     403}
     404/*----------------------------------------------------------------------------*/
     405static void batch_setup_control(uhci_transfer_batch_t *uhci_batch)
     406{
     407        // TODO Find a better way to do this
     408        assert(uhci_batch);
     409        assert(uhci_batch->usb_batch);
     410        if (uhci_batch->usb_batch->setup_buffer[0] & (1 << 7))
     411                control_read(uhci_batch);
     412        else
     413                control_write(uhci_batch);
     414}
     415/*----------------------------------------------------------------------------*/
     416static void (*batch_setup[4][3])(uhci_transfer_batch_t*) =
     417{
     418        { NULL, NULL, batch_setup_control },
     419        { NULL, NULL, NULL },
     420        { bulk_in, bulk_out, NULL },
     421        { interrupt_in, interrupt_out, NULL },
     422};
    443423/**
    444424 * @}
  • uspace/drv/bus/usb/uhci/uhci_batch.h

    r96e2d01 rb991d37  
    3636
    3737#include <usb/host/batch.h>
     38#include <adt/list.h>
    3839
    3940#include "hw_struct/queue_head.h"
     41#include "hw_struct/transfer_descriptor.h"
    4042
    41 int batch_init_uhci(usb_transfer_batch_t *batch);
    42 bool batch_is_complete(usb_transfer_batch_t *batch);
    43 qh_t * batch_qh(usb_transfer_batch_t *batch);
     43/** UHCI specific data required for USB transfer */
     44typedef struct uhci_transfer_batch {
     45        /** Queue head
     46         * This QH is used to maintain UHCI schedule structure and the element
     47         * pointer points to the first TD of this batch.
     48         */
     49        qh_t *qh;
     50        /** List of TDs needed for the transfer */
     51        td_t *tds;
     52        /** Number of TDs used by the transfer */
     53        size_t td_count;
     54        /** Data buffer, must be accessible by the UHCI hw */
     55        void *device_buffer;
     56        /** Generic transfer data */
     57        usb_transfer_batch_t *usb_batch;
     58        /** List element */
     59        link_t link;
     60} uhci_transfer_batch_t;
     61
     62uhci_transfer_batch_t * uhci_transfer_batch_get(usb_transfer_batch_t *batch);
     63void uhci_transfer_batch_call_dispose(uhci_transfer_batch_t *uhci_batch);
     64bool uhci_transfer_batch_is_complete(uhci_transfer_batch_t *uhci_batch);
     65
     66static inline void * uhci_transfer_batch_data_buffer(
     67    uhci_transfer_batch_t *uhci_batch)
     68{
     69        assert(uhci_batch);
     70        assert(uhci_batch->usb_batch);
     71        assert(uhci_batch->device_buffer);
     72        return uhci_batch->device_buffer + sizeof(qh_t) +
     73            uhci_batch->td_count * sizeof(td_t) +
     74            uhci_batch->usb_batch->setup_size;
     75}
     76/*----------------------------------------------------------------------------*/
     77static inline void * uhci_transfer_batch_setup_buffer(
     78    uhci_transfer_batch_t *uhci_batch)
     79{
     80        assert(uhci_batch);
     81        assert(uhci_batch->usb_batch);
     82        assert(uhci_batch->device_buffer);
     83        return uhci_batch->device_buffer + sizeof(qh_t) +
     84            uhci_batch->td_count * sizeof(td_t);
     85}
     86/*----------------------------------------------------------------------------*/
     87static inline uhci_transfer_batch_t *uhci_transfer_batch_from_link(link_t *l)
     88{
     89        assert(l);
     90        return list_get_instance(l, uhci_transfer_batch_t, link);
     91}
     92
    4493#endif
    4594/**
Note: See TracChangeset for help on using the changeset viewer.