Changeset 17c5e62 in mainline
- Timestamp:
- 2018-01-08T22:30:12Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0eadfd1e
- Parents:
- bdd8842c
- Location:
- uspace
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/bus/usb/xhci/bus.c
rbdd8842c r17c5e62 36 36 #include <usb/host/endpoint.h> 37 37 #include <usb/host/hcd.h> 38 #include <usb/descriptor.h> 38 39 #include <usb/debug.h> 39 40 … … 368 369 static endpoint_t *endpoint_create(device_t *dev, const usb_endpoint_descriptors_t *desc) 369 370 { 370 xhci_endpoint_t *ep = calloc(1, sizeof(xhci_endpoint_t)); 371 const usb_transfer_type_t type = USB_ED_GET_TRANSFER_TYPE(desc->endpoint); 372 373 xhci_endpoint_t *ep = calloc(1, sizeof(xhci_endpoint_t) 374 + (type == USB_TRANSFER_ISOCHRONOUS) * sizeof(*ep->isoch)); 371 375 if (!ep) 372 376 return NULL; -
uspace/drv/bus/usb/xhci/endpoint.c
rbdd8842c r17c5e62 89 89 90 90 if (xhci_ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS) { 91 xhci_ep->isoch _max_size = desc->companion.bytes_per_interval91 xhci_ep->isoch->max_size = desc->companion.bytes_per_interval 92 92 ? desc->companion.bytes_per_interval 93 93 : ep->max_transfer_size; … … 95 95 96 96 /* Allocate and setup isochronous-specific structures. */ 97 xhci_ep->isoch _enqueue = 0;98 xhci_ep->isoch _dequeue = 0;99 xhci_ep->isoch _started = false;100 101 fibril_mutex_initialize(&xhci_ep->isoch _guard);102 fibril_condvar_initialize(&xhci_ep->isoch _avail);97 xhci_ep->isoch->enqueue = 0; 98 xhci_ep->isoch->dequeue = 0; 99 xhci_ep->isoch->started = false; 100 101 fibril_mutex_initialize(&xhci_ep->isoch->guard); 102 fibril_condvar_initialize(&xhci_ep->isoch->avail); 103 103 } 104 104 … … 266 266 int err = EOK; 267 267 while (i < XHCI_ISOCH_BUFFER_COUNT) { 268 xhci_isoch_transfer_t *transfer = &xhci_ep->isoch _transfers[i];269 if (dma_buffer_alloc(&transfer->data, xhci_ep->isoch _max_size)) {268 xhci_isoch_transfer_t *transfer = &xhci_ep->isoch->transfers[i]; 269 if (dma_buffer_alloc(&transfer->data, xhci_ep->isoch->max_size)) { 270 270 err = ENOMEM; 271 271 break; … … 278 278 --i; 279 279 while(i >= 0) { 280 dma_buffer_free(&xhci_ep->isoch _transfers[i].data);280 dma_buffer_free(&xhci_ep->isoch->transfers[i].data); 281 281 --i; 282 282 } … … 342 342 if (xhci_ep->base.transfer_type == USB_TRANSFER_ISOCHRONOUS) { 343 343 for (size_t i = 0; i < XHCI_ISOCH_BUFFER_COUNT; ++i) { 344 dma_buffer_free(&xhci_ep->isoch _transfers[i].data);344 dma_buffer_free(&xhci_ep->isoch->transfers[i].data); 345 345 } 346 346 } … … 417 417 XHCI_EP_INTERVAL_SET(*ctx, fnzb32(ep->interval) % 32 - 1); 418 418 419 XHCI_EP_MAX_ESIT_PAYLOAD_LO_SET(*ctx, ep->isoch _max_size & 0xFFFF);420 XHCI_EP_MAX_ESIT_PAYLOAD_HI_SET(*ctx, (ep->isoch _max_size >> 16) & 0xFF);419 XHCI_EP_MAX_ESIT_PAYLOAD_LO_SET(*ctx, ep->isoch->max_size & 0xFFFF); 420 XHCI_EP_MAX_ESIT_PAYLOAD_HI_SET(*ctx, (ep->isoch->max_size >> 16) & 0xFF); 421 421 } 422 422 -
uspace/drv/bus/usb/xhci/endpoint.h
rbdd8842c r17c5e62 93 93 uint32_t interval; 94 94 95 /** The maximum size of an isochronous transfer and therefore the size of buffers */ 96 size_t isoch_max_size; 95 /** This field is a valid pointer for (and only for) isochronous transfers. */ 96 struct { 97 /** The maximum size of an isochronous transfer and therefore the size of buffers */ 98 size_t max_size; 97 99 98 /** Isochronous scheduled transfers with respective buffers */99 #define XHCI_ISOCH_BUFFER_COUNT 4100 xhci_isoch_transfer_t isoch_transfers[XHCI_ISOCH_BUFFER_COUNT];100 /** Isochronous scheduled transfers with respective buffers */ 101 #define XHCI_ISOCH_BUFFER_COUNT 4 102 xhci_isoch_transfer_t transfers[XHCI_ISOCH_BUFFER_COUNT]; 101 103 102 /** Indices to transfers */103 size_t isoch_dequeue, isoch_enqueue;104 /** Indices to transfers */ 105 size_t dequeue, enqueue; 104 106 105 /** Are isochronous transfers started? */106 bool isoch_started;107 /** Are isochronous transfers started? */ 108 bool started; 107 109 108 /** Protects common buffers. */109 fibril_mutex_t isoch_guard;110 /** Protects common buffers. */ 111 fibril_mutex_t guard; 110 112 111 /** Signals filled buffer. */112 fibril_condvar_t isoch_avail;113 113 /** Signals filled buffer. */ 114 fibril_condvar_t avail; 115 } isoch [0]; 114 116 } xhci_endpoint_t; 115 117 -
uspace/drv/bus/usb/xhci/transfers.c
rbdd8842c r17c5e62 237 237 238 238 static xhci_isoch_transfer_t* isoch_transfer_get_enqueue(xhci_endpoint_t *ep) { 239 if (((ep->isoch _enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT) == ep->isoch_dequeue) {239 if (((ep->isoch->enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT) == ep->isoch->dequeue) { 240 240 /* None ready */ 241 241 return NULL; 242 242 } 243 xhci_isoch_transfer_t *isoch_transfer = &ep->isoch _transfers[ep->isoch_enqueue];244 ep->isoch _enqueue = (ep->isoch_enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT;243 xhci_isoch_transfer_t *isoch_transfer = &ep->isoch->transfers[ep->isoch->enqueue]; 244 ep->isoch->enqueue = (ep->isoch->enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT; 245 245 return isoch_transfer; 246 246 } 247 247 248 248 static xhci_isoch_transfer_t* isoch_transfer_get_dequeue(xhci_endpoint_t *ep) { 249 xhci_isoch_transfer_t *isoch_transfer = &ep->isoch _transfers[ep->isoch_dequeue];250 ep->isoch _dequeue = (ep->isoch_dequeue + 1) % XHCI_ISOCH_BUFFER_COUNT;249 xhci_isoch_transfer_t *isoch_transfer = &ep->isoch->transfers[ep->isoch->dequeue]; 250 ep->isoch->dequeue = (ep->isoch->dequeue + 1) % XHCI_ISOCH_BUFFER_COUNT; 251 251 return isoch_transfer; 252 252 } … … 283 283 xhci_trb_clean(&trb); 284 284 285 fibril_mutex_lock(&xhci_ep->isoch _guard);285 fibril_mutex_lock(&xhci_ep->isoch->guard); 286 286 xhci_isoch_transfer_t *isoch_transfer = isoch_transfer_get_enqueue(xhci_ep); 287 287 while (!isoch_transfer) { 288 fibril_condvar_wait(&xhci_ep->isoch _avail, &xhci_ep->isoch_guard);288 fibril_condvar_wait(&xhci_ep->isoch->avail, &xhci_ep->isoch->guard); 289 289 isoch_transfer = isoch_transfer_get_enqueue(xhci_ep); 290 290 } … … 301 301 &isoch_transfer->interrupt_trb_phys); 302 302 if (err) { 303 fibril_mutex_unlock(&xhci_ep->isoch _guard);303 fibril_mutex_unlock(&xhci_ep->isoch->guard); 304 304 return err; 305 305 } … … 307 307 /* If not yet started, start the isochronous endpoint transfers - after buffer count - 1 writes */ 308 308 /* The -1 is there because of the enqueue != dequeue check. The buffer must have at least 2 transfers. */ 309 if (((xhci_ep->isoch _enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT) == xhci_ep->isoch_dequeue && !xhci_ep->isoch_started) {309 if (((xhci_ep->isoch->enqueue + 1) % XHCI_ISOCH_BUFFER_COUNT) == xhci_ep->isoch->dequeue && !xhci_ep->isoch->started) { 310 310 const uint8_t slot_id = xhci_dev->slot_id; 311 311 const uint8_t target = xhci_endpoint_index(xhci_ep) + 1; /* EP Doorbells start at 1 */ 312 312 err = hc_ring_doorbell(hc, slot_id, target); 313 xhci_ep->isoch _started = true;314 } 315 fibril_mutex_unlock(&xhci_ep->isoch _guard);313 xhci_ep->isoch->started = true; 314 } 315 fibril_mutex_unlock(&xhci_ep->isoch->guard); 316 316 if (err) { 317 317 return err; … … 331 331 xhci_trb_clean(&trb); 332 332 trb.parameter = isoch_transfer->data.phys; 333 isoch_transfer->size = xhci_ep->isoch _max_size;333 isoch_transfer->size = xhci_ep->isoch->max_size; 334 334 335 335 int err = schedule_isochronous_trb(ring, xhci_ep, &trb, isoch_transfer->size, … … 344 344 xhci_device_t *xhci_dev) 345 345 { 346 fibril_mutex_lock(&xhci_ep->isoch _guard);346 fibril_mutex_lock(&xhci_ep->isoch->guard); 347 347 /* If not yet started, start the isochronous endpoint transfers - before first read */ 348 if (!xhci_ep->isoch _started) {348 if (!xhci_ep->isoch->started) { 349 349 xhci_trb_ring_t *ring = get_ring(hc, transfer); 350 350 /* Fill the TRB ring. */ 351 351 int err = schedule_isochronous_in_trbs(xhci_ep, ring); 352 352 if (err) { 353 fibril_mutex_unlock(&xhci_ep->isoch _guard);353 fibril_mutex_unlock(&xhci_ep->isoch->guard); 354 354 return err; 355 355 } … … 359 359 err = hc_ring_doorbell(hc, slot_id, target); 360 360 if (err) { 361 fibril_mutex_unlock(&xhci_ep->isoch _guard);361 fibril_mutex_unlock(&xhci_ep->isoch->guard); 362 362 return err; 363 363 } 364 xhci_ep->isoch _started = true;364 xhci_ep->isoch->started = true; 365 365 } 366 366 367 367 xhci_isoch_transfer_t *isoch_transfer = isoch_transfer_get_enqueue(xhci_ep); 368 368 while(!isoch_transfer) { 369 fibril_condvar_wait(&xhci_ep->isoch _avail, &xhci_ep->isoch_guard);369 fibril_condvar_wait(&xhci_ep->isoch->avail, &xhci_ep->isoch->guard); 370 370 isoch_transfer = isoch_transfer_get_enqueue(xhci_ep); 371 371 } … … 391 391 392 392 trb.parameter = isoch_transfer->data.phys; 393 isoch_transfer->size = xhci_ep->isoch _max_size;393 isoch_transfer->size = xhci_ep->isoch->max_size; 394 394 395 395 xhci_trb_ring_t *ring = get_ring(hc, transfer); 396 396 int err = schedule_isochronous_trb(ring, xhci_ep, &trb, isoch_transfer->size, 397 397 &isoch_transfer->interrupt_trb_phys); 398 fibril_mutex_unlock(&xhci_ep->isoch _guard);398 fibril_mutex_unlock(&xhci_ep->isoch->guard); 399 399 400 400 if (err) { … … 411 411 xhci_device_t *xhci_dev) 412 412 { 413 if (transfer->batch.buffer_size > xhci_ep->isoch _max_size) {413 if (transfer->batch.buffer_size > xhci_ep->isoch->max_size) { 414 414 usb_log_error("Cannot schedule an oversized isochronous transfer."); 415 415 return EINVAL; … … 425 425 426 426 static int handle_isochronous_transfer_event(xhci_hc_t *hc, xhci_trb_t *trb, xhci_endpoint_t *ep) { 427 fibril_mutex_lock(&ep->isoch _guard);427 fibril_mutex_lock(&ep->isoch->guard); 428 428 429 429 int err = EOK; … … 434 434 case XHCI_TRBC_RING_UNDERRUN: 435 435 /* Rings are unscheduled by xHC now */ 436 ep->isoch _started = false;436 ep->isoch->started = false; 437 437 /* For OUT, there was nothing to process */ 438 438 /* For IN, the buffer has overfilled, we empty the buffers and readd TRBs */ 439 ep->isoch _enqueue = ep->isoch_dequeue = 0;439 ep->isoch->enqueue = ep->isoch->dequeue = 0; 440 440 err = EIO; 441 441 break; … … 462 462 } 463 463 464 fibril_condvar_signal(&ep->isoch _avail);465 fibril_mutex_unlock(&ep->isoch _guard);464 fibril_condvar_signal(&ep->isoch->avail); 465 fibril_mutex_unlock(&ep->isoch->guard); 466 466 return err; 467 467 } -
uspace/lib/usb/include/usb/descriptor.h
rbdd8842c r17c5e62 217 217 #define USB_ED_GET_ADD_OPPS(ed) \ 218 218 ((uint16_usb2host((ed).max_packet_size) >> 11) & 0x3) 219 /** Polling interval in milliseconds. 220 * Ignored for bulk and control endpoints. 221 * Isochronous endpoints must use value 1. 222 * Interrupt endpoints any value from 1 to 255. 219 /** Polling interval. Different semantics for various (speed, type) 220 * pairs. 223 221 */ 224 222 uint8_t poll_interval;
Note:
See TracChangeset
for help on using the changeset viewer.