Changes in uspace/drv/uhci-hcd/batch.c [87644b4:a963a68] in mainline
- File:
-
- 1 edited
-
uspace/drv/uhci-hcd/batch.c (modified) (24 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/uhci-hcd/batch.c
r87644b4 ra963a68 40 40 #include "batch.h" 41 41 #include "transfer_list.h" 42 #include " hw_struct/transfer_descriptor.h"42 #include "uhci_hc.h" 43 43 #include "utils/malloc32.h" 44 44 45 45 #define DEFAULT_ERROR_COUNT 3 46 46 47 typedef struct uhci_batch { 48 qh_t *qh; 49 td_t *tds; 50 size_t packets; 51 usb_device_keeper_t *manager; 52 } uhci_batch_t; 53 54 static void batch_control(usb_transfer_batch_t *instance, 47 static void batch_control(batch_t *instance, 55 48 usb_packet_id data_stage, usb_packet_id status_stage); 56 static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid); 57 static void batch_call_in_and_dispose(usb_transfer_batch_t *instance); 58 static void batch_call_out_and_dispose(usb_transfer_batch_t *instance); 49 static void batch_data(batch_t *instance, usb_packet_id pid); 50 static void batch_call_in(batch_t *instance); 51 static void batch_call_out(batch_t *instance); 52 static void batch_call_in_and_dispose(batch_t *instance); 53 static void batch_call_out_and_dispose(batch_t *instance); 59 54 60 55 … … 81 76 * transaction and callback. 82 77 */ 83 usb_transfer_batch_t * batch_get(ddf_fun_t *fun, usb_target_t target,78 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target, 84 79 usb_transfer_type_t transfer_type, size_t max_packet_size, 85 usb_speed_t speed, char *buffer, size_t buffer_size,80 usb_speed_t speed, char *buffer, size_t size, 86 81 char* setup_buffer, size_t setup_size, 87 82 usbhc_iface_transfer_in_callback_t func_in, 88 83 usbhc_iface_transfer_out_callback_t func_out, void *arg, 89 usb_device_keeper_t *manager84 device_keeper_t *manager 90 85 ) 91 86 { … … 102 97 } else (void)0 103 98 104 usb_transfer_batch_t *instance = malloc(sizeof(usb_transfer_batch_t));99 batch_t *instance = malloc(sizeof(batch_t)); 105 100 CHECK_NULL_DISPOSE_RETURN(instance, 106 101 "Failed to allocate batch instance.\n"); 107 usb_transfer_batch_init(instance, target, transfer_type, speed, max_packet_size, 108 buffer, NULL, buffer_size, NULL, setup_size, func_in, 109 func_out, arg, fun, NULL); 110 111 112 uhci_batch_t *data = malloc(sizeof(uhci_batch_t)); 113 CHECK_NULL_DISPOSE_RETURN(instance, 114 "Failed to allocate batch instance.\n"); 115 bzero(data, sizeof(uhci_batch_t)); 116 data->manager = manager; 117 instance->private_data = data; 118 119 data->packets = (buffer_size + max_packet_size - 1) / max_packet_size; 102 bzero(instance, sizeof(batch_t)); 103 104 instance->qh = malloc32(sizeof(qh_t)); 105 CHECK_NULL_DISPOSE_RETURN(instance->qh, 106 "Failed to allocate batch queue head.\n"); 107 qh_init(instance->qh); 108 109 instance->packets = (size + max_packet_size - 1) / max_packet_size; 120 110 if (transfer_type == USB_TRANSFER_CONTROL) { 121 data->packets += 2;122 } 123 124 data->tds = malloc32(sizeof(td_t) * data->packets);111 instance->packets += 2; 112 } 113 114 instance->tds = malloc32(sizeof(td_t) * instance->packets); 125 115 CHECK_NULL_DISPOSE_RETURN( 126 data->tds, "Failed to allocate transfer descriptors.\n"); 127 bzero(data->tds, sizeof(td_t) * data->packets); 128 129 data->qh = malloc32(sizeof(qh_t)); 130 CHECK_NULL_DISPOSE_RETURN(data->qh, 131 "Failed to allocate batch queue head.\n"); 132 qh_init(data->qh); 133 qh_set_element_td(data->qh, addr_to_phys(data->tds)); 134 135 if (buffer_size > 0) { 136 instance->transport_buffer = malloc32(buffer_size); 116 instance->tds, "Failed to allocate transfer descriptors.\n"); 117 bzero(instance->tds, sizeof(td_t) * instance->packets); 118 119 if (size > 0) { 120 instance->transport_buffer = malloc32(size); 137 121 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer, 138 122 "Failed to allocate device accessible buffer.\n"); … … 146 130 } 147 131 132 133 link_initialize(&instance->link); 134 135 instance->max_packet_size = max_packet_size; 136 instance->target = target; 137 instance->transfer_type = transfer_type; 138 instance->buffer = buffer; 139 instance->buffer_size = size; 140 instance->setup_size = setup_size; 141 instance->fun = fun; 142 instance->arg = arg; 143 instance->speed = speed; 144 instance->manager = manager; 145 instance->callback_out = func_out; 146 instance->callback_in = func_in; 147 148 qh_set_element_td(instance->qh, addr_to_phys(instance->tds)); 149 148 150 usb_log_debug("Batch(%p) %d:%d memory structures ready.\n", 149 151 instance, target.address, target.endpoint); … … 151 153 } 152 154 /*----------------------------------------------------------------------------*/ 155 /** Mark batch as failed and continue with next step. 156 * 157 * @param[in] instance Batch structure to use. 158 * 159 */ 160 void batch_abort(batch_t *instance) 161 { 162 assert(instance); 163 instance->error = EIO; 164 instance->next_step(instance); 165 } 166 /*----------------------------------------------------------------------------*/ 153 167 /** Check batch TDs for activity. 154 168 * … … 160 174 * is reached. 161 175 */ 162 bool batch_is_complete(usb_transfer_batch_t *instance) 163 { 164 assert(instance); 165 uhci_batch_t *data = instance->private_data; 166 assert(data); 167 176 bool batch_is_complete(batch_t *instance) 177 { 178 assert(instance); 168 179 usb_log_debug2("Batch(%p) checking %d packet(s) for completion.\n", 169 instance, data->packets);180 instance, instance->packets); 170 181 instance->transfered_size = 0; 171 182 size_t i = 0; 172 for (;i < data->packets; ++i) {173 if (td_is_active(& data->tds[i])) {183 for (;i < instance->packets; ++i) { 184 if (td_is_active(&instance->tds[i])) { 174 185 return false; 175 186 } 176 187 177 instance->error = td_status(& data->tds[i]);188 instance->error = td_status(&instance->tds[i]); 178 189 if (instance->error != EOK) { 179 190 usb_log_debug("Batch(%p) found error TD(%d):%x.\n", 180 instance, i, data->tds[i].status); 181 td_print_status(&data->tds[i]); 182 183 usb_device_keeper_set_toggle(data->manager, 184 instance->target, instance->direction, 185 td_toggle(&data->tds[i])); 191 instance, i, instance->tds[i].status); 192 td_print_status(&instance->tds[i]); 193 194 device_keeper_set_toggle(instance->manager, 195 instance->target, td_toggle(&instance->tds[i])); 186 196 if (i > 0) 187 197 goto substract_ret; … … 189 199 } 190 200 191 instance->transfered_size += td_act_size(& data->tds[i]);192 if (td_is_short(& data->tds[i]))201 instance->transfered_size += td_act_size(&instance->tds[i]); 202 if (td_is_short(&instance->tds[i])) 193 203 goto substract_ret; 194 204 } … … 204 214 * Uses genercir control function with pids OUT and IN. 205 215 */ 206 void batch_control_write( usb_transfer_batch_t *instance)216 void batch_control_write(batch_t *instance) 207 217 { 208 218 assert(instance); … … 221 231 * Uses generic control with pids IN and OUT. 222 232 */ 223 void batch_control_read( usb_transfer_batch_t *instance)233 void batch_control_read(batch_t *instance) 224 234 { 225 235 assert(instance); … … 235 245 * Data transaction with PID_IN. 236 246 */ 237 void batch_interrupt_in(usb_transfer_batch_t *instance) 238 { 239 assert(instance); 240 instance->direction = USB_DIRECTION_IN; 247 void batch_interrupt_in(batch_t *instance) 248 { 249 assert(instance); 241 250 batch_data(instance, USB_PID_IN); 242 251 instance->next_step = batch_call_in_and_dispose; … … 250 259 * Data transaction with PID_OUT. 251 260 */ 252 void batch_interrupt_out(usb_transfer_batch_t *instance) 253 { 254 assert(instance); 255 instance->direction = USB_DIRECTION_OUT; 261 void batch_interrupt_out(batch_t *instance) 262 { 263 assert(instance); 256 264 /* We are data out, we are supposed to provide data */ 257 265 memcpy(instance->transport_buffer, instance->buffer, … … 268 276 * Data transaction with PID_IN. 269 277 */ 270 void batch_bulk_in( usb_transfer_batch_t *instance)278 void batch_bulk_in(batch_t *instance) 271 279 { 272 280 assert(instance); 273 281 batch_data(instance, USB_PID_IN); 274 instance->direction = USB_DIRECTION_IN;275 282 instance->next_step = batch_call_in_and_dispose; 276 283 usb_log_debug("Batch(%p) BULK IN initialized.\n", instance); … … 283 290 * Data transaction with PID_OUT. 284 291 */ 285 void batch_bulk_out(usb_transfer_batch_t *instance) 286 { 287 assert(instance); 288 instance->direction = USB_DIRECTION_OUT; 292 void batch_bulk_out(batch_t *instance) 293 { 294 assert(instance); 289 295 /* We are data out, we are supposed to provide data */ 290 296 memcpy(instance->transport_buffer, instance->buffer, … … 303 309 * The last packet is marked with IOC flag. 304 310 */ 305 void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid) 306 { 307 assert(instance); 308 uhci_batch_t *data = instance->private_data; 309 assert(data); 310 311 void batch_data(batch_t *instance, usb_packet_id pid) 312 { 313 assert(instance); 311 314 const bool low_speed = instance->speed == USB_SPEED_LOW; 312 int toggle = usb_device_keeper_get_toggle(313 d ata->manager, instance->target, instance->direction);315 int toggle = 316 device_keeper_get_toggle(instance->manager, instance->target); 314 317 assert(toggle == 0 || toggle == 1); 315 318 … … 317 320 size_t remain_size = instance->buffer_size; 318 321 while (remain_size > 0) { 319 char * trans_data =322 char *data = 320 323 instance->transport_buffer + instance->buffer_size 321 324 - remain_size; … … 325 328 remain_size : instance->max_packet_size; 326 329 327 td_t *next_packet = (packet + 1 < data->packets)328 ? & data->tds[packet + 1] : NULL;329 330 assert(packet < data->packets);330 td_t *next_packet = (packet + 1 < instance->packets) 331 ? &instance->tds[packet + 1] : NULL; 332 333 assert(packet < instance->packets); 331 334 assert(packet_size <= remain_size); 332 335 333 336 td_init( 334 & data->tds[packet], DEFAULT_ERROR_COUNT, packet_size,335 toggle, false, low_speed, instance->target, pid, trans_data,337 &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size, 338 toggle, false, low_speed, instance->target, pid, data, 336 339 next_packet); 337 340 … … 341 344 ++packet; 342 345 } 343 td_set_ioc(&data->tds[packet - 1]); 344 usb_device_keeper_set_toggle(data->manager, instance->target, 345 instance->direction, toggle); 346 td_set_ioc(&instance->tds[packet - 1]); 347 device_keeper_set_toggle(instance->manager, instance->target, toggle); 346 348 } 347 349 /*----------------------------------------------------------------------------*/ … … 357 359 * The last packet is marked with IOC. 358 360 */ 359 void batch_control( usb_transfer_batch_t *instance,361 void batch_control(batch_t *instance, 360 362 usb_packet_id data_stage, usb_packet_id status_stage) 361 363 { 362 364 assert(instance); 363 uhci_batch_t *data = instance->private_data;364 assert(data);365 assert(data->packets >= 2);366 365 367 366 const bool low_speed = instance->speed == USB_SPEED_LOW; 368 367 int toggle = 0; 369 368 /* setup stage */ 370 td_init( 371 data->tds, DEFAULT_ERROR_COUNT, instance->setup_size, toggle, false, 372 low_speed, instance->target, USB_PID_SETUP, instance->setup_buffer, 373 &data->tds[1]); 369 td_init(instance->tds, DEFAULT_ERROR_COUNT, 370 instance->setup_size, toggle, false, low_speed, instance->target, 371 USB_PID_SETUP, instance->setup_buffer, &instance->tds[1]); 374 372 375 373 /* data stage */ … … 377 375 size_t remain_size = instance->buffer_size; 378 376 while (remain_size > 0) { 379 char * control_data =377 char *data = 380 378 instance->transport_buffer + instance->buffer_size 381 379 - remain_size; … … 388 386 389 387 td_init( 390 & data->tds[packet], DEFAULT_ERROR_COUNT, packet_size,388 &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size, 391 389 toggle, false, low_speed, instance->target, data_stage, 392 control_data, &data->tds[packet + 1]);390 data, &instance->tds[packet + 1]); 393 391 394 392 ++packet; 395 assert(packet < data->packets);393 assert(packet < instance->packets); 396 394 assert(packet_size <= remain_size); 397 395 remain_size -= packet_size; … … 399 397 400 398 /* status stage */ 401 assert(packet == data->packets - 1); 402 403 td_init( 404 &data->tds[packet], DEFAULT_ERROR_COUNT, 0, 1, false, low_speed, 405 instance->target, status_stage, NULL, NULL); 406 td_set_ioc(&data->tds[packet]); 407 399 assert(packet == instance->packets - 1); 400 td_init(&instance->tds[packet], DEFAULT_ERROR_COUNT, 401 0, 1, false, low_speed, instance->target, status_stage, NULL, NULL); 402 403 td_set_ioc(&instance->tds[packet]); 408 404 usb_log_debug2("Control last TD status: %x.\n", 409 data->tds[packet].status); 410 } 411 /*----------------------------------------------------------------------------*/ 412 qh_t * batch_qh(usb_transfer_batch_t *instance) 413 { 414 assert(instance); 415 uhci_batch_t *data = instance->private_data; 416 assert(data); 417 return data->qh; 405 instance->tds[packet].status); 406 } 407 /*----------------------------------------------------------------------------*/ 408 /** Prepare data, get error status and call callback in. 409 * 410 * @param[in] instance Batch structure to use. 411 * Copies data from transport buffer, and calls callback with appropriate 412 * parameters. 413 */ 414 void batch_call_in(batch_t *instance) 415 { 416 assert(instance); 417 assert(instance->callback_in); 418 419 /* We are data in, we need data */ 420 memcpy(instance->buffer, instance->transport_buffer, 421 instance->buffer_size); 422 423 int err = instance->error; 424 usb_log_debug("Batch(%p) callback IN(type:%d): %s(%d), %zu.\n", 425 instance, instance->transfer_type, str_error(err), err, 426 instance->transfered_size); 427 428 instance->callback_in( 429 instance->fun, err, instance->transfered_size, instance->arg); 430 } 431 /*----------------------------------------------------------------------------*/ 432 /** Get error status and call callback out. 433 * 434 * @param[in] instance Batch structure to use. 435 */ 436 void batch_call_out(batch_t *instance) 437 { 438 assert(instance); 439 assert(instance->callback_out); 440 441 int err = instance->error; 442 usb_log_debug("Batch(%p) callback OUT(type:%d): %s(%d).\n", 443 instance, instance->transfer_type, str_error(err), err); 444 instance->callback_out(instance->fun, 445 err, instance->arg); 418 446 } 419 447 /*----------------------------------------------------------------------------*/ … … 422 450 * @param[in] instance Batch structure to use. 423 451 */ 424 void batch_call_in_and_dispose( usb_transfer_batch_t *instance)425 { 426 assert(instance); 427 usb_transfer_batch_call_in(instance);452 void batch_call_in_and_dispose(batch_t *instance) 453 { 454 assert(instance); 455 batch_call_in(instance); 428 456 batch_dispose(instance); 429 457 } … … 433 461 * @param[in] instance Batch structure to use. 434 462 */ 435 void batch_call_out_and_dispose( usb_transfer_batch_t *instance)436 { 437 assert(instance); 438 usb_transfer_batch_call_out(instance);463 void batch_call_out_and_dispose(batch_t *instance) 464 { 465 assert(instance); 466 batch_call_out(instance); 439 467 batch_dispose(instance); 440 468 } … … 444 472 * @param[in] instance Batch structure to use. 445 473 */ 446 void batch_dispose(usb_transfer_batch_t *instance) 447 { 448 assert(instance); 449 uhci_batch_t *data = instance->private_data; 450 assert(data); 474 void batch_dispose(batch_t *instance) 475 { 476 assert(instance); 451 477 usb_log_debug("Batch(%p) disposing.\n", instance); 452 478 /* free32 is NULL safe */ 453 free32( data->tds);454 free32( data->qh);479 free32(instance->tds); 480 free32(instance->qh); 455 481 free32(instance->setup_buffer); 456 482 free32(instance->transport_buffer); 457 free(data);458 483 free(instance); 459 484 }
Note:
See TracChangeset
for help on using the changeset viewer.
