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