Changeset 9c10e51 in mainline
- Timestamp:
- 2011-08-31T22:50:21Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 4e9ecf4
- Parents:
- f18d82f0
- Location:
- uspace/drv/bus/usb/ohci
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/ohci/hc.c
rf18d82f0 r9c10e51 289 289 { 290 290 assert(hcd); 291 batch_init_ohci(batch);292 291 hc_t *instance = hcd->private_data; 293 292 assert(instance); … … 298 297 return EOK; 299 298 } 299 ohci_transfer_batch_t *ohci_batch = ohci_transfer_batch_get(batch); 300 if (!ohci_batch) 301 return ENOMEM; 300 302 301 303 fibril_mutex_lock(&instance->guard); 302 list_append(& batch->link, &instance->pending_batches);303 batch_commit(batch);304 list_append(&ohci_batch->link, &instance->pending_batches); 305 ohci_transfer_batch_commit(ohci_batch); 304 306 305 307 /* Control and bulk schedules need a kick to start working */ … … 341 343 instance->registers->periodic_current); 342 344 343 link_t *current = instance->pending_batches.head.next;344 while (current != &instance->pending_batches.head) {345 link_t *current = list_first(&instance->pending_batches); 346 while (current && current != &instance->pending_batches.head) { 345 347 link_t *next = current->next; 346 usb_transfer_batch_t *batch =347 usb_transfer_batch_from_link(current);348 349 if ( batch_is_complete(batch)) {348 ohci_transfer_batch_t *batch = 349 ohci_transfer_batch_from_link(current); 350 351 if (ohci_transfer_batch_is_complete(batch)) { 350 352 list_remove(current); 351 usb_transfer_batch_finish(batch);353 ohci_transfer_batch_finish_dispose(batch); 352 354 } 353 355 -
uspace/drv/bus/usb/ohci/ohci_batch.c
rf18d82f0 r9c10e51 41 41 #include "ohci_endpoint.h" 42 42 #include "utils/malloc32.h" 43 #include "hw_struct/endpoint_descriptor.h" 44 #include "hw_struct/transfer_descriptor.h" 45 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) 43 44 static void control_write(ohci_transfer_batch_t *instance); 45 static void control_read(ohci_transfer_batch_t *instance); 46 47 static void interrupt_in(ohci_transfer_batch_t *instance); 48 static void interrupt_out(ohci_transfer_batch_t *instance); 49 50 static void bulk_in(ohci_transfer_batch_t *instance); 51 static void bulk_out(ohci_transfer_batch_t *instance); 52 53 static void setup_control(ohci_transfer_batch_t *ohci_batch) 56 54 { 57 55 // TODO Find a better way to do this 58 if ( batch->setup_buffer[0] & (1 << 7))59 batch_control_read(batch);56 if (ohci_batch->device_buffer[0] & (1 << 7)) 57 control_read(ohci_batch); 60 58 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 }, 59 control_write(ohci_batch); 60 } 61 /*----------------------------------------------------------------------------*/ 62 static void batch_control(ohci_transfer_batch_t *instance, 63 usb_direction_t data_dir, usb_direction_t status_dir); 64 static void batch_data(ohci_transfer_batch_t *instance); 65 /*----------------------------------------------------------------------------*/ 66 void (*batch_setup[4][3])(ohci_transfer_batch_t*) = 67 { 68 { NULL, NULL, setup_control }, 67 69 { NULL, NULL, NULL }, 68 { b atch_bulk_in, batch_bulk_out, NULL },69 { batch_interrupt_in, batch_interrupt_out, NULL },70 { bulk_in, bulk_out, NULL }, 71 { interrupt_in, interrupt_out, NULL }, 70 72 }; 71 72 73 /** OHCI specific data required for USB transfer */74 typedef struct ohci_transfer_batch {75 /** Endpoint descriptor of the target endpoint. */76 ed_t *ed;77 /** List of TDs needed for the transfer */78 td_t **tds;79 /** Number of TDs used by the transfer */80 size_t td_count;81 /** Dummy TD to be left at the ED and used by the next transfer */82 size_t leave_td;83 /** Data buffer, must be accessible byb the OHCI hw. */84 void *device_buffer;85 } ohci_transfer_batch_t;86 /*----------------------------------------------------------------------------*/87 static void batch_control(usb_transfer_batch_t *instance,88 usb_direction_t data_dir, usb_direction_t status_dir);89 static void batch_data(usb_transfer_batch_t *instance);90 73 /*----------------------------------------------------------------------------*/ 91 74 /** Safely destructs ohci_transfer_batch_t structure … … 93 76 * @param[in] ohci_batch Instance to destroy. 94 77 */ 95 static void ohci_batch_dispose(void *ohci_batch) 96 { 97 ohci_transfer_batch_t *instance = ohci_batch; 98 if (!instance) 78 static void ohci_transfer_batch_dispose(ohci_transfer_batch_t *ohci_batch) 79 { 80 if (!ohci_batch) 99 81 return; 100 82 unsigned i = 0; 101 if ( instance->tds) {102 for (; i< instance->td_count; ++i) {103 if (i != instance->leave_td)104 free32( instance->tds[i]);83 if (ohci_batch->tds) { 84 for (; i< ohci_batch->td_count; ++i) { 85 if (i != ohci_batch->leave_td) 86 free32(ohci_batch->tds[i]); 105 87 } 106 free(instance->tds); 107 } 108 free32(instance->device_buffer); 109 free(instance); 110 } 111 /*----------------------------------------------------------------------------*/ 112 int batch_init_ohci(usb_transfer_batch_t *batch) 113 { 114 assert(batch); 115 #define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \ 116 if (ptr == NULL) { \ 117 usb_log_error(message); \ 118 if (data) { \ 119 ohci_batch_dispose(data); \ 120 } \ 121 return ENOMEM; \ 122 } else (void)0 123 124 ohci_transfer_batch_t *data = calloc(sizeof(ohci_transfer_batch_t), 1); 125 CHECK_NULL_DISPOSE_RETURN(data, "Failed to allocate batch data.\n"); 126 127 data->td_count = ((batch->buffer_size + OHCI_TD_MAX_TRANSFER - 1) 128 / OHCI_TD_MAX_TRANSFER); 88 free(ohci_batch->tds); 89 } 90 usb_transfer_batch_dispose(ohci_batch->usb_batch); 91 free32(ohci_batch->device_buffer); 92 free(ohci_batch); 93 } 94 /*----------------------------------------------------------------------------*/ 95 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *ohci_batch) 96 { 97 assert(ohci_batch); 98 assert(ohci_batch->usb_batch); 99 usb_transfer_batch_finish(ohci_batch->usb_batch, 100 ohci_batch->device_buffer + ohci_batch->usb_batch->setup_size, 101 ohci_batch->usb_batch->buffer_size); 102 ohci_transfer_batch_dispose(ohci_batch); 103 } 104 /*----------------------------------------------------------------------------*/ 105 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *usb_batch) 106 { 107 assert(usb_batch); 108 #define CHECK_NULL_DISPOSE_RET(ptr, message...) \ 109 if (ptr == NULL) { \ 110 usb_log_error(message); \ 111 ohci_transfer_batch_dispose(ohci_batch); \ 112 return NULL; \ 113 } else (void)0 114 115 ohci_transfer_batch_t *ohci_batch = 116 calloc(sizeof(ohci_transfer_batch_t), 1); 117 CHECK_NULL_DISPOSE_RET(ohci_batch, 118 "Failed to allocate OHCI batch data.\n"); 119 120 ohci_batch->td_count = 121 (usb_batch->buffer_size + OHCI_TD_MAX_TRANSFER - 1) 122 / OHCI_TD_MAX_TRANSFER; 129 123 /* Control transfer need Setup and Status stage */ 130 if ( batch->ep->transfer_type == USB_TRANSFER_CONTROL) {131 data->td_count += 2;124 if (usb_batch->ep->transfer_type == USB_TRANSFER_CONTROL) { 125 ohci_batch->td_count += 2; 132 126 } 133 127 134 128 /* We need an extra place for TD that was left at ED */ 135 data->tds = calloc(sizeof(td_t*), data->td_count + 1);136 CHECK_NULL_DISPOSE_RET URN(data->tds,137 "Failed to allocate transfer descriptors.\n");129 ohci_batch->tds = calloc(ohci_batch->td_count + 1, sizeof(td_t*)); 130 CHECK_NULL_DISPOSE_RET(ohci_batch->tds, 131 "Failed to allocate OHCI transfer descriptors.\n"); 138 132 139 133 /* Add TD left over by the previous transfer */ 140 data->ed = ohci_endpoint_get(batch->ep)->ed;141 data->tds[0] = ohci_endpoint_get(batch->ep)->td;142 data->leave_td = 0;134 ohci_batch->ed = ohci_endpoint_get(usb_batch->ep)->ed; 135 ohci_batch->tds[0] = ohci_endpoint_get(usb_batch->ep)->td; 136 ohci_batch->leave_td = 0; 143 137 unsigned i = 1; 144 for (; i <= data->td_count; ++i) {145 data->tds[i] = malloc32(sizeof(td_t));146 CHECK_NULL_DISPOSE_RET URN(data->tds[i],138 for (; i <= ohci_batch->td_count; ++i) { 139 ohci_batch->tds[i] = malloc32(sizeof(td_t)); 140 CHECK_NULL_DISPOSE_RET(ohci_batch->tds[i], 147 141 "Failed to allocate TD %d.\n", i ); 148 142 } … … 153 147 * than two pages (the first page is computed using start pointer, the 154 148 * other using the end pointer) */ 155 if (batch->setup_size + batch->buffer_size > 0) { 156 data->device_buffer = 157 malloc32(batch->setup_size + batch->buffer_size); 158 CHECK_NULL_DISPOSE_RETURN(data->device_buffer, 149 if (usb_batch->setup_size + usb_batch->buffer_size > 0) { 150 /* Use one buffer for setup and data stage */ 151 ohci_batch->device_buffer = 152 malloc32(usb_batch->setup_size + usb_batch->buffer_size); 153 CHECK_NULL_DISPOSE_RET(ohci_batch->device_buffer, 159 154 "Failed to allocate device accessible buffer.\n"); 160 155 /* Copy setup data */ 161 memcpy(data->device_buffer, batch->setup_buffer, 162 batch->setup_size); 163 batch->data_buffer = data->device_buffer + batch->setup_size; 156 memcpy(ohci_batch->device_buffer, usb_batch->setup_buffer, 157 usb_batch->setup_size); 158 /* Copy generic data */ 159 if (usb_batch->ep->direction != USB_DIRECTION_IN) 160 memcpy( 161 ohci_batch->device_buffer + usb_batch->setup_size, 162 usb_batch->buffer, usb_batch->buffer_size); 164 163 } 165 166 batch->private_data = data; 167 batch->private_data_dtor = ohci_batch_dispose; 168 169 assert(batch_setup[batch->ep->transfer_type][batch->ep->direction]);170 batch_setup[batch->ep->transfer_type][batch->ep->direction](batch);171 172 return EOK;173 #undef CHECK_NULL_DISPOSE_RET URN164 ohci_batch->usb_batch = usb_batch; 165 166 assert( 167 batch_setup[usb_batch->ep->transfer_type][usb_batch->ep->direction]); 168 batch_setup[usb_batch->ep->transfer_type][usb_batch->ep->direction]( 169 ohci_batch); 170 171 return ohci_batch; 172 #undef CHECK_NULL_DISPOSE_RET 174 173 } 175 174 /*----------------------------------------------------------------------------*/ … … 183 182 * completes with the last TD. 184 183 */ 185 bool batch_is_complete(usb_transfer_batch_t *instance) 186 { 187 assert(instance); 188 ohci_transfer_batch_t *data = instance->private_data; 189 assert(data); 190 usb_log_debug("Batch(%p) checking %zu td(s) for completion.\n", 191 instance, data->td_count); 192 usb_log_debug("ED: %x:%x:%x:%x.\n", 193 data->ed->status, data->ed->td_head, data->ed->td_tail, 194 data->ed->next); 184 bool ohci_transfer_batch_is_complete(ohci_transfer_batch_t *ohci_batch) 185 { 186 assert(ohci_batch); 187 assert(ohci_batch->usb_batch); 188 189 usb_log_debug("Batch %p checking %zu td(s) for completion.\n", 190 ohci_batch->usb_batch, ohci_batch->td_count); 191 usb_log_debug2("ED: %x:%x:%x:%x.\n", 192 ohci_batch->ed->status, ohci_batch->ed->td_head, 193 ohci_batch->ed->td_tail, ohci_batch->ed->next); 194 195 195 size_t i = 0; 196 instance->transfered_size = instance->buffer_size; 197 for (; i < data->td_count; ++i) { 198 assert(data->tds[i] != NULL); 196 for (; i < ohci_batch->td_count; ++i) { 197 assert(ohci_batch->tds[i] != NULL); 199 198 usb_log_debug("TD %zu: %x:%x:%x:%x.\n", i, 200 data->tds[i]->status, data->tds[i]->cbp, data->tds[i]->next,201 data->tds[i]->be);202 if (!td_is_finished( data->tds[i])) {199 ohci_batch->tds[i]->status, ohci_batch->tds[i]->cbp, 200 ohci_batch->tds[i]->next, ohci_batch->tds[i]->be); 201 if (!td_is_finished(ohci_batch->tds[i])) { 203 202 return false; 204 203 } 205 instance->error = td_error(data->tds[i]); 206 if (instance->error != EOK) { 207 usb_log_debug("Batch(%p) found error TD(%zu):%x.\n", 208 instance, i, data->tds[i]->status); 204 ohci_batch->usb_batch->error = td_error(ohci_batch->tds[i]); 205 if (ohci_batch->usb_batch->error != EOK) { 206 usb_log_debug("Batch %p found error TD(%zu):%x.\n", 207 ohci_batch->usb_batch, i, 208 ohci_batch->tds[i]->status); 209 209 /* Make sure TD queue is empty (one TD), 210 210 * ED should be marked as halted */ 211 data->ed->td_tail =212 ( data->ed->td_head & ED_TDTAIL_PTR_MASK);211 ohci_batch->ed->td_tail = 212 (ohci_batch->ed->td_head & ED_TDTAIL_PTR_MASK); 213 213 ++i; 214 214 break; 215 215 } 216 216 } 217 data->leave_td = i; 218 assert(data->leave_td <= data->td_count); 219 220 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(instance->ep); 217 218 assert(i <= ohci_batch->td_count); 219 ohci_batch->leave_td = i; 220 221 ohci_endpoint_t *ohci_ep = ohci_endpoint_get(ohci_batch->usb_batch->ep); 221 222 assert(ohci_ep); 222 ohci_ep->td = data->tds[data->leave_td];223 ohci_ep->td = ohci_batch->tds[ohci_batch->leave_td]; 223 224 assert(i > 0); 224 for (--i;i < data->td_count; ++i) 225 instance->transfered_size -= td_remain_size(data->tds[i]); 225 ohci_batch->usb_batch->transfered_size = 226 ohci_batch->usb_batch->buffer_size; 227 for (--i;i < ohci_batch->td_count; ++i) 228 ohci_batch->usb_batch->transfered_size 229 -= td_remain_size(ohci_batch->tds[i]); 226 230 227 231 /* Clear possible ED HALT */ 228 data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG; 232 ohci_batch->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG; 233 /* just make sure that we are leaving the right TD behind */ 229 234 const uint32_t pa = addr_to_phys(ohci_ep->td); 230 assert(pa == ( data->ed->td_head & ED_TDHEAD_PTR_MASK));231 assert(pa == ( data->ed->td_tail & ED_TDTAIL_PTR_MASK));235 assert(pa == (ohci_batch->ed->td_head & ED_TDHEAD_PTR_MASK)); 236 assert(pa == (ohci_batch->ed->td_tail & ED_TDTAIL_PTR_MASK)); 232 237 233 238 return true; … … 238 243 * @param[in] instance Batch structure to use 239 244 */ 240 void batch_commit(usb_transfer_batch_t *instance) 241 { 242 assert(instance); 243 ohci_transfer_batch_t *data = instance->private_data; 244 assert(data); 245 ed_set_end_td(data->ed, data->tds[data->td_count]); 245 void ohci_transfer_batch_commit(ohci_transfer_batch_t *ohci_batch) 246 { 247 assert(ohci_batch); 248 ed_set_end_td(ohci_batch->ed, ohci_batch->tds[ohci_batch->td_count]); 246 249 } 247 250 /*----------------------------------------------------------------------------*/ … … 253 256 * IN(status stage). 254 257 */ 255 void batch_control_write(usb_transfer_batch_t *instance) 256 { 257 assert(instance); 258 /* We are data out, we are supposed to provide data */ 259 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 260 instance->next_step = usb_transfer_batch_call_out_and_dispose; 261 batch_control(instance, USB_DIRECTION_OUT, USB_DIRECTION_IN); 262 usb_log_debug("Batch(%p) CONTROL WRITE initialized.\n", instance); 258 void control_write(ohci_transfer_batch_t *ohci_batch) 259 { 260 assert(ohci_batch); 261 batch_control(ohci_batch, USB_DIRECTION_OUT, USB_DIRECTION_IN); 262 usb_log_debug("Batch %p CONTROL WRITE initialized.\n", ohci_batch); 263 263 } 264 264 /*----------------------------------------------------------------------------*/ … … 270 270 * OUT(status stage). 271 271 */ 272 void batch_control_read(usb_transfer_batch_t *instance) 273 { 274 assert(instance); 275 instance->next_step = usb_transfer_batch_call_in_and_dispose; 276 batch_control(instance, USB_DIRECTION_IN, USB_DIRECTION_OUT); 277 usb_log_debug("Batch(%p) CONTROL READ initialized.\n", instance); 272 void control_read(ohci_transfer_batch_t *ohci_batch) 273 { 274 assert(ohci_batch); 275 batch_control(ohci_batch, USB_DIRECTION_IN, USB_DIRECTION_OUT); 276 usb_log_debug("Batch %p CONTROL READ initialized.\n", ohci_batch); 278 277 } 279 278 /*----------------------------------------------------------------------------*/ … … 284 283 * Data transfer. 285 284 */ 286 void batch_interrupt_in(usb_transfer_batch_t *instance) 287 { 288 assert(instance); 289 instance->next_step = usb_transfer_batch_call_in_and_dispose; 290 batch_data(instance); 291 usb_log_debug("Batch(%p) INTERRUPT IN initialized.\n", instance); 285 void interrupt_in(ohci_transfer_batch_t *ohci_batch) 286 { 287 assert(ohci_batch); 288 batch_data(ohci_batch); 289 usb_log_debug("Batch %p INTERRUPT IN initialized.\n", ohci_batch); 292 290 } 293 291 /*----------------------------------------------------------------------------*/ … … 298 296 * Data transfer. 299 297 */ 300 void batch_interrupt_out(usb_transfer_batch_t *instance) 301 { 302 assert(instance); 303 /* We are data out, we are supposed to provide data */ 304 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 305 instance->next_step = usb_transfer_batch_call_out_and_dispose; 306 batch_data(instance); 307 usb_log_debug("Batch(%p) INTERRUPT OUT initialized.\n", instance); 298 void interrupt_out(ohci_transfer_batch_t *ohci_batch) 299 { 300 assert(ohci_batch); 301 batch_data(ohci_batch); 302 usb_log_debug("Batch %p INTERRUPT OUT initialized.\n", ohci_batch); 308 303 } 309 304 /*----------------------------------------------------------------------------*/ … … 314 309 * Data transfer. 315 310 */ 316 void batch_bulk_in(usb_transfer_batch_t *instance) 317 { 318 assert(instance); 319 instance->next_step = usb_transfer_batch_call_in_and_dispose; 320 batch_data(instance); 321 usb_log_debug("Batch(%p) BULK IN initialized.\n", instance); 311 void bulk_in(ohci_transfer_batch_t *ohci_batch) 312 { 313 assert(ohci_batch); 314 batch_data(ohci_batch); 315 usb_log_debug("Batch %p BULK IN initialized.\n", ohci_batch); 322 316 } 323 317 /*----------------------------------------------------------------------------*/ … … 328 322 * Data transfer. 329 323 */ 330 void batch_bulk_out(usb_transfer_batch_t *instance) 331 { 332 assert(instance); 333 /* We are data out, we are supposed to provide data */ 334 memcpy(instance->data_buffer, instance->buffer, instance->buffer_size); 335 instance->next_step = usb_transfer_batch_call_out_and_dispose; 336 batch_data(instance); 337 usb_log_debug("Batch(%p) BULK OUT initialized.\n", instance); 324 void bulk_out(ohci_transfer_batch_t *ohci_batch) 325 { 326 assert(ohci_batch); 327 batch_data(ohci_batch); 328 usb_log_debug("Batch %p BULK OUT initialized.\n", ohci_batch); 338 329 } 339 330 /*----------------------------------------------------------------------------*/ … … 348 339 * Status stage with toggle 1 and direction supplied by parameter. 349 340 */ 350 void batch_control( usb_transfer_batch_t *instance,341 void batch_control(ohci_transfer_batch_t *ohci_batch, 351 342 usb_direction_t data_dir, usb_direction_t status_dir) 352 343 { 353 assert( instance);354 ohci_transfer_batch_t *data = instance->private_data;355 assert(data);356 usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed,357 data->ed->status, data->ed->td_tail, data->ed->td_head,358 data->ed->next); 344 assert(ohci_batch); 345 assert(ohci_batch->usb_batch); 346 usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", ohci_batch->ed, 347 ohci_batch->ed->status, ohci_batch->ed->td_tail, 348 ohci_batch->ed->td_head, ohci_batch->ed->next); 349 359 350 int toggle = 0; 351 char* buffer = ohci_batch->device_buffer; 352 360 353 /* setup stage */ 361 td_init( data->tds[0], USB_DIRECTION_BOTH, instance->setup_buffer,362 instance->setup_size, toggle);363 td_set_next( data->tds[0], data->tds[1]);354 td_init(ohci_batch->tds[0], USB_DIRECTION_BOTH, buffer, 355 ohci_batch->usb_batch->setup_size, toggle); 356 td_set_next(ohci_batch->tds[0], ohci_batch->tds[1]); 364 357 usb_log_debug("Created CONTROL SETUP TD: %x:%x:%x:%x.\n", 365 data->tds[0]->status, data->tds[0]->cbp, data->tds[0]->next, 366 data->tds[0]->be); 358 ohci_batch->tds[0]->status, ohci_batch->tds[0]->cbp, 359 ohci_batch->tds[0]->next, ohci_batch->tds[0]->be); 360 buffer += ohci_batch->usb_batch->setup_size; 367 361 368 362 /* data stage */ 369 363 size_t td_current = 1; 370 size_t remain_size = instance->buffer_size; 371 char *buffer = instance->data_buffer; 364 size_t remain_size = ohci_batch->usb_batch->buffer_size; 372 365 while (remain_size > 0) { 373 size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER ? 366 const size_t transfer_size = 367 remain_size > OHCI_TD_MAX_TRANSFER ? 374 368 OHCI_TD_MAX_TRANSFER : remain_size; 375 369 toggle = 1 - toggle; 376 370 377 td_init( data->tds[td_current], data_dir, buffer,371 td_init(ohci_batch->tds[td_current], data_dir, buffer, 378 372 transfer_size, toggle); 379 td_set_next(data->tds[td_current], data->tds[td_current + 1]); 373 td_set_next(ohci_batch->tds[td_current], 374 ohci_batch->tds[td_current + 1]); 380 375 usb_log_debug("Created CONTROL DATA TD: %x:%x:%x:%x.\n", 381 data->tds[td_current]->status, data->tds[td_current]->cbp, 382 data->tds[td_current]->next, data->tds[td_current]->be); 376 ohci_batch->tds[td_current]->status, 377 ohci_batch->tds[td_current]->cbp, 378 ohci_batch->tds[td_current]->next, 379 ohci_batch->tds[td_current]->be); 383 380 384 381 buffer += transfer_size; 385 382 remain_size -= transfer_size; 386 assert(td_current < data->td_count - 1);383 assert(td_current < ohci_batch->td_count - 1); 387 384 ++td_current; 388 385 } 389 386 390 387 /* status stage */ 391 assert(td_current == data->td_count - 1); 392 td_init(data->tds[td_current], status_dir, NULL, 0, 1); 393 td_set_next(data->tds[td_current], data->tds[td_current + 1]); 388 assert(td_current == ohci_batch->td_count - 1); 389 td_init(ohci_batch->tds[td_current], status_dir, NULL, 0, 1); 390 td_set_next(ohci_batch->tds[td_current], 391 ohci_batch->tds[td_current + 1]); 394 392 usb_log_debug("Created CONTROL STATUS TD: %x:%x:%x:%x.\n", 395 data->tds[td_current]->status, data->tds[td_current]->cbp, 396 data->tds[td_current]->next, data->tds[td_current]->be); 393 ohci_batch->tds[td_current]->status, 394 ohci_batch->tds[td_current]->cbp, 395 ohci_batch->tds[td_current]->next, 396 ohci_batch->tds[td_current]->be); 397 397 } 398 398 /*----------------------------------------------------------------------------*/ … … 404 404 * OHCI hw in ED. 405 405 */ 406 void batch_data(usb_transfer_batch_t *instance) 407 { 408 assert(instance); 409 ohci_transfer_batch_t *data = instance->private_data; 410 assert(data); 411 usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", data->ed, 412 data->ed->status, data->ed->td_tail, data->ed->td_head, 413 data->ed->next); 414 406 void batch_data(ohci_transfer_batch_t *ohci_batch) 407 { 408 assert(ohci_batch); 409 usb_log_debug("Using ED(%p): %x:%x:%x:%x.\n", ohci_batch->ed, 410 ohci_batch->ed->status, ohci_batch->ed->td_tail, 411 ohci_batch->ed->td_head, ohci_batch->ed->next); 412 413 const usb_direction_t direction = ohci_batch->usb_batch->ep->direction; 415 414 size_t td_current = 0; 416 size_t remain_size = instance->buffer_size;417 char *buffer = instance->data_buffer;415 size_t remain_size = ohci_batch->usb_batch->buffer_size; 416 char *buffer = ohci_batch->device_buffer; 418 417 while (remain_size > 0) { 419 418 const size_t transfer_size = remain_size > OHCI_TD_MAX_TRANSFER 420 419 ? OHCI_TD_MAX_TRANSFER : remain_size; 421 420 422 td_init( data->tds[td_current], instance->ep->direction,421 td_init(ohci_batch->tds[td_current], direction, 423 422 buffer, transfer_size, -1); 424 td_set_next(data->tds[td_current], data->tds[td_current + 1]); 423 td_set_next(ohci_batch->tds[td_current], 424 ohci_batch->tds[td_current + 1]); 425 425 usb_log_debug("Created DATA TD: %x:%x:%x:%x.\n", 426 data->tds[td_current]->status, data->tds[td_current]->cbp, 427 data->tds[td_current]->next, data->tds[td_current]->be); 426 ohci_batch->tds[td_current]->status, 427 ohci_batch->tds[td_current]->cbp, 428 ohci_batch->tds[td_current]->next, 429 ohci_batch->tds[td_current]->be); 428 430 429 431 buffer += transfer_size; 430 432 remain_size -= transfer_size; 431 assert(td_current < data->td_count);433 assert(td_current < ohci_batch->td_count); 432 434 ++td_current; 433 435 } -
uspace/drv/bus/usb/ohci/ohci_batch.h
rf18d82f0 r9c10e51 35 35 #define DRV_OHCI_BATCH_H 36 36 37 #include <adt/list.h> 37 38 #include <usbhc_iface.h> 38 39 #include <usb/usb.h> 39 #include <usb/host/device_keeper.h>40 #include <usb/host/endpoint.h>41 40 #include <usb/host/batch.h> 42 41 43 int batch_init_ohci(usb_transfer_batch_t *batch); 44 bool batch_is_complete(usb_transfer_batch_t *batch); 45 void batch_commit(usb_transfer_batch_t *batch); 42 #include "hw_struct/transfer_descriptor.h" 43 #include "hw_struct/endpoint_descriptor.h" 44 45 /** OHCI specific data required for USB transfer */ 46 typedef struct ohci_transfer_batch { 47 /** Link */ 48 link_t link; 49 /** Endpoint descriptor of the target endpoint. */ 50 ed_t *ed; 51 /** List of TDs needed for the transfer */ 52 td_t **tds; 53 /** Number of TDs used by the transfer */ 54 size_t td_count; 55 /** Dummy TD to be left at the ED and used by the next transfer */ 56 size_t leave_td; 57 /** Data buffer, must be accessible by the OHCI hw. */ 58 char *device_buffer; 59 /** Generic USB transfer structure */ 60 usb_transfer_batch_t *usb_batch; 61 } ohci_transfer_batch_t; 62 63 ohci_transfer_batch_t * ohci_transfer_batch_get(usb_transfer_batch_t *batch); 64 bool ohci_transfer_batch_is_complete(ohci_transfer_batch_t *batch); 65 void ohci_transfer_batch_commit(ohci_transfer_batch_t *batch); 66 void ohci_transfer_batch_finish_dispose(ohci_transfer_batch_t *batch); 67 /*----------------------------------------------------------------------------*/ 68 static inline ohci_transfer_batch_t *ohci_transfer_batch_from_link(link_t *l) 69 { 70 assert(l); 71 return list_get_instance(l, ohci_transfer_batch_t, link); 72 } 46 73 #endif 47 74 /** -
uspace/drv/bus/usb/ohci/root_hub.c
rf18d82f0 r9c10e51 121 121 assert(request); 122 122 123 memcpy(request->data_buffer, &mask, size);124 123 request->transfered_size = size; 125 usb_transfer_batch_finish_error(request, EOK);124 usb_transfer_batch_finish_error(request, &mask, size, EOK); 126 125 } 127 126 … … 206 205 usb_log_debug("Root hub got CONTROL packet\n"); 207 206 const int ret = control_request(instance, request); 208 usb_transfer_batch_finish_error(request, ret);207 usb_transfer_batch_finish_error(request, NULL, 0, ret); 209 208 break; 210 209 case USB_TRANSFER_INTERRUPT: … … 215 214 assert(instance->unfinished_interrupt_transfer == NULL); 216 215 instance->unfinished_interrupt_transfer = request; 217 break;216 return; 218 217 } 219 218 usb_log_debug("Processing changes...\n"); … … 223 222 default: 224 223 usb_log_error("Root hub got unsupported request.\n"); 225 usb_transfer_batch_finish_error(request, EINVAL); 226 } 224 usb_transfer_batch_finish_error(request, NULL, 0, EINVAL); 225 } 226 usb_transfer_batch_dispose(request); 227 227 } 228 228 /*----------------------------------------------------------------------------*/ … … 244 244 interrupt_request(instance->unfinished_interrupt_transfer, 245 245 mask, instance->interrupt_mask_size); 246 usb_transfer_batch_dispose(instance->unfinished_interrupt_transfer); 246 247 247 248 instance->unfinished_interrupt_transfer = NULL; … … 389 390 const uint32_t data = instance->registers->rh_status & 390 391 (RHS_LPS_FLAG | RHS_LPSC_FLAG | RHS_OCI_FLAG | RHS_OCIC_FLAG); 391 memcpy(request-> data_buffer, &data, 4);392 TRANSFER_OK( 4);392 memcpy(request->buffer, &data, sizeof(data)); 393 TRANSFER_OK(sizeof(data)); 393 394 } 394 395 … … 402 403 const uint32_t data = 403 404 instance->registers->rh_port_status[port - 1]; 404 memcpy(request-> data_buffer, &data, 4);405 TRANSFER_OK( 4);405 memcpy(request->buffer, &data, sizeof(data)); 406 TRANSFER_OK(sizeof(data)); 406 407 } 407 408 … … 483 484 } 484 485 485 memcpy(request-> data_buffer, descriptor, size);486 memcpy(request->buffer, descriptor, size); 486 487 TRANSFER_OK(size); 487 488 } … … 713 714 if (request->buffer_size != 1) 714 715 return EINVAL; 715 request-> data_buffer[0] = 1;716 request->buffer[0] = 1; 716 717 TRANSFER_OK(1); 717 718
Note:
See TracChangeset
for help on using the changeset viewer.