Changes in uspace/drv/uhci-hcd/batch.c [eae83aa:a7e2f0d] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/uhci-hcd/batch.c
reae83aa ra7e2f0d 54 54 static void batch_call_in_and_dispose(batch_t *instance); 55 55 static void batch_call_out_and_dispose(batch_t *instance); 56 57 56 static void batch_dispose(batch_t *instance); 57 58 59 /** Allocates memory and initializes internal data structures. 60 * 61 * @param[in] fun DDF function to pass to callback. 62 * @param[in] target Device and endpoint target of the transaction. 63 * @param[in] transfer_type Interrupt, Control or Bulk. 64 * @param[in] max_packet_size maximum allowed size of data packets. 65 * @param[in] speed Speed of the transaction. 66 * @param[in] buffer Data source/destination. 67 * @param[in] size Size of the buffer. 68 * @param[in] setup_buffer Setup data source (if not NULL) 69 * @param[in] setup_size Size of setup_buffer (should be always 8) 70 * @param[in] func_in function to call on inbound transaction completion 71 * @param[in] func_out function to call on outbound transaction completion 72 * @param[in] arg additional parameter to func_in or func_out 73 * @param[in] manager Pointer to toggle management structure. 74 * @return False, if there is an active TD, true otherwise. 75 */ 58 76 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target, 59 77 usb_transfer_type_t transfer_type, size_t max_packet_size, … … 61 79 char* setup_buffer, size_t setup_size, 62 80 usbhc_iface_transfer_in_callback_t func_in, 63 usbhc_iface_transfer_out_callback_t func_out, void *arg) 81 usbhc_iface_transfer_out_callback_t func_out, void *arg, 82 device_keeper_t *manager 83 ) 64 84 { 65 85 assert(func_in == NULL || func_out == NULL); 66 86 assert(func_in != NULL || func_out != NULL); 67 87 88 #define CHECK_NULL_DISPOSE_RETURN(ptr, message...) \ 89 if (ptr == NULL) { \ 90 usb_log_error(message); \ 91 if (instance) { \ 92 batch_dispose(instance); \ 93 } \ 94 return NULL; \ 95 } else (void)0 96 68 97 batch_t *instance = malloc(sizeof(batch_t)); 69 if (instance == NULL) { 70 usb_log_error("Failed to allocate batch instance.\n"); 71 return NULL; 72 } 73 74 instance->qh = queue_head_get(); 75 if (instance->qh == NULL) { 76 usb_log_error("Failed to allocate queue head.\n"); 77 free(instance); 78 return NULL; 79 } 98 CHECK_NULL_DISPOSE_RETURN(instance, 99 "Failed to allocate batch instance.\n"); 100 bzero(instance, sizeof(batch_t)); 101 102 instance->qh = malloc32(sizeof(queue_head_t)); 103 CHECK_NULL_DISPOSE_RETURN(instance->qh, 104 "Failed to allocate batch queue head.\n"); 105 queue_head_init(instance->qh); 80 106 81 107 instance->packets = (size + max_packet_size - 1) / max_packet_size; … … 85 111 86 112 instance->tds = malloc32(sizeof(td_t) * instance->packets); 87 if (instance->tds == NULL) { 88 usb_log_error("Failed to allocate transfer descriptors.\n"); 89 queue_head_dispose(instance->qh); 90 free(instance); 91 return NULL; 92 } 113 CHECK_NULL_DISPOSE_RETURN( 114 instance->tds, "Failed to allocate transfer descriptors.\n"); 93 115 bzero(instance->tds, sizeof(td_t) * instance->packets); 94 116 95 const size_t transport_size = max_packet_size * instance->packets; 96 97 instance->transport_buffer = 98 (size > 0) ? malloc32(transport_size) : NULL; 99 100 if ((size > 0) && (instance->transport_buffer == NULL)) { 101 usb_log_error("Failed to allocate device accessible buffer.\n"); 102 queue_head_dispose(instance->qh); 103 free32(instance->tds); 104 free(instance); 105 return NULL; 106 } 107 108 instance->setup_buffer = setup_buffer ? malloc32(setup_size) : NULL; 109 if ((setup_size > 0) && (instance->setup_buffer == NULL)) { 110 usb_log_error("Failed to allocate device accessible setup buffer.\n"); 111 queue_head_dispose(instance->qh); 112 free32(instance->tds); 113 free32(instance->transport_buffer); 114 free(instance); 115 return NULL; 116 } 117 if (instance->setup_buffer) { 117 // const size_t transport_size = max_packet_size * instance->packets; 118 119 if (size > 0) { 120 instance->transport_buffer = malloc32(size); 121 CHECK_NULL_DISPOSE_RETURN(instance->transport_buffer, 122 "Failed to allocate device accessible buffer.\n"); 123 } 124 125 if (setup_size > 0) { 126 instance->setup_buffer = malloc32(setup_size); 127 CHECK_NULL_DISPOSE_RETURN(instance->setup_buffer, 128 "Failed to allocate device accessible setup buffer.\n"); 118 129 memcpy(instance->setup_buffer, setup_buffer, setup_size); 119 130 } 120 131 132 133 link_initialize(&instance->link); 134 121 135 instance->max_packet_size = max_packet_size; 122 123 link_initialize(&instance->link);124 125 136 instance->target = target; 126 137 instance->transfer_type = transfer_type; 127 128 if (func_out)129 instance->callback_out = func_out;130 if (func_in)131 instance->callback_in = func_in;132 133 138 instance->buffer = buffer; 134 139 instance->buffer_size = size; … … 137 142 instance->arg = arg; 138 143 instance->speed = speed; 139 140 queue_head_element_td(instance->qh, addr_to_phys(instance->tds)); 144 instance->manager = manager; 145 146 if (func_out) 147 instance->callback_out = func_out; 148 if (func_in) 149 instance->callback_in = func_in; 150 151 queue_head_set_element_td(instance->qh, addr_to_phys(instance->tds)); 152 141 153 usb_log_debug("Batch(%p) %d:%d memory structures ready.\n", 142 154 instance, target.address, target.endpoint); … … 144 156 } 145 157 /*----------------------------------------------------------------------------*/ 158 /** Checks batch TDs for activity. 159 * 160 * @param[in] instance Batch structure to use. 161 * @return False, if there is an active TD, true otherwise. 162 */ 146 163 bool batch_is_complete(batch_t *instance) 147 164 { … … 160 177 usb_log_debug("Batch(%p) found error TD(%d):%x.\n", 161 178 instance, i, instance->tds[i].status); 179 180 device_keeper_set_toggle(instance->manager, 181 instance->target, td_toggle(&instance->tds[i])); 162 182 if (i > 0) 163 183 goto substract_ret; … … 174 194 } 175 195 /*----------------------------------------------------------------------------*/ 196 /** Prepares control write transaction. 197 * 198 * @param[in] instance Batch structure to use. 199 */ 176 200 void batch_control_write(batch_t *instance) 177 201 { 178 202 assert(instance); 179 203 /* we are data out, we are supposed to provide data */ 180 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 204 memcpy(instance->transport_buffer, instance->buffer, 205 instance->buffer_size); 181 206 batch_control(instance, USB_PID_OUT, USB_PID_IN); 182 207 instance->next_step = batch_call_out_and_dispose; … … 185 210 } 186 211 /*----------------------------------------------------------------------------*/ 212 /** Prepares control read transaction. 213 * 214 * @param[in] instance Batch structure to use. 215 */ 187 216 void batch_control_read(batch_t *instance) 188 217 { … … 194 223 } 195 224 /*----------------------------------------------------------------------------*/ 225 /** Prepares interrupt in transaction. 226 * 227 * @param[in] instance Batch structure to use. 228 */ 196 229 void batch_interrupt_in(batch_t *instance) 197 230 { … … 203 236 } 204 237 /*----------------------------------------------------------------------------*/ 238 /** Prepares interrupt out transaction. 239 * 240 * @param[in] instance Batch structure to use. 241 */ 205 242 void batch_interrupt_out(batch_t *instance) 206 243 { 207 244 assert(instance); 245 /* we are data out, we are supposed to provide data */ 208 246 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 209 247 batch_data(instance, USB_PID_OUT); … … 213 251 } 214 252 /*----------------------------------------------------------------------------*/ 253 /** Prepares bulk in transaction. 254 * 255 * @param[in] instance Batch structure to use. 256 */ 215 257 void batch_bulk_in(batch_t *instance) 216 258 { … … 222 264 } 223 265 /*----------------------------------------------------------------------------*/ 266 /** Prepares bulk out transaction. 267 * 268 * @param[in] instance Batch structure to use. 269 */ 224 270 void batch_bulk_out(batch_t *instance) 225 271 { … … 232 278 } 233 279 /*----------------------------------------------------------------------------*/ 234 static void batch_data(batch_t *instance, usb_packet_id pid) 280 /** Prepares generic data transaction 281 * 282 * @param[in] instance Batch structure to use. 283 * @param[in] pid to use for data packets. 284 */ 285 void batch_data(batch_t *instance, usb_packet_id pid) 235 286 { 236 287 assert(instance); 237 288 const bool low_speed = instance->speed == USB_SPEED_LOW; 238 int toggle = 1; 289 int toggle = 290 device_keeper_get_toggle(instance->manager, instance->target); 291 assert(toggle == 0 || toggle == 1); 239 292 240 293 size_t packet = 0; … … 245 298 - remain_size; 246 299 247 toggle = 1 - toggle;248 249 300 const size_t packet_size = 250 301 (instance->max_packet_size > remain_size) ? 251 302 remain_size : instance->max_packet_size; 252 303 253 td_init(&instance->tds[packet], 254 DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed, 255 instance->target, pid, data, 256 &instance->tds[packet + 1]); 257 304 td_t *next_packet = (packet + 1 < instance->packets) 305 ? &instance->tds[packet + 1] : NULL; 306 307 assert(packet < instance->packets); 308 assert(packet_size <= remain_size); 309 310 td_init( 311 &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size, 312 toggle, false, low_speed, instance->target, pid, data, 313 next_packet); 314 315 316 toggle = 1 - toggle; 317 remain_size -= packet_size; 258 318 ++packet; 259 assert(packet <= instance->packets); 260 assert(packet_size <= remain_size); 261 remain_size -= packet_size; 262 } 263 264 instance->tds[packet - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG; 265 instance->tds[packet - 1].next = 0 | LINK_POINTER_TERMINATE_FLAG; 266 } 267 /*----------------------------------------------------------------------------*/ 268 static void batch_control(batch_t *instance, 319 } 320 device_keeper_set_toggle(instance->manager, instance->target, toggle); 321 } 322 /*----------------------------------------------------------------------------*/ 323 /** Prepares generic control transaction 324 * 325 * @param[in] instance Batch structure to use. 326 * @param[in] data_stage to use for data packets. 327 * @param[in] status_stage to use for data packets. 328 */ 329 void batch_control(batch_t *instance, 269 330 usb_packet_id data_stage, usb_packet_id status_stage) 270 331 { … … 292 353 remain_size : instance->max_packet_size; 293 354 294 td_init( &instance->tds[packet],295 DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed,296 instance->target, data_stage, data,297 &instance->tds[packet + 1]);355 td_init( 356 &instance->tds[packet], DEFAULT_ERROR_COUNT, packet_size, 357 toggle, false, low_speed, instance->target, data_stage, 358 data, &instance->tds[packet + 1]); 298 359 299 360 ++packet; … … 314 375 } 315 376 /*----------------------------------------------------------------------------*/ 377 /** Prepares data, gets error status and calls callback in. 378 * 379 * @param[in] instance Batch structure to use. 380 */ 316 381 void batch_call_in(batch_t *instance) 317 382 { … … 319 384 assert(instance->callback_in); 320 385 321 memcpy(instance->buffer, instance->transport_buffer, instance->buffer_size); 386 /* we are data in, we need data */ 387 memcpy(instance->buffer, instance->transport_buffer, 388 instance->buffer_size); 322 389 323 390 int err = instance->error; … … 326 393 instance->transfered_size); 327 394 328 instance->callback_in(instance->fun, 329 err, instance->transfered_size, 330 instance->arg); 331 } 332 /*----------------------------------------------------------------------------*/ 395 instance->callback_in( 396 instance->fun, err, instance->transfered_size, instance->arg); 397 } 398 /*----------------------------------------------------------------------------*/ 399 /** Gets error status and calls callback out. 400 * 401 * @param[in] instance Batch structure to use. 402 */ 333 403 void batch_call_out(batch_t *instance) 334 404 { … … 343 413 } 344 414 /*----------------------------------------------------------------------------*/ 415 /** Prepares data, gets error status, calls callback in and dispose. 416 * 417 * @param[in] instance Batch structure to use. 418 */ 345 419 void batch_call_in_and_dispose(batch_t *instance) 346 420 { 347 421 assert(instance); 348 422 batch_call_in(instance); 423 batch_dispose(instance); 424 } 425 /*----------------------------------------------------------------------------*/ 426 /** Gets error status, calls callback out and dispose. 427 * 428 * @param[in] instance Batch structure to use. 429 */ 430 void batch_call_out_and_dispose(batch_t *instance) 431 { 432 assert(instance); 433 batch_call_out(instance); 434 batch_dispose(instance); 435 } 436 /*----------------------------------------------------------------------------*/ 437 /** Correctly disposes all used data structures. 438 * 439 * @param[in] instance Batch structure to use. 440 */ 441 void batch_dispose(batch_t *instance) 442 { 443 assert(instance); 349 444 usb_log_debug("Batch(%p) disposing.\n", instance); 445 /* free32 is NULL safe */ 350 446 free32(instance->tds); 351 447 free32(instance->qh); … … 355 451 } 356 452 /*----------------------------------------------------------------------------*/ 357 void batch_call_out_and_dispose(batch_t *instance)358 {359 assert(instance);360 batch_call_out(instance);361 usb_log_debug("Batch(%p) disposing.\n", instance);362 free32(instance->tds);363 free32(instance->qh);364 free32(instance->setup_buffer);365 free32(instance->transport_buffer);366 free(instance);367 }368 /*----------------------------------------------------------------------------*/369 453 int batch_schedule(batch_t *instance) 370 454 {
Note:
See TracChangeset
for help on using the changeset viewer.