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