1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 27 /* 28 * EHCI Host Controller Driver (EHCI) 29 * 30 * The EHCI driver is a software driver which interfaces to the Universal 31 * Serial Bus layer (USBA) and the Host Controller (HC). The interface to 32 * the Host Controller is defined by the EHCI Host Controller Interface. 33 * 34 * This module contains the EHCI driver isochronous code, which handles all 35 * Checking of status of USB transfers, error recovery and callbacks. 36 */ 37 #include <sys/usb/hcd/ehci/ehcid.h> 38 #include <sys/usb/hcd/ehci/ehci_xfer.h> 39 #include <sys/usb/hcd/ehci/ehci_util.h> 40 #include <sys/usb/hcd/ehci/ehci_isoch.h> 41 #include <sys/usb/hcd/ehci/ehci_isoch_util.h> 42 #include <sys/strsun.h> 43 44 /* 45 * Isochronous initialization functions 46 */ 47 int ehci_isoc_init( 48 ehci_state_t *ehcip); 49 void ehci_isoc_cleanup( 50 ehci_state_t *ehcip); 51 void ehci_isoc_pipe_cleanup( 52 ehci_state_t *ehcip, 53 usba_pipe_handle_data_t *ph); 54 static void ehci_wait_for_isoc_completion( 55 ehci_state_t *ehcip, 56 ehci_pipe_private_t *pp); 57 58 /* 59 * Isochronous request functions 60 */ 61 ehci_isoc_xwrapper_t *ehci_allocate_isoc_resources( 62 ehci_state_t *ehcip, 63 usba_pipe_handle_data_t *ph, 64 usb_isoc_req_t *isoc_reqp, 65 usb_flags_t usb_flags); 66 int ehci_insert_isoc_req( 67 ehci_state_t *ehcip, 68 ehci_pipe_private_t *pp, 69 ehci_isoc_xwrapper_t *itw, 70 usb_flags_t usb_flags); 71 static int ehci_insert_itd_req( 72 ehci_state_t *ehcip, 73 ehci_pipe_private_t *pp, 74 ehci_isoc_xwrapper_t *itw, 75 usb_flags_t usb_flags); 76 static int ehci_insert_sitd_req( 77 ehci_state_t *ehcip, 78 ehci_pipe_private_t *pp, 79 ehci_isoc_xwrapper_t *itw, 80 usb_flags_t usb_flags); 81 static void ehci_remove_isoc_itds( 82 ehci_state_t *ehcip, 83 ehci_pipe_private_t *pp); 84 static void ehci_mark_reclaim_isoc( 85 ehci_state_t *ehcip, 86 ehci_pipe_private_t *pp); 87 static void ehci_reclaim_isoc( 88 ehci_state_t *ehcip, 89 ehci_isoc_xwrapper_t *itw, 90 ehci_itd_t *itd, 91 ehci_pipe_private_t *pp); 92 int ehci_start_isoc_polling( 93 ehci_state_t *ehcip, 94 usba_pipe_handle_data_t *ph, 95 usb_flags_t flags); 96 97 /* 98 * Isochronronous handling functions. 99 */ 100 void ehci_traverse_active_isoc_list( 101 ehci_state_t *ehcip); 102 static void ehci_handle_isoc( 103 ehci_state_t *ehcip, 104 ehci_isoc_xwrapper_t *itw, 105 ehci_itd_t *itd); 106 static void ehci_handle_itd( 107 ehci_state_t *ehcip, 108 ehci_pipe_private_t *pp, 109 ehci_isoc_xwrapper_t *itw, 110 ehci_itd_t *itd, 111 void *tw_handle_callback_value); 112 static void ehci_sendup_itd_message( 113 ehci_state_t *ehcip, 114 ehci_pipe_private_t *pp, 115 ehci_isoc_xwrapper_t *itw, 116 ehci_itd_t *td, 117 usb_cr_t error); 118 void ehci_hcdi_isoc_callback( 119 usba_pipe_handle_data_t *ph, 120 ehci_isoc_xwrapper_t *itw, 121 usb_cr_t completion_reason); 122 123 124 /* 125 * Isochronous initialization functions 126 */ 127 /* 128 * Initialize all the needed resources needed by isochronous pipes. 129 */ 130 int 131 ehci_isoc_init( 132 ehci_state_t *ehcip) 133 { 134 return (ehci_allocate_isoc_pools(ehcip)); 135 } 136 137 138 /* 139 * Cleanup isochronous resources. 140 */ 141 void 142 ehci_isoc_cleanup( 143 ehci_state_t *ehcip) 144 { 145 ehci_isoc_xwrapper_t *itw; 146 ehci_pipe_private_t *pp; 147 ehci_itd_t *itd; 148 int i, ctrl, rval; 149 150 /* Free all the buffers */ 151 if (ehcip->ehci_itd_pool_addr && ehcip->ehci_itd_pool_mem_handle) { 152 for (i = 0; i < ehci_get_itd_pool_size(); i ++) { 153 itd = &ehcip->ehci_itd_pool_addr[i]; 154 ctrl = Get_ITD(ehcip-> 155 ehci_itd_pool_addr[i].itd_state); 156 157 if ((ctrl != EHCI_ITD_FREE) && 158 (ctrl != EHCI_ITD_DUMMY) && 159 (itd->itd_trans_wrapper)) { 160 161 mutex_enter(&ehcip->ehci_int_mutex); 162 163 itw = (ehci_isoc_xwrapper_t *) 164 EHCI_LOOKUP_ID((uint32_t) 165 Get_ITD(itd->itd_trans_wrapper)); 166 167 /* Obtain the pipe private structure */ 168 pp = itw->itw_pipe_private; 169 170 ehci_deallocate_itd(ehcip, itw, itd); 171 ehci_deallocate_itw(ehcip, pp, itw); 172 173 mutex_exit(&ehcip->ehci_int_mutex); 174 } 175 } 176 177 /* 178 * If EHCI_ITD_POOL_BOUND flag is set, then unbind 179 * the handle for ITD pools. 180 */ 181 if ((ehcip->ehci_dma_addr_bind_flag & 182 EHCI_ITD_POOL_BOUND) == EHCI_ITD_POOL_BOUND) { 183 184 rval = ddi_dma_unbind_handle( 185 ehcip->ehci_itd_pool_dma_handle); 186 187 ASSERT(rval == DDI_SUCCESS); 188 } 189 ddi_dma_mem_free(&ehcip->ehci_itd_pool_mem_handle); 190 } 191 192 /* Free the ITD pool */ 193 if (ehcip->ehci_itd_pool_dma_handle) { 194 ddi_dma_free_handle(&ehcip->ehci_itd_pool_dma_handle); 195 } 196 } 197 198 199 /* 200 * ehci_isoc_pipe_cleanup 201 * 202 * Cleanup ehci isoc pipes. 203 */ 204 void ehci_isoc_pipe_cleanup( 205 ehci_state_t *ehcip, 206 usba_pipe_handle_data_t *ph) { 207 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 208 uint_t pipe_state = pp->pp_state; 209 usb_cr_t completion_reason; 210 211 USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 212 "ehci_isoc_pipe_cleanup: ph = 0x%p", (void *)ph); 213 214 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 215 216 /* Stop all further processing */ 217 ehci_mark_reclaim_isoc(ehcip, pp); 218 219 /* 220 * Wait for processing all completed transfers 221 * and send result upstream/ 222 */ 223 ehci_wait_for_isoc_completion(ehcip, pp); 224 225 /* Go ahead and remove all remaining itds if there are any */ 226 ehci_remove_isoc_itds(ehcip, pp); 227 228 switch (pipe_state) { 229 case EHCI_PIPE_STATE_CLOSE: 230 completion_reason = USB_CR_PIPE_CLOSING; 231 break; 232 case EHCI_PIPE_STATE_RESET: 233 case EHCI_PIPE_STATE_STOP_POLLING: 234 /* Set completion reason */ 235 completion_reason = (pipe_state == 236 EHCI_PIPE_STATE_RESET) ? 237 USB_CR_PIPE_RESET: USB_CR_STOPPED_POLLING; 238 239 /* Set pipe state to idle */ 240 pp->pp_state = EHCI_PIPE_STATE_IDLE; 241 242 break; 243 } 244 245 /* 246 * Do the callback for the original client 247 * periodic IN request. 248 */ 249 if ((ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK) == 250 USB_EP_DIR_IN) { 251 252 ehci_do_client_periodic_in_req_callback( 253 ehcip, pp, completion_reason); 254 } 255 } 256 257 258 /* 259 * ehci_wait_for_transfers_completion: 260 * 261 * Wait for processing all completed transfers and to send results 262 * to upstream. 263 */ 264 static void 265 ehci_wait_for_isoc_completion( 266 ehci_state_t *ehcip, 267 ehci_pipe_private_t *pp) 268 { 269 clock_t xfer_cmpl_time_wait; 270 271 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 272 273 if (pp->pp_itw_head == NULL) { 274 275 return; 276 } 277 278 /* Get the number of clock ticks to wait */ 279 xfer_cmpl_time_wait = drv_usectohz(EHCI_XFER_CMPL_TIMEWAIT * 1000000); 280 281 (void) cv_timedwait(&pp->pp_xfer_cmpl_cv, 282 &ehcip->ehci_int_mutex, 283 ddi_get_lbolt() + xfer_cmpl_time_wait); 284 285 if (pp->pp_itw_head) { 286 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 287 "ehci_wait_for_isoc_completion: " 288 "No transfers completion confirmation received"); 289 } 290 } 291 292 293 /* 294 * Isochronous request functions 295 */ 296 /* 297 * ehci_allocate_isoc_resources: 298 * 299 * Calculates the number of tds necessary for a isoch transfer, and 300 * allocates all the necessary resources. 301 * 302 * Returns NULL if there is insufficient resources otherwise ITW. 303 */ 304 ehci_isoc_xwrapper_t * 305 ehci_allocate_isoc_resources( 306 ehci_state_t *ehcip, 307 usba_pipe_handle_data_t *ph, 308 usb_isoc_req_t *isoc_reqp, 309 usb_flags_t usb_flags) 310 { 311 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 312 int pipe_dir, i; 313 uint_t max_ep_pkt_size, max_isoc_xfer_size; 314 usb_isoc_pkt_descr_t *isoc_pkt_descr; 315 size_t isoc_pkt_count, isoc_pkts_length; 316 size_t itw_xfer_size = 0; 317 ehci_isoc_xwrapper_t *itw; 318 319 USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 320 "ehci_allocate_isoc_resources: flags = 0x%x", usb_flags); 321 322 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 323 324 /* 325 * Check whether pipe is in halted state. 326 */ 327 if (pp->pp_state == EHCI_PIPE_STATE_ERROR) { 328 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 329 "ehci_allocate_isoc_resources:" 330 "Pipe is in error state, need pipe reset to continue"); 331 332 return (NULL); 333 } 334 335 /* Calculate the maximum isochronous transfer size we allow */ 336 max_ep_pkt_size = (ph->p_ep.wMaxPacketSize & 337 EHCI_ITD_CTRL_MAX_PACKET_MASK) * 338 CalculateITDMultiField(ph->p_ep.wMaxPacketSize); 339 340 max_isoc_xfer_size = EHCI_MAX_ISOC_PKTS_PER_XFER * max_ep_pkt_size; 341 342 /* Get the packet descriptor and number of packets to send */ 343 if (isoc_reqp) { 344 isoc_pkt_descr = isoc_reqp->isoc_pkt_descr; 345 isoc_pkt_count = isoc_reqp->isoc_pkts_count; 346 isoc_pkts_length = isoc_reqp->isoc_pkts_length; 347 } else { 348 isoc_pkt_descr = ((usb_isoc_req_t *) 349 pp->pp_client_periodic_in_reqp)->isoc_pkt_descr; 350 351 isoc_pkt_count = ((usb_isoc_req_t *) 352 pp->pp_client_periodic_in_reqp)->isoc_pkts_count; 353 354 isoc_pkts_length = ((usb_isoc_req_t *) 355 pp->pp_client_periodic_in_reqp)->isoc_pkts_length; 356 } 357 358 /* Calculate the size of the transfer. */ 359 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK; 360 if (pipe_dir == USB_EP_DIR_IN) { 361 for (i = 0; i < isoc_pkt_count; i++) { 362 /* 363 * isoc_pkt_length is used as Transaction Length and 364 * according to EHCI spec Table 3-3, the maximum value 365 * allowed is 3072 366 */ 367 if (isoc_pkt_descr->isoc_pkt_length > 3072) { 368 369 return (NULL); 370 } 371 372 itw_xfer_size += isoc_pkt_descr->isoc_pkt_length; 373 374 isoc_pkt_descr++; 375 } 376 377 if ((isoc_pkts_length) && 378 (isoc_pkts_length != itw_xfer_size)) { 379 380 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 381 "ehci_allocate_isoc_resources: " 382 "isoc_pkts_length 0x%lx is not equal to the sum of " 383 "all pkt lengths 0x%lx in an isoc request", 384 isoc_pkts_length, itw_xfer_size); 385 386 return (NULL); 387 } 388 389 } else { 390 ASSERT(isoc_reqp != NULL); 391 itw_xfer_size = MBLKL(isoc_reqp->isoc_data); 392 } 393 394 /* Check the size of isochronous request */ 395 if (itw_xfer_size > max_isoc_xfer_size) { 396 397 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 398 "ehci_allocate_isoc_resources: Maximum isoc request " 399 "size 0x%x Given isoc request size 0x%lx", 400 max_isoc_xfer_size, itw_xfer_size); 401 402 return (NULL); 403 } 404 405 USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 406 "ehci_allocate_isoc_resources: length = 0x%lx", itw_xfer_size); 407 408 /* Allocate the itw for this request */ 409 if ((itw = ehci_allocate_itw_resources(ehcip, pp, itw_xfer_size, 410 usb_flags, isoc_pkt_count)) == NULL) { 411 412 return (NULL); 413 } 414 415 itw->itw_handle_callback_value = NULL; 416 417 if (pipe_dir == USB_EP_DIR_IN) { 418 if (ehci_allocate_isoc_in_resource(ehcip, pp, itw, usb_flags) != 419 USB_SUCCESS) { 420 421 ehci_deallocate_itw(ehcip, pp, itw); 422 423 return (NULL); 424 } 425 } else { 426 if (itw->itw_length) { 427 ASSERT(isoc_reqp->isoc_data != NULL); 428 429 /* Copy the data into the buffer */ 430 bcopy(isoc_reqp->isoc_data->b_rptr, 431 itw->itw_buf, itw->itw_length); 432 433 Sync_IO_Buffer_for_device(itw->itw_dmahandle, 434 itw->itw_length); 435 } 436 itw->itw_curr_xfer_reqp = isoc_reqp; 437 } 438 439 return (itw); 440 } 441 442 443 /* 444 * ehci_insert_isoc_req: 445 * 446 * Insert an isochronous request into the Host Controller's 447 * isochronous list. 448 */ 449 int 450 ehci_insert_isoc_req( 451 ehci_state_t *ehcip, 452 ehci_pipe_private_t *pp, 453 ehci_isoc_xwrapper_t *itw, 454 usb_flags_t usb_flags) 455 { 456 int error; 457 ehci_itd_t *new_itd, *temp_itd; 458 459 USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 460 "ehci_insert_isoc_req: flags = 0x%x port status = 0x%x", 461 usb_flags, itw->itw_port_status); 462 463 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 464 465 ASSERT(itw->itw_curr_xfer_reqp != NULL); 466 ASSERT(itw->itw_curr_xfer_reqp->isoc_pkt_descr != NULL); 467 468 /* 469 * Save address of first usb isochronous packet descriptor. 470 */ 471 itw->itw_curr_isoc_pktp = itw->itw_curr_xfer_reqp->isoc_pkt_descr; 472 473 if (itw->itw_port_status == USBA_HIGH_SPEED_DEV) { 474 error = ehci_insert_itd_req(ehcip, pp, itw, usb_flags); 475 } else { 476 error = ehci_insert_sitd_req(ehcip, pp, itw, usb_flags); 477 } 478 479 /* Either all the isocs will be added or none of them will */ 480 error = ehci_insert_isoc_to_pfl(ehcip, pp, itw); 481 482 if (error != USB_SUCCESS) { 483 /* 484 * Deallocate all the ITDs, otherwise they will be 485 * lost forever. 486 */ 487 new_itd = itw->itw_itd_head; 488 while (new_itd) { 489 temp_itd = ehci_itd_iommu_to_cpu(ehcip, 490 Get_ITD(new_itd->itd_itw_next_itd)); 491 ehci_deallocate_itd(ehcip, itw, new_itd); 492 new_itd = temp_itd; 493 } 494 if ((itw->itw_direction == USB_EP_DIR_IN)) { 495 ehci_deallocate_isoc_in_resource(ehcip, pp, itw); 496 497 if (pp->pp_cur_periodic_req_cnt) { 498 /* 499 * Set pipe state to stop polling and 500 * error to no resource. Don't insert 501 * any more isoch polling requests. 502 */ 503 pp->pp_state = 504 EHCI_PIPE_STATE_STOP_POLLING; 505 pp->pp_error = error; 506 } else { 507 /* Set periodic in pipe state to idle */ 508 pp->pp_state = EHCI_PIPE_STATE_IDLE; 509 } 510 511 return (error); 512 } 513 514 /* Save how many packets and data actually went */ 515 itw->itw_num_itds = 0; 516 itw->itw_length = 0; 517 } 518 519 /* 520 * Reset back to the address of first usb isochronous 521 * packet descriptor. 522 */ 523 itw->itw_curr_isoc_pktp = itw->itw_curr_xfer_reqp->isoc_pkt_descr; 524 525 /* Reset the CONTINUE flag */ 526 pp->pp_flag &= ~EHCI_ISOC_XFER_CONTINUE; 527 528 return (error); 529 } 530 531 532 /* 533 * ehci_insert_itd_req: 534 * 535 * Insert an ITD request into the Host Controller's isochronous list. 536 */ 537 /* ARGSUSED */ 538 static int 539 ehci_insert_itd_req( 540 ehci_state_t *ehcip, 541 ehci_pipe_private_t *pp, 542 ehci_isoc_xwrapper_t *itw, 543 usb_flags_t usb_flags) 544 { 545 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle; 546 usb_isoc_req_t *curr_isoc_reqp; 547 usb_isoc_pkt_descr_t *curr_isoc_pkt_descr; 548 size_t curr_isoc_xfer_offset; 549 size_t isoc_pkt_length; 550 uint_t count, xactcount; 551 uint32_t xact_status; 552 uint32_t page, pageselected; 553 uint32_t buf[EHCI_ITD_BUFFER_LIST_SIZE]; 554 uint16_t index = 0; 555 uint16_t multi = 0; 556 ehci_itd_t *new_itd; 557 558 /* 559 * Get the current isochronous request and packet 560 * descriptor pointers. 561 */ 562 curr_isoc_reqp = (usb_isoc_req_t *)itw->itw_curr_xfer_reqp; 563 564 page = itw->itw_cookie.dmac_address; 565 ASSERT((page % EHCI_4K_ALIGN) == 0); 566 567 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 568 "ehci_insert_itd_req: itw_curr_xfer_reqp = 0x%p page = 0x%x," 569 " pagesize = 0x%lx", (void *)itw->itw_curr_xfer_reqp, page, 570 itw->itw_cookie.dmac_size); 571 572 /* Insert all the isochronous TDs */ 573 count = 0; 574 curr_isoc_xfer_offset = 0; 575 576 while (count < curr_isoc_reqp->isoc_pkts_count) { 577 578 /* Grab a new itd */ 579 new_itd = itw->itw_itd_free_list; 580 581 ASSERT(new_itd != NULL); 582 583 itw->itw_itd_free_list = ehci_itd_iommu_to_cpu(ehcip, 584 Get_ITD(new_itd->itd_link_ptr)); 585 Set_ITD(new_itd->itd_link_ptr, NULL); 586 587 bzero(buf, EHCI_ITD_BUFFER_LIST_SIZE * sizeof (uint32_t)); 588 589 multi = CalculateITDMultiField(ph->p_ep.wMaxPacketSize); 590 591 if (multi > EHCI_ITD_CTRL_MULTI_MASK) { 592 USB_DPRINTF_L2(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 593 "ehci_insert_itd_req: Wrong multi value."); 594 595 return (USB_FAILURE); 596 } 597 598 /* Fill 8 transaction for every iTD */ 599 for (xactcount = 0, pageselected = 0; 600 xactcount < EHCI_ITD_CTRL_LIST_SIZE; xactcount++) { 601 602 curr_isoc_pkt_descr = itw->itw_curr_isoc_pktp; 603 604 isoc_pkt_length = 605 curr_isoc_pkt_descr->isoc_pkt_length; 606 607 curr_isoc_pkt_descr->isoc_pkt_actual_length 608 = (ushort_t)isoc_pkt_length; 609 610 xact_status = 0; 611 612 if (pageselected < EHCI_ITD_BUFFER_LIST_SIZE) { 613 614 buf[pageselected] |= page; 615 } else { 616 USB_DPRINTF_L2(PRINT_MASK_INTR, 617 ehcip->ehci_log_hdl, 618 "ehci_insert_itd_req: " 619 "Error in buffer pointer."); 620 621 return (USB_FAILURE); 622 } 623 624 xact_status = (uint32_t)curr_isoc_xfer_offset; 625 xact_status |= (pageselected << 12); 626 xact_status |= isoc_pkt_length << 16; 627 xact_status |= EHCI_ITD_XFER_ACTIVE; 628 629 /* Set IOC on the last TD. */ 630 if (count == (curr_isoc_reqp->isoc_pkts_count - 1)) { 631 xact_status |= EHCI_ITD_XFER_IOC_ON; 632 } 633 634 USB_DPRINTF_L3(PRINT_MASK_INTR, 635 ehcip->ehci_log_hdl, 636 "ehci_insert_itd_req: count = 0x%x multi = %d" 637 "status = 0x%x page = 0x%x index = %d " 638 "pageselected = %d isoc_pkt_length = 0x%lx", 639 xactcount, multi, xact_status, page, 640 index, pageselected, isoc_pkt_length); 641 642 /* Fill in the new itd */ 643 Set_ITD_BODY(new_itd, xactcount, xact_status); 644 645 itw->itw_curr_isoc_pktp++; 646 Set_ITD_INDEX(new_itd, xactcount, index++); 647 648 curr_isoc_xfer_offset += isoc_pkt_length; 649 650 if (curr_isoc_xfer_offset >= EHCI_4K_ALIGN) { 651 pageselected ++; 652 page += EHCI_4K_ALIGN; 653 curr_isoc_xfer_offset -= EHCI_4K_ALIGN; 654 } 655 656 count ++; 657 if (count >= curr_isoc_reqp->isoc_pkts_count) { 658 659 break; 660 } 661 } 662 663 buf[0] |= (itw->itw_endpoint_num << 8); 664 buf[0] |= itw->itw_device_addr; 665 buf[1] |= ph->p_ep.wMaxPacketSize & 666 EHCI_ITD_CTRL_MAX_PACKET_MASK; 667 668 if (itw->itw_direction == USB_EP_DIR_IN) { 669 buf[1] |= EHCI_ITD_CTRL_DIR_IN; 670 } 671 buf[2] |= multi; 672 673 Set_ITD_BODY(new_itd, EHCI_ITD_BUFFER0, buf[0]); 674 Set_ITD_BODY(new_itd, EHCI_ITD_BUFFER1, buf[1]); 675 Set_ITD_BODY(new_itd, EHCI_ITD_BUFFER2, buf[2]); 676 Set_ITD_BODY(new_itd, EHCI_ITD_BUFFER3, buf[3]); 677 Set_ITD_BODY(new_itd, EHCI_ITD_BUFFER4, buf[4]); 678 Set_ITD_BODY(new_itd, EHCI_ITD_BUFFER5, buf[5]); 679 Set_ITD_BODY(new_itd, EHCI_ITD_BUFFER6, buf[6]); 680 681 Set_ITD(new_itd->itd_state, EHCI_ITD_ACTIVE); 682 ehci_print_itd(ehcip, new_itd); 683 684 /* 685 * Add this itd to the itw before we add it in the PFL 686 * If adding it to the PFL fails, we will have to cleanup. 687 */ 688 ehci_insert_itd_on_itw(ehcip, itw, new_itd); 689 690 } 691 692 return (USB_SUCCESS); 693 } 694 695 696 /* 697 * ehci_insert_sitd_req: 698 * 699 * Insert an SITD request into the Host Controller's isochronous list. 700 */ 701 /* ARGSUSED */ 702 static int 703 ehci_insert_sitd_req( 704 ehci_state_t *ehcip, 705 ehci_pipe_private_t *pp, 706 ehci_isoc_xwrapper_t *itw, 707 usb_flags_t usb_flags) 708 { 709 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle; 710 usb_isoc_req_t *curr_isoc_reqp; 711 usb_isoc_pkt_descr_t *curr_isoc_pkt_descr; 712 size_t curr_isoc_xfer_offset; 713 size_t isoc_pkt_length; 714 uint_t count; 715 uint32_t ctrl, uframe_sched, xfer_state; 716 uint32_t page0, page1, prev_sitd; 717 uint32_t ssplit_count; 718 ehci_itd_t *new_sitd; 719 720 /* 721 * Get the current isochronous request and packet 722 * descriptor pointers. 723 */ 724 curr_isoc_reqp = (usb_isoc_req_t *)itw->itw_curr_xfer_reqp; 725 726 /* Set the ctrl field */ 727 ctrl = 0; 728 if (itw->itw_direction == USB_EP_DIR_IN) { 729 ctrl |= EHCI_SITD_CTRL_DIR_IN; 730 } else { 731 ctrl |= EHCI_SITD_CTRL_DIR_OUT; 732 } 733 734 ctrl |= (itw->itw_hub_port << EHCI_SITD_CTRL_PORT_SHIFT) & 735 EHCI_SITD_CTRL_PORT_MASK; 736 ctrl |= (itw->itw_hub_addr << EHCI_SITD_CTRL_HUB_SHIFT) & 737 EHCI_SITD_CTRL_HUB_MASK; 738 ctrl |= (itw->itw_endpoint_num << EHCI_SITD_CTRL_END_PT_SHIFT) & 739 EHCI_SITD_CTRL_END_PT_MASK; 740 ctrl |= (itw->itw_device_addr << EHCI_SITD_CTRL_DEVICE_SHIFT) & 741 EHCI_SITD_CTRL_DEVICE_MASK; 742 743 /* Set the micro frame schedule */ 744 uframe_sched = 0; 745 uframe_sched |= (pp->pp_smask << EHCI_SITD_UFRAME_SMASK_SHIFT) & 746 EHCI_SITD_UFRAME_SMASK_MASK; 747 uframe_sched |= (pp->pp_cmask << EHCI_SITD_UFRAME_CMASK_SHIFT) & 748 EHCI_SITD_UFRAME_CMASK_MASK; 749 750 /* Set the default page information */ 751 page0 = itw->itw_cookie.dmac_address; 752 page1 = 0; 753 754 prev_sitd = EHCI_ITD_LINK_PTR_INVALID; 755 756 /* 757 * Save the number of isochronous TDs needs 758 * to be insert to complete current isochronous request. 759 */ 760 itw->itw_num_itds = curr_isoc_reqp->isoc_pkts_count; 761 762 /* Insert all the isochronous TDs */ 763 for (count = 0, curr_isoc_xfer_offset = 0; 764 count < itw->itw_num_itds; count++) { 765 766 curr_isoc_pkt_descr = itw->itw_curr_isoc_pktp; 767 768 isoc_pkt_length = curr_isoc_pkt_descr->isoc_pkt_length; 769 curr_isoc_pkt_descr->isoc_pkt_actual_length = 770 (ushort_t)isoc_pkt_length; 771 772 /* Set the transfer state information */ 773 xfer_state = 0; 774 775 if (itw->itw_direction == USB_EP_DIR_IN) { 776 /* Set the size to the max packet size */ 777 xfer_state |= (ph->p_ep.wMaxPacketSize << 778 EHCI_SITD_XFER_TOTAL_SHIFT) & 779 EHCI_SITD_XFER_TOTAL_MASK; 780 } else { 781 /* Set the size to the packet length */ 782 xfer_state |= (isoc_pkt_length << 783 EHCI_SITD_XFER_TOTAL_SHIFT) & 784 EHCI_SITD_XFER_TOTAL_MASK; 785 } 786 xfer_state |= EHCI_SITD_XFER_ACTIVE; 787 788 /* Set IOC on the last TD. */ 789 if (count == (itw->itw_num_itds - 1)) { 790 xfer_state |= EHCI_SITD_XFER_IOC_ON; 791 } 792 793 ssplit_count = isoc_pkt_length / MAX_UFRAME_SITD_XFER; 794 if (isoc_pkt_length % MAX_UFRAME_SITD_XFER) { 795 ssplit_count++; 796 } 797 798 page1 = (ssplit_count & EHCI_SITD_XFER_TCOUNT_MASK) << 799 EHCI_SITD_XFER_TCOUNT_SHIFT; 800 if (ssplit_count > 1) { 801 page1 |= EHCI_SITD_XFER_TP_BEGIN; 802 } else { 803 page1 |= EHCI_SITD_XFER_TP_ALL; 804 } 805 806 /* Grab a new sitd */ 807 new_sitd = itw->itw_itd_free_list; 808 809 ASSERT(new_sitd != NULL); 810 811 itw->itw_itd_free_list = ehci_itd_iommu_to_cpu(ehcip, 812 Get_ITD(new_sitd->itd_link_ptr)); 813 Set_ITD(new_sitd->itd_link_ptr, NULL); 814 815 /* Fill in the new sitd */ 816 Set_ITD_BODY(new_sitd, EHCI_SITD_CTRL, ctrl); 817 Set_ITD_BODY(new_sitd, EHCI_SITD_UFRAME_SCHED, uframe_sched); 818 Set_ITD_BODY(new_sitd, EHCI_SITD_XFER_STATE, xfer_state); 819 Set_ITD_BODY(new_sitd, EHCI_SITD_BUFFER0, 820 page0 + curr_isoc_xfer_offset); 821 Set_ITD_BODY(new_sitd, EHCI_SITD_BUFFER1, page1); 822 Set_ITD_BODY(new_sitd, EHCI_SITD_PREV_SITD, prev_sitd); 823 824 Set_ITD(new_sitd->itd_state, EHCI_ITD_ACTIVE); 825 826 /* 827 * Add this itd to the itw before we add it in the PFL 828 * If adding it to the PFL fails, we will have to cleanup. 829 */ 830 ehci_insert_itd_on_itw(ehcip, itw, new_sitd); 831 832 itw->itw_curr_isoc_pktp++; 833 curr_isoc_xfer_offset += isoc_pkt_length; 834 } 835 836 return (USB_SUCCESS); 837 } 838 839 840 /* 841 * ehci_remove_isoc_itds: 842 * 843 * Remove all itds from the PFL. 844 */ 845 static void 846 ehci_remove_isoc_itds( 847 ehci_state_t *ehcip, 848 ehci_pipe_private_t *pp) 849 { 850 ehci_isoc_xwrapper_t *curr_itw, *next_itw; 851 ehci_itd_t *curr_itd, *next_itd; 852 853 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 854 "ehci_remove_isoc_itds: pp = 0x%p", (void *)pp); 855 856 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 857 858 curr_itw = pp->pp_itw_head; 859 while (curr_itw) { 860 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 861 "ehci_remove_isoc_itds: itw = 0x%p num itds = %d", 862 (void *)curr_itw, curr_itw->itw_num_itds); 863 864 next_itw = curr_itw->itw_next; 865 866 curr_itd = curr_itw->itw_itd_head; 867 while (curr_itd) { 868 next_itd = ehci_itd_iommu_to_cpu(ehcip, 869 Get_ITD(curr_itd->itd_itw_next_itd)); 870 871 ehci_reclaim_isoc(ehcip, curr_itw, curr_itd, pp); 872 873 curr_itd = next_itd; 874 } 875 876 ehci_deallocate_itw(ehcip, pp, curr_itw); 877 878 curr_itw = next_itw; 879 } 880 } 881 882 883 /* 884 * ehci_mark_reclaim_isoc: 885 * 886 * Set active ITDs to RECLAIM. 887 * Return number of ITD that need to be processed. 888 */ 889 static void 890 ehci_mark_reclaim_isoc( 891 ehci_state_t *ehcip, 892 ehci_pipe_private_t *pp) 893 { 894 usb_frame_number_t current_frame_number; 895 ehci_isoc_xwrapper_t *curr_itw, *next_itw; 896 ehci_itd_t *curr_itd, *next_itd; 897 uint_t ctrl; 898 uint_t isActive; 899 int i; 900 901 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 902 "ehci_mark_reclaim_isoc: pp = 0x%p", (void *)pp); 903 904 if (pp->pp_itw_head == NULL) { 905 906 return; 907 } 908 909 /* Get the current frame number. */ 910 current_frame_number = ehci_get_current_frame_number(ehcip); 911 912 /* Traverse the list of transfer descriptors */ 913 curr_itw = pp->pp_itw_head; 914 while (curr_itw) { 915 next_itw = curr_itw->itw_next; 916 917 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 918 "ehci_mark_reclaim_isoc: itw = 0x%p num itds = %d", 919 (void *)curr_itw, curr_itw->itw_num_itds); 920 921 curr_itd = curr_itw->itw_itd_head; 922 while (curr_itd) { 923 next_itd = ehci_itd_iommu_to_cpu(ehcip, 924 Get_ITD(curr_itd->itd_itw_next_itd)); 925 926 if (curr_itw->itw_port_status == USBA_HIGH_SPEED_DEV) { 927 928 for (i = 0; i < EHCI_ITD_CTRL_LIST_SIZE; i++) { 929 ctrl = Get_ITD_BODY(curr_itd, 930 EHCI_ITD_CTRL0 + i); 931 isActive = ctrl & EHCI_ITD_XFER_ACTIVE; 932 /* If still active, deactivate it */ 933 if (isActive) { 934 ctrl &= ~EHCI_ITD_XFER_ACTIVE; 935 Set_ITD_BODY(curr_itd, 936 EHCI_ITD_CTRL0 + i, 937 ctrl); 938 break; 939 } 940 } 941 } else { 942 ctrl = Get_ITD_BODY(curr_itd, 943 EHCI_SITD_XFER_STATE); 944 isActive = ctrl & EHCI_SITD_XFER_ACTIVE; 945 /* If it is still active deactivate it */ 946 if (isActive) { 947 ctrl &= ~EHCI_SITD_XFER_ACTIVE; 948 Set_ITD_BODY(curr_itd, 949 EHCI_SITD_XFER_STATE, 950 ctrl); 951 } 952 } 953 954 /* 955 * If the itd was active put it on the reclaim status, 956 * so the interrupt handler will know not to process it. 957 * Otherwise leave it alone and let the interrupt 958 * handler process it normally. 959 */ 960 if (isActive) { 961 Set_ITD(curr_itd->itd_state, EHCI_ITD_RECLAIM); 962 Set_ITD_FRAME(curr_itd->itd_reclaim_number, 963 current_frame_number); 964 ehci_remove_isoc_from_pfl(ehcip, curr_itd); 965 } 966 curr_itd = next_itd; 967 } 968 curr_itw = next_itw; 969 } 970 } 971 972 973 /* 974 * ehci_reclaim_isoc: 975 * 976 * "Reclaim" itds that were marked as RECLAIM. 977 */ 978 static void 979 ehci_reclaim_isoc( 980 ehci_state_t *ehcip, 981 ehci_isoc_xwrapper_t *itw, 982 ehci_itd_t *itd, 983 ehci_pipe_private_t *pp) 984 { 985 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 986 "ehci_reclaim_isoc: itd = 0x%p", (void *)itd); 987 988 /* 989 * These are itds that were marked "RECLAIM" 990 * by the pipe cleanup. 991 * 992 * Decrement the num_itds and the periodic in 993 * request count if necessary. 994 */ 995 if ((--itw->itw_num_itds == 0) && (itw->itw_curr_xfer_reqp)) { 996 if (itw->itw_direction == USB_EP_DIR_IN) { 997 998 pp->pp_cur_periodic_req_cnt--; 999 1000 ehci_deallocate_isoc_in_resource(ehcip, pp, itw); 1001 } else { 1002 ehci_hcdi_isoc_callback(pp->pp_pipe_handle, itw, 1003 USB_CR_FLUSHED); 1004 } 1005 } 1006 1007 /* Deallocate this transfer descriptor */ 1008 ehci_deallocate_itd(ehcip, itw, itd); 1009 } 1010 1011 1012 /* 1013 * ehci_start_isoc_polling: 1014 * 1015 * Insert the number of periodic requests corresponding to polling 1016 * interval as calculated during pipe open. 1017 */ 1018 int 1019 ehci_start_isoc_polling( 1020 ehci_state_t *ehcip, 1021 usba_pipe_handle_data_t *ph, 1022 usb_flags_t flags) 1023 { 1024 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 1025 ehci_isoc_xwrapper_t *itw_list, *itw; 1026 int i, total_itws; 1027 int error = USB_SUCCESS; 1028 1029 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1030 "ehci_start_isoc_polling:"); 1031 1032 /* Allocate all the necessary resources for the IN transfer */ 1033 itw_list = NULL; 1034 total_itws = pp->pp_max_periodic_req_cnt - pp->pp_cur_periodic_req_cnt; 1035 for (i = 0; i < total_itws; i += 1) { 1036 itw = ehci_allocate_isoc_resources(ehcip, ph, NULL, flags); 1037 if (itw == NULL) { 1038 error = USB_NO_RESOURCES; 1039 /* There are not enough resources deallocate the ITWs */ 1040 itw = itw_list; 1041 while (itw != NULL) { 1042 itw_list = itw->itw_next; 1043 ehci_deallocate_isoc_in_resource( 1044 ehcip, pp, itw); 1045 ehci_deallocate_itw(ehcip, pp, itw); 1046 itw = itw_list; 1047 } 1048 1049 return (error); 1050 } else { 1051 if (itw_list == NULL) { 1052 itw_list = itw; 1053 } 1054 } 1055 } 1056 1057 i = 0; 1058 while (pp->pp_cur_periodic_req_cnt < pp->pp_max_periodic_req_cnt) { 1059 1060 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1061 "ehci_start_isoc_polling: max = %d curr = %d itw = %p:", 1062 pp->pp_max_periodic_req_cnt, pp->pp_cur_periodic_req_cnt, 1063 (void *)itw_list); 1064 1065 itw = itw_list; 1066 itw_list = itw->itw_next; 1067 1068 error = ehci_insert_isoc_req(ehcip, pp, itw, flags); 1069 1070 if (error == USB_SUCCESS) { 1071 pp->pp_cur_periodic_req_cnt++; 1072 } else { 1073 /* 1074 * Deallocate the remaining tw 1075 * The current tw should have already been deallocated 1076 */ 1077 itw = itw_list; 1078 while (itw != NULL) { 1079 itw_list = itw->itw_next; 1080 ehci_deallocate_isoc_in_resource( 1081 ehcip, pp, itw); 1082 ehci_deallocate_itw(ehcip, pp, itw); 1083 itw = itw_list; 1084 } 1085 /* 1086 * If this is the first req return an error. 1087 * Otherwise return success. 1088 */ 1089 if (i != 0) { 1090 error = USB_SUCCESS; 1091 } 1092 1093 break; 1094 } 1095 i++; 1096 } 1097 1098 return (error); 1099 } 1100 1101 1102 /* 1103 * Isochronronous handling functions. 1104 */ 1105 /* 1106 * ehci_traverse_active_isoc_list: 1107 */ 1108 void 1109 ehci_traverse_active_isoc_list( 1110 ehci_state_t *ehcip) 1111 { 1112 ehci_isoc_xwrapper_t *curr_itw; 1113 ehci_itd_t *curr_itd, *next_itd; 1114 uint_t state; 1115 ehci_pipe_private_t *pp; 1116 1117 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1118 "ehci_traverse_active_isoc_list:"); 1119 1120 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1121 1122 /* Sync ITD pool */ 1123 Sync_ITD_Pool(ehcip); 1124 1125 /* Traverse the list of done itds */ 1126 curr_itd = ehci_create_done_itd_list(ehcip); 1127 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1128 "ehci_traverse_active_isoc_list: current itd = 0x%p", 1129 (void *)curr_itd); 1130 1131 while (curr_itd) { 1132 /* Save the next_itd */ 1133 next_itd = ehci_itd_iommu_to_cpu(ehcip, 1134 Get_ITD(curr_itd->itd_next_active_itd)); 1135 1136 /* Get the transfer wrapper and the pp */ 1137 curr_itw = (ehci_isoc_xwrapper_t *)EHCI_LOOKUP_ID( 1138 (uint32_t)Get_ITD(curr_itd->itd_trans_wrapper)); 1139 pp = curr_itw->itw_pipe_private; 1140 1141 if (curr_itw->itw_port_status == USBA_HIGH_SPEED_DEV) { 1142 ehci_print_itd(ehcip, curr_itd); 1143 } else { 1144 ehci_print_sitd(ehcip, curr_itd); 1145 } 1146 1147 /* Get the ITD state */ 1148 state = Get_ITD(curr_itd->itd_state); 1149 1150 /* Only process the ITDs marked as active. */ 1151 if (state == EHCI_ITD_ACTIVE) { 1152 ehci_parse_isoc_error(ehcip, curr_itw, curr_itd); 1153 ehci_handle_isoc(ehcip, curr_itw, curr_itd); 1154 } else { 1155 ASSERT(state == EHCI_ITD_RECLAIM); 1156 ehci_reclaim_isoc(ehcip, curr_itw, curr_itd, pp); 1157 } 1158 1159 /* 1160 * Deallocate the transfer wrapper if there are no more 1161 * ITD's for the transfer wrapper. ehci_deallocate_itw() 1162 * will not deallocate the tw for a periodic in endpoint 1163 * since it will always have a ITD attached to it. 1164 */ 1165 ehci_deallocate_itw(ehcip, pp, curr_itw); 1166 1167 /* Check any ISOC is waiting for transfers completion event */ 1168 if (pp->pp_itw_head == NULL) { 1169 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1170 "ehci_traverse_active_isoc_list: " 1171 "Sent transfers completion event pp = 0x%p", 1172 (void *)pp); 1173 cv_signal(&pp->pp_xfer_cmpl_cv); 1174 } 1175 1176 curr_itd = next_itd; 1177 1178 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1179 "ehci_traverse_active_isoc_list: state = 0x%x " 1180 "pp = 0x%p itw = 0x%p itd = 0x%p next_itd = 0x%p", 1181 state, (void *)pp, (void *)curr_itw, (void *)curr_itd, 1182 (void *)next_itd); 1183 } 1184 } 1185 1186 1187 static void 1188 ehci_handle_isoc( 1189 ehci_state_t *ehcip, 1190 ehci_isoc_xwrapper_t *itw, 1191 ehci_itd_t *itd) 1192 { 1193 ehci_pipe_private_t *pp; /* Pipe private field */ 1194 1195 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1196 1197 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1198 "ehci_handle_isoc:"); 1199 1200 /* Obtain the pipe private structure */ 1201 pp = itw->itw_pipe_private; 1202 1203 ehci_handle_itd(ehcip, pp, itw, itd, itw->itw_handle_callback_value); 1204 } 1205 1206 1207 /* 1208 * ehci_handle_itd: 1209 * 1210 * Handle an (split) isochronous transfer descriptor. 1211 * This function will deallocate the itd from the list as well. 1212 */ 1213 /* ARGSUSED */ 1214 static void 1215 ehci_handle_itd( 1216 ehci_state_t *ehcip, 1217 ehci_pipe_private_t *pp, 1218 ehci_isoc_xwrapper_t *itw, 1219 ehci_itd_t *itd, 1220 void *tw_handle_callback_value) 1221 { 1222 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle; 1223 usb_isoc_req_t *curr_isoc_reqp = 1224 (usb_isoc_req_t *)itw->itw_curr_xfer_reqp; 1225 int error = USB_SUCCESS; 1226 int i, index; 1227 1228 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1229 "ehci_handle_itd: pp=0x%p itw=0x%p itd=0x%p " 1230 "isoc_reqp=0%p data=0x%p", (void *)pp, (void *)itw, (void *)itd, 1231 (void *)curr_isoc_reqp, (void *)curr_isoc_reqp->isoc_data); 1232 1233 if (itw->itw_port_status == USBA_HIGH_SPEED_DEV && 1234 curr_isoc_reqp != NULL) { 1235 1236 for (i = 0; i < EHCI_ITD_CTRL_LIST_SIZE; i++) { 1237 1238 index = Get_ITD_INDEX(itd, i); 1239 if (index == EHCI_ITD_UNUSED_INDEX) { 1240 1241 continue; 1242 } 1243 curr_isoc_reqp-> 1244 isoc_pkt_descr[index].isoc_pkt_actual_length = 1245 (Get_ITD_BODY(itd, i) & EHCI_ITD_XFER_LENGTH) >> 16; 1246 } 1247 } 1248 1249 /* 1250 * Decrement the ITDs counter and check whether all the isoc 1251 * data has been send or received. If ITDs counter reaches 1252 * zero then inform client driver about completion current 1253 * isoc request. Otherwise wait for completion of other isoc 1254 * ITDs or transactions on this pipe. 1255 */ 1256 if (--itw->itw_num_itds != 0) { 1257 /* Deallocate this transfer descriptor */ 1258 ehci_deallocate_itd(ehcip, itw, itd); 1259 1260 return; 1261 } 1262 1263 /* 1264 * If this is a isoc in pipe, return the data to the client. 1265 * For a isoc out pipe, there is no need to do anything. 1266 */ 1267 if (itw->itw_direction == USB_EP_DIR_OUT) { 1268 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1269 "ehci_handle_itd: Isoc out pipe, isoc_reqp=0x%p, data=0x%p", 1270 (void *)curr_isoc_reqp, (void *)curr_isoc_reqp->isoc_data); 1271 1272 /* Do the callback */ 1273 ehci_hcdi_isoc_callback(ph, itw, USB_CR_OK); 1274 1275 /* Deallocate this transfer descriptor */ 1276 ehci_deallocate_itd(ehcip, itw, itd); 1277 1278 return; 1279 } 1280 1281 /* Decrement number of IN isochronous request count */ 1282 pp->pp_cur_periodic_req_cnt--; 1283 1284 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1285 "ehci_handle_itd: pp_cur_periodic_req_cnt = 0x%x ", 1286 pp->pp_cur_periodic_req_cnt); 1287 1288 /* Call ehci_sendup_itd_message to send message to upstream */ 1289 ehci_sendup_itd_message(ehcip, pp, itw, itd, USB_CR_OK); 1290 1291 /* Deallocate this transfer descriptor */ 1292 ehci_deallocate_itd(ehcip, itw, itd); 1293 1294 /* 1295 * If isochronous pipe state is still active, insert next isochronous 1296 * request into the Host Controller's isochronous list. 1297 */ 1298 if (pp->pp_state != EHCI_PIPE_STATE_ACTIVE) { 1299 1300 return; 1301 } 1302 1303 if ((error = ehci_allocate_isoc_in_resource(ehcip, pp, itw, 0)) == 1304 USB_SUCCESS) { 1305 curr_isoc_reqp = (usb_isoc_req_t *)itw->itw_curr_xfer_reqp; 1306 1307 ASSERT(curr_isoc_reqp != NULL); 1308 1309 itw->itw_num_itds = ehci_calc_num_itds(itw, 1310 curr_isoc_reqp->isoc_pkts_count); 1311 1312 if (ehci_allocate_itds_for_itw(ehcip, itw, itw->itw_num_itds) != 1313 USB_SUCCESS) { 1314 ehci_deallocate_isoc_in_resource(ehcip, pp, itw); 1315 itw->itw_num_itds = 0; 1316 error = USB_FAILURE; 1317 } 1318 } 1319 1320 if ((error != USB_SUCCESS) || 1321 (ehci_insert_isoc_req(ehcip, pp, itw, 0) != USB_SUCCESS)) { 1322 /* 1323 * Set pipe state to stop polling and error to no 1324 * resource. Don't insert any more isoch polling 1325 * requests. 1326 */ 1327 pp->pp_state = EHCI_PIPE_STATE_STOP_POLLING; 1328 pp->pp_error = USB_CR_NO_RESOURCES; 1329 1330 } else { 1331 /* Increment number of IN isochronous request count */ 1332 pp->pp_cur_periodic_req_cnt++; 1333 1334 ASSERT(pp->pp_cur_periodic_req_cnt == 1335 pp->pp_max_periodic_req_cnt); 1336 } 1337 } 1338 1339 1340 /* 1341 * ehci_sendup_qtd_message: 1342 * copy data, if necessary and do callback 1343 */ 1344 /* ARGSUSED */ 1345 static void 1346 ehci_sendup_itd_message( 1347 ehci_state_t *ehcip, 1348 ehci_pipe_private_t *pp, 1349 ehci_isoc_xwrapper_t *itw, 1350 ehci_itd_t *td, 1351 usb_cr_t error) 1352 { 1353 usb_isoc_req_t *isoc_reqp = itw->itw_curr_xfer_reqp; 1354 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle; 1355 size_t length; 1356 uchar_t *buf; 1357 mblk_t *mp; 1358 1359 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1360 1361 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1362 "ehci_sendup_itd_message:"); 1363 1364 ASSERT(itw != NULL); 1365 1366 length = itw->itw_length; 1367 1368 /* Copy the data into the mblk_t */ 1369 buf = (uchar_t *)itw->itw_buf; 1370 1371 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1372 "ehci_sendup_itd_message: length %ld error %d", length, error); 1373 1374 /* Get the message block */ 1375 mp = isoc_reqp->isoc_data; 1376 1377 ASSERT(mp != NULL); 1378 1379 if (length) { 1380 /* Sync IO buffer */ 1381 Sync_IO_Buffer(itw->itw_dmahandle, length); 1382 1383 /* Copy the data into the message */ 1384 ddi_rep_get8(itw->itw_accesshandle, 1385 mp->b_rptr, buf, length, DDI_DEV_AUTOINCR); 1386 1387 /* Increment the write pointer */ 1388 mp->b_wptr = mp->b_wptr + length; 1389 } else { 1390 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1391 "ehci_sendup_itd_message: Zero length packet"); 1392 } 1393 1394 ehci_hcdi_isoc_callback(ph, itw, error); 1395 } 1396 1397 1398 /* 1399 * ehci_hcdi_isoc_callback: 1400 * 1401 * Convenience wrapper around usba_hcdi_cb() other than root hub. 1402 */ 1403 void 1404 ehci_hcdi_isoc_callback( 1405 usba_pipe_handle_data_t *ph, 1406 ehci_isoc_xwrapper_t *itw, 1407 usb_cr_t completion_reason) 1408 { 1409 ehci_state_t *ehcip = ehci_obtain_state( 1410 ph->p_usba_device->usb_root_hub_dip); 1411 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 1412 usb_opaque_t curr_xfer_reqp; 1413 uint_t pipe_state = 0; 1414 1415 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1416 "ehci_hcdi_isoc_callback: ph = 0x%p, itw = 0x%p, cr = 0x%x", 1417 (void *)ph, (void *)itw, completion_reason); 1418 1419 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1420 1421 /* Set the pipe state as per completion reason */ 1422 switch (completion_reason) { 1423 case USB_CR_OK: 1424 pipe_state = pp->pp_state; 1425 break; 1426 case USB_CR_NO_RESOURCES: 1427 case USB_CR_NOT_SUPPORTED: 1428 case USB_CR_PIPE_RESET: 1429 case USB_CR_STOPPED_POLLING: 1430 pipe_state = EHCI_PIPE_STATE_IDLE; 1431 break; 1432 case USB_CR_PIPE_CLOSING: 1433 break; 1434 } 1435 1436 pp->pp_state = pipe_state; 1437 1438 if (itw && itw->itw_curr_xfer_reqp) { 1439 curr_xfer_reqp = (usb_opaque_t)itw->itw_curr_xfer_reqp; 1440 itw->itw_curr_xfer_reqp = NULL; 1441 } else { 1442 ASSERT(pp->pp_client_periodic_in_reqp != NULL); 1443 1444 curr_xfer_reqp = pp->pp_client_periodic_in_reqp; 1445 pp->pp_client_periodic_in_reqp = NULL; 1446 } 1447 1448 ASSERT(curr_xfer_reqp != NULL); 1449 1450 mutex_exit(&ehcip->ehci_int_mutex); 1451 1452 usba_hcdi_cb(ph, curr_xfer_reqp, completion_reason); 1453 1454 mutex_enter(&ehcip->ehci_int_mutex); 1455 } 1456