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 2009 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 672 /* If it has been marked RECLAIM it has already been removed */ 673 if (Get_ITD(old_itd->itd_state) != EHCI_ITD_RECLAIM) { 674 ehci_remove_isoc_from_pfl(ehcip, old_itd); 675 } 676 677 /* Make sure the ITD is not in the PFL */ 678 ASSERT(Get_ITD_FRAME(old_itd->itd_frame_number) == 0); 679 680 /* Remove the itd from the itw */ 681 itd = itw->itw_itd_head; 682 if (old_itd != itd) { 683 next_itd = ehci_itd_iommu_to_cpu(ehcip, 684 Get_ITD(itd->itd_itw_next_itd)); 685 686 while (next_itd != old_itd) { 687 itd = next_itd; 688 next_itd = ehci_itd_iommu_to_cpu(ehcip, 689 Get_ITD(itd->itd_itw_next_itd)); 690 } 691 692 Set_ITD(itd->itd_itw_next_itd, old_itd->itd_itw_next_itd); 693 694 if (itd->itd_itw_next_itd == NULL) { 695 itw->itw_itd_tail = itd; 696 } 697 } else { 698 itw->itw_itd_head = ehci_itd_iommu_to_cpu( 699 ehcip, Get_ITD(old_itd->itd_itw_next_itd)); 700 701 if (itw->itw_itd_head == NULL) { 702 itw->itw_itd_tail = NULL; 703 } 704 } 705 706 bzero((char *)old_itd, sizeof (ehci_itd_t)); 707 Set_ITD(old_itd->itd_state, EHCI_ITD_FREE); 708 709 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 710 "Dealloc_itd: itd 0x%p", (void *)old_itd); 711 } 712 713 714 /* 715 * ehci_calc_num_itds: 716 * 717 * Calculates how many ITDs are needed for this request. 718 * The calculation is based on weather it is an HIGH speed 719 * transaction of a FULL/LOW transaction. 720 * 721 * For FULL/LOW transaction more itds are necessary if it 722 * spans frames. 723 */ 724 uint_t 725 ehci_calc_num_itds( 726 ehci_isoc_xwrapper_t *itw, 727 size_t pkt_count) 728 { 729 uint_t multiplier, itd_count; 730 731 /* Allocate the appropriate isoc resources */ 732 if (itw->itw_port_status == USBA_HIGH_SPEED_DEV) { 733 /* Multiplier needs to be passed in somehow */ 734 multiplier = 1 * 8; 735 itd_count = pkt_count / multiplier; 736 if (pkt_count % multiplier) { 737 itd_count++; 738 } 739 } else { 740 itd_count = (uint_t)pkt_count; 741 } 742 743 return (itd_count); 744 } 745 746 /* 747 * ehci_allocate_itds_for_itw: 748 * 749 * Allocate n Transfer Descriptors (TD) from the TD buffer pool and places it 750 * into the TW. 751 * 752 * Returns USB_NO_RESOURCES if it was not able to allocate all the requested TD 753 * otherwise USB_SUCCESS. 754 */ 755 int 756 ehci_allocate_itds_for_itw( 757 ehci_state_t *ehcip, 758 ehci_isoc_xwrapper_t *itw, 759 uint_t itd_count) 760 { 761 ehci_itd_t *itd; 762 uint32_t itd_addr; 763 int i; 764 int error = USB_SUCCESS; 765 766 for (i = 0; i < itd_count; i += 1) { 767 itd = ehci_allocate_itd(ehcip); 768 if (itd == NULL) { 769 error = USB_NO_RESOURCES; 770 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 771 "ehci_allocate_itds_for_itw: " 772 "Unable to allocate %d ITDs", 773 itd_count); 774 break; 775 } 776 if (i > 0) { 777 itd_addr = ehci_itd_cpu_to_iommu(ehcip, 778 itw->itw_itd_free_list); 779 Set_ITD(itd->itd_link_ptr, itd_addr); 780 } 781 Set_ITD_INDEX(itd, 0, EHCI_ITD_UNUSED_INDEX); 782 Set_ITD_INDEX(itd, 1, EHCI_ITD_UNUSED_INDEX); 783 Set_ITD_INDEX(itd, 2, EHCI_ITD_UNUSED_INDEX); 784 Set_ITD_INDEX(itd, 3, EHCI_ITD_UNUSED_INDEX); 785 Set_ITD_INDEX(itd, 4, EHCI_ITD_UNUSED_INDEX); 786 Set_ITD_INDEX(itd, 5, EHCI_ITD_UNUSED_INDEX); 787 Set_ITD_INDEX(itd, 6, EHCI_ITD_UNUSED_INDEX); 788 Set_ITD_INDEX(itd, 7, EHCI_ITD_UNUSED_INDEX); 789 itw->itw_itd_free_list = itd; 790 } 791 792 return (error); 793 } 794 795 796 /* 797 * ehci_deallocate_itds_for_itw: 798 * 799 * Free all allocated resources for Transaction Wrapper (TW). 800 * Does not free the iTW itself. 801 */ 802 static void 803 ehci_deallocate_itds_for_itw( 804 ehci_state_t *ehcip, 805 ehci_isoc_xwrapper_t *itw) 806 { 807 ehci_itd_t *itd = NULL; 808 ehci_itd_t *temp_itd = NULL; 809 810 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 811 "ehci_free_itw_itd_resources: itw = 0x%p", (void *)itw); 812 813 itd = itw->itw_itd_free_list; 814 while (itd != NULL) { 815 /* Save the pointer to the next itd before destroying it */ 816 temp_itd = ehci_itd_iommu_to_cpu(ehcip, 817 Get_ITD(itd->itd_link_ptr)); 818 ehci_deallocate_itd(ehcip, itw, itd); 819 itd = temp_itd; 820 } 821 itw->itw_itd_free_list = NULL; 822 } 823 824 825 /* 826 * ehci_insert_itd_on_itw: 827 * 828 * The transfer wrapper keeps a list of all Transfer Descriptors (iTD) that 829 * are allocated for this transfer. Insert a iTD onto this list. 830 */ 831 void ehci_insert_itd_on_itw( 832 ehci_state_t *ehcip, 833 ehci_isoc_xwrapper_t *itw, 834 ehci_itd_t *itd) 835 { 836 /* 837 * Set the next pointer to NULL because 838 * this is the last ITD on list. 839 */ 840 Set_ITD(itd->itd_itw_next_itd, NULL); 841 842 if (itw->itw_itd_head == NULL) { 843 ASSERT(itw->itw_itd_tail == NULL); 844 itw->itw_itd_head = itd; 845 itw->itw_itd_tail = itd; 846 } else { 847 ehci_itd_t *dummy = (ehci_itd_t *)itw->itw_itd_tail; 848 849 ASSERT(dummy != NULL); 850 ASSERT(Get_ITD(itd->itd_state) == EHCI_ITD_ACTIVE); 851 852 /* Add the itd to the end of the list */ 853 Set_ITD(dummy->itd_itw_next_itd, 854 ehci_itd_cpu_to_iommu(ehcip, itd)); 855 856 itw->itw_itd_tail = itd; 857 } 858 859 Set_ITD(itd->itd_trans_wrapper, (uint32_t)itw->itw_id); 860 } 861 862 863 /* 864 * ehci_insert_itd_into_active_list: 865 * 866 * Add current ITD into the active ITD list in reverse order. 867 * When he done list is created, remove it in the reverse order. 868 */ 869 void 870 ehci_insert_itd_into_active_list( 871 ehci_state_t *ehcip, 872 ehci_itd_t *itd) 873 { 874 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 875 ASSERT(itd != NULL); 876 877 Set_ITD(itd->itd_next_active_itd, 878 ehci_itd_cpu_to_iommu(ehcip, ehcip->ehci_active_itd_list)); 879 ehcip->ehci_active_itd_list = itd; 880 } 881 882 883 /* 884 * ehci_remove_itd_from_active_list: 885 * 886 * Remove current ITD from the active ITD list. 887 */ 888 void 889 ehci_remove_itd_from_active_list( 890 ehci_state_t *ehcip, 891 ehci_itd_t *itd) 892 { 893 ehci_itd_t *curr_itd, *next_itd; 894 895 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 896 ASSERT(itd != NULL); 897 898 USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 899 "ehci_remove_itd_from_active_list: " 900 "ehci_active_itd_list = 0x%p itd = 0x%p", 901 (void *)ehcip->ehci_active_itd_list, (void *)itd); 902 903 curr_itd = ehcip->ehci_active_itd_list; 904 905 if (curr_itd == itd) { 906 ehcip->ehci_active_itd_list = 907 ehci_itd_iommu_to_cpu(ehcip, itd->itd_next_active_itd); 908 itd->itd_next_active_itd = NULL; 909 910 return; 911 } 912 913 next_itd = ehci_itd_iommu_to_cpu(ehcip, curr_itd->itd_next_active_itd); 914 while (next_itd != itd) { 915 curr_itd = next_itd; 916 if (curr_itd) { 917 next_itd = ehci_itd_iommu_to_cpu(ehcip, 918 curr_itd->itd_next_active_itd); 919 } else { 920 break; 921 } 922 } 923 924 if ((curr_itd) && (next_itd == itd)) { 925 Set_ITD(curr_itd->itd_next_active_itd, 926 Get_ITD(itd->itd_next_active_itd)); 927 Set_ITD(itd->itd_next_active_itd, NULL); 928 } else { 929 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 930 "ehci_remove_itd_from_active_list: " 931 "Unable to find ITD in active_itd_list"); 932 } 933 } 934 935 936 /* 937 * ehci_create_done_itd_list: 938 * 939 * Traverse the active list and create a done list and remove them 940 * from the active list. 941 */ 942 ehci_itd_t * 943 ehci_create_done_itd_list( 944 ehci_state_t *ehcip) 945 { 946 usb_frame_number_t current_frame_number; 947 usb_frame_number_t itd_frame_number, itd_reclaim_number; 948 ehci_itd_t *curr_itd = NULL, *next_itd = NULL; 949 ehci_itd_t *done_itd_list = NULL; 950 uint_t state; 951 952 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 953 "ehci_create_done_itd_list:"); 954 955 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 956 957 /* 958 * Get the current frame number. 959 * Only process itd that were inserted before the current 960 * frame number. 961 */ 962 current_frame_number = ehci_get_current_frame_number(ehcip); 963 964 curr_itd = ehcip->ehci_active_itd_list; 965 966 while (curr_itd) { 967 /* Get next itd from the active itd list */ 968 next_itd = ehci_itd_iommu_to_cpu(ehcip, 969 Get_ITD(curr_itd->itd_next_active_itd)); 970 971 /* 972 * If haven't past the frame number that the ITD was 973 * suppose to be executed, don't touch it. Just in 974 * case it is being processed by the HCD and cause 975 * a race condition. 976 */ 977 itd_frame_number = Get_ITD_FRAME(curr_itd->itd_frame_number); 978 itd_reclaim_number = 979 Get_ITD_FRAME(curr_itd->itd_reclaim_number); 980 981 /* Get the ITD state */ 982 state = Get_ITD(curr_itd->itd_state); 983 984 if (((state == EHCI_ITD_ACTIVE) && 985 (itd_frame_number < current_frame_number)) || 986 ((state == EHCI_ITD_RECLAIM) && 987 (itd_reclaim_number < current_frame_number))) { 988 989 /* Remove this ITD from active ITD list */ 990 ehci_remove_itd_from_active_list(ehcip, curr_itd); 991 992 /* 993 * Create the done list in reverse order, since the 994 * active list was also created in reverse order. 995 */ 996 Set_ITD(curr_itd->itd_next_active_itd, 997 ehci_itd_cpu_to_iommu(ehcip, done_itd_list)); 998 done_itd_list = curr_itd; 999 } 1000 1001 curr_itd = next_itd; 1002 } 1003 1004 return (done_itd_list); 1005 } 1006 1007 1008 /* 1009 * ehci_insert_isoc_to_pfl: 1010 * 1011 * Insert a ITD request into the Host Controller's isochronous list. 1012 * All the ITDs in the ITW will be added the PFL at once. Either all 1013 * of them will make it or none of them will. 1014 */ 1015 int 1016 ehci_insert_isoc_to_pfl( 1017 ehci_state_t *ehcip, 1018 ehci_pipe_private_t *pp, 1019 ehci_isoc_xwrapper_t *itw) 1020 { 1021 usb_isoc_req_t *isoc_reqp = itw->itw_curr_xfer_reqp; 1022 usb_frame_number_t current_frame_number, start_frame_number; 1023 uint_t ddic, pfl_number; 1024 ehci_periodic_frame_list_t *periodic_frame_list = 1025 ehcip->ehci_periodic_frame_list_tablep; 1026 uint32_t addr, port_status; 1027 ehci_itd_t *itd; 1028 1029 USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1030 "ehci_insert_isoc_to_pfl: " 1031 "isoc flags 0x%x itw = 0x%p", 1032 isoc_reqp->isoc_attributes, (void *)itw); 1033 1034 /* 1035 * Enter critical, while programming the usb frame number 1036 * and inserting current isochronous TD into the ED's list. 1037 */ 1038 ddic = ddi_enter_critical(); 1039 1040 /* Get the current frame number */ 1041 current_frame_number = ehci_get_current_frame_number(ehcip); 1042 1043 /* 1044 * Check the given isochronous flags and get the frame number 1045 * to insert the itd into. 1046 */ 1047 switch (isoc_reqp->isoc_attributes & 1048 (USB_ATTRS_ISOC_START_FRAME | USB_ATTRS_ISOC_XFER_ASAP)) { 1049 case USB_ATTRS_ISOC_START_FRAME: 1050 1051 /* Starting frame number is specified */ 1052 if (pp->pp_flag & EHCI_ISOC_XFER_CONTINUE) { 1053 /* Get the starting usb frame number */ 1054 start_frame_number = pp->pp_next_frame_number; 1055 } else { 1056 /* Check for the Starting usb frame number */ 1057 if ((isoc_reqp->isoc_frame_no == 0) || 1058 ((isoc_reqp->isoc_frame_no + 1059 isoc_reqp->isoc_pkts_count) < 1060 current_frame_number)) { 1061 1062 /* Exit the critical */ 1063 ddi_exit_critical(ddic); 1064 1065 USB_DPRINTF_L2(PRINT_MASK_LISTS, 1066 ehcip->ehci_log_hdl, 1067 "ehci_insert_isoc_to_pfl:" 1068 "Invalid starting frame number"); 1069 1070 return (USB_INVALID_START_FRAME); 1071 } 1072 1073 /* Get the starting usb frame number */ 1074 start_frame_number = isoc_reqp->isoc_frame_no; 1075 1076 pp->pp_next_frame_number = 0; 1077 } 1078 break; 1079 case USB_ATTRS_ISOC_XFER_ASAP: 1080 /* ehci has to specify starting frame number */ 1081 if ((pp->pp_next_frame_number) && 1082 (pp->pp_next_frame_number > current_frame_number)) { 1083 /* 1084 * Get the next usb frame number. 1085 */ 1086 start_frame_number = pp->pp_next_frame_number; 1087 } else { 1088 /* 1089 * Add appropriate offset to the current usb 1090 * frame number and use it as a starting frame 1091 * number. 1092 */ 1093 start_frame_number = 1094 current_frame_number + EHCI_FRAME_OFFSET; 1095 } 1096 1097 if (!(pp->pp_flag & EHCI_ISOC_XFER_CONTINUE)) { 1098 isoc_reqp->isoc_frame_no = start_frame_number; 1099 } 1100 break; 1101 default: 1102 /* Exit the critical */ 1103 ddi_exit_critical(ddic); 1104 1105 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1106 "ehci_insert_isoc_to_pfl: Either starting " 1107 "frame number or ASAP flags are not set, attrs = 0x%x", 1108 isoc_reqp->isoc_attributes); 1109 1110 return (USB_NO_FRAME_NUMBER); 1111 } 1112 1113 if (itw->itw_port_status == USBA_HIGH_SPEED_DEV) { 1114 port_status = EHCI_ITD_LINK_REF_ITD; 1115 } else { 1116 port_status = EHCI_ITD_LINK_REF_SITD; 1117 } 1118 1119 itd = itw->itw_itd_head; 1120 while (itd) { 1121 /* Find the appropriate frame list to put the itd into */ 1122 pfl_number = start_frame_number % EHCI_NUM_PERIODIC_FRAME_LISTS; 1123 1124 addr = Get_PFLT(periodic_frame_list-> 1125 ehci_periodic_frame_list_table[pfl_number]); 1126 Set_ITD(itd->itd_link_ptr, addr); 1127 1128 /* Set the link_ref correctly as ITD or SITD. */ 1129 addr = ehci_itd_cpu_to_iommu(ehcip, itd) & EHCI_ITD_LINK_PTR; 1130 addr |= port_status; 1131 1132 Set_PFLT(periodic_frame_list-> 1133 ehci_periodic_frame_list_table[pfl_number], addr); 1134 1135 /* Save which frame the ITD was inserted into */ 1136 Set_ITD_FRAME(itd->itd_frame_number, start_frame_number); 1137 1138 ehci_insert_itd_into_active_list(ehcip, itd); 1139 1140 /* Get the next ITD in the ITW */ 1141 itd = ehci_itd_iommu_to_cpu(ehcip, 1142 Get_ITD(itd->itd_itw_next_itd)); 1143 1144 start_frame_number++; 1145 } 1146 1147 /* Exit the critical */ 1148 ddi_exit_critical(ddic); 1149 1150 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1151 "ehci_insert_isoc_to_pfl: " 1152 "current frame number 0x%llx start frame number 0x%llx num itds %d", 1153 (unsigned long long)current_frame_number, 1154 (unsigned long long)start_frame_number, itw->itw_num_itds); 1155 1156 /* 1157 * Increment this saved frame number by current number 1158 * of data packets needs to be transfer. 1159 */ 1160 pp->pp_next_frame_number = start_frame_number; 1161 1162 /* 1163 * Set EHCI_ISOC_XFER_CONTINUE flag in order to send other 1164 * isochronous packets, part of the current isoch request 1165 * in the subsequent frames. 1166 */ 1167 pp->pp_flag |= EHCI_ISOC_XFER_CONTINUE; 1168 1169 return (USB_SUCCESS); 1170 } 1171 1172 1173 /* 1174 * ehci_remove_isoc_to_pfl: 1175 * 1176 * Remove an ITD request from the Host Controller's isochronous list. 1177 * If we can't find it, something has gone wrong. 1178 */ 1179 void 1180 ehci_remove_isoc_from_pfl( 1181 ehci_state_t *ehcip, 1182 ehci_itd_t *curr_itd) 1183 { 1184 ehci_periodic_frame_list_t *periodic_frame_list; 1185 uint_t pfl_number; 1186 uint32_t next_addr, curr_itd_addr; 1187 uint32_t link_ref; 1188 ehci_itd_t *prev_itd = NULL; 1189 1190 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 1191 "ehci_remove_isoc_from_pfl:"); 1192 1193 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1194 1195 /* Get the address of the current itd */ 1196 curr_itd_addr = ehci_itd_cpu_to_iommu(ehcip, curr_itd); 1197 1198 /* 1199 * Remove this ITD from the PFL 1200 * But first we need to find it in the PFL 1201 */ 1202 periodic_frame_list = ehcip->ehci_periodic_frame_list_tablep; 1203 pfl_number = Get_ITD_FRAME(curr_itd->itd_frame_number) % 1204 EHCI_NUM_PERIODIC_FRAME_LISTS; 1205 1206 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 1207 "ehci_remove_isoc_from_pfl: itd = 0x%p pfl number 0x%x", 1208 (void *)curr_itd, pfl_number); 1209 1210 next_addr = Get_PFLT(periodic_frame_list-> 1211 ehci_periodic_frame_list_table[pfl_number]); 1212 while ((next_addr & EHCI_ITD_LINK_PTR) != 1213 (curr_itd_addr & EHCI_ITD_LINK_PTR)) { 1214 1215 link_ref = next_addr & EHCI_ITD_LINK_REF; 1216 1217 if ((link_ref == EHCI_ITD_LINK_REF_ITD) || 1218 (link_ref == EHCI_ITD_LINK_REF_SITD)) { 1219 1220 prev_itd = ehci_itd_iommu_to_cpu(ehcip, 1221 (next_addr & EHCI_ITD_LINK_PTR)); 1222 next_addr = Get_ITD(prev_itd->itd_link_ptr); 1223 } else { 1224 1225 break; 1226 } 1227 } 1228 1229 /* 1230 * If the next itd is the current itd, that means we found it. 1231 * Set the previous's ITD link ptr to the Curr_ITD's link ptr. 1232 * But do not touch the Curr_ITD's link ptr. 1233 */ 1234 if ((next_addr & EHCI_ITD_LINK_PTR) == 1235 (curr_itd_addr & EHCI_ITD_LINK_PTR)) { 1236 1237 next_addr = Get_ITD(curr_itd->itd_link_ptr); 1238 1239 if (prev_itd == NULL) { 1240 /* This means PFL points to this ITD */ 1241 Set_PFLT(periodic_frame_list-> 1242 ehci_periodic_frame_list_table[pfl_number], 1243 next_addr); 1244 } else { 1245 /* Set the previous ITD's itd_link_ptr */ 1246 Set_ITD(prev_itd->itd_link_ptr, next_addr); 1247 } 1248 1249 Set_ITD_FRAME(curr_itd->itd_frame_number, 0); 1250 } else { 1251 ASSERT((next_addr & EHCI_ITD_LINK_PTR) == 1252 (curr_itd_addr & EHCI_ITD_LINK_PTR)); 1253 USB_DPRINTF_L3(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 1254 "ehci_remove_isoc_from_pfl: Unable to find ITD in PFL"); 1255 } 1256 } 1257 1258 1259 /* 1260 * Isochronous in resource functions 1261 */ 1262 /* 1263 * ehci_allocate_periodic_in_resource 1264 * 1265 * Allocate interrupt request structure for the interrupt IN transfer. 1266 */ 1267 int 1268 ehci_allocate_isoc_in_resource( 1269 ehci_state_t *ehcip, 1270 ehci_pipe_private_t *pp, 1271 ehci_isoc_xwrapper_t *itw, 1272 usb_flags_t flags) 1273 { 1274 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle; 1275 usb_isoc_req_t *orig_isoc_reqp, *clone_isoc_reqp; 1276 1277 USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1278 "ehci_allocate_isoc_in_resource:" 1279 "pp = 0x%p itw = 0x%p flags = 0x%x", (void *)pp, (void *)itw, 1280 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", (void *)pp, (void *)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 if (error != USB_CR_OK) { 1452 isoc_reqp->isoc_error_count++; 1453 1454 USB_DPRINTF_L2(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1455 "ehci_parse_sitd_error: Error %d Device Address %d" 1456 " Endpoint number %d", error, itw->itw_device_addr, 1457 itw->itw_endpoint_num); 1458 } 1459 1460 } 1461 } 1462 1463 1464 /* ARGSUSED */ 1465 static usb_cr_t ehci_parse_itd_error( 1466 ehci_state_t *ehcip, 1467 ehci_isoc_xwrapper_t *itw, 1468 ehci_itd_t *itd) 1469 { 1470 uint32_t status, index; 1471 usb_cr_t error = USB_CR_OK; 1472 uint32_t i; 1473 usb_isoc_req_t *isoc_reqp; 1474 1475 isoc_reqp = itw->itw_curr_xfer_reqp; 1476 1477 for (i = 0; i < EHCI_ITD_CTRL_LIST_SIZE; i++) { 1478 index = Get_ITD_INDEX(itd, i); 1479 if (index == 0xffffffff) { 1480 1481 continue; 1482 } 1483 1484 error = USB_CR_OK; 1485 1486 status = Get_ITD_BODY(itd, EHCI_ITD_CTRL0 + i) & 1487 EHCI_ITD_XFER_STATUS_MASK; 1488 1489 if (status & EHCI_ITD_XFER_DATA_BUFFER_ERR) { 1490 if (itw->itw_direction == USB_EP_DIR_OUT) { 1491 USB_DPRINTF_L3(PRINT_MASK_INTR, 1492 ehcip->ehci_log_hdl, 1493 "ehci_parse_itd_error: BUFFER Underrun"); 1494 1495 error = USB_CR_BUFFER_UNDERRUN; 1496 } else { 1497 USB_DPRINTF_L3(PRINT_MASK_INTR, 1498 ehcip->ehci_log_hdl, 1499 "ehci_parse_itd_error: BUFFER Overrun"); 1500 1501 error = USB_CR_BUFFER_OVERRUN; 1502 } 1503 } 1504 1505 if (status & EHCI_ITD_XFER_BABBLE) { 1506 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1507 "ehci_parse_itd_error: BABBLE DETECTED"); 1508 1509 error = USB_CR_DATA_OVERRUN; 1510 } 1511 1512 if (status & EHCI_ITD_XFER_ERROR) { 1513 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1514 "ehci_parse_itd_error: XACT ERROR"); 1515 1516 error = USB_CR_DEV_NOT_RESP; 1517 } 1518 1519 if (status & EHCI_ITD_XFER_ACTIVE) { 1520 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1521 "ehci_parse_itd_error: NOT ACCESSED"); 1522 1523 error = USB_CR_NOT_ACCESSED; 1524 } 1525 1526 itw->itw_curr_isoc_pktp->isoc_pkt_actual_length = 0; 1527 1528 /* Write the status of isoc data packet */ 1529 itw->itw_curr_isoc_pktp->isoc_pkt_status = error; 1530 1531 /* counts total number of error packets in this req */ 1532 if (error != USB_CR_OK) { 1533 isoc_reqp->isoc_error_count++; 1534 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1535 "ehci_parse_itd_error: Error %d Device Address %d " 1536 "Endpoint number %d", error, itw->itw_device_addr, 1537 itw->itw_endpoint_num); 1538 } 1539 1540 itw->itw_curr_isoc_pktp++; 1541 } 1542 1543 return (error); 1544 } 1545 1546 static usb_cr_t ehci_parse_sitd_error( 1547 ehci_state_t *ehcip, 1548 ehci_isoc_xwrapper_t *itw, 1549 ehci_itd_t *itd) 1550 { 1551 uint32_t status; 1552 usb_cr_t error; 1553 usb_isoc_pkt_descr_t *isoc_pkt_descr; 1554 uint32_t residue; 1555 1556 isoc_pkt_descr = itw->itw_curr_isoc_pktp; 1557 1558 status = Get_ITD_BODY(itd, EHCI_SITD_XFER_STATE) & 1559 EHCI_SITD_XFER_STATUS_MASK; 1560 1561 switch (status) { 1562 case EHCI_SITD_XFER_ACTIVE: 1563 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1564 "ehci_check_for_sitd_error: NOT ACCESSED"); 1565 error = USB_CR_NOT_ACCESSED; 1566 1567 break; 1568 case EHCI_SITD_XFER_ERROR: 1569 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1570 "ehci_check_for_sitd_error: TT ERROR"); 1571 1572 error = USB_CR_UNSPECIFIED_ERR; 1573 1574 break; 1575 case EHCI_SITD_XFER_DATA_BUFFER_ERR: 1576 if (itw->itw_direction == USB_EP_DIR_OUT) { 1577 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1578 "ehci_check_for_sitd_error: BUFFER Underrun"); 1579 error = USB_CR_BUFFER_UNDERRUN; 1580 } else { 1581 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1582 "ehci_check_for_sitd_error: BUFFER Overrun"); 1583 error = USB_CR_BUFFER_OVERRUN; 1584 } 1585 1586 break; 1587 case EHCI_SITD_XFER_BABBLE: 1588 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1589 "ehci_check_for_sitd_error: BABBLE"); 1590 error = USB_CR_DATA_OVERRUN; 1591 1592 break; 1593 case EHCI_SITD_XFER_XACT_ERROR: 1594 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1595 "ehci_check_for_sitd_error: XACT ERROR"); 1596 1597 error = USB_CR_DEV_NOT_RESP; 1598 break; 1599 case EHCI_SITD_XFER_MISSED_UFRAME: 1600 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1601 "ehci_check_for_sitd_error: MISSED UFRAME"); 1602 1603 error = USB_CR_NOT_ACCESSED; 1604 break; 1605 default: 1606 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1607 "ehci_check_for_sitd_error: NO ERROR"); 1608 error = USB_CR_OK; 1609 1610 break; 1611 } 1612 1613 /* This is HCD specific and may not have this information */ 1614 residue = 1615 (Get_ITD_BODY(itd, EHCI_SITD_XFER_STATE) & 1616 EHCI_SITD_XFER_TOTAL_MASK) >> 1617 EHCI_SITD_XFER_TOTAL_SHIFT; 1618 1619 /* 1620 * Subtract the residue from the isoc_pkt_descr that 1621 * was set when this ITD was inserted. 1622 */ 1623 isoc_pkt_descr->isoc_pkt_actual_length -= residue; 1624 1625 /* Write the status of isoc data packet */ 1626 isoc_pkt_descr->isoc_pkt_status = error; 1627 1628 itw->itw_curr_isoc_pktp++; 1629 1630 return (error); 1631 } 1632 1633 1634 /* 1635 * debug print functions 1636 */ 1637 void 1638 ehci_print_itd( 1639 ehci_state_t *ehcip, 1640 ehci_itd_t *itd) 1641 { 1642 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1643 "ehci_print_itd: itd = 0x%p", (void *)itd); 1644 1645 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1646 "\titd_link_ptr: 0x%x ", Get_ITD(itd->itd_link_ptr)); 1647 1648 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1649 "\titd_ctrl0: 0x%x ", 1650 Get_ITD(itd->itd_body[EHCI_ITD_CTRL0])); 1651 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1652 "\titd_ctrl1: 0x%x ", 1653 Get_ITD(itd->itd_body[EHCI_ITD_CTRL1])); 1654 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1655 "\titd_ctrl2: 0x%x ", 1656 Get_ITD(itd->itd_body[EHCI_ITD_CTRL2])); 1657 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1658 "\titd_ctrl3: 0x%x ", 1659 Get_ITD(itd->itd_body[EHCI_ITD_CTRL3])); 1660 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1661 "\titd_ctrl4: 0x%x ", 1662 Get_ITD(itd->itd_body[EHCI_ITD_CTRL4])); 1663 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1664 "\titd_ctrl5: 0x%x ", 1665 Get_ITD(itd->itd_body[EHCI_ITD_CTRL5])); 1666 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1667 "\titd_ctrl6: 0x%x ", 1668 Get_ITD(itd->itd_body[EHCI_ITD_CTRL6])); 1669 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1670 "\titd_ctrl7: 0x%x ", 1671 Get_ITD(itd->itd_body[EHCI_ITD_CTRL7])); 1672 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1673 "\titd_buffer0: 0x%x ", 1674 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER0])); 1675 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1676 "\titd_buffer1: 0x%x ", 1677 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER1])); 1678 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1679 "\titd_buffer2: 0x%x ", 1680 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER2])); 1681 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1682 "\titd_buffer3: 0x%x ", 1683 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER3])); 1684 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1685 "\titd_buffer4: 0x%x ", 1686 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER4])); 1687 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1688 "\titd_buffer5: 0x%x ", 1689 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER5])); 1690 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1691 "\titd_buffer6: 0x%x ", 1692 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER6])); 1693 1694 /* HCD private fields */ 1695 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1696 "\titd_trans_wrapper: 0x%x ", 1697 Get_ITD(itd->itd_trans_wrapper)); 1698 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1699 "\titd_itw_next_itd: 0x%x ", 1700 Get_ITD(itd->itd_itw_next_itd)); 1701 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1702 "\titd_state: 0x%x ", 1703 Get_ITD(itd->itd_state)); 1704 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1705 "\titd_index: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x ", 1706 Get_ITD_INDEX(itd, 0), Get_ITD_INDEX(itd, 1), 1707 Get_ITD_INDEX(itd, 2), Get_ITD_INDEX(itd, 3), 1708 Get_ITD_INDEX(itd, 4), Get_ITD_INDEX(itd, 5), 1709 Get_ITD_INDEX(itd, 6), Get_ITD_INDEX(itd, 7)); 1710 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1711 "\titd_frame_number: 0x%x ", 1712 Get_ITD(itd->itd_frame_number)); 1713 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1714 "\titd_reclaim_number: 0x%x ", 1715 Get_ITD(itd->itd_reclaim_number)); 1716 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1717 "\titd_next_active_itd: 0x%x ", 1718 Get_ITD(itd->itd_next_active_itd)); 1719 } 1720 1721 1722 void 1723 ehci_print_sitd( 1724 ehci_state_t *ehcip, 1725 ehci_itd_t *itd) 1726 { 1727 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1728 "ehci_print_itd: itd = 0x%p", (void *)itd); 1729 1730 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1731 "\titd_link_ptr: 0x%x ", Get_ITD(itd->itd_link_ptr)); 1732 1733 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1734 "\tsitd_ctrl: 0x%x ", 1735 Get_ITD(itd->itd_body[EHCI_SITD_CTRL])); 1736 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1737 "\tsitd_uframe_sched: 0x%x ", 1738 Get_ITD(itd->itd_body[EHCI_SITD_UFRAME_SCHED])); 1739 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1740 "\tsitd_xfer_state: 0x%x ", 1741 Get_ITD(itd->itd_body[EHCI_SITD_XFER_STATE])); 1742 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1743 "\tsitd_buffer0: 0x%x ", 1744 Get_ITD(itd->itd_body[EHCI_SITD_BUFFER0])); 1745 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1746 "\tsitd_buffer1: 0x%x ", 1747 Get_ITD(itd->itd_body[EHCI_SITD_BUFFER1])); 1748 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1749 "\tsitd_prev_sitd: 0x%x ", 1750 Get_ITD(itd->itd_body[EHCI_SITD_PREV_SITD])); 1751 1752 /* HCD private fields */ 1753 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1754 "\titd_trans_wrapper: 0x%x ", 1755 Get_ITD(itd->itd_trans_wrapper)); 1756 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1757 "\titd_itw_next_itd: 0x%x ", 1758 Get_ITD(itd->itd_itw_next_itd)); 1759 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1760 "\titd_state: 0x%x ", 1761 Get_ITD(itd->itd_state)); 1762 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1763 "\titd_frame_number: 0x%x ", 1764 Get_ITD(itd->itd_frame_number)); 1765 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1766 "\titd_reclaim_number: 0x%x ", 1767 Get_ITD(itd->itd_reclaim_number)); 1768 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1769 "\titd_next_active_itd: 0x%x ", 1770 Get_ITD(itd->itd_next_active_itd)); 1771 } 1772