Changeset 651b352 in mainline
- Timestamp:
- 2011-04-13T15:00:43Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8b4ce802
- Parents:
- 4deca9b (diff), d6522dd (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. - Location:
- uspace
- Files:
-
- 2 added
- 13 edited
- 2 moved
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/ohci/Makefile
r4deca9b r651b352 34 34 SOURCES = \ 35 35 batch.c \ 36 endpoint_list.c \ 36 37 hc.c \ 38 hcd_endpoint.c \ 37 39 iface.c \ 38 40 main.c \ … … 40 42 pci.c \ 41 43 root_hub.c \ 42 transfer_list.c \43 44 hw_struct/endpoint_descriptor.c \ 44 45 hw_struct/transfer_descriptor.c -
uspace/drv/ohci/batch.c
r4deca9b r651b352 39 39 40 40 #include "batch.h" 41 #include "hcd_endpoint.h" 41 42 #include "utils/malloc32.h" 42 43 #include "hw_struct/endpoint_descriptor.h" 43 44 #include "hw_struct/transfer_descriptor.h" 44 45 45 typedef struct ohci_ batch {46 typedef struct ohci_transfer_batch { 46 47 ed_t *ed; 47 td_t * tds;48 td_t **tds; 48 49 size_t td_count; 49 } ohci_batch_t; 50 50 size_t leave_td; 51 char *device_buffer; 52 } ohci_transfer_batch_t; 53 54 static void ohci_transfer_batch_dispose(void *ohci_batch) 55 { 56 ohci_transfer_batch_t *instance = ohci_batch; 57 if (!instance) 58 return; 59 free32(instance->device_buffer); 60 unsigned i = 0; 61 if (instance->tds) { 62 for (; i< instance->td_count; ++i) { 63 if (i != instance->leave_td) 64 free32(instance->tds[i]); 65 } 66 free(instance->tds); 67 } 68 free(instance); 69 } 70 /*----------------------------------------------------------------------------*/ 51 71 static void batch_control(usb_transfer_batch_t *instance, 52 72 usb_direction_t data_dir, usb_direction_t status_dir); 53 73 static void batch_data(usb_transfer_batch_t *instance); 54 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance); 55 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance); 56 57 #define DEFAULT_ERROR_COUNT 3 74 /*----------------------------------------------------------------------------*/ 58 75 usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep, 59 76 char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size, … … 65 82 usb_log_error(message); \ 66 83 if (instance) { \ 67 batch_dispose(instance); \84 usb_transfer_batch_dispose(instance); \ 68 85 } \ 69 86 return NULL; \ … … 74 91 "Failed to allocate batch instance.\n"); 75 92 usb_transfer_batch_init(instance, ep, buffer, NULL, buffer_size, 76 NULL, setup_size, func_in, func_out, arg, fun, NULL); 77 78 ohci_batch_t *data = malloc(sizeof(ohci_batch_t)); 93 NULL, setup_size, func_in, func_out, arg, fun, NULL, 94 ohci_transfer_batch_dispose); 95 96 hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep); 97 assert(hcd_ep); 98 99 ohci_transfer_batch_t *data = calloc(sizeof(ohci_transfer_batch_t), 1); 79 100 CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n"); 80 bzero(data, sizeof(ohci_batch_t));81 101 instance->private_data = data; 82 102 83 /* we needs + 1 transfer descriptor as the last one won't be executed */ 84 data->td_count = 1 + 103 data->td_count = 85 104 ((buffer_size + OHCI_TD_MAX_TRANSFER - 1) / OHCI_TD_MAX_TRANSFER); 86 105 if (ep->transfer_type == USB_TRANSFER_CONTROL) { … … 88 107 } 89 108 90 data->tds = malloc32(sizeof(td_t) * data->td_count); 109 /* we need one extra place for td that is currently assigned to hcd_ep*/ 110 data->tds = calloc(sizeof(td_t*), data->td_count + 1); 91 111 CHECK_NULL_DISPOSE_RETURN(data->tds, 92 112 "Failed to allocate transfer descriptors.\n"); 93 bzero(data->tds, sizeof(td_t) * data->td_count); 94 95 data->ed = malloc32(sizeof(ed_t)); 96 CHECK_NULL_DISPOSE_RETURN(data->ed, 97 "Failed to allocate endpoint descriptor.\n"); 98 99 if (buffer_size > 0) { 100 instance->data_buffer = malloc32(buffer_size); 101 CHECK_NULL_DISPOSE_RETURN(instance->data_buffer, 113 114 data->tds[0] = hcd_ep->td; 115 data->leave_td = 0; 116 unsigned i = 1; 117 for (; i <= data->td_count; ++i) { 118 data->tds[i] = malloc32(sizeof(td_t)); 119 CHECK_NULL_DISPOSE_RETURN(data->tds[i], 120 "Failed to allocate TD %d.\n", i ); 121 } 122 123 data->ed = hcd_ep->ed; 124 125 if (setup_size + buffer_size > 0) { 126 data->device_buffer = malloc32(setup_size + buffer_size); 127 CHECK_NULL_DISPOSE_RETURN(data->device_buffer, 102 128 "Failed to allocate device accessible buffer.\n"); 103 } 104 105 if (setup_size > 0) { 106 instance->setup_buffer = malloc32(setup_size); 107 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer, 108 "Failed to allocate device accessible setup buffer.\n"); 129 instance->setup_buffer = data->device_buffer; 130 instance->data_buffer = data->device_buffer + setup_size; 109 131 memcpy(instance->setup_buffer, setup_buffer, setup_size); 110 132 } … … 113 135 } 114 136 /*----------------------------------------------------------------------------*/ 115 void batch_dispose(usb_transfer_batch_t *instance)116 {117 assert(instance);118 ohci_batch_t *data = instance->private_data;119 assert(data);120 free32(data->ed);121 free32(data->tds);122 free32(instance->setup_buffer);123 free32(instance->data_buffer);124 free(data);125 free(instance);126 }127 /*----------------------------------------------------------------------------*/128 137 bool batch_is_complete(usb_transfer_batch_t *instance) 129 138 { 130 139 assert(instance); 131 ohci_ batch_t *data = instance->private_data;132 assert(data); 133 size_t tds = data->td_count - 1;140 ohci_transfer_batch_t *data = instance->private_data; 141 assert(data); 142 size_t tds = data->td_count; 134 143 usb_log_debug("Batch(%p) checking %d td(s) for completion.\n", 135 144 instance, tds); … … 139 148 size_t i = 0; 140 149 for (; i < tds; ++i) { 150 assert(data->tds[i] != NULL); 141 151 usb_log_debug("TD %d: %x:%x:%x:%x.\n", i, 142 data->tds[i] .status, data->tds[i].cbp, data->tds[i].next,143 data->tds[i] .be);144 if (!td_is_finished( &data->tds[i])) {152 data->tds[i]->status, data->tds[i]->cbp, data->tds[i]->next, 153 data->tds[i]->be); 154 if (!td_is_finished(data->tds[i])) { 145 155 return false; 146 156 } 147 instance->error = td_error( &data->tds[i]);157 instance->error = td_error(data->tds[i]); 148 158 /* FIXME: calculate real transfered size */ 149 159 instance->transfered_size = instance->buffer_size; 150 160 if (instance->error != EOK) { 151 161 usb_log_debug("Batch(%p) found error TD(%d):%x.\n", 152 instance, i, data->tds[i].status); 153 return true; 154 // endpoint_toggle_set(instance->ep, 162 instance, i, data->tds[i]->status); 163 break; 155 164 } 156 165 } 166 data->leave_td = i; 167 assert(data->leave_td <= data->td_count); 168 hcd_endpoint_t *hcd_ep = hcd_endpoint_get(instance->ep); 169 assert(hcd_ep); 170 hcd_ep->td = data->tds[i]; 171 157 172 return true; 173 } 174 /*----------------------------------------------------------------------------*/ 175 void batch_commit(usb_transfer_batch_t *instance) 176 { 177 assert(instance); 178 ohci_transfer_batch_t *data = instance->private_data; 179 assert(data); 180 ed_set_end_td(data->ed, data->tds[data->td_count]); 158 181 } 159 182 /*----------------------------------------------------------------------------*/ … … 163 186 /* We are data out, we are supposed to provide data */ 164 187 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 165 instance->next_step = batch_call_out_and_dispose;188 instance->next_step = usb_transfer_batch_call_out_and_dispose; 166 189 batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN); 167 190 usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance); … … 171 194 { 172 195 assert(instance); 173 instance->next_step = batch_call_in_and_dispose;196 instance->next_step = usb_transfer_batch_call_in_and_dispose; 174 197 batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT); 175 198 usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance); … … 179 202 { 180 203 assert(instance); 181 instance->next_step = batch_call_in_and_dispose;204 instance->next_step = usb_transfer_batch_call_in_and_dispose; 182 205 batch_data(instance); 183 206 usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance); … … 189 212 /* We are data out, we are supposed to provide data */ 190 213 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 191 instance->next_step = batch_call_out_and_dispose;214 instance->next_step = usb_transfer_batch_call_out_and_dispose; 192 215 batch_data(instance); 193 216 usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance); … … 197 220 { 198 221 assert(instance); 199 instance->next_step = batch_call_in_and_dispose;222 instance->next_step = usb_transfer_batch_call_in_and_dispose; 200 223 batch_data(instance); 201 224 usb_log_debug("Batch(%p) BULK IN initialized.\n", instance); … … 205 228 { 206 229 assert(instance); 207 instance->next_step = batch_call_in_and_dispose;230 instance->next_step = usb_transfer_batch_call_in_and_dispose; 208 231 batch_data(instance); 209 232 usb_log_debug("Batch(%p) BULK IN initialized.\n", instance); … … 213 236 { 214 237 assert(instance); 215 ohci_ batch_t *data = instance->private_data;238 ohci_transfer_batch_t *data = instance->private_data; 216 239 assert(data); 217 240 return data->ed; … … 222 245 { 223 246 assert(instance); 224 ohci_batch_t *data = instance->private_data; 225 assert(data); 226 ed_init(data->ed, instance->ep); 227 ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]); 228 usb_log_debug("Created ED(%p): %x:%x:%x:%x.\n", data->ed, 247 ohci_transfer_batch_t *data = instance->private_data; 248 assert(data); 249 usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed, 229 250 data->ed->status, data->ed->td_tail, data->ed->td_head, 230 251 data->ed->next); 231 252 int toggle = 0; 232 253 /* setup stage */ 233 td_init( &data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,254 td_init(data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer, 234 255 instance->setup_size, toggle); 235 td_set_next( &data->tds[0], &data->tds[1]);236 usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0] .status,237 data->tds[0] .cbp, data->tds[0].next, data->tds[0].be);256 td_set_next(data->tds[0], data->tds[1]); 257 usb_log_debug("Created SETUP TD: %x:%x:%x:%x.\n", data->tds[0]->status, 258 data->tds[0]->cbp, data->tds[0]->next, data->tds[0]->be); 238 259 239 260 /* data stage */ … … 246 267 toggle = 1 - toggle; 247 268 248 td_init( &data->tds[td_current], data_dir, buffer,269 td_init(data->tds[td_current], data_dir, buffer, 249 270 transfer_size, toggle); 250 td_set_next( &data->tds[td_current], &data->tds[td_current + 1]);271 td_set_next(data->tds[td_current], data->tds[td_current + 1]); 251 272 usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n", 252 data->tds[td_current] .status, data->tds[td_current].cbp,253 data->tds[td_current] .next, data->tds[td_current].be);273 data->tds[td_current]->status, data->tds[td_current]->cbp, 274 data->tds[td_current]->next, data->tds[td_current]->be); 254 275 255 276 buffer += transfer_size; 256 277 remain_size -= transfer_size; 257 assert(td_current < data->td_count - 2);278 assert(td_current < data->td_count - 1); 258 279 ++td_current; 259 280 } 260 281 261 282 /* status stage */ 262 assert(td_current == data->td_count - 2); 263 td_init(&data->tds[td_current], status_dir, NULL, 0, 1); 283 assert(td_current == data->td_count - 1); 284 td_init(data->tds[td_current], status_dir, NULL, 0, 1); 285 td_set_next(data->tds[td_current], data->tds[td_current + 1]); 264 286 usb_log_debug("Created STATUS TD: %x:%x:%x:%x.\n", 265 data->tds[td_current] .status, data->tds[td_current].cbp,266 data->tds[td_current] .next, data->tds[td_current].be);287 data->tds[td_current]->status, data->tds[td_current]->cbp, 288 data->tds[td_current]->next, data->tds[td_current]->be); 267 289 } 268 290 /*----------------------------------------------------------------------------*/ … … 270 292 { 271 293 assert(instance); 272 ohci_batch_t *data = instance->private_data; 273 assert(data); 274 ed_init(data->ed, instance->ep); 275 ed_add_tds(data->ed, &data->tds[0], &data->tds[data->td_count - 1]); 276 usb_log_debug("Created ED(%p): %x:%x:%x:%x.\n", data->ed, 294 ohci_transfer_batch_t *data = instance->private_data; 295 assert(data); 296 usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed, 277 297 data->ed->status, data->ed->td_tail, data->ed->td_head, 278 298 data->ed->next); 279 299 280 /* data stage */281 300 size_t td_current = 0; 282 301 size_t remain_size = instance->buffer_size; … … 286 305 OHCI_TD_MAX_TRANSFER : remain_size; 287 306 288 td_init( &data->tds[td_current], instance->ep->direction,307 td_init(data->tds[td_current], instance->ep->direction, 289 308 buffer, transfer_size, -1); 290 td_set_next( &data->tds[td_current], &data->tds[td_current + 1]);309 td_set_next(data->tds[td_current], data->tds[td_current + 1]); 291 310 usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n", 292 data->tds[td_current] .status, data->tds[td_current].cbp,293 data->tds[td_current] .next, data->tds[td_current].be);311 data->tds[td_current]->status, data->tds[td_current]->cbp, 312 data->tds[td_current]->next, data->tds[td_current]->be); 294 313 295 314 buffer += transfer_size; … … 299 318 } 300 319 } 301 /*----------------------------------------------------------------------------*/302 /** Helper function calls callback and correctly disposes of batch structure.303 *304 * @param[in] instance Batch structure to use.305 */306 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)307 {308 assert(instance);309 usb_transfer_batch_call_in(instance);310 batch_dispose(instance);311 }312 /*----------------------------------------------------------------------------*/313 /** Helper function calls callback and correctly disposes of batch structure.314 *315 * @param[in] instance Batch structure to use.316 */317 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)318 {319 assert(instance);320 usb_transfer_batch_call_out(instance);321 batch_dispose(instance);322 }323 320 /** 324 321 * @} -
uspace/drv/ohci/batch.h
r4deca9b r651b352 50 50 void *arg); 51 51 52 void batch_dispose(usb_transfer_batch_t *instance);52 bool batch_is_complete(usb_transfer_batch_t *instance); 53 53 54 bool batch_is_complete(usb_transfer_batch_t *instance);54 void batch_commit(usb_transfer_batch_t *instance); 55 55 56 56 void batch_control_write(usb_transfer_batch_t *instance); -
uspace/drv/ohci/endpoint_list.c
r4deca9b r651b352 35 35 #include <usb/debug.h> 36 36 37 #include "transfer_list.h" 38 39 static void transfer_list_remove_batch( 40 transfer_list_t *instance, usb_transfer_batch_t *batch); 41 /*----------------------------------------------------------------------------*/ 37 #include "endpoint_list.h" 38 42 39 /** Initialize transfer list structures. 43 40 * … … 48 45 * Allocates memory for internal qh_t structure. 49 46 */ 50 int transfer_list_init(transfer_list_t *instance, const char *name)47 int endpoint_list_init(endpoint_list_t *instance, const char *name) 51 48 { 52 49 assert(instance); … … 62 59 63 60 ed_init(instance->list_head, NULL); 64 list_initialize(&instance-> batch_list);61 list_initialize(&instance->endpoint_list); 65 62 fibril_mutex_initialize(&instance->guard); 66 63 return EOK; … … 75 72 * Does not check whether this replaces an existing list . 76 73 */ 77 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next)74 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next) 78 75 { 79 76 assert(instance); … … 82 79 } 83 80 /*----------------------------------------------------------------------------*/ 84 /** Submit transfer batchto the list and queue.85 * 86 * @param[in] instance List to use. 87 * @param[in] batch Transfer batchto submit.88 * @return Error code 89 * 90 * The batchis added to the end of the list and queue.91 */ 92 void transfer_list_add_batch(93 transfer_list_t *instance, usb_transfer_batch_t *batch) 94 { 95 assert( instance);96 assert(batch);97 usb_log_debug2("Queue %s: Adding batch(%p).\n", instance->name, batch);81 /** Submit transfer endpoint to the list and queue. 82 * 83 * @param[in] instance List to use. 84 * @param[in] endpoint Transfer endpoint to submit. 85 * @return Error code 86 * 87 * The endpoint is added to the end of the list and queue. 88 */ 89 void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep) 90 { 91 assert(instance); 92 assert(hcd_ep); 93 usb_log_debug2("Queue %s: Adding endpoint(%p).\n", 94 instance->name, hcd_ep); 98 95 99 96 fibril_mutex_lock(&instance->guard); … … 101 98 ed_t *last_ed = NULL; 102 99 /* Add to the hardware queue. */ 103 if (list_empty(&instance-> batch_list)) {100 if (list_empty(&instance->endpoint_list)) { 104 101 /* There is nothing scheduled */ 105 102 last_ed = instance->list_head; 106 103 } else { 107 104 /* There is something scheduled */ 108 usb_transfer_batch_t *last = list_get_instance(109 instance-> batch_list.prev, usb_transfer_batch_t, link);110 last_ed = batch_ed(last);105 hcd_endpoint_t *last = list_get_instance( 106 instance->endpoint_list.prev, hcd_endpoint_t, link); 107 last_ed = last->ed; 111 108 } 112 109 /* keep link */ 113 batch_ed(batch)->next = last_ed->next;114 ed_append_ed(last_ed, batch_ed(batch));110 hcd_ep->ed->next = last_ed->next; 111 ed_append_ed(last_ed, hcd_ep->ed); 115 112 116 113 asm volatile ("": : :"memory"); 117 114 118 115 /* Add to the driver list */ 119 list_append(& batch->link, &instance->batch_list);120 121 usb_transfer_batch_t *first = list_get_instance(122 instance-> batch_list.next, usb_transfer_batch_t, link);123 usb_log_debug(" Batch(%p) added to list %s, first is %p(%p).\n",124 batch, instance->name, first, batch_ed(first));116 list_append(&hcd_ep->link, &instance->endpoint_list); 117 118 hcd_endpoint_t *first = list_get_instance( 119 instance->endpoint_list.next, hcd_endpoint_t, link); 120 usb_log_debug("HCD EP(%p) added to list %s, first is %p(%p).\n", 121 hcd_ep, instance->name, first, first->ed); 125 122 if (last_ed == instance->list_head) { 126 123 usb_log_debug2("%s head ED(%p-%p): %x:%x:%x:%x.\n", … … 132 129 } 133 130 /*----------------------------------------------------------------------------*/ 134 /** Create list for finished batches. 131 #if 0 132 /** Create list for finished endpoints. 135 133 * 136 134 * @param[in] instance List to use. 137 135 * @param[in] done list to fill 138 136 */ 139 void transfer_list_remove_finished(transfer_list_t *instance, link_t *done)137 void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done) 140 138 { 141 139 assert(instance); … … 143 141 144 142 fibril_mutex_lock(&instance->guard); 145 usb_log_debug2("Checking list %s for completed batches(%d).\n",146 instance->name, list_count(&instance-> batch_list));147 link_t *current = instance-> batch_list.next;148 while (current != &instance-> batch_list) {143 usb_log_debug2("Checking list %s for completed endpointes(%d).\n", 144 instance->name, list_count(&instance->endpoint_list)); 145 link_t *current = instance->endpoint_list.next; 146 while (current != &instance->endpoint_list) { 149 147 link_t *next = current->next; 150 usb_transfer_batch_t *batch=151 list_get_instance(current, usb_transfer_batch_t, link);152 153 if ( batch_is_complete(batch)) {148 hcd_endpoint_t *endpoint = 149 list_get_instance(current, hcd_endpoint_t, link); 150 151 if (endpoint_is_complete(endpoint)) { 154 152 /* Save for post-processing */ 155 transfer_list_remove_batch(instance, batch);153 endpoint_list_remove_endpoint(instance, endpoint); 156 154 list_append(current, done); 157 155 } … … 161 159 } 162 160 /*----------------------------------------------------------------------------*/ 163 /** Walk the list and abort all batches. 164 * 165 * @param[in] instance List to use. 166 */ 167 void transfer_list_abort_all(transfer_list_t *instance) 168 { 169 fibril_mutex_lock(&instance->guard); 170 while (!list_empty(&instance->batch_list)) { 171 link_t *current = instance->batch_list.next; 172 usb_transfer_batch_t *batch = 173 list_get_instance(current, usb_transfer_batch_t, link); 174 transfer_list_remove_batch(instance, batch); 175 usb_transfer_batch_finish_error(batch, EIO); 176 } 177 fibril_mutex_unlock(&instance->guard); 178 } 179 /*----------------------------------------------------------------------------*/ 180 /** Remove a transfer batch from the list and queue. 181 * 182 * @param[in] instance List to use. 183 * @param[in] batch Transfer batch to remove. 161 /** Walk the list and abort all endpointes. 162 * 163 * @param[in] instance List to use. 164 */ 165 void endpoint_list_abort_all(endpoint_list_t *instance) 166 { 167 fibril_mutex_lock(&instance->guard); 168 while (!list_empty(&instance->endpoint_list)) { 169 link_t *current = instance->endpoint_list.next; 170 hcd_endpoint_t *endpoint = 171 list_get_instance(current, hcd_endpoint_t, link); 172 endpoint_list_remove_endpoint(instance, endpoint); 173 hcd_endpoint_finish_error(endpoint, EIO); 174 } 175 fibril_mutex_unlock(&instance->guard); 176 } 177 #endif 178 /*----------------------------------------------------------------------------*/ 179 /** Remove a transfer endpoint from the list and queue. 180 * 181 * @param[in] instance List to use. 182 * @param[in] endpoint Transfer endpoint to remove. 184 183 * @return Error code 185 184 * 186 185 * Does not lock the transfer list, caller is responsible for that. 187 186 */ 188 void transfer_list_remove_batch( 189 transfer_list_t *instance, usb_transfer_batch_t *batch) 187 void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep) 190 188 { 191 189 assert(instance); 192 190 assert(instance->list_head); 193 assert(batch); 194 assert(batch_ed(batch)); 195 assert(fibril_mutex_is_locked(&instance->guard)); 191 assert(hcd_ep); 192 assert(hcd_ep->ed); 193 194 fibril_mutex_lock(&instance->guard); 196 195 197 196 usb_log_debug2( 198 "Queue %s: removing batch(%p).\n", instance->name, batch);197 "Queue %s: removing endpoint(%p).\n", instance->name, hcd_ep); 199 198 200 199 const char *qpos = NULL; 200 ed_t *prev_ed; 201 201 /* Remove from the hardware queue */ 202 if (instance-> batch_list.next == &batch->link) {202 if (instance->endpoint_list.next == &hcd_ep->link) { 203 203 /* I'm the first one here */ 204 assert((instance->list_head->next & ED_NEXT_PTR_MASK) 205 == addr_to_phys(batch_ed(batch))); 206 instance->list_head->next = batch_ed(batch)->next; 204 prev_ed = instance->list_head; 207 205 qpos = "FIRST"; 208 206 } else { 209 usb_transfer_batch_t *prev = 210 list_get_instance( 211 batch->link.prev, usb_transfer_batch_t, link); 212 assert((batch_ed(prev)->next & ED_NEXT_PTR_MASK) 213 == addr_to_phys(batch_ed(batch))); 214 batch_ed(prev)->next = batch_ed(batch)->next; 207 hcd_endpoint_t *prev = 208 list_get_instance(hcd_ep->link.prev, hcd_endpoint_t, link); 209 prev_ed = prev->ed; 215 210 qpos = "NOT FIRST"; 216 211 } 212 assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed)); 213 prev_ed->next = hcd_ep->ed->next; 214 217 215 asm volatile ("": : :"memory"); 218 usb_log_debug("Batch(%p) removed (%s) from %s, next %x.\n", 219 batch, qpos, instance->name, batch_ed(batch)->next); 220 221 /* Remove from the batch list */ 222 list_remove(&batch->link); 216 usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n", 217 hcd_ep, qpos, instance->name, hcd_ep->ed->next); 218 219 /* Remove from the endpoint list */ 220 list_remove(&hcd_ep->link); 221 fibril_mutex_unlock(&instance->guard); 223 222 } 224 223 /** -
uspace/drv/ohci/endpoint_list.h
r4deca9b r651b352 32 32 * @brief OHCI driver transfer list structure 33 33 */ 34 #ifndef DRV_OHCI_ TRANSFER_LIST_H35 #define DRV_OHCI_ TRANSFER_LIST_H34 #ifndef DRV_OHCI_ENDPOINT_LIST_H 35 #define DRV_OHCI_ENDPOINT_LIST_H 36 36 37 37 #include <fibril_synch.h> 38 38 39 #include " batch.h"39 #include "hcd_endpoint.h" 40 40 #include "hw_struct/endpoint_descriptor.h" 41 41 #include "utils/malloc32.h" 42 42 43 typedef struct transfer_list43 typedef struct endpoint_list 44 44 { 45 45 fibril_mutex_t guard; … … 47 47 uint32_t list_head_pa; 48 48 const char *name; 49 link_t batch_list;50 } transfer_list_t;49 link_t endpoint_list; 50 } endpoint_list_t; 51 51 52 52 /** Dispose transfer list structures. … … 56 56 * Frees memory for internal qh_t structure. 57 57 */ 58 static inline void transfer_list_fini(transfer_list_t *instance)58 static inline void endpoint_list_fini(endpoint_list_t *instance) 59 59 { 60 60 assert(instance); … … 62 62 } 63 63 64 int transfer_list_init(transfer_list_t *instance, const char *name);64 int endpoint_list_init(endpoint_list_t *instance, const char *name); 65 65 66 void transfer_list_set_next(transfer_list_t *instance, transfer_list_t *next);66 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next); 67 67 68 void transfer_list_add_batch(transfer_list_t *instance, usb_transfer_batch_t *batch);68 void endpoint_list_add_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep); 69 69 70 void transfer_list_remove_finished(transfer_list_t *instance, link_t *done); 70 void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep); 71 #if 0 72 void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done); 71 73 72 void transfer_list_abort_all(transfer_list_t *instance); 74 void endpoint_list_abort_all(endpoint_list_t *instance); 75 #endif 73 76 #endif 74 77 /** -
uspace/drv/ohci/hc.c
r4deca9b r651b352 43 43 44 44 #include "hc.h" 45 #include "hcd_endpoint.h" 45 46 46 47 static int interrupt_emulator(hc_t *instance); … … 67 68 &instance->manager, hub_address, hub_fun->handle); 68 69 69 ret = usb_endpoint_manager_add_ep(&instance->ep_manager, 70 hub_address, 0, USB_DIRECTION_BOTH, USB_TRANSFER_CONTROL, 71 USB_SPEED_FULL, 64, 0); 70 ret = hc_add_endpoint(instance, hub_address, 0, USB_SPEED_FULL, 71 USB_TRANSFER_CONTROL, USB_DIRECTION_BOTH, 64, 0, 0); 72 72 if (ret != EOK) { 73 73 usb_log_error("Failed to add OHCI rh endpoint 0.\n"); … … 109 109 ret, str_error(ret)); 110 110 111 instance->ddf_instance = fun;112 111 usb_device_keeper_init(&instance->manager); 113 112 ret = usb_endpoint_manager_init(&instance->ep_manager, … … 131 130 } 132 131 133 return EOK; 132 list_initialize(&instance->pending_batches); 133 #undef CHECK_RET_RETURN 134 return EOK; 135 } 136 /*----------------------------------------------------------------------------*/ 137 int hc_add_endpoint( 138 hc_t *instance, usb_address_t address, usb_endpoint_t endpoint, 139 usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction, 140 size_t mps, size_t size, unsigned interval) 141 { 142 endpoint_t *ep = malloc(sizeof(endpoint_t)); 143 if (ep == NULL) 144 return ENOMEM; 145 int ret = 146 endpoint_init(ep, address, endpoint, direction, type, speed, mps); 147 if (ret != EOK) { 148 free(ep); 149 return ret; 150 } 151 152 hcd_endpoint_t *hcd_ep = hcd_endpoint_assign(ep); 153 if (hcd_ep == NULL) { 154 endpoint_destroy(ep); 155 return ENOMEM; 156 } 157 158 ret = usb_endpoint_manager_register_ep(&instance->ep_manager, ep, size); 159 if (ret != EOK) { 160 hcd_endpoint_clear(ep); 161 endpoint_destroy(ep); 162 return ret; 163 } 164 165 /* Enqueue hcd_ep */ 166 switch (ep->transfer_type) { 167 case USB_TRANSFER_CONTROL: 168 instance->registers->control &= ~C_CLE; 169 endpoint_list_add_ep( 170 &instance->lists[ep->transfer_type], hcd_ep); 171 instance->registers->control_current = 0; 172 instance->registers->control |= C_CLE; 173 break; 174 case USB_TRANSFER_BULK: 175 instance->registers->control &= ~C_BLE; 176 endpoint_list_add_ep( 177 &instance->lists[ep->transfer_type], hcd_ep); 178 instance->registers->control |= C_BLE; 179 break; 180 case USB_TRANSFER_ISOCHRONOUS: 181 case USB_TRANSFER_INTERRUPT: 182 instance->registers->control &= (~C_PLE & ~C_IE); 183 endpoint_list_add_ep( 184 &instance->lists[ep->transfer_type], hcd_ep); 185 instance->registers->control |= C_PLE | C_IE; 186 break; 187 default: 188 break; 189 } 190 191 return EOK; 192 } 193 /*----------------------------------------------------------------------------*/ 194 int hc_remove_endpoint(hc_t *instance, usb_address_t address, 195 usb_endpoint_t endpoint, usb_direction_t direction) 196 { 197 assert(instance); 198 fibril_mutex_lock(&instance->guard); 199 endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager, 200 address, endpoint, direction, NULL); 201 if (ep == NULL) { 202 usb_log_error("Endpoint unregister failed: No such EP.\n"); 203 fibril_mutex_unlock(&instance->guard); 204 return ENOENT; 205 } 206 207 hcd_endpoint_t *hcd_ep = hcd_endpoint_get(ep); 208 if (hcd_ep) { 209 /* Dequeue hcd_ep */ 210 switch (ep->transfer_type) { 211 case USB_TRANSFER_CONTROL: 212 instance->registers->control &= ~C_CLE; 213 endpoint_list_remove_ep( 214 &instance->lists[ep->transfer_type], hcd_ep); 215 instance->registers->control_current = 0; 216 instance->registers->control |= C_CLE; 217 break; 218 case USB_TRANSFER_BULK: 219 instance->registers->control &= ~C_BLE; 220 endpoint_list_remove_ep( 221 &instance->lists[ep->transfer_type], hcd_ep); 222 instance->registers->control |= C_BLE; 223 break; 224 case USB_TRANSFER_ISOCHRONOUS: 225 case USB_TRANSFER_INTERRUPT: 226 instance->registers->control &= (~C_PLE & ~C_IE); 227 endpoint_list_remove_ep( 228 &instance->lists[ep->transfer_type], hcd_ep); 229 instance->registers->control |= C_PLE | C_IE; 230 break; 231 default: 232 break; 233 } 234 hcd_endpoint_clear(ep); 235 } else { 236 usb_log_warning("Endpoint without hcd equivalent structure.\n"); 237 } 238 int ret = usb_endpoint_manager_unregister_ep(&instance->ep_manager, 239 address, endpoint, direction); 240 fibril_mutex_unlock(&instance->guard); 241 return ret; 242 } 243 /*----------------------------------------------------------------------------*/ 244 endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address, 245 usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw) 246 { 247 assert(instance); 248 fibril_mutex_lock(&instance->guard); 249 endpoint_t *ep = usb_endpoint_manager_get_ep(&instance->ep_manager, 250 address, endpoint, direction, bw); 251 fibril_mutex_unlock(&instance->guard); 252 return ep; 134 253 } 135 254 /*----------------------------------------------------------------------------*/ … … 146 265 147 266 fibril_mutex_lock(&instance->guard); 267 list_append(&batch->link, &instance->pending_batches); 268 batch_commit(batch); 148 269 switch (batch->ep->transfer_type) { 149 270 case USB_TRANSFER_CONTROL: 150 instance->registers->control &= ~C_CLE;151 transfer_list_add_batch(152 instance->transfers[batch->ep->transfer_type], batch);153 271 instance->registers->command_status |= CS_CLF; 154 usb_log_debug2("Set CS control transfer filled: %x.\n",155 instance->registers->command_status);156 instance->registers->control_current = 0;157 instance->registers->control |= C_CLE;158 272 break; 159 273 case USB_TRANSFER_BULK: 160 instance->registers->control &= ~C_BLE;161 transfer_list_add_batch(162 instance->transfers[batch->ep->transfer_type], batch);163 274 instance->registers->command_status |= CS_BLF; 164 usb_log_debug2("Set bulk transfer filled: %x.\n",165 instance->registers->command_status);166 instance->registers->control |= C_BLE;167 break;168 case USB_TRANSFER_INTERRUPT:169 case USB_TRANSFER_ISOCHRONOUS:170 instance->registers->control &= (~C_PLE & ~C_IE);171 transfer_list_add_batch(172 instance->transfers[batch->ep->transfer_type], batch);173 instance->registers->control |= C_PLE | C_IE;174 usb_log_debug2("Added periodic transfer: %x.\n",175 instance->registers->periodic_current);176 275 break; 177 276 default: 178 277 break; 179 278 } 279 180 280 fibril_mutex_unlock(&instance->guard); 181 281 return EOK; … … 198 298 usb_log_debug2("Periodic current: %p.\n", 199 299 instance->registers->periodic_current); 200 LIST_INITIALIZE(done); 201 transfer_list_remove_finished( 202 &instance->transfers_interrupt, &done); 203 transfer_list_remove_finished( 204 &instance->transfers_isochronous, &done); 205 transfer_list_remove_finished( 206 &instance->transfers_control, &done); 207 transfer_list_remove_finished( 208 &instance->transfers_bulk, &done); 209 210 while (!list_empty(&done)) { 211 link_t *item = done.next; 212 list_remove(item); 300 301 link_t *current = instance->pending_batches.next; 302 while (current != &instance->pending_batches) { 303 link_t *next = current->next; 213 304 usb_transfer_batch_t *batch = 214 list_get_instance(item, usb_transfer_batch_t, link); 215 usb_transfer_batch_finish(batch); 305 usb_transfer_batch_from_link(current); 306 307 if (batch_is_complete(batch)) { 308 list_remove(current); 309 usb_transfer_batch_finish(batch); 310 } 311 current = next; 216 312 } 217 313 fibril_mutex_unlock(&instance->guard); … … 307 403 308 404 /* Use queues */ 309 instance->registers->bulk_head = instance->transfers_bulk.list_head_pa; 405 instance->registers->bulk_head = 406 instance->lists[USB_TRANSFER_BULK].list_head_pa; 310 407 usb_log_debug2("Bulk HEAD set to: %p(%p).\n", 311 instance-> transfers_bulk.list_head,312 instance-> transfers_bulk.list_head_pa);408 instance->lists[USB_TRANSFER_BULK].list_head, 409 instance->lists[USB_TRANSFER_BULK].list_head_pa); 313 410 314 411 instance->registers->control_head = 315 instance-> transfers_control.list_head_pa;412 instance->lists[USB_TRANSFER_CONTROL].list_head_pa; 316 413 usb_log_debug2("Control HEAD set to: %p(%p).\n", 317 instance-> transfers_control.list_head,318 instance-> transfers_control.list_head_pa);414 instance->lists[USB_TRANSFER_CONTROL].list_head, 415 instance->lists[USB_TRANSFER_CONTROL].list_head_pa); 319 416 320 417 /* Enable queues */ … … 347 444 assert(instance); 348 445 349 #define SETUP_ TRANSFER_LIST(type, name) \446 #define SETUP_ENDPOINT_LIST(type) \ 350 447 do { \ 351 int ret = transfer_list_init(&instance->type, name); \ 448 const char *name = usb_str_transfer_type(type); \ 449 int ret = endpoint_list_init(&instance->lists[type], name); \ 352 450 if (ret != EOK) { \ 353 usb_log_error("Failed(%d) to setup %s transferlist.\n", \451 usb_log_error("Failed(%d) to setup %s endpoint list.\n", \ 354 452 ret, name); \ 355 transfer_list_fini(&instance->transfers_isochronous); \356 transfer_list_fini(&instance->transfers_interrupt); \357 transfer_list_fini(&instance->transfers_control); \358 transfer_list_fini(&instance->transfers_bulk); \453 endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \ 454 endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \ 455 endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \ 456 endpoint_list_fini(&instance->lists[USB_TRANSFER_BULK]); \ 359 457 } \ 360 458 } while (0) 361 459 362 SETUP_TRANSFER_LIST(transfers_isochronous, "ISOCHRONOUS"); 363 SETUP_TRANSFER_LIST(transfers_interrupt, "INTERRUPT"); 364 SETUP_TRANSFER_LIST(transfers_control, "CONTROL"); 365 SETUP_TRANSFER_LIST(transfers_bulk, "BULK"); 366 #undef SETUP_TRANSFER_LIST 367 transfer_list_set_next(&instance->transfers_interrupt, 368 &instance->transfers_isochronous); 369 370 /* Assign pointers to be used during scheduling */ 371 instance->transfers[USB_TRANSFER_INTERRUPT] = 372 &instance->transfers_interrupt; 373 instance->transfers[USB_TRANSFER_ISOCHRONOUS] = 374 &instance->transfers_interrupt; 375 instance->transfers[USB_TRANSFER_CONTROL] = 376 &instance->transfers_control; 377 instance->transfers[USB_TRANSFER_BULK] = 378 &instance->transfers_bulk; 460 SETUP_ENDPOINT_LIST(USB_TRANSFER_ISOCHRONOUS); 461 SETUP_ENDPOINT_LIST(USB_TRANSFER_INTERRUPT); 462 SETUP_ENDPOINT_LIST(USB_TRANSFER_CONTROL); 463 SETUP_ENDPOINT_LIST(USB_TRANSFER_BULK); 464 #undef SETUP_ENDPOINT_LIST 465 endpoint_list_set_next(&instance->lists[USB_TRANSFER_INTERRUPT], 466 &instance->lists[USB_TRANSFER_ISOCHRONOUS]); 379 467 380 468 return EOK; … … 397 485 for (; i < 32; ++i) { 398 486 instance->hcca->int_ep[i] = 399 instance-> transfers_interrupt.list_head_pa;487 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa; 400 488 } 401 489 usb_log_debug2("Interrupt HEADs set to: %p(%p).\n", 402 instance-> transfers_interrupt.list_head,403 instance-> transfers_interrupt.list_head_pa);490 instance->lists[USB_TRANSFER_INTERRUPT].list_head, 491 instance->lists[USB_TRANSFER_INTERRUPT].list_head_pa); 404 492 405 493 return EOK; -
uspace/drv/ohci/hc.h
r4deca9b r651b352 48 48 #include "ohci_regs.h" 49 49 #include "root_hub.h" 50 #include " transfer_list.h"50 #include "endpoint_list.h" 51 51 #include "hw_struct/hcca.h" 52 52 53 53 typedef struct hc { 54 54 ohci_regs_t *registers; 55 hcca_t *hcca; 56 55 57 usb_address_t rh_address; 56 58 rh_t rh; 57 59 58 hcca_t *hcca; 60 endpoint_list_t lists[4]; 61 link_t pending_batches; 59 62 60 transfer_list_t transfers_isochronous;61 transfer_list_t transfers_interrupt;62 transfer_list_t transfers_control;63 transfer_list_t transfers_bulk;64 65 transfer_list_t *transfers[4];66 67 ddf_fun_t *ddf_instance;68 63 usb_device_keeper_t manager; 69 64 usb_endpoint_manager_t ep_manager; … … 77 72 uintptr_t regs, size_t reg_size, bool interrupts); 78 73 79 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch);80 81 void hc_interrupt(hc_t *instance, uint32_t status);82 83 74 /** Safely dispose host controller internal structures 84 75 * … … 86 77 */ 87 78 static inline void hc_fini(hc_t *instance) { /* TODO: implement*/ }; 79 80 int hc_add_endpoint(hc_t *instance, usb_address_t address, usb_endpoint_t ep, 81 usb_speed_t speed, usb_transfer_type_t type, usb_direction_t direction, 82 size_t max_packet_size, size_t size, unsigned interval); 83 84 int hc_remove_endpoint(hc_t *instance, usb_address_t address, 85 usb_endpoint_t endpoint, usb_direction_t direction); 86 87 endpoint_t * hc_get_endpoint(hc_t *instance, usb_address_t address, 88 usb_endpoint_t endpoint, usb_direction_t direction, size_t *bw); 89 90 int hc_schedule(hc_t *instance, usb_transfer_batch_t *batch); 91 92 void hc_interrupt(hc_t *instance, uint32_t status); 88 93 89 94 /** Get and cast pointer to the driver data -
uspace/drv/ohci/hw_struct/endpoint_descriptor.h
r4deca9b r651b352 81 81 void ed_init(ed_t *instance, endpoint_t *ep); 82 82 83 static inline void ed_ add_tds(ed_t *instance, td_t *head, td_t *tail)83 static inline void ed_set_td(ed_t *instance, td_t *td) 84 84 { 85 85 assert(instance); 86 uintptr_t pa = addr_to_phys(td); 86 87 instance->td_head = 87 (( addr_to_phys(head)& ED_TDHEAD_PTR_MASK)88 ((pa & ED_TDHEAD_PTR_MASK) 88 89 | (instance->td_head & ~ED_TDHEAD_PTR_MASK)); 89 instance->td_tail = addr_to_phys(tail) & ED_TDTAIL_PTR_MASK; 90 instance->td_tail = pa & ED_TDTAIL_PTR_MASK; 91 } 92 93 static inline void ed_set_end_td(ed_t *instance, td_t *td) 94 { 95 assert(instance); 96 uintptr_t pa = addr_to_phys(td); 97 instance->td_tail = pa & ED_TDTAIL_PTR_MASK; 90 98 } 91 99 -
uspace/drv/ohci/iface.c
r4deca9b r651b352 55 55 56 56 size_t res_bw; 57 endpoint_t *ep = usb_endpoint_manager_get_ep(&(*hc)->ep_manager,57 endpoint_t *ep = hc_get_endpoint(*hc, 58 58 target.address, target.endpoint, direction, &res_bw); 59 59 if (ep == NULL) { … … 164 164 } 165 165 const size_t size = max_packet_size; 166 int ret;167 166 168 167 usb_log_debug("Register endpoint %d:%d %s %s(%d) %zu(%zu) %u.\n", … … 170 169 usb_str_speed(speed), direction, size, max_packet_size, interval); 171 170 172 endpoint_t *ep = malloc(sizeof(endpoint_t)); 173 if (ep == NULL) 174 return ENOMEM; 175 ret = endpoint_init(ep, address, endpoint, direction, 176 transfer_type, speed, max_packet_size); 177 if (ret != EOK) { 178 free(ep); 179 return ret; 180 } 181 182 ret = usb_endpoint_manager_register_ep(&hc->ep_manager, ep, size); 183 if (ret != EOK) { 184 endpoint_destroy(ep); 185 } 186 return ret; 171 return hc_add_endpoint(hc, address, endpoint, speed, transfer_type, 172 direction, max_packet_size, size, interval); 187 173 } 188 174 /*----------------------------------------------------------------------------*/ … … 195 181 usb_log_debug("Unregister endpoint %d:%d %d.\n", 196 182 address, endpoint, direction); 197 return usb_endpoint_manager_unregister_ep(&hc->ep_manager, address, 198 endpoint, direction); 183 return hc_remove_endpoint(hc, address, endpoint, direction); 199 184 } 200 185 /*----------------------------------------------------------------------------*/ … … 228 213 ret = hc_schedule(hc, batch); 229 214 if (ret != EOK) { 230 batch_dispose(batch);215 usb_transfer_batch_dispose(batch); 231 216 } 232 217 return ret; … … 262 247 ret = hc_schedule(hc, batch); 263 248 if (ret != EOK) { 264 batch_dispose(batch);249 usb_transfer_batch_dispose(batch); 265 250 } 266 251 return ret; … … 296 281 ret = hc_schedule(hc, batch); 297 282 if (ret != EOK) { 298 batch_dispose(batch);283 usb_transfer_batch_dispose(batch); 299 284 } 300 285 return ret; … … 330 315 ret = hc_schedule(hc, batch); 331 316 if (ret != EOK) { 332 batch_dispose(batch);317 usb_transfer_batch_dispose(batch); 333 318 } 334 319 return ret; … … 346 331 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 347 332 * and deallocated by the caller). 348 * @param[in] setup_ packet_size Size of @p setup_packet buffer in bytes.333 * @param[in] setup_size Size of @p setup_packet buffer in bytes. 349 334 * @param[in] data_buffer Data buffer (in USB endianess, allocated and 350 335 * deallocated by the caller). 351 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.336 * @param[in] size Size of @p data_buffer buffer in bytes. 352 337 * @param[in] callback Callback to be issued once the transfer is complete. 353 338 * @param[in] arg Pass-through argument to the callback. … … 370 355 ret = hc_schedule(hc, batch); 371 356 if (ret != EOK) { 372 batch_dispose(batch);357 usb_transfer_batch_dispose(batch); 373 358 } 374 359 return ret; … … 386 371 * @param[in] setup_packet Setup packet buffer (in USB endianess, allocated 387 372 * and deallocated by the caller). 388 * @param[in] setup_ packet_size Size of @p setup_packet buffer in bytes.373 * @param[in] setup_size Size of @p setup_packet buffer in bytes. 389 374 * @param[in] data_buffer Buffer where to store the data (in USB endianess, 390 375 * allocated and deallocated by the caller). 391 * @param[in] data_buffer_size Size of @p data_buffer buffer in bytes.376 * @param[in] size Size of @p data_buffer buffer in bytes. 392 377 * @param[in] callback Callback to be issued once the transfer is complete. 393 378 * @param[in] arg Pass-through argument to the callback. … … 409 394 ret = hc_schedule(hc, batch); 410 395 if (ret != EOK) { 411 batch_dispose(batch);396 usb_transfer_batch_dispose(batch); 412 397 } 413 398 return ret; -
uspace/drv/uhci-hcd/batch.c
r4deca9b r651b352 45 45 #define DEFAULT_ERROR_COUNT 3 46 46 47 typedef struct uhci_ batch {47 typedef struct uhci_transfer_batch { 48 48 qh_t *qh; 49 49 td_t *tds; 50 void *device_buffer; 50 51 size_t td_count; 51 } uhci_batch_t; 52 } uhci_transfer_batch_t; 53 /*----------------------------------------------------------------------------*/ 54 static 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 /*----------------------------------------------------------------------------*/ 52 62 53 63 static void batch_control(usb_transfer_batch_t *instance, 54 64 usb_packet_id data_stage, usb_packet_id status_stage); 55 65 static 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 59 66 60 67 /** Allocate memory and initialize internal data structure. … … 88 95 if (ptr == NULL) { \ 89 96 usb_log_error(message); \ 90 if ( instance) { \91 batch_dispose(instance); \97 if (uhci_data) { \ 98 uhci_transfer_batch_dispose(uhci_data); \ 92 99 } \ 93 100 return NULL; \ 94 101 } else (void)0 95 102 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, addr_to_phys(uhci_data->tds)); 129 96 130 usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t)); 97 131 CHECK_NULL_DISPOSE_RETURN(instance, 98 132 "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; 99 137 usb_target_t target = 100 138 { .address = ep->address, .endpoint = ep->endpoint }; 101 usb_transfer_batch_init(instance, ep, 102 buffer, NULL, buffer_size, NULL, setup_size, 103 func_in, func_out, arg, fun, NULL); 104 105 106 uhci_batch_t *data = malloc(sizeof(uhci_batch_t)); 107 CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n"); 108 bzero(data, sizeof(uhci_batch_t)); 109 instance->private_data = data; 110 111 data->td_count = 112 (buffer_size + ep->max_packet_size - 1) / ep->max_packet_size; 113 if (ep->transfer_type == USB_TRANSFER_CONTROL) { 114 data->td_count += 2; 115 } 116 117 data->tds = malloc32(sizeof(td_t) * data->td_count); 118 CHECK_NULL_DISPOSE_RETURN( 119 data->tds, "Failed to allocate transfer descriptors.\n"); 120 bzero(data->tds, sizeof(td_t) * data->td_count); 121 122 data->qh = malloc32(sizeof(qh_t)); 123 CHECK_NULL_DISPOSE_RETURN(data->qh, 124 "Failed to allocate batch queue head.\n"); 125 qh_init(data->qh); 126 qh_set_element_td(data->qh, addr_to_phys(data->tds)); 127 128 if (buffer_size > 0) { 129 instance->data_buffer = malloc32(buffer_size); 130 CHECK_NULL_DISPOSE_RETURN(instance->data_buffer, 131 "Failed to allocate device accessible buffer.\n"); 132 } 133 134 if (setup_size > 0) { 135 instance->setup_buffer = malloc32(setup_size); 136 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer, 137 "Failed to allocate device accessible setup buffer.\n"); 138 memcpy(instance->setup_buffer, setup_buffer, setup_size); 139 } 140 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); 141 144 usb_log_debug("Batch(%p) %d:%d memory structures ready.\n", 142 145 instance, target.address, target.endpoint); … … 156 159 { 157 160 assert(instance); 158 uhci_ batch_t *data = instance->private_data;161 uhci_transfer_batch_t *data = instance->private_data; 159 162 assert(data); 160 163 … … 203 206 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 204 207 batch_control(instance, USB_PID_OUT, USB_PID_IN); 205 instance->next_step = batch_call_out_and_dispose;208 instance->next_step = usb_transfer_batch_call_out_and_dispose; 206 209 usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance); 207 210 } … … 217 220 assert(instance); 218 221 batch_control(instance, USB_PID_IN, USB_PID_OUT); 219 instance->next_step = batch_call_in_and_dispose;222 instance->next_step = usb_transfer_batch_call_in_and_dispose; 220 223 usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance); 221 224 } … … 231 234 assert(instance); 232 235 batch_data(instance, USB_PID_IN); 233 instance->next_step = batch_call_in_and_dispose;236 instance->next_step = usb_transfer_batch_call_in_and_dispose; 234 237 usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance); 235 238 } … … 247 250 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 248 251 batch_data(instance, USB_PID_OUT); 249 instance->next_step = batch_call_out_and_dispose;252 instance->next_step = usb_transfer_batch_call_out_and_dispose; 250 253 usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance); 251 254 } … … 261 264 assert(instance); 262 265 batch_data(instance, USB_PID_IN); 263 instance->next_step = batch_call_in_and_dispose;266 instance->next_step = usb_transfer_batch_call_in_and_dispose; 264 267 usb_log_debug("Batch(%p) BULK IN initialized.\n", instance); 265 268 } … … 277 280 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 278 281 batch_data(instance, USB_PID_OUT); 279 instance->next_step = batch_call_out_and_dispose;282 instance->next_step = usb_transfer_batch_call_out_and_dispose; 280 283 usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance); 281 284 } … … 292 295 { 293 296 assert(instance); 294 uhci_ batch_t *data = instance->private_data;297 uhci_transfer_batch_t *data = instance->private_data; 295 298 assert(data); 296 299 … … 344 347 { 345 348 assert(instance); 346 uhci_ batch_t *data = instance->private_data;349 uhci_transfer_batch_t *data = instance->private_data; 347 350 assert(data); 348 351 assert(data->td_count >= 2); … … 396 399 { 397 400 assert(instance); 398 uhci_ batch_t *data = instance->private_data;401 uhci_transfer_batch_t *data = instance->private_data; 399 402 assert(data); 400 403 return data->qh; 401 404 } 402 /*----------------------------------------------------------------------------*/403 /** Helper function, calls callback and correctly destroys batch structure.404 *405 * @param[in] instance Batch structure to use.406 */407 void batch_call_in_and_dispose(usb_transfer_batch_t *instance)408 {409 assert(instance);410 usb_transfer_batch_call_in(instance);411 batch_dispose(instance);412 }413 /*----------------------------------------------------------------------------*/414 /** Helper function calls callback and correctly destroys batch structure.415 *416 * @param[in] instance Batch structure to use.417 */418 void batch_call_out_and_dispose(usb_transfer_batch_t *instance)419 {420 assert(instance);421 usb_transfer_batch_call_out(instance);422 batch_dispose(instance);423 }424 /*----------------------------------------------------------------------------*/425 /** Correctly dispose all used data structures.426 *427 * @param[in] instance Batch structure to use.428 */429 void batch_dispose(usb_transfer_batch_t *instance)430 {431 assert(instance);432 uhci_batch_t *data = instance->private_data;433 assert(data);434 usb_log_debug("Batch(%p) disposing.\n", instance);435 /* free32 is NULL safe */436 free32(data->tds);437 free32(data->qh);438 free32(instance->setup_buffer);439 free32(instance->data_buffer);440 free(data);441 free(instance);442 }443 405 /** 444 406 * @} -
uspace/drv/uhci-hcd/iface.c
r4deca9b r651b352 195 195 ret = hc_schedule(hc, batch); 196 196 if (ret != EOK) { 197 batch_dispose(batch);197 usb_transfer_batch_dispose(batch); 198 198 } 199 199 return ret; … … 223 223 ret = hc_schedule(hc, batch); 224 224 if (ret != EOK) { 225 batch_dispose(batch);225 usb_transfer_batch_dispose(batch); 226 226 } 227 227 return ret; … … 251 251 ret = hc_schedule(hc, batch); 252 252 if (ret != EOK) { 253 batch_dispose(batch);253 usb_transfer_batch_dispose(batch); 254 254 } 255 255 return ret; … … 279 279 ret = hc_schedule(hc, batch); 280 280 if (ret != EOK) { 281 batch_dispose(batch);281 usb_transfer_batch_dispose(batch); 282 282 } 283 283 return ret; … … 312 312 ret = hc_schedule(hc, batch); 313 313 if (ret != EOK) { 314 batch_dispose(batch);314 usb_transfer_batch_dispose(batch); 315 315 } 316 316 return ret; … … 344 344 ret = hc_schedule(hc, batch); 345 345 if (ret != EOK) { 346 batch_dispose(batch);346 usb_transfer_batch_dispose(batch); 347 347 } 348 348 return ret; -
uspace/lib/usb/include/usb/host/batch.h
r4deca9b r651b352 58 58 ddf_fun_t *fun; 59 59 void *private_data; 60 void (*private_data_dtor)(void *p_data); 60 61 }; 61 62 62 63 void usb_transfer_batch_init( 63 64 usb_transfer_batch_t *instance, 64 65 endpoint_t *ep, 65 66 char *buffer, 66 67 char *data_buffer, … … 72 73 void *arg, 73 74 ddf_fun_t *fun, 74 void *private_data 75 void *private_data, 76 void (*private_data_dtor)(void *p_data) 75 77 ); 76 78 77 static inline usb_transfer_batch_t *usb_transfer_batch_from_link(link_t *l) 78 { 79 assert(l); 80 return list_get_instance(l, usb_transfer_batch_t, link); 81 } 82 83 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance); 84 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance); 79 void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance); 80 void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance); 85 81 void usb_transfer_batch_finish(usb_transfer_batch_t *instance); 82 void usb_transfer_batch_dispose(usb_transfer_batch_t *instance); 86 83 87 84 static inline void usb_transfer_batch_finish_error( … … 93 90 } 94 91 92 static inline usb_transfer_batch_t *usb_transfer_batch_from_link(link_t *l) 93 { 94 assert(l); 95 return list_get_instance(l, usb_transfer_batch_t, link); 96 } 97 95 98 #endif 96 99 /** -
uspace/lib/usb/include/usb/host/endpoint.h
r4deca9b r651b352 54 54 fibril_condvar_t avail; 55 55 volatile bool active; 56 struct { 57 void *data; 58 int (*toggle_get)(void *); 59 void (*toggle_set)(void *, int); 60 } hc_data; 56 61 } endpoint_t; 57 62 … … 61 66 62 67 void endpoint_destroy(endpoint_t *instance); 68 69 void endpoint_set_hc_data(endpoint_t *instance, 70 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)); 71 72 void endpoint_clear_hc_data(endpoint_t *instance); 63 73 64 74 void endpoint_use(endpoint_t *instance); -
uspace/lib/usb/src/host/batch.c
r4deca9b r651b352 39 39 #include <usb/host/batch.h> 40 40 41 void usb_transfer_batch_call_in(usb_transfer_batch_t *instance); 42 void usb_transfer_batch_call_out(usb_transfer_batch_t *instance); 43 41 44 void usb_transfer_batch_init( 42 45 usb_transfer_batch_t *instance, 43 46 endpoint_t *ep, 44 47 char *buffer, 45 48 char *data_buffer, … … 51 54 void *arg, 52 55 ddf_fun_t *fun, 53 void *private_data 56 void *private_data, 57 void (*private_data_dtor)(void *p_data) 54 58 ) 55 59 { … … 67 71 instance->fun = fun; 68 72 instance->private_data = private_data; 73 instance->private_data_dtor = private_data_dtor; 69 74 instance->transfered_size = 0; 70 75 instance->next_step = NULL; 71 76 instance->error = EOK; 72 77 endpoint_use(instance->ep); 78 } 79 /*----------------------------------------------------------------------------*/ 80 /** Helper function, calls callback and correctly destroys batch structure. 81 * 82 * @param[in] instance Batch structure to use. 83 */ 84 void usb_transfer_batch_call_in_and_dispose(usb_transfer_batch_t *instance) 85 { 86 assert(instance); 87 usb_transfer_batch_call_in(instance); 88 usb_transfer_batch_dispose(instance); 89 } 90 /*----------------------------------------------------------------------------*/ 91 /** Helper function calls callback and correctly destroys batch structure. 92 * 93 * @param[in] instance Batch structure to use. 94 */ 95 void usb_transfer_batch_call_out_and_dispose(usb_transfer_batch_t *instance) 96 { 97 assert(instance); 98 usb_transfer_batch_call_out(instance); 99 usb_transfer_batch_dispose(instance); 73 100 } 74 101 /*----------------------------------------------------------------------------*/ … … 129 156 instance->error, instance->arg); 130 157 } 158 /*----------------------------------------------------------------------------*/ 159 /** Correctly dispose all used data structures. 160 * 161 * @param[in] instance Batch structure to use. 162 */ 163 void usb_transfer_batch_dispose(usb_transfer_batch_t *instance) 164 { 165 assert(instance); 166 usb_log_debug("Batch(%p) disposing.\n", instance); 167 if (instance->private_data) { 168 assert(instance->private_data_dtor); 169 instance->private_data_dtor(instance->private_data); 170 } 171 free(instance); 172 } 131 173 /** 132 174 * @} -
uspace/lib/usb/src/host/endpoint.c
r4deca9b r651b352 63 63 } 64 64 /*----------------------------------------------------------------------------*/ 65 void endpoint_set_hc_data(endpoint_t *instance, 66 void *data, int (*toggle_get)(void *), void (*toggle_set)(void *, int)) 67 { 68 assert(instance); 69 instance->hc_data.data = data; 70 instance->hc_data.toggle_get = toggle_get; 71 instance->hc_data.toggle_set = toggle_set; 72 } 73 /*----------------------------------------------------------------------------*/ 74 void endpoint_clear_hc_data(endpoint_t *instance) 75 { 76 assert(instance); 77 instance->hc_data.data = NULL; 78 instance->hc_data.toggle_get = NULL; 79 instance->hc_data.toggle_set = NULL; 80 } 81 /*----------------------------------------------------------------------------*/ 65 82 void endpoint_use(endpoint_t *instance) 66 83 { … … 85 102 { 86 103 assert(instance); 104 if (instance->hc_data.toggle_get) 105 instance->toggle = 106 instance->hc_data.toggle_get(instance->hc_data.data); 87 107 return (int)instance->toggle; 88 108 } … … 92 112 assert(instance); 93 113 assert(toggle == 0 || toggle == 1); 114 if (instance->hc_data.toggle_set) 115 instance->hc_data.toggle_set(instance->hc_data.data, toggle); 94 116 instance->toggle = toggle; 95 117 }
Note:
See TracChangeset
for help on using the changeset viewer.