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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * EHCI Host Controller Driver (EHCI) 31 * 32 * The EHCI driver is a software driver which interfaces to the Universal 33 * Serial Bus layer (USBA) and the Host Controller (HC). The interface to 34 * the Host Controller is defined by the EHCI Host Controller Interface. 35 * 36 * This module contains the EHCI driver isochronous code, which handles all 37 * Checking of status of USB transfers, error recovery and callbacks. 38 */ 39 #include <sys/usb/hcd/ehci/ehcid.h> 40 #include <sys/usb/hcd/ehci/ehci_xfer.h> 41 #include <sys/usb/hcd/ehci/ehci_util.h> 42 43 /* Adjustable variables for the size of isoc pools */ 44 int ehci_itd_pool_size = EHCI_ITD_POOL_SIZE; 45 46 /* 47 * pool functions 48 */ 49 int ehci_allocate_isoc_pools( 50 ehci_state_t *ehcip); 51 int ehci_get_itd_pool_size(); 52 53 /* 54 * Isochronous Transfer Wrapper Functions 55 */ 56 ehci_isoc_xwrapper_t *ehci_allocate_itw_resources( 57 ehci_state_t *ehcip, 58 ehci_pipe_private_t *pp, 59 size_t itw_length, 60 usb_flags_t usb_flags, 61 size_t pkt_count); 62 static ehci_isoc_xwrapper_t *ehci_allocate_itw( 63 ehci_state_t *ehcip, 64 ehci_pipe_private_t *pp, 65 size_t length, 66 usb_flags_t usb_flags); 67 void ehci_deallocate_itw( 68 ehci_state_t *ehcip, 69 ehci_pipe_private_t *pp, 70 ehci_isoc_xwrapper_t *itw); 71 static void ehci_free_itw_dma( 72 ehci_state_t *ehcip, 73 ehci_pipe_private_t *pp, 74 ehci_isoc_xwrapper_t *itw); 75 76 /* 77 * transfer descriptor functions 78 */ 79 static ehci_itd_t *ehci_allocate_itd( 80 ehci_state_t *ehcip); 81 void ehci_deallocate_itd( 82 ehci_state_t *ehcip, 83 ehci_isoc_xwrapper_t *itw, 84 ehci_itd_t *old_itd); 85 uint_t ehci_calc_num_itds( 86 ehci_isoc_xwrapper_t *itw, 87 size_t pkt_count); 88 int ehci_allocate_itds_for_itw( 89 ehci_state_t *ehcip, 90 ehci_isoc_xwrapper_t *itw, 91 uint_t itd_count); 92 static void ehci_deallocate_itds_for_itw( 93 ehci_state_t *ehcip, 94 ehci_isoc_xwrapper_t *itw); 95 void ehci_insert_itd_on_itw( 96 ehci_state_t *ehcip, 97 ehci_isoc_xwrapper_t *itw, 98 ehci_itd_t *itd); 99 void ehci_insert_itd_into_active_list( 100 ehci_state_t *ehcip, 101 ehci_itd_t *itd); 102 void ehci_remove_itd_from_active_list( 103 ehci_state_t *ehcip, 104 ehci_itd_t *itd); 105 ehci_itd_t *ehci_create_done_itd_list( 106 ehci_state_t *ehcip); 107 int ehci_insert_isoc_to_pfl( 108 ehci_state_t *ehcip, 109 ehci_pipe_private_t *pp, 110 ehci_isoc_xwrapper_t *itw); 111 void ehci_remove_isoc_from_pfl( 112 ehci_state_t *ehcip, 113 ehci_itd_t *curr_itd); 114 115 116 /* 117 * Isochronous in resource functions 118 */ 119 int ehci_allocate_isoc_in_resource( 120 ehci_state_t *ehcip, 121 ehci_pipe_private_t *pp, 122 ehci_isoc_xwrapper_t *tw, 123 usb_flags_t flags); 124 void ehci_deallocate_isoc_in_resource( 125 ehci_state_t *ehcip, 126 ehci_pipe_private_t *pp, 127 ehci_isoc_xwrapper_t *itw); 128 129 /* 130 * memory addr functions 131 */ 132 uint32_t ehci_itd_cpu_to_iommu( 133 ehci_state_t *ehcip, 134 ehci_itd_t *addr); 135 ehci_itd_t *ehci_itd_iommu_to_cpu( 136 ehci_state_t *ehcip, 137 uintptr_t addr); 138 139 /* 140 * Error parsing functions 141 */ 142 void ehci_parse_isoc_error( 143 ehci_state_t *ehcip, 144 ehci_isoc_xwrapper_t *itw, 145 ehci_itd_t *itd); 146 static usb_cr_t ehci_parse_itd_error( 147 ehci_state_t *ehcip, 148 ehci_isoc_xwrapper_t *itw, 149 ehci_itd_t *itd); 150 static usb_cr_t ehci_parse_sitd_error( 151 ehci_state_t *ehcip, 152 ehci_isoc_xwrapper_t *itw, 153 ehci_itd_t *itd); 154 155 /* 156 * print functions 157 */ 158 void ehci_print_itd( 159 ehci_state_t *ehcip, 160 ehci_itd_t *itd); 161 162 163 /* 164 * ehci_allocate_isoc_pools: 165 * 166 * Allocate the system memory for itd which are for low/full/high speed 167 * Transfer Descriptors. Must be aligned to a 32 byte boundary. 168 */ 169 int 170 ehci_allocate_isoc_pools(ehci_state_t *ehcip) 171 { 172 ddi_device_acc_attr_t dev_attr; 173 size_t real_length; 174 int result; 175 uint_t ccount; 176 int i; 177 178 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, 179 "ehci_allocate_isoc_pools:"); 180 181 /* Byte alignment */ 182 ehcip->ehci_dma_attr.dma_attr_align = EHCI_DMA_ATTR_TD_QH_ALIGNMENT; 183 184 /* Allocate the itd pool DMA handle */ 185 result = ddi_dma_alloc_handle(ehcip->ehci_dip, 186 &ehcip->ehci_dma_attr, 187 DDI_DMA_SLEEP, 188 0, 189 &ehcip->ehci_itd_pool_dma_handle); 190 191 if (result != DDI_SUCCESS) { 192 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 193 "ehci_allocate_isoc_pools: Alloc handle failed"); 194 195 return (DDI_FAILURE); 196 } 197 198 /* The host controller will be little endian */ 199 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 200 dev_attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC; 201 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 202 203 /* Allocate the memory */ 204 result = ddi_dma_mem_alloc(ehcip->ehci_itd_pool_dma_handle, 205 ehci_itd_pool_size * sizeof (ehci_itd_t), 206 &dev_attr, 207 DDI_DMA_CONSISTENT, 208 DDI_DMA_SLEEP, 209 0, 210 (caddr_t *)&ehcip->ehci_itd_pool_addr, 211 &real_length, 212 &ehcip->ehci_itd_pool_mem_handle); 213 214 if (result != DDI_SUCCESS) { 215 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 216 "ehci_allocate_isoc_pools: Alloc memory failed"); 217 218 return (DDI_FAILURE); 219 } 220 221 /* Map the ITD pool into the I/O address space */ 222 result = ddi_dma_addr_bind_handle( 223 ehcip->ehci_itd_pool_dma_handle, 224 NULL, 225 (caddr_t)ehcip->ehci_itd_pool_addr, 226 real_length, 227 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 228 DDI_DMA_SLEEP, 229 NULL, 230 &ehcip->ehci_itd_pool_cookie, 231 &ccount); 232 233 bzero((void *)ehcip->ehci_itd_pool_addr, 234 ehci_itd_pool_size * sizeof (ehci_itd_t)); 235 236 /* Process the result */ 237 if (result == DDI_DMA_MAPPED) { 238 /* The cookie count should be 1 */ 239 if (ccount != 1) { 240 USB_DPRINTF_L2(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, 241 "ehci_allocate_isoc_pools: More than 1 cookie"); 242 243 return (DDI_FAILURE); 244 } 245 } else { 246 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, 247 "ehci_allocate_isoc_pools: Result = %d", result); 248 249 ehci_decode_ddi_dma_addr_bind_handle_result(ehcip, result); 250 251 return (DDI_FAILURE); 252 } 253 254 /* 255 * DMA addresses for ITD pools are bound 256 */ 257 ehcip->ehci_dma_addr_bind_flag |= EHCI_ITD_POOL_BOUND; 258 259 /* Initialize the ITD pool */ 260 for (i = 0; i < ehci_itd_pool_size; i++) { 261 Set_ITD(ehcip->ehci_itd_pool_addr[i].itd_state, 262 EHCI_ITD_FREE); 263 } 264 265 return (DDI_SUCCESS); 266 } 267 268 269 int 270 ehci_get_itd_pool_size() 271 { 272 return (ehci_itd_pool_size); 273 } 274 275 276 /* 277 * Isochronous Transfer Wrapper Functions 278 */ 279 /* 280 * ehci_allocate_itw: 281 * 282 * Allocate an iTW and n iTD from the iTD buffer pool and places it into the 283 * ITW. It does an all or nothing transaction. 284 * 285 * Calculates the number of iTD needed based on pipe speed. 286 * For LOW/FULL speed devices, 1 iTD is needed for each packet. 287 * For HIGH speed device, 1 iTD is needed for 8 to 24 packets, depending on 288 * the multiplier for "HIGH BANDWIDTH" transfers look at 4.7 in EHCI spec. 289 * 290 * Returns NULL if there is insufficient resources otherwise ITW. 291 */ 292 ehci_isoc_xwrapper_t * 293 ehci_allocate_itw_resources( 294 ehci_state_t *ehcip, 295 ehci_pipe_private_t *pp, 296 size_t itw_length, 297 usb_flags_t usb_flags, 298 size_t pkt_count) 299 { 300 uint_t itd_count; 301 ehci_isoc_xwrapper_t *itw; 302 303 itw = ehci_allocate_itw(ehcip, pp, itw_length, usb_flags); 304 305 if (itw == NULL) { 306 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 307 "ehci_allocate_itw_resources: Unable to allocate ITW"); 308 } else { 309 itd_count = ehci_calc_num_itds(itw, pkt_count); 310 311 if (ehci_allocate_itds_for_itw(ehcip, itw, itd_count) == 312 USB_SUCCESS) { 313 itw->itw_num_itds = itd_count; 314 } else { 315 ehci_deallocate_itw(ehcip, pp, itw); 316 itw = NULL; 317 } 318 } 319 320 return (itw); 321 } 322 323 324 /* 325 * ehci_allocate_itw: 326 * 327 * Creates a Isochronous Transfer Wrapper (itw) and populate it with this 328 * endpoint's data. This involves the allocation of DMA resources. 329 * 330 * ITW Fields not set by this function: 331 * - will be populated itds are allocated 332 * num_ids 333 * itd_head 334 * itd_tail 335 * curr_xfer_reqp 336 * curr_isoc_pktp 337 * itw_itd_free_list 338 * - Should be set by the calling function 339 * itw_handle_callback_value 340 */ 341 static ehci_isoc_xwrapper_t * 342 ehci_allocate_itw( 343 ehci_state_t *ehcip, 344 ehci_pipe_private_t *pp, 345 size_t length, 346 usb_flags_t usb_flags) 347 { 348 ddi_device_acc_attr_t dev_attr; 349 int result; 350 size_t real_length; 351 uint_t ccount; /* Cookie count */ 352 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle; 353 usba_device_t *usba_device = ph->p_usba_device; 354 usb_ep_descr_t *endpoint = &ph->p_ep; 355 ehci_isoc_xwrapper_t *itw; 356 357 USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 358 "ehci_allocate_itw: length = 0x%x flags = 0x%x", 359 length, usb_flags); 360 361 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 362 363 /* Allocate space for the transfer wrapper */ 364 itw = kmem_zalloc(sizeof (ehci_isoc_xwrapper_t), KM_NOSLEEP); 365 366 if (itw == NULL) { 367 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 368 "ehci_allocate_itw: kmem_zalloc failed"); 369 370 return (NULL); 371 } 372 373 ehcip->ehci_dma_attr.dma_attr_align = EHCI_DMA_ATTR_ALIGNMENT; 374 375 /* Allocate the DMA handle */ 376 result = ddi_dma_alloc_handle(ehcip->ehci_dip, 377 &ehcip->ehci_dma_attr, 378 DDI_DMA_DONTWAIT, 379 0, 380 &itw->itw_dmahandle); 381 382 if (result != DDI_SUCCESS) { 383 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 384 "ehci_create_transfer_wrapper: Alloc handle failed"); 385 386 kmem_free(itw, sizeof (ehci_isoc_xwrapper_t)); 387 388 return (NULL); 389 } 390 391 /* no need for swapping the raw data in the buffers */ 392 dev_attr.devacc_attr_version = DDI_DEVICE_ATTR_V0; 393 dev_attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; 394 dev_attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; 395 396 /* Allocate the memory */ 397 result = ddi_dma_mem_alloc(itw->itw_dmahandle, 398 length, 399 &dev_attr, 400 DDI_DMA_CONSISTENT, 401 DDI_DMA_DONTWAIT, 402 NULL, 403 (caddr_t *)&itw->itw_buf, 404 &real_length, 405 &itw->itw_accesshandle); 406 407 if (result != DDI_SUCCESS) { 408 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 409 "ehci_create_transfer_wrapper: dma_mem_alloc fail"); 410 411 ddi_dma_free_handle(&itw->itw_dmahandle); 412 kmem_free(itw, sizeof (ehci_isoc_xwrapper_t)); 413 414 return (NULL); 415 } 416 417 ASSERT(real_length >= length); 418 419 /* Bind the handle */ 420 result = ddi_dma_addr_bind_handle(itw->itw_dmahandle, 421 NULL, 422 (caddr_t)itw->itw_buf, 423 real_length, 424 DDI_DMA_RDWR|DDI_DMA_CONSISTENT, 425 DDI_DMA_DONTWAIT, 426 NULL, 427 &itw->itw_cookie, 428 &ccount); 429 430 if (result == DDI_DMA_MAPPED) { 431 /* The cookie count should be 1 */ 432 if (ccount != 1) { 433 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 434 "ehci_create_transfer_wrapper: More than 1 cookie"); 435 436 result = ddi_dma_unbind_handle(itw->itw_dmahandle); 437 ASSERT(result == DDI_SUCCESS); 438 439 ddi_dma_mem_free(&itw->itw_accesshandle); 440 ddi_dma_free_handle(&itw->itw_dmahandle); 441 kmem_free(itw, sizeof (ehci_isoc_xwrapper_t)); 442 443 return (NULL); 444 } 445 } else { 446 ehci_decode_ddi_dma_addr_bind_handle_result(ehcip, result); 447 448 ddi_dma_mem_free(&itw->itw_accesshandle); 449 ddi_dma_free_handle(&itw->itw_dmahandle); 450 kmem_free(itw, sizeof (ehci_isoc_xwrapper_t)); 451 452 return (NULL); 453 } 454 455 /* Store a back pointer to the pipe private structure */ 456 itw->itw_pipe_private = pp; 457 if (pp->pp_itw_head == NULL) { 458 pp->pp_itw_head = itw; 459 pp->pp_itw_tail = itw; 460 } else { 461 pp->pp_itw_tail->itw_next = itw; 462 pp->pp_itw_tail = itw; 463 } 464 465 /* 466 * Store transfer information 467 * itw_buf has been allocated and will be set later 468 */ 469 itw->itw_length = length; 470 itw->itw_flags = usb_flags; 471 itw->itw_port_status = usba_device->usb_port_status; 472 itw->itw_direction = endpoint->bEndpointAddress & USB_EP_DIR_MASK; 473 474 /* 475 * Store the endpoint information that will be used by the 476 * transfer descriptors later. 477 */ 478 mutex_enter(&usba_device->usb_mutex); 479 itw->itw_hub_addr = usba_device->usb_hs_hub_addr; 480 itw->itw_hub_port = usba_device->usb_hs_hub_port; 481 itw->itw_endpoint_num = endpoint->bEndpointAddress & USB_EP_NUM_MASK; 482 itw->itw_device_addr = usba_device->usb_addr; 483 mutex_exit(&usba_device->usb_mutex); 484 485 /* Get and Store 32bit ID */ 486 itw->itw_id = EHCI_GET_ID((void *)itw); 487 ASSERT(itw->itw_id != NULL); 488 489 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 490 "ehci_create_itw: itw = 0x%p", itw); 491 492 return (itw); 493 } 494 495 496 /* 497 * ehci_deallocate_itw: 498 * 499 * Deallocate of a Isochronous Transaction Wrapper (TW) and this involves the 500 * freeing of DMA resources. 501 */ 502 void 503 ehci_deallocate_itw( 504 ehci_state_t *ehcip, 505 ehci_pipe_private_t *pp, 506 ehci_isoc_xwrapper_t *itw) 507 { 508 ehci_isoc_xwrapper_t *prev, *next; 509 510 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 511 "ehci_deallocate_itw: itw = 0x%p", itw); 512 513 /* 514 * If the transfer wrapper has no Host Controller (HC) 515 * Transfer Descriptors (ITD) associated with it, then 516 * remove the transfer wrapper. 517 */ 518 if (itw->itw_itd_head) { 519 ASSERT(itw->itw_itd_tail != NULL); 520 521 return; 522 } 523 524 ASSERT(itw->itw_itd_tail == NULL); 525 526 /* Make sure we return all the unused itd's to the pool as well */ 527 ehci_deallocate_itds_for_itw(ehcip, itw); 528 529 /* 530 * If pp->pp_tw_head and pp->pp_tw_tail are pointing to 531 * given TW then set the head and tail equal to NULL. 532 * Otherwise search for this TW in the linked TW's list 533 * and then remove this TW from the list. 534 */ 535 if (pp->pp_itw_head == itw) { 536 if (pp->pp_itw_tail == itw) { 537 pp->pp_itw_head = NULL; 538 pp->pp_itw_tail = NULL; 539 } else { 540 pp->pp_itw_head = itw->itw_next; 541 } 542 } else { 543 prev = pp->pp_itw_head; 544 next = prev->itw_next; 545 546 while (next && (next != itw)) { 547 prev = next; 548 next = next->itw_next; 549 } 550 551 if (next == itw) { 552 prev->itw_next = next->itw_next; 553 554 if (pp->pp_itw_tail == itw) { 555 pp->pp_itw_tail = prev; 556 } 557 } 558 } 559 560 /* Free this iTWs dma resources */ 561 ehci_free_itw_dma(ehcip, pp, itw); 562 } 563 564 565 /* 566 * ehci_free_itw_dma: 567 * 568 * Free the Isochronous Transfer Wrapper dma resources. 569 */ 570 /*ARGSUSED*/ 571 static void 572 ehci_free_itw_dma( 573 ehci_state_t *ehcip, 574 ehci_pipe_private_t *pp, 575 ehci_isoc_xwrapper_t *itw) 576 { 577 int rval; 578 579 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 580 "ehci_free_itw_dma: itw = 0x%p", itw); 581 582 ASSERT(itw != NULL); 583 ASSERT(itw->itw_id != NULL); 584 585 /* Free 32bit ID */ 586 EHCI_FREE_ID((uint32_t)itw->itw_id); 587 588 rval = ddi_dma_unbind_handle(itw->itw_dmahandle); 589 ASSERT(rval == DDI_SUCCESS); 590 591 ddi_dma_mem_free(&itw->itw_accesshandle); 592 ddi_dma_free_handle(&itw->itw_dmahandle); 593 594 /* Free transfer wrapper */ 595 kmem_free(itw, sizeof (ehci_isoc_xwrapper_t)); 596 } 597 598 599 /* 600 * transfer descriptor functions 601 */ 602 /* 603 * ehci_allocate_itd: 604 * 605 * Allocate a Transfer Descriptor (iTD) from the iTD buffer pool. 606 */ 607 static ehci_itd_t * 608 ehci_allocate_itd(ehci_state_t *ehcip) 609 { 610 int i, state; 611 ehci_itd_t *itd; 612 613 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 614 615 /* 616 * Search for a blank Transfer Descriptor (iTD) 617 * in the iTD buffer pool. 618 */ 619 for (i = 0; i < ehci_itd_pool_size; i ++) { 620 state = Get_ITD(ehcip->ehci_itd_pool_addr[i].itd_state); 621 if (state == EHCI_ITD_FREE) { 622 break; 623 } 624 } 625 626 if (i >= ehci_itd_pool_size) { 627 USB_DPRINTF_L2(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 628 "ehci_allocate_itd: ITD exhausted"); 629 630 return (NULL); 631 } 632 633 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 634 "ehci_allocate_itd: Allocated %d", i); 635 636 /* Create a new dummy for the end of the ITD list */ 637 itd = &ehcip->ehci_itd_pool_addr[i]; 638 639 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 640 "ehci_allocate_itd: itd 0x%p", (void *)itd); 641 642 /* Mark the newly allocated ITD as a empty */ 643 Set_ITD(itd->itd_state, EHCI_ITD_DUMMY); 644 645 return (itd); 646 } 647 648 649 /* 650 * ehci_deallocate_itd: 651 * 652 * Deallocate a Host Controller's (HC) Transfer Descriptor (ITD). 653 * 654 */ 655 void 656 ehci_deallocate_itd( 657 ehci_state_t *ehcip, 658 ehci_isoc_xwrapper_t *itw, 659 ehci_itd_t *old_itd) 660 { 661 ehci_itd_t *itd, *next_itd; 662 663 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 664 "ehci_deallocate_itd: old_itd = 0x%p", (void *)old_itd); 665 666 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 667 ASSERT(Get_ITD(old_itd->itd_trans_wrapper) == itw->itw_id); 668 669 /* If it has been marked RECLAIM it has already been removed */ 670 if (Get_ITD(old_itd->itd_state) != EHCI_ITD_RECLAIM) { 671 ehci_remove_isoc_from_pfl(ehcip, old_itd); 672 } 673 674 /* Make sure the ITD is not in the PFL */ 675 ASSERT(Get_ITD_FRAME(old_itd->itd_frame_number) == 0); 676 677 /* Remove the itd from the itw */ 678 itd = itw->itw_itd_head; 679 if (old_itd != itd) { 680 next_itd = ehci_itd_iommu_to_cpu(ehcip, 681 Get_ITD(itd->itd_itw_next_itd)); 682 683 while (next_itd != old_itd) { 684 itd = next_itd; 685 next_itd = ehci_itd_iommu_to_cpu(ehcip, 686 Get_ITD(itd->itd_itw_next_itd)); 687 } 688 689 Set_ITD(itd->itd_itw_next_itd, old_itd->itd_itw_next_itd); 690 691 if (itd->itd_itw_next_itd == NULL) { 692 itw->itw_itd_tail = itd; 693 } 694 } else { 695 itw->itw_itd_head = ehci_itd_iommu_to_cpu( 696 ehcip, Get_ITD(old_itd->itd_itw_next_itd)); 697 698 if (itw->itw_itd_head == NULL) { 699 itw->itw_itd_tail = NULL; 700 } 701 } 702 703 bzero((char *)old_itd, sizeof (ehci_itd_t)); 704 Set_ITD(old_itd->itd_state, EHCI_ITD_FREE); 705 706 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 707 "Dealloc_itd: itd 0x%p", (void *)old_itd); 708 } 709 710 711 /* 712 * ehci_calc_num_itds: 713 * 714 * Calculates how many ITDs are needed for this request. 715 * The calculation is based on weather it is an HIGH speed 716 * transaction of a FULL/LOW transaction. 717 * 718 * For FULL/LOW transaction more itds are necessary if it 719 * spans frames. 720 */ 721 uint_t 722 ehci_calc_num_itds( 723 ehci_isoc_xwrapper_t *itw, 724 size_t pkt_count) 725 { 726 uint_t multiplier, itd_count; 727 728 /* Allocate the appropriate isoc resources */ 729 if (itw->itw_port_status == USBA_HIGH_SPEED_DEV) { 730 /* Multiplier needs to be passed in somehow */ 731 multiplier = 1 * 8; 732 itd_count = pkt_count / multiplier; 733 if (pkt_count % multiplier) { 734 itd_count++; 735 } 736 } else { 737 itd_count = pkt_count; 738 } 739 740 return (pkt_count); 741 } 742 743 /* 744 * ehci_allocate_itds_for_itw: 745 * 746 * Allocate n Transfer Descriptors (TD) from the TD buffer pool and places it 747 * into the TW. 748 * 749 * Returns USB_NO_RESOURCES if it was not able to allocate all the requested TD 750 * otherwise USB_SUCCESS. 751 */ 752 int 753 ehci_allocate_itds_for_itw( 754 ehci_state_t *ehcip, 755 ehci_isoc_xwrapper_t *itw, 756 uint_t itd_count) 757 { 758 ehci_itd_t *itd; 759 uint32_t itd_addr; 760 int i; 761 int error = USB_SUCCESS; 762 763 for (i = 0; i < itd_count; i += 1) { 764 itd = ehci_allocate_itd(ehcip); 765 if (itd == NULL) { 766 error = USB_NO_RESOURCES; 767 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 768 "ehci_allocate_itds_for_itw: " 769 "Unable to allocate %d ITDs", 770 itd_count); 771 break; 772 } 773 if (i > 0) { 774 itd_addr = ehci_itd_cpu_to_iommu(ehcip, 775 itw->itw_itd_free_list); 776 Set_ITD(itd->itd_link_ptr, itd_addr); 777 } 778 itw->itw_itd_free_list = itd; 779 } 780 781 return (error); 782 } 783 784 785 /* 786 * ehci_deallocate_itds_for_itw: 787 * 788 * Free all allocated resources for Transaction Wrapper (TW). 789 * Does not free the iTW itself. 790 */ 791 static void 792 ehci_deallocate_itds_for_itw( 793 ehci_state_t *ehcip, 794 ehci_isoc_xwrapper_t *itw) 795 { 796 ehci_itd_t *itd = NULL; 797 ehci_itd_t *temp_itd = NULL; 798 799 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 800 "ehci_free_itw_itd_resources: itw = 0x%p", itw); 801 802 itd = itw->itw_itd_free_list; 803 while (itd != NULL) { 804 /* Save the pointer to the next itd before destroying it */ 805 temp_itd = ehci_itd_iommu_to_cpu(ehcip, 806 Get_ITD(itd->itd_link_ptr)); 807 ehci_deallocate_itd(ehcip, itw, itd); 808 itd = temp_itd; 809 } 810 itw->itw_itd_free_list = NULL; 811 } 812 813 814 /* 815 * ehci_insert_itd_on_itw: 816 * 817 * The transfer wrapper keeps a list of all Transfer Descriptors (iTD) that 818 * are allocated for this transfer. Insert a iTD onto this list. 819 */ 820 void ehci_insert_itd_on_itw( 821 ehci_state_t *ehcip, 822 ehci_isoc_xwrapper_t *itw, 823 ehci_itd_t *itd) 824 { 825 /* 826 * Set the next pointer to NULL because 827 * this is the last ITD on list. 828 */ 829 Set_ITD(itd->itd_itw_next_itd, NULL); 830 831 if (itw->itw_itd_head == NULL) { 832 ASSERT(itw->itw_itd_tail == NULL); 833 itw->itw_itd_head = itd; 834 itw->itw_itd_tail = itd; 835 } else { 836 ehci_itd_t *dummy = (ehci_itd_t *)itw->itw_itd_tail; 837 838 ASSERT(dummy != NULL); 839 ASSERT(Get_ITD(itd->itd_state) == EHCI_ITD_ACTIVE); 840 841 /* Add the itd to the end of the list */ 842 Set_ITD(dummy->itd_itw_next_itd, 843 ehci_itd_cpu_to_iommu(ehcip, itd)); 844 845 itw->itw_itd_tail = itd; 846 } 847 848 Set_ITD(itd->itd_trans_wrapper, (uint32_t)itw->itw_id); 849 } 850 851 852 /* 853 * ehci_insert_itd_into_active_list: 854 * 855 * Add current ITD into the active ITD list in reverse order. 856 * When he done list is created, remove it in the reverse order. 857 */ 858 void 859 ehci_insert_itd_into_active_list( 860 ehci_state_t *ehcip, 861 ehci_itd_t *itd) 862 { 863 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 864 ASSERT(itd != NULL); 865 866 Set_ITD(itd->itd_next_active_itd, 867 ehci_itd_cpu_to_iommu(ehcip, ehcip->ehci_active_itd_list)); 868 ehcip->ehci_active_itd_list = itd; 869 } 870 871 872 /* 873 * ehci_remove_itd_from_active_list: 874 * 875 * Remove current ITD from the active ITD list. 876 */ 877 void 878 ehci_remove_itd_from_active_list( 879 ehci_state_t *ehcip, 880 ehci_itd_t *itd) 881 { 882 ehci_itd_t *curr_itd, *next_itd; 883 884 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 885 ASSERT(itd != NULL); 886 887 curr_itd = ehcip->ehci_active_itd_list; 888 889 if (curr_itd == itd) { 890 ehcip->ehci_active_itd_list = 891 ehci_itd_iommu_to_cpu(ehcip, itd->itd_next_active_itd); 892 itd->itd_next_active_itd = NULL; 893 894 return; 895 } 896 897 next_itd = ehci_itd_iommu_to_cpu(ehcip, curr_itd->itd_next_active_itd); 898 while (next_itd != itd) { 899 curr_itd = next_itd; 900 if (curr_itd) { 901 next_itd = ehci_itd_iommu_to_cpu(ehcip, 902 curr_itd->itd_next_active_itd); 903 } else { 904 break; 905 } 906 } 907 908 if ((curr_itd) && (next_itd == itd)) { 909 Set_ITD(curr_itd->itd_next_active_itd, 910 Get_ITD(itd->itd_next_active_itd)); 911 Set_ITD(itd->itd_next_active_itd, NULL); 912 } else { 913 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 914 "ehci_remove_itd_from_active_list: " 915 "Unable to find ITD in active_itd_list"); 916 } 917 } 918 919 920 /* 921 * ehci_create_done_itd_list: 922 * 923 * Traverse the active list and create a done list and remove them 924 * from the active list. 925 */ 926 ehci_itd_t * 927 ehci_create_done_itd_list( 928 ehci_state_t *ehcip) 929 { 930 usb_frame_number_t current_frame_number; 931 usb_frame_number_t itd_frame_number, itd_reclaim_number; 932 ehci_itd_t *curr_itd = NULL, *next_itd = NULL; 933 ehci_itd_t *done_itd_list = NULL; 934 uint_t state; 935 936 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 937 "ehci_create_done_itd_list:"); 938 939 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 940 941 /* 942 * Get the current frame number. 943 * Only process itd that were inserted before the current 944 * frame number. 945 */ 946 current_frame_number = ehci_get_current_frame_number(ehcip); 947 948 curr_itd = ehcip->ehci_active_itd_list; 949 950 while (curr_itd) { 951 /* Get next itd from the active itd list */ 952 next_itd = ehci_itd_iommu_to_cpu(ehcip, 953 Get_ITD(curr_itd->itd_next_active_itd)); 954 955 /* 956 * If haven't past the frame number that the ITD was 957 * suppose to be executed, don't touch it. Just in 958 * case it is being processed by the HCD and cause 959 * a race condition. 960 */ 961 itd_frame_number = Get_ITD_FRAME(curr_itd->itd_frame_number); 962 itd_reclaim_number = 963 Get_ITD_FRAME(curr_itd->itd_reclaim_number); 964 965 /* Get the ITD state */ 966 state = Get_ITD(curr_itd->itd_state); 967 968 if (((state == EHCI_ITD_ACTIVE) && 969 (itd_frame_number < current_frame_number)) || 970 ((state == EHCI_ITD_RECLAIM) && 971 (itd_reclaim_number < current_frame_number))) { 972 973 /* Remove this ITD from active ITD list */ 974 ehci_remove_itd_from_active_list(ehcip, curr_itd); 975 976 /* 977 * Create the done list in reverse order, since the 978 * active list was also created in reverse order. 979 */ 980 Set_ITD(curr_itd->itd_next_active_itd, 981 ehci_itd_cpu_to_iommu(ehcip, done_itd_list)); 982 done_itd_list = curr_itd; 983 } 984 985 curr_itd = next_itd; 986 } 987 988 return (done_itd_list); 989 } 990 991 992 /* 993 * ehci_insert_isoc_to_pfl: 994 * 995 * Insert a ITD request into the Host Controller's isochronous list. 996 * All the ITDs in the ITW will be added the PFL at once. Either all 997 * of them will make it or none of them will. 998 */ 999 int 1000 ehci_insert_isoc_to_pfl( 1001 ehci_state_t *ehcip, 1002 ehci_pipe_private_t *pp, 1003 ehci_isoc_xwrapper_t *itw) 1004 { 1005 usb_isoc_req_t *isoc_reqp = itw->itw_curr_xfer_reqp; 1006 usb_frame_number_t current_frame_number, start_frame_number; 1007 uint_t ddic, pfl_number; 1008 ehci_periodic_frame_list_t *periodic_frame_list = 1009 ehcip->ehci_periodic_frame_list_tablep; 1010 uint32_t addr, port_status; 1011 ehci_itd_t *itd; 1012 1013 USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1014 "ehci_insert_isoc_to_pfl: " 1015 "isoc flags 0x%x", isoc_reqp->isoc_attributes); 1016 1017 /* 1018 * Enter critical, while programming the usb frame number 1019 * and inserting current isochronous TD into the ED's list. 1020 */ 1021 ddic = ddi_enter_critical(); 1022 1023 /* Get the current frame number */ 1024 current_frame_number = ehci_get_current_frame_number(ehcip); 1025 1026 /* 1027 * Check the given isochronous flags and get the frame number 1028 * to insert the itd into. 1029 */ 1030 switch (isoc_reqp->isoc_attributes & 1031 (USB_ATTRS_ISOC_START_FRAME | USB_ATTRS_ISOC_XFER_ASAP)) { 1032 case USB_ATTRS_ISOC_START_FRAME: 1033 1034 /* Starting frame number is specified */ 1035 if (pp->pp_flag & EHCI_ISOC_XFER_CONTINUE) { 1036 /* Get the starting usb frame number */ 1037 start_frame_number = pp->pp_next_frame_number; 1038 } else { 1039 /* Check for the Starting usb frame number */ 1040 if ((isoc_reqp->isoc_frame_no == 0) || 1041 ((isoc_reqp->isoc_frame_no + 1042 isoc_reqp->isoc_pkts_count) < 1043 current_frame_number)) { 1044 1045 /* Exit the critical */ 1046 ddi_exit_critical(ddic); 1047 1048 USB_DPRINTF_L2(PRINT_MASK_LISTS, 1049 ehcip->ehci_log_hdl, 1050 "ehci_insert_isoc_to_pfl:" 1051 "Invalid starting frame number"); 1052 1053 return (USB_INVALID_START_FRAME); 1054 } 1055 1056 /* Get the starting usb frame number */ 1057 start_frame_number = isoc_reqp->isoc_frame_no; 1058 1059 pp->pp_next_frame_number = 0; 1060 } 1061 break; 1062 case USB_ATTRS_ISOC_XFER_ASAP: 1063 /* ehci has to specify starting frame number */ 1064 if ((pp->pp_next_frame_number) && 1065 (pp->pp_next_frame_number > current_frame_number)) { 1066 /* 1067 * Get the next usb frame number. 1068 */ 1069 start_frame_number = pp->pp_next_frame_number; 1070 } else { 1071 /* 1072 * Add appropriate offset to the current usb 1073 * frame number and use it as a starting frame 1074 * number. 1075 */ 1076 start_frame_number = 1077 current_frame_number + EHCI_FRAME_OFFSET; 1078 } 1079 1080 if (!(pp->pp_flag & EHCI_ISOC_XFER_CONTINUE)) { 1081 isoc_reqp->isoc_frame_no = start_frame_number; 1082 } 1083 break; 1084 default: 1085 /* Exit the critical */ 1086 ddi_exit_critical(ddic); 1087 1088 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1089 "ehci_insert_isoc_to_pfl: Either starting " 1090 "frame number or ASAP flags are not set, attrs = 0x%x", 1091 isoc_reqp->isoc_attributes); 1092 1093 return (USB_NO_FRAME_NUMBER); 1094 } 1095 1096 if (itw->itw_port_status == USBA_HIGH_SPEED_DEV) { 1097 port_status = 0; 1098 } else { 1099 port_status = EHCI_ITD_LINK_REF_SITD; 1100 } 1101 1102 itd = itw->itw_itd_head; 1103 while (itd) { 1104 /* Find the appropriate frame list to put the itd into */ 1105 pfl_number = start_frame_number % EHCI_NUM_PERIODIC_FRAME_LISTS; 1106 1107 addr = Get_PFLT(periodic_frame_list-> 1108 ehci_periodic_frame_list_table[pfl_number]); 1109 Set_ITD(itd->itd_link_ptr, addr); 1110 1111 /* Set the link_ref correctly as ITD or SITD. */ 1112 addr = ehci_itd_cpu_to_iommu(ehcip, itd) & EHCI_ITD_LINK_PTR; 1113 addr |= port_status; 1114 1115 Set_PFLT(periodic_frame_list-> 1116 ehci_periodic_frame_list_table[pfl_number], addr); 1117 1118 /* Save which frame the ITD was inserted into */ 1119 Set_ITD_FRAME(itd->itd_frame_number, start_frame_number); 1120 1121 ehci_insert_itd_into_active_list(ehcip, itd); 1122 1123 /* Get the next ITD in the ITW */ 1124 itd = ehci_itd_iommu_to_cpu(ehcip, 1125 Get_ITD(itd->itd_itw_next_itd)); 1126 1127 start_frame_number++; 1128 } 1129 1130 /* Exit the critical */ 1131 ddi_exit_critical(ddic); 1132 1133 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1134 "ehci_isoc_to_pfl: " 1135 "current frame number 0x%llx start frame number 0x%llx num itds %d", 1136 current_frame_number, start_frame_number, itw->itw_num_itds); 1137 1138 /* 1139 * Increment this saved frame number by current number 1140 * of data packets needs to be transfer. 1141 */ 1142 pp->pp_next_frame_number = start_frame_number; 1143 1144 /* 1145 * Set EHCI_ISOC_XFER_CONTINUE flag in order to send other 1146 * isochronous packets, part of the current isoch request 1147 * in the subsequent frames. 1148 */ 1149 pp->pp_flag |= EHCI_ISOC_XFER_CONTINUE; 1150 1151 return (USB_SUCCESS); 1152 } 1153 1154 1155 /* 1156 * ehci_remove_isoc_to_pfl: 1157 * 1158 * Remove an ITD request from the Host Controller's isochronous list. 1159 * If we can't find it, something has gone wrong. 1160 */ 1161 void 1162 ehci_remove_isoc_from_pfl( 1163 ehci_state_t *ehcip, 1164 ehci_itd_t *curr_itd) 1165 { 1166 ehci_periodic_frame_list_t *periodic_frame_list; 1167 uint_t pfl_number; 1168 uint32_t next_addr, curr_itd_addr; 1169 uint32_t link_ref; 1170 ehci_itd_t *prev_itd = NULL; 1171 1172 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 1173 "ehci_remove_isoc_from_pfl:"); 1174 1175 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1176 1177 /* Get the address of the current itd */ 1178 curr_itd_addr = ehci_itd_cpu_to_iommu(ehcip, curr_itd); 1179 1180 /* 1181 * Remove this ITD from the PFL 1182 * But first we need to find it in the PFL 1183 */ 1184 periodic_frame_list = ehcip->ehci_periodic_frame_list_tablep; 1185 pfl_number = Get_ITD_FRAME(curr_itd->itd_frame_number) % 1186 EHCI_NUM_PERIODIC_FRAME_LISTS; 1187 1188 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 1189 "ehci_remove_isoc_from_pfl: itd = 0x%p pfl number 0x%x", 1190 curr_itd, pfl_number); 1191 1192 next_addr = Get_PFLT(periodic_frame_list-> 1193 ehci_periodic_frame_list_table[pfl_number]); 1194 while ((next_addr & EHCI_ITD_LINK_PTR) != 1195 (curr_itd_addr & EHCI_ITD_LINK_PTR)) { 1196 1197 link_ref = next_addr & EHCI_ITD_LINK_REF; 1198 1199 if ((link_ref == EHCI_ITD_LINK_REF_ITD) || 1200 (link_ref == EHCI_ITD_LINK_REF_SITD)) { 1201 1202 prev_itd = ehci_itd_iommu_to_cpu(ehcip, 1203 (next_addr & EHCI_ITD_LINK_PTR)); 1204 next_addr = Get_ITD(prev_itd->itd_link_ptr); 1205 } else { 1206 1207 break; 1208 } 1209 } 1210 1211 /* 1212 * If the next itd is the current itd, that means we found it. 1213 * Set the previous's ITD link ptr to the Curr_ITD's link ptr. 1214 * But do not touch the Curr_ITD's link ptr. 1215 */ 1216 if ((next_addr & EHCI_ITD_LINK_PTR) == 1217 (curr_itd_addr & EHCI_ITD_LINK_PTR)) { 1218 1219 next_addr = Get_ITD(curr_itd->itd_link_ptr); 1220 1221 if (prev_itd == NULL) { 1222 /* This means PFL points to this ITD */ 1223 Set_PFLT(periodic_frame_list-> 1224 ehci_periodic_frame_list_table[pfl_number], 1225 next_addr); 1226 } else { 1227 /* Set the previous ITD's itd_link_ptr */ 1228 Set_ITD(prev_itd->itd_link_ptr, next_addr); 1229 } 1230 1231 Set_ITD_FRAME(curr_itd->itd_frame_number, 0); 1232 } else { 1233 ASSERT((next_addr & EHCI_ITD_LINK_PTR) == 1234 (curr_itd_addr & EHCI_ITD_LINK_PTR)); 1235 USB_DPRINTF_L3(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 1236 "ehci_remove_isoc_from_pfl: Unable to find ITD in PFL"); 1237 } 1238 } 1239 1240 1241 /* 1242 * Isochronous in resource functions 1243 */ 1244 /* 1245 * ehci_allocate_periodic_in_resource 1246 * 1247 * Allocate interrupt request structure for the interrupt IN transfer. 1248 */ 1249 int 1250 ehci_allocate_isoc_in_resource( 1251 ehci_state_t *ehcip, 1252 ehci_pipe_private_t *pp, 1253 ehci_isoc_xwrapper_t *itw, 1254 usb_flags_t flags) 1255 { 1256 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle; 1257 usb_isoc_req_t *orig_isoc_reqp, *clone_isoc_reqp; 1258 1259 USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1260 "ehci_allocate_isoc_in_resource:" 1261 "pp = 0x%p itw = 0x%p flags = 0x%x", pp, itw, flags); 1262 1263 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1264 ASSERT(itw->itw_curr_xfer_reqp == NULL); 1265 1266 /* Get the client periodic in request pointer */ 1267 orig_isoc_reqp = (usb_isoc_req_t *)(pp->pp_client_periodic_in_reqp); 1268 1269 ASSERT(orig_isoc_reqp != NULL); 1270 1271 clone_isoc_reqp = usba_hcdi_dup_isoc_req(ph->p_dip, 1272 orig_isoc_reqp, flags); 1273 1274 if (clone_isoc_reqp == NULL) { 1275 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1276 "ehci_allocate_isoc_in_resource: Isochronous" 1277 "request structure allocation failed"); 1278 1279 return (USB_NO_RESOURCES); 1280 } 1281 1282 /* 1283 * Save the client's isochronous request pointer and 1284 * length of isochronous transfer in transfer wrapper. 1285 * The dup'ed request is saved in pp_client_periodic_in_reqp 1286 */ 1287 itw->itw_curr_xfer_reqp = orig_isoc_reqp; 1288 itw->itw_length = clone_isoc_reqp->isoc_pkts_length; 1289 pp->pp_client_periodic_in_reqp = (usb_opaque_t)clone_isoc_reqp; 1290 1291 mutex_enter(&ph->p_mutex); 1292 ph->p_req_count++; 1293 mutex_exit(&ph->p_mutex); 1294 1295 pp->pp_state = EHCI_PIPE_STATE_ACTIVE; 1296 1297 return (USB_SUCCESS); 1298 } 1299 1300 1301 /* 1302 * ehci_deallocate_isoc_in_resource 1303 * 1304 * Deallocate interrupt request structure for the interrupt IN transfer. 1305 */ 1306 void 1307 ehci_deallocate_isoc_in_resource( 1308 ehci_state_t *ehcip, 1309 ehci_pipe_private_t *pp, 1310 ehci_isoc_xwrapper_t *itw) 1311 { 1312 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle; 1313 uchar_t ep_attr = ph->p_ep.bmAttributes; 1314 usb_isoc_req_t *isoc_reqp; 1315 1316 USB_DPRINTF_L4(PRINT_MASK_LISTS, 1317 ehcip->ehci_log_hdl, 1318 "ehci_deallocate_isoc_in_resource: " 1319 "pp = 0x%p itw = 0x%p", pp, itw); 1320 1321 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1322 ASSERT((ep_attr & USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH); 1323 1324 isoc_reqp = itw->itw_curr_xfer_reqp; 1325 1326 /* Check the current periodic in request pointer */ 1327 if (isoc_reqp) { 1328 itw->itw_curr_xfer_reqp = NULL; 1329 itw->itw_curr_isoc_pktp = NULL; 1330 1331 mutex_enter(&ph->p_mutex); 1332 ph->p_req_count--; 1333 mutex_exit(&ph->p_mutex); 1334 1335 usb_free_isoc_req(isoc_reqp); 1336 1337 /* Set periodic in pipe state to idle */ 1338 pp->pp_state = EHCI_PIPE_STATE_IDLE; 1339 } 1340 } 1341 1342 1343 /* 1344 * ehci_itd_cpu_to_iommu: 1345 * 1346 * This function converts for the given Transfer Descriptor (ITD) CPU address 1347 * to IO address. 1348 */ 1349 uint32_t 1350 ehci_itd_cpu_to_iommu( 1351 ehci_state_t *ehcip, 1352 ehci_itd_t *addr) 1353 { 1354 uint32_t td; 1355 1356 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1357 1358 if (addr == NULL) { 1359 1360 return (NULL); 1361 } 1362 1363 td = (uint32_t)ehcip->ehci_itd_pool_cookie.dmac_address + 1364 (uint32_t)((uintptr_t)addr - 1365 (uintptr_t)(ehcip->ehci_itd_pool_addr)); 1366 1367 ASSERT(((uint32_t) (sizeof (ehci_itd_t) * 1368 (addr - ehcip->ehci_itd_pool_addr))) == 1369 ((uint32_t)((uintptr_t)addr - (uintptr_t) 1370 (ehcip->ehci_itd_pool_addr)))); 1371 1372 ASSERT(td >= ehcip->ehci_itd_pool_cookie.dmac_address); 1373 ASSERT(td <= ehcip->ehci_itd_pool_cookie.dmac_address + 1374 sizeof (ehci_itd_t) * ehci_itd_pool_size); 1375 1376 return (td); 1377 } 1378 1379 1380 /* 1381 * ehci_itd_iommu_to_cpu: 1382 * 1383 * This function converts for the given Transfer Descriptor (ITD) IO address 1384 * to CPU address. 1385 */ 1386 ehci_itd_t * 1387 ehci_itd_iommu_to_cpu( 1388 ehci_state_t *ehcip, 1389 uintptr_t addr) 1390 { 1391 ehci_itd_t *itd; 1392 1393 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1394 1395 if (addr == NULL) { 1396 1397 return (NULL); 1398 } 1399 1400 itd = (ehci_itd_t *)((uintptr_t) 1401 (addr - ehcip->ehci_itd_pool_cookie.dmac_address) + 1402 (uintptr_t)ehcip->ehci_itd_pool_addr); 1403 1404 ASSERT(itd >= ehcip->ehci_itd_pool_addr); 1405 ASSERT((uintptr_t)itd <= (uintptr_t)ehcip->ehci_itd_pool_addr + 1406 (uintptr_t)(sizeof (ehci_itd_t) * ehci_itd_pool_size)); 1407 1408 return (itd); 1409 } 1410 1411 1412 /* 1413 * Error parsing functions 1414 */ 1415 void ehci_parse_isoc_error( 1416 ehci_state_t *ehcip, 1417 ehci_isoc_xwrapper_t *itw, 1418 ehci_itd_t *itd) { 1419 1420 usb_isoc_req_t *isoc_reqp; 1421 usb_isoc_pkt_descr_t *isoc_pkt_descr; 1422 usb_cr_t error; 1423 1424 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1425 1426 isoc_reqp = itw->itw_curr_xfer_reqp; 1427 isoc_pkt_descr = itw->itw_curr_isoc_pktp; 1428 1429 if (itw->itw_port_status == USBA_HIGH_SPEED_DEV) { 1430 error = ehci_parse_itd_error(ehcip, itw, itd); 1431 } else { 1432 error = ehci_parse_sitd_error(ehcip, itw, itd); 1433 } 1434 1435 /* Write the status of isoc data packet */ 1436 isoc_pkt_descr->isoc_pkt_status = error; 1437 1438 if (error != USB_CR_OK) { 1439 isoc_reqp->isoc_error_count++; 1440 1441 USB_DPRINTF_L2(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1442 "ehci_parse_isoc_error: Error %d Device Address %d " 1443 "Endpoint number %d", error, itw->itw_device_addr, 1444 itw->itw_endpoint_num); 1445 } 1446 1447 itw->itw_curr_isoc_pktp++; 1448 } 1449 1450 1451 /* ARGSUSED */ 1452 static usb_cr_t ehci_parse_itd_error( 1453 ehci_state_t *ehcip, 1454 ehci_isoc_xwrapper_t *itw, 1455 ehci_itd_t *itd) { 1456 1457 return (USB_NOT_SUPPORTED); 1458 } 1459 1460 static usb_cr_t ehci_parse_sitd_error( 1461 ehci_state_t *ehcip, 1462 ehci_isoc_xwrapper_t *itw, 1463 ehci_itd_t *itd) { 1464 1465 uint32_t status; 1466 usb_cr_t error; 1467 usb_isoc_pkt_descr_t *isoc_pkt_descr; 1468 uint32_t residue; 1469 1470 isoc_pkt_descr = itw->itw_curr_isoc_pktp; 1471 1472 status = Get_ITD_BODY(itd, EHCI_SITD_XFER_STATE) & 1473 EHCI_SITD_XFER_STATUS_MASK; 1474 1475 switch (status) { 1476 case EHCI_SITD_XFER_ACTIVE: 1477 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1478 "ehci_check_for_sitd_error: NOT ACCESSED"); 1479 error = USB_CR_NOT_ACCESSED; 1480 1481 break; 1482 case EHCI_SITD_XFER_ERROR: 1483 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1484 "ehci_check_for_sitd_error: TT ERROR"); 1485 1486 error = USB_CR_UNSPECIFIED_ERR; 1487 1488 break; 1489 case EHCI_SITD_XFER_DATA_BUFFER_ERR: 1490 if (itw->itw_direction == USB_EP_DIR_OUT) { 1491 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1492 "ehci_check_for_sitd_error: BUFFER Underrun"); 1493 error = USB_CR_BUFFER_UNDERRUN; 1494 } else { 1495 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1496 "ehci_check_for_sitd_error: BUFFER Overrun"); 1497 error = USB_CR_BUFFER_OVERRUN; 1498 } 1499 1500 break; 1501 case EHCI_SITD_XFER_BABBLE: 1502 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1503 "ehci_check_for_sitd_error: BABBLE"); 1504 error = USB_CR_DATA_OVERRUN; 1505 1506 break; 1507 case EHCI_SITD_XFER_XACT_ERROR: 1508 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1509 "ehci_check_for_sitd_error: XACT ERROR"); 1510 1511 error = USB_CR_DEV_NOT_RESP; 1512 break; 1513 case EHCI_SITD_XFER_MISSED_UFRAME: 1514 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1515 "ehci_check_for_sitd_error: MISSED UFRAME"); 1516 1517 error = USB_CR_NOT_ACCESSED; 1518 break; 1519 default: 1520 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1521 "ehci_check_for_sitd_error: NO ERROR"); 1522 error = USB_CR_OK; 1523 1524 break; 1525 } 1526 1527 /* This is HCD specific and may not have this information */ 1528 residue = 1529 (Get_ITD_BODY(itd, EHCI_SITD_XFER_STATE) & 1530 EHCI_SITD_XFER_TOTAL_MASK) >> 1531 EHCI_SITD_XFER_TOTAL_SHIFT; 1532 1533 /* 1534 * Subtract the residue from the isoc_pkt_descr that 1535 * was set when this ITD was inserted. 1536 */ 1537 isoc_pkt_descr->isoc_pkt_actual_length -= residue; 1538 1539 return (error); 1540 } 1541 1542 1543 /* 1544 * debug print functions 1545 */ 1546 void 1547 ehci_print_itd( 1548 ehci_state_t *ehcip, 1549 ehci_itd_t *itd) 1550 { 1551 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1552 "ehci_print_itd: itd = 0x%p", (void *)itd); 1553 1554 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1555 "\titd_link_ptr: 0x%x ", Get_ITD(itd->itd_link_ptr)); 1556 1557 if ((Get_ITD(itd->itd_link_ptr) & EHCI_ITD_LINK_REF) == 1558 EHCI_ITD_LINK_REF_ITD) { 1559 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1560 "\titd_ctrl0: 0x%x ", 1561 Get_ITD(itd->itd_body[EHCI_ITD_CTRL0])); 1562 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1563 "\titd_ctrl1: 0x%x ", 1564 Get_ITD(itd->itd_body[EHCI_ITD_CTRL1])); 1565 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1566 "\titd_ctrl2: 0x%x ", 1567 Get_ITD(itd->itd_body[EHCI_ITD_CTRL2])); 1568 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1569 "\titd_ctrl3: 0x%x ", 1570 Get_ITD(itd->itd_body[EHCI_ITD_CTRL3])); 1571 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1572 "\titd_ctrl4: 0x%x ", 1573 Get_ITD(itd->itd_body[EHCI_ITD_CTRL4])); 1574 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1575 "\titd_ctrl5: 0x%x ", 1576 Get_ITD(itd->itd_body[EHCI_ITD_CTRL5])); 1577 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1578 "\titd_ctrl6: 0x%x ", 1579 Get_ITD(itd->itd_body[EHCI_ITD_CTRL6])); 1580 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1581 "\titd_ctrl7: 0x%x ", 1582 Get_ITD(itd->itd_body[EHCI_ITD_CTRL7])); 1583 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1584 "\titd_buffer0: 0x%x ", 1585 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER0])); 1586 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1587 "\titd_buffer1: 0x%x ", 1588 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER1])); 1589 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1590 "\titd_buffer2: 0x%x ", 1591 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER2])); 1592 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1593 "\titd_buffer3: 0x%x ", 1594 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER3])); 1595 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1596 "\titd_buffer4: 0x%x ", 1597 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER4])); 1598 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1599 "\titd_buffer5: 0x%x ", 1600 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER5])); 1601 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1602 "\titd_buffer6: 0x%x ", 1603 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER6])); 1604 } else { 1605 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1606 "\tsitd_ctrl: 0x%x ", 1607 Get_ITD(itd->itd_body[EHCI_SITD_CTRL])); 1608 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1609 "\tsitd_uframe_sched: 0x%x ", 1610 Get_ITD(itd->itd_body[EHCI_SITD_UFRAME_SCHED])); 1611 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1612 "\tsitd_xfer_state: 0x%x ", 1613 Get_ITD(itd->itd_body[EHCI_SITD_XFER_STATE])); 1614 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1615 "\tsitd_buffer0: 0x%x ", 1616 Get_ITD(itd->itd_body[EHCI_SITD_BUFFER0])); 1617 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1618 "\tsitd_buffer1: 0x%x ", 1619 Get_ITD(itd->itd_body[EHCI_SITD_BUFFER1])); 1620 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1621 "\tsitd_prev_sitd: 0x%x ", 1622 Get_ITD(itd->itd_body[EHCI_SITD_PREV_SITD])); 1623 } 1624 1625 /* HCD private fields */ 1626 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1627 "\titd_trans_wrapper: 0x%x ", 1628 Get_ITD(itd->itd_trans_wrapper)); 1629 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1630 "\titd_itw_next_itd: 0x%x ", 1631 Get_ITD(itd->itd_itw_next_itd)); 1632 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1633 "\titd_state: 0x%x ", 1634 Get_ITD(itd->itd_state)); 1635 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1636 "\titd_frame_number: 0x%x ", 1637 Get_ITD(itd->itd_frame_number)); 1638 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1639 "\titd_reclaim_number: 0x%x ", 1640 Get_ITD(itd->itd_reclaim_number)); 1641 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1642 "\titd_next_active_itd: 0x%x ", 1643 Get_ITD(itd->itd_next_active_itd)); 1644 } 1645