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