Changes in uspace/drv/uhci-hcd/batch.c [a60150a:a7e2f0d] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/uhci-hcd/batch.c
ra60150a ra7e2f0d 57 57 58 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 */ 59 76 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target, 60 77 usb_transfer_type_t transfer_type, size_t max_packet_size, … … 69 86 assert(func_in != NULL || func_out != NULL); 70 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 71 97 batch_t *instance = malloc(sizeof(batch_t)); 72 if (instance == NULL) { 73 usb_log_error("Failed to allocate batch instance.\n"); 74 return NULL; 75 } 76 77 instance->qh = queue_head_get(); 78 if (instance->qh == NULL) { 79 usb_log_error("Failed to allocate queue head.\n"); 80 free(instance); 81 return NULL; 82 } 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); 83 106 84 107 instance->packets = (size + max_packet_size - 1) / max_packet_size; … … 88 111 89 112 instance->tds = malloc32(sizeof(td_t) * instance->packets); 90 if (instance->tds == NULL) { 91 usb_log_error("Failed to allocate transfer descriptors.\n"); 92 queue_head_dispose(instance->qh); 93 free(instance); 94 return NULL; 95 } 113 CHECK_NULL_DISPOSE_RETURN( 114 instance->tds, "Failed to allocate transfer descriptors.\n"); 96 115 bzero(instance->tds, sizeof(td_t) * instance->packets); 97 116 98 const size_t transport_size = max_packet_size * instance->packets; 99 100 instance->transport_buffer = 101 (size > 0) ? malloc32(transport_size) : NULL; 102 103 if ((size > 0) && (instance->transport_buffer == NULL)) { 104 usb_log_error("Failed to allocate device accessible buffer.\n"); 105 queue_head_dispose(instance->qh); 106 free32(instance->tds); 107 free(instance); 108 return NULL; 109 } 110 111 instance->setup_buffer = setup_buffer ? malloc32(setup_size) : NULL; 112 if ((setup_size > 0) && (instance->setup_buffer == NULL)) { 113 usb_log_error("Failed to allocate device accessible setup buffer.\n"); 114 queue_head_dispose(instance->qh); 115 free32(instance->tds); 116 free32(instance->transport_buffer); 117 free(instance); 118 return NULL; 119 } 120 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"); 121 129 memcpy(instance->setup_buffer, setup_buffer, setup_size); 122 130 } 123 131 132 133 link_initialize(&instance->link); 134 124 135 instance->max_packet_size = max_packet_size; 125 126 link_initialize(&instance->link);127 128 136 instance->target = target; 129 137 instance->transfer_type = transfer_type; 130 131 if (func_out)132 instance->callback_out = func_out;133 if (func_in)134 instance->callback_in = func_in;135 136 138 instance->buffer = buffer; 137 139 instance->buffer_size = size; … … 142 144 instance->manager = manager; 143 145 144 queue_head_element_td(instance->qh, addr_to_phys(instance->tds)); 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 145 153 usb_log_debug("Batch(%p) %d:%d memory structures ready.\n", 146 154 instance, target.address, target.endpoint); … … 148 156 } 149 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 */ 150 163 bool batch_is_complete(batch_t *instance) 151 164 { … … 165 178 instance, i, instance->tds[i].status); 166 179 167 device_keeper_set_toggle(instance->manager, instance->target,168 td_toggle(&instance->tds[i]));180 device_keeper_set_toggle(instance->manager, 181 instance->target, td_toggle(&instance->tds[i])); 169 182 if (i > 0) 170 183 goto substract_ret; … … 181 194 } 182 195 /*----------------------------------------------------------------------------*/ 196 /** Prepares control write transaction. 197 * 198 * @param[in] instance Batch structure to use. 199 */ 183 200 void batch_control_write(batch_t *instance) 184 201 { 185 202 assert(instance); 186 203 /* we are data out, we are supposed to provide data */ 187 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 204 memcpy(instance->transport_buffer, instance->buffer, 205 instance->buffer_size); 188 206 batch_control(instance, USB_PID_OUT, USB_PID_IN); 189 207 instance->next_step = batch_call_out_and_dispose; … … 192 210 } 193 211 /*----------------------------------------------------------------------------*/ 212 /** Prepares control read transaction. 213 * 214 * @param[in] instance Batch structure to use. 215 */ 194 216 void batch_control_read(batch_t *instance) 195 217 { … … 201 223 } 202 224 /*----------------------------------------------------------------------------*/ 225 /** Prepares interrupt in transaction. 226 * 227 * @param[in] instance Batch structure to use. 228 */ 203 229 void batch_interrupt_in(batch_t *instance) 204 230 { … … 210 236 } 211 237 /*----------------------------------------------------------------------------*/ 238 /** Prepares interrupt out transaction. 239 * 240 * @param[in] instance Batch structure to use. 241 */ 212 242 void batch_interrupt_out(batch_t *instance) 213 243 { 214 244 assert(instance); 245 /* we are data out, we are supposed to provide data */ 215 246 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 216 247 batch_data(instance, USB_PID_OUT); … … 220 251 } 221 252 /*----------------------------------------------------------------------------*/ 253 /** Prepares bulk in transaction. 254 * 255 * @param[in] instance Batch structure to use. 256 */ 222 257 void batch_bulk_in(batch_t *instance) 223 258 { … … 229 264 } 230 265 /*----------------------------------------------------------------------------*/ 266 /** Prepares bulk out transaction. 267 * 268 * @param[in] instance Batch structure to use. 269 */ 231 270 void batch_bulk_out(batch_t *instance) 232 271 { … … 239 278 } 240 279 /*----------------------------------------------------------------------------*/ 280 /** Prepares generic data transaction 281 * 282 * @param[in] instance Batch structure to use. 283 * @param[in] pid to use for data packets. 284 */ 241 285 void batch_data(batch_t *instance, usb_packet_id pid) 242 286 { 243 287 assert(instance); 244 288 const bool low_speed = instance->speed == USB_SPEED_LOW; 245 int toggle = device_keeper_get_toggle(instance->manager, instance->target); 289 int toggle = 290 device_keeper_get_toggle(instance->manager, instance->target); 246 291 assert(toggle == 0 || toggle == 1); 247 292 … … 253 298 - remain_size; 254 299 255 256 300 const size_t packet_size = 257 301 (instance->max_packet_size > remain_size) ? 258 302 remain_size : instance->max_packet_size; 259 303 260 td_init(&instance->tds[packet], 261 DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed, 262 instance->target, pid, data, 263 &instance->tds[packet + 1]); 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 264 315 265 316 toggle = 1 - toggle; 317 remain_size -= packet_size; 266 318 ++packet; 267 assert(packet <= instance->packets);268 assert(packet_size <= remain_size);269 remain_size -= packet_size;270 319 } 271 320 device_keeper_set_toggle(instance->manager, instance->target, toggle); 272 273 instance->tds[packet - 1].status |= TD_STATUS_COMPLETE_INTERRUPT_FLAG; 274 instance->tds[packet - 1].next = 0 | LINK_POINTER_TERMINATE_FLAG; 275 } 276 /*----------------------------------------------------------------------------*/ 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 */ 277 329 void batch_control(batch_t *instance, 278 330 usb_packet_id data_stage, usb_packet_id status_stage) … … 301 353 remain_size : instance->max_packet_size; 302 354 303 td_init( &instance->tds[packet],304 DEFAULT_ERROR_COUNT, packet_size, toggle, false, low_speed,305 instance->target, data_stage, data,306 &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]); 307 359 308 360 ++packet; … … 323 375 } 324 376 /*----------------------------------------------------------------------------*/ 377 /** Prepares data, gets error status and calls callback in. 378 * 379 * @param[in] instance Batch structure to use. 380 */ 325 381 void batch_call_in(batch_t *instance) 326 382 { … … 328 384 assert(instance->callback_in); 329 385 330 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); 331 389 332 390 int err = instance->error; … … 335 393 instance->transfered_size); 336 394 337 instance->callback_in(instance->fun, 338 err, instance->transfered_size, 339 instance->arg); 340 } 341 /*----------------------------------------------------------------------------*/ 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 */ 342 403 void batch_call_out(batch_t *instance) 343 404 { … … 352 413 } 353 414 /*----------------------------------------------------------------------------*/ 415 /** Prepares data, gets error status, calls callback in and dispose. 416 * 417 * @param[in] instance Batch structure to use. 418 */ 354 419 void batch_call_in_and_dispose(batch_t *instance) 355 420 { … … 359 424 } 360 425 /*----------------------------------------------------------------------------*/ 426 /** Gets error status, calls callback out and dispose. 427 * 428 * @param[in] instance Batch structure to use. 429 */ 361 430 void batch_call_out_and_dispose(batch_t *instance) 362 431 { … … 366 435 } 367 436 /*----------------------------------------------------------------------------*/ 437 /** Correctly disposes all used data structures. 438 * 439 * @param[in] instance Batch structure to use. 440 */ 368 441 void batch_dispose(batch_t *instance) 369 442 { 370 443 assert(instance); 371 444 usb_log_debug("Batch(%p) disposing.\n", instance); 445 /* free32 is NULL safe */ 372 446 free32(instance->tds); 373 447 free32(instance->qh);
Note:
See TracChangeset
for help on using the changeset viewer.