Changes in uspace/drv/uhci-hcd/batch.c [a7e2f0d:eae83aa] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/uhci-hcd/batch.c
ra7e2f0d reae83aa 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 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 */ 56 57 76 58 batch_t * batch_get(ddf_fun_t *fun, usb_target_t target, 77 59 usb_transfer_type_t transfer_type, size_t max_packet_size, … … 79 61 char* setup_buffer, size_t setup_size, 80 62 usbhc_iface_transfer_in_callback_t func_in, 81 usbhc_iface_transfer_out_callback_t func_out, void *arg, 82 device_keeper_t *manager 83 ) 63 usbhc_iface_transfer_out_callback_t func_out, void *arg) 84 64 { 85 65 assert(func_in == NULL || func_out == NULL); 86 66 assert(func_in != NULL || func_out != NULL); 87 67 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)096 97 68 batch_t *instance = malloc(sizeof(batch_t)); 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); 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 } 106 80 107 81 instance->packets = (size + max_packet_size - 1) / max_packet_size; … … 111 85 112 86 instance->tds = malloc32(sizeof(td_t) * instance->packets); 113 CHECK_NULL_DISPOSE_RETURN( 114 instance->tds, "Failed to allocate transfer descriptors.\n"); 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 } 115 93 bzero(instance->tds, sizeof(td_t) * instance->packets); 116 94 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"); 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) { 129 118 memcpy(instance->setup_buffer, setup_buffer, setup_size); 130 119 } 131 120 121 instance->max_packet_size = max_packet_size; 132 122 133 123 link_initialize(&instance->link); 134 124 135 instance->max_packet_size = max_packet_size;136 125 instance->target = target; 137 126 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 138 133 instance->buffer = buffer; 139 134 instance->buffer_size = size; … … 142 137 instance->arg = arg; 143 138 instance->speed = speed; 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 139 140 queue_head_element_td(instance->qh, addr_to_phys(instance->tds)); 153 141 usb_log_debug("Batch(%p) %d:%d memory structures ready.\n", 154 142 instance, target.address, target.endpoint); … … 156 144 } 157 145 /*----------------------------------------------------------------------------*/ 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 */163 146 bool batch_is_complete(batch_t *instance) 164 147 { … … 177 160 usb_log_debug("Batch(%p) found error TD(%d):%x.\n", 178 161 instance, i, instance->tds[i].status); 179 180 device_keeper_set_toggle(instance->manager,181 instance->target, td_toggle(&instance->tds[i]));182 162 if (i > 0) 183 163 goto substract_ret; … … 194 174 } 195 175 /*----------------------------------------------------------------------------*/ 196 /** Prepares control write transaction.197 *198 * @param[in] instance Batch structure to use.199 */200 176 void batch_control_write(batch_t *instance) 201 177 { 202 178 assert(instance); 203 179 /* we are data out, we are supposed to provide data */ 204 memcpy(instance->transport_buffer, instance->buffer, 205 instance->buffer_size); 180 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 206 181 batch_control(instance, USB_PID_OUT, USB_PID_IN); 207 182 instance->next_step = batch_call_out_and_dispose; … … 210 185 } 211 186 /*----------------------------------------------------------------------------*/ 212 /** Prepares control read transaction.213 *214 * @param[in] instance Batch structure to use.215 */216 187 void batch_control_read(batch_t *instance) 217 188 { … … 223 194 } 224 195 /*----------------------------------------------------------------------------*/ 225 /** Prepares interrupt in transaction.226 *227 * @param[in] instance Batch structure to use.228 */229 196 void batch_interrupt_in(batch_t *instance) 230 197 { … … 236 203 } 237 204 /*----------------------------------------------------------------------------*/ 238 /** Prepares interrupt out transaction.239 *240 * @param[in] instance Batch structure to use.241 */242 205 void batch_interrupt_out(batch_t *instance) 243 206 { 244 207 assert(instance); 245 /* we are data out, we are supposed to provide data */246 208 memcpy(instance->transport_buffer, instance->buffer, instance->buffer_size); 247 209 batch_data(instance, USB_PID_OUT); … … 251 213 } 252 214 /*----------------------------------------------------------------------------*/ 253 /** Prepares bulk in transaction.254 *255 * @param[in] instance Batch structure to use.256 */257 215 void batch_bulk_in(batch_t *instance) 258 216 { … … 264 222 } 265 223 /*----------------------------------------------------------------------------*/ 266 /** Prepares bulk out transaction.267 *268 * @param[in] instance Batch structure to use.269 */270 224 void batch_bulk_out(batch_t *instance) 271 225 { … … 278 232 } 279 233 /*----------------------------------------------------------------------------*/ 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) 234 static void batch_data(batch_t *instance, usb_packet_id pid) 286 235 { 287 236 assert(instance); 288 237 const bool low_speed = instance->speed == USB_SPEED_LOW; 289 int toggle = 290 device_keeper_get_toggle(instance->manager, instance->target); 291 assert(toggle == 0 || toggle == 1); 238 int toggle = 1; 292 239 293 240 size_t packet = 0; … … 298 245 - remain_size; 299 246 247 toggle = 1 - toggle; 248 300 249 const size_t packet_size = 301 250 (instance->max_packet_size > remain_size) ? 302 251 remain_size : instance->max_packet_size; 303 252 304 td_t *next_packet = (packet + 1 < instance->packets) 305 ? &instance->tds[packet + 1] : NULL; 306 307 assert(packet < instance->packets); 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 258 ++packet; 259 assert(packet <= instance->packets); 308 260 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 261 remain_size -= packet_size; 318 ++packet; 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, 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, 330 269 usb_packet_id data_stage, usb_packet_id status_stage) 331 270 { … … 353 292 remain_size : instance->max_packet_size; 354 293 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]);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]); 359 298 360 299 ++packet; … … 375 314 } 376 315 /*----------------------------------------------------------------------------*/ 377 /** Prepares data, gets error status and calls callback in.378 *379 * @param[in] instance Batch structure to use.380 */381 316 void batch_call_in(batch_t *instance) 382 317 { … … 384 319 assert(instance->callback_in); 385 320 386 /* we are data in, we need data */ 387 memcpy(instance->buffer, instance->transport_buffer, 388 instance->buffer_size); 321 memcpy(instance->buffer, instance->transport_buffer, instance->buffer_size); 389 322 390 323 int err = instance->error; … … 393 326 instance->transfered_size); 394 327 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 */ 328 instance->callback_in(instance->fun, 329 err, instance->transfered_size, 330 instance->arg); 331 } 332 /*----------------------------------------------------------------------------*/ 403 333 void batch_call_out(batch_t *instance) 404 334 { … … 413 343 } 414 344 /*----------------------------------------------------------------------------*/ 415 /** Prepares data, gets error status, calls callback in and dispose.416 *417 * @param[in] instance Batch structure to use.418 */419 345 void batch_call_in_and_dispose(batch_t *instance) 420 346 { 421 347 assert(instance); 422 348 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);444 349 usb_log_debug("Batch(%p) disposing.\n", instance); 445 /* free32 is NULL safe */446 350 free32(instance->tds); 447 351 free32(instance->qh); … … 451 355 } 452 356 /*----------------------------------------------------------------------------*/ 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 /*----------------------------------------------------------------------------*/ 453 369 int batch_schedule(batch_t *instance) 454 370 {
Note:
See TracChangeset
for help on using the changeset viewer.