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 /* 23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright (c) 2016 by Delphix. All rights reserved. 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 ehcip->ehci_periodic_req_count++; 497 ehci_toggle_scheduler(ehcip); 498 499 return (itw); 500 } 501 502 503 /* 504 * ehci_deallocate_itw: 505 * 506 * Deallocate of a Isochronous Transaction Wrapper (TW) and this involves the 507 * freeing of DMA resources. 508 */ 509 void 510 ehci_deallocate_itw( 511 ehci_state_t *ehcip, 512 ehci_pipe_private_t *pp, 513 ehci_isoc_xwrapper_t *itw) 514 { 515 ehci_isoc_xwrapper_t *prev, *next; 516 517 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 518 "ehci_deallocate_itw: itw = 0x%p", (void *)itw); 519 520 /* 521 * If the transfer wrapper has no Host Controller (HC) 522 * Transfer Descriptors (ITD) associated with it, then 523 * remove the transfer wrapper. 524 */ 525 if (itw->itw_itd_head) { 526 ASSERT(itw->itw_itd_tail != NULL); 527 528 return; 529 } 530 531 ASSERT(itw->itw_itd_tail == NULL); 532 533 /* Make sure we return all the unused itd's to the pool as well */ 534 ehci_deallocate_itds_for_itw(ehcip, itw); 535 536 /* 537 * If pp->pp_tw_head and pp->pp_tw_tail are pointing to 538 * given TW then set the head and tail equal to NULL. 539 * Otherwise search for this TW in the linked TW's list 540 * and then remove this TW from the list. 541 */ 542 if (pp->pp_itw_head == itw) { 543 if (pp->pp_itw_tail == itw) { 544 pp->pp_itw_head = NULL; 545 pp->pp_itw_tail = NULL; 546 } else { 547 pp->pp_itw_head = itw->itw_next; 548 } 549 } else { 550 prev = pp->pp_itw_head; 551 next = prev->itw_next; 552 553 while (next && (next != itw)) { 554 prev = next; 555 next = next->itw_next; 556 } 557 558 if (next == itw) { 559 prev->itw_next = next->itw_next; 560 561 if (pp->pp_itw_tail == itw) { 562 pp->pp_itw_tail = prev; 563 } 564 } 565 } 566 567 /* Free this iTWs dma resources */ 568 ehci_free_itw_dma(ehcip, pp, itw); 569 570 ehcip->ehci_periodic_req_count--; 571 ehci_toggle_scheduler(ehcip); 572 } 573 574 575 /* 576 * ehci_free_itw_dma: 577 * 578 * Free the Isochronous Transfer Wrapper dma resources. 579 */ 580 /*ARGSUSED*/ 581 static void 582 ehci_free_itw_dma( 583 ehci_state_t *ehcip, 584 ehci_pipe_private_t *pp, 585 ehci_isoc_xwrapper_t *itw) 586 { 587 int rval; 588 589 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 590 "ehci_free_itw_dma: itw = 0x%p", (void *)itw); 591 592 ASSERT(itw != NULL); 593 ASSERT(itw->itw_id != NULL); 594 595 /* Free 32bit ID */ 596 EHCI_FREE_ID((uint32_t)itw->itw_id); 597 598 rval = ddi_dma_unbind_handle(itw->itw_dmahandle); 599 ASSERT(rval == DDI_SUCCESS); 600 601 ddi_dma_mem_free(&itw->itw_accesshandle); 602 ddi_dma_free_handle(&itw->itw_dmahandle); 603 604 /* Free transfer wrapper */ 605 kmem_free(itw, sizeof (ehci_isoc_xwrapper_t)); 606 } 607 608 609 /* 610 * transfer descriptor functions 611 */ 612 /* 613 * ehci_allocate_itd: 614 * 615 * Allocate a Transfer Descriptor (iTD) from the iTD buffer pool. 616 */ 617 static ehci_itd_t * 618 ehci_allocate_itd(ehci_state_t *ehcip) 619 { 620 int i, state; 621 ehci_itd_t *itd; 622 623 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 624 625 /* 626 * Search for a blank Transfer Descriptor (iTD) 627 * in the iTD buffer pool. 628 */ 629 for (i = 0; i < ehci_itd_pool_size; i ++) { 630 state = Get_ITD(ehcip->ehci_itd_pool_addr[i].itd_state); 631 if (state == EHCI_ITD_FREE) { 632 break; 633 } 634 } 635 636 if (i >= ehci_itd_pool_size) { 637 USB_DPRINTF_L2(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 638 "ehci_allocate_itd: ITD exhausted"); 639 640 return (NULL); 641 } 642 643 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 644 "ehci_allocate_itd: Allocated %d", i); 645 646 /* Create a new dummy for the end of the ITD list */ 647 itd = &ehcip->ehci_itd_pool_addr[i]; 648 649 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 650 "ehci_allocate_itd: itd 0x%p", (void *)itd); 651 652 /* Mark the newly allocated ITD as a empty */ 653 Set_ITD(itd->itd_state, EHCI_ITD_DUMMY); 654 655 return (itd); 656 } 657 658 659 /* 660 * ehci_deallocate_itd: 661 * 662 * Deallocate a Host Controller's (HC) Transfer Descriptor (ITD). 663 * 664 */ 665 void 666 ehci_deallocate_itd( 667 ehci_state_t *ehcip, 668 ehci_isoc_xwrapper_t *itw, 669 ehci_itd_t *old_itd) 670 { 671 ehci_itd_t *itd, *next_itd; 672 673 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 674 "ehci_deallocate_itd: old_itd = 0x%p", (void *)old_itd); 675 676 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 677 678 /* If it has been marked RECLAIM it has already been removed */ 679 if (Get_ITD(old_itd->itd_state) != EHCI_ITD_RECLAIM) { 680 ehci_remove_isoc_from_pfl(ehcip, old_itd); 681 } 682 683 /* Make sure the ITD is not in the PFL */ 684 ASSERT(Get_ITD_FRAME(old_itd->itd_frame_number) == 0); 685 686 /* Remove the itd from the itw */ 687 itd = itw->itw_itd_head; 688 if (old_itd != itd) { 689 next_itd = ehci_itd_iommu_to_cpu(ehcip, 690 Get_ITD(itd->itd_itw_next_itd)); 691 692 while (next_itd != old_itd) { 693 itd = next_itd; 694 next_itd = ehci_itd_iommu_to_cpu(ehcip, 695 Get_ITD(itd->itd_itw_next_itd)); 696 } 697 698 Set_ITD(itd->itd_itw_next_itd, old_itd->itd_itw_next_itd); 699 700 if (itd->itd_itw_next_itd == 0) { 701 itw->itw_itd_tail = itd; 702 } 703 } else { 704 itw->itw_itd_head = ehci_itd_iommu_to_cpu( 705 ehcip, Get_ITD(old_itd->itd_itw_next_itd)); 706 707 if (itw->itw_itd_head == NULL) { 708 itw->itw_itd_tail = NULL; 709 } 710 } 711 712 bzero((char *)old_itd, sizeof (ehci_itd_t)); 713 Set_ITD(old_itd->itd_state, EHCI_ITD_FREE); 714 715 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 716 "Dealloc_itd: itd 0x%p", (void *)old_itd); 717 } 718 719 720 /* 721 * ehci_calc_num_itds: 722 * 723 * Calculates how many ITDs are needed for this request. 724 * The calculation is based on weather it is an HIGH speed 725 * transaction of a FULL/LOW transaction. 726 * 727 * For FULL/LOW transaction more itds are necessary if it 728 * spans frames. 729 */ 730 uint_t 731 ehci_calc_num_itds( 732 ehci_isoc_xwrapper_t *itw, 733 size_t pkt_count) 734 { 735 uint_t multiplier, itd_count; 736 737 /* Allocate the appropriate isoc resources */ 738 if (itw->itw_port_status == USBA_HIGH_SPEED_DEV) { 739 /* Multiplier needs to be passed in somehow */ 740 multiplier = 1 * 8; 741 itd_count = pkt_count / multiplier; 742 if (pkt_count % multiplier) { 743 itd_count++; 744 } 745 } else { 746 itd_count = (uint_t)pkt_count; 747 } 748 749 return (itd_count); 750 } 751 752 /* 753 * ehci_allocate_itds_for_itw: 754 * 755 * Allocate n Transfer Descriptors (TD) from the TD buffer pool and places it 756 * into the TW. 757 * 758 * Returns USB_NO_RESOURCES if it was not able to allocate all the requested TD 759 * otherwise USB_SUCCESS. 760 */ 761 int 762 ehci_allocate_itds_for_itw( 763 ehci_state_t *ehcip, 764 ehci_isoc_xwrapper_t *itw, 765 uint_t itd_count) 766 { 767 ehci_itd_t *itd; 768 uint32_t itd_addr; 769 int i; 770 int error = USB_SUCCESS; 771 772 for (i = 0; i < itd_count; i += 1) { 773 itd = ehci_allocate_itd(ehcip); 774 if (itd == NULL) { 775 error = USB_NO_RESOURCES; 776 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 777 "ehci_allocate_itds_for_itw: " 778 "Unable to allocate %d ITDs", 779 itd_count); 780 break; 781 } 782 if (i > 0) { 783 itd_addr = ehci_itd_cpu_to_iommu(ehcip, 784 itw->itw_itd_free_list); 785 Set_ITD(itd->itd_link_ptr, itd_addr); 786 } 787 Set_ITD_INDEX(itd, 0, EHCI_ITD_UNUSED_INDEX); 788 Set_ITD_INDEX(itd, 1, EHCI_ITD_UNUSED_INDEX); 789 Set_ITD_INDEX(itd, 2, EHCI_ITD_UNUSED_INDEX); 790 Set_ITD_INDEX(itd, 3, EHCI_ITD_UNUSED_INDEX); 791 Set_ITD_INDEX(itd, 4, EHCI_ITD_UNUSED_INDEX); 792 Set_ITD_INDEX(itd, 5, EHCI_ITD_UNUSED_INDEX); 793 Set_ITD_INDEX(itd, 6, EHCI_ITD_UNUSED_INDEX); 794 Set_ITD_INDEX(itd, 7, EHCI_ITD_UNUSED_INDEX); 795 itw->itw_itd_free_list = itd; 796 } 797 798 return (error); 799 } 800 801 802 /* 803 * ehci_deallocate_itds_for_itw: 804 * 805 * Free all allocated resources for Transaction Wrapper (TW). 806 * Does not free the iTW itself. 807 */ 808 static void 809 ehci_deallocate_itds_for_itw( 810 ehci_state_t *ehcip, 811 ehci_isoc_xwrapper_t *itw) 812 { 813 ehci_itd_t *itd = NULL; 814 ehci_itd_t *temp_itd = NULL; 815 816 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 817 "ehci_free_itw_itd_resources: itw = 0x%p", (void *)itw); 818 819 itd = itw->itw_itd_free_list; 820 while (itd != NULL) { 821 /* Save the pointer to the next itd before destroying it */ 822 temp_itd = ehci_itd_iommu_to_cpu(ehcip, 823 Get_ITD(itd->itd_link_ptr)); 824 ehci_deallocate_itd(ehcip, itw, itd); 825 itd = temp_itd; 826 } 827 itw->itw_itd_free_list = NULL; 828 } 829 830 831 /* 832 * ehci_insert_itd_on_itw: 833 * 834 * The transfer wrapper keeps a list of all Transfer Descriptors (iTD) that 835 * are allocated for this transfer. Insert a iTD onto this list. 836 */ 837 void ehci_insert_itd_on_itw( 838 ehci_state_t *ehcip, 839 ehci_isoc_xwrapper_t *itw, 840 ehci_itd_t *itd) 841 { 842 /* 843 * Set the next pointer to NULL because 844 * this is the last ITD on list. 845 */ 846 Set_ITD(itd->itd_itw_next_itd, 0); 847 848 if (itw->itw_itd_head == NULL) { 849 ASSERT(itw->itw_itd_tail == NULL); 850 itw->itw_itd_head = itd; 851 itw->itw_itd_tail = itd; 852 } else { 853 ehci_itd_t *dummy = (ehci_itd_t *)itw->itw_itd_tail; 854 855 ASSERT(dummy != NULL); 856 ASSERT(Get_ITD(itd->itd_state) == EHCI_ITD_ACTIVE); 857 858 /* Add the itd to the end of the list */ 859 Set_ITD(dummy->itd_itw_next_itd, 860 ehci_itd_cpu_to_iommu(ehcip, itd)); 861 862 itw->itw_itd_tail = itd; 863 } 864 865 Set_ITD(itd->itd_trans_wrapper, (uint32_t)itw->itw_id); 866 } 867 868 869 /* 870 * ehci_insert_itd_into_active_list: 871 * 872 * Add current ITD into the active ITD list in reverse order. 873 * When the done list is created, remove it in the reverse order. 874 */ 875 void 876 ehci_insert_itd_into_active_list( 877 ehci_state_t *ehcip, 878 ehci_itd_t *itd) 879 { 880 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 881 ASSERT(itd != NULL); 882 883 Set_ITD(itd->itd_next_active_itd, 884 ehci_itd_cpu_to_iommu(ehcip, ehcip->ehci_active_itd_list)); 885 ehcip->ehci_active_itd_list = itd; 886 } 887 888 889 /* 890 * ehci_remove_itd_from_active_list: 891 * 892 * Remove current ITD from the active ITD list. 893 */ 894 void 895 ehci_remove_itd_from_active_list( 896 ehci_state_t *ehcip, 897 ehci_itd_t *itd) 898 { 899 ehci_itd_t *curr_itd, *next_itd; 900 901 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 902 ASSERT(itd != NULL); 903 904 USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 905 "ehci_remove_itd_from_active_list: " 906 "ehci_active_itd_list = 0x%p itd = 0x%p", 907 (void *)ehcip->ehci_active_itd_list, (void *)itd); 908 909 curr_itd = ehcip->ehci_active_itd_list; 910 911 if (curr_itd == itd) { 912 ehcip->ehci_active_itd_list = 913 ehci_itd_iommu_to_cpu(ehcip, itd->itd_next_active_itd); 914 itd->itd_next_active_itd = 0; 915 916 return; 917 } 918 919 next_itd = ehci_itd_iommu_to_cpu(ehcip, curr_itd->itd_next_active_itd); 920 while (next_itd != itd) { 921 curr_itd = next_itd; 922 if (curr_itd) { 923 next_itd = ehci_itd_iommu_to_cpu(ehcip, 924 curr_itd->itd_next_active_itd); 925 } else { 926 break; 927 } 928 } 929 930 if ((curr_itd) && (next_itd == itd)) { 931 Set_ITD(curr_itd->itd_next_active_itd, 932 Get_ITD(itd->itd_next_active_itd)); 933 Set_ITD(itd->itd_next_active_itd, 0); 934 } else { 935 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 936 "ehci_remove_itd_from_active_list: " 937 "Unable to find ITD in active_itd_list"); 938 } 939 } 940 941 942 /* 943 * ehci_create_done_itd_list: 944 * 945 * Traverse the active list and create a done list and remove them 946 * from the active list. 947 */ 948 ehci_itd_t * 949 ehci_create_done_itd_list( 950 ehci_state_t *ehcip) 951 { 952 usb_frame_number_t current_frame_number; 953 usb_frame_number_t itd_frame_number, itd_reclaim_number; 954 ehci_itd_t *curr_itd = NULL, *next_itd = NULL; 955 ehci_itd_t *done_itd_list = NULL; 956 uint_t state; 957 958 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 959 "ehci_create_done_itd_list:"); 960 961 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 962 963 /* 964 * Get the current frame number. 965 * Only process itd that were inserted before the current 966 * frame number. 967 */ 968 current_frame_number = ehci_get_current_frame_number(ehcip); 969 970 curr_itd = ehcip->ehci_active_itd_list; 971 972 while (curr_itd) { 973 /* Get next itd from the active itd list */ 974 next_itd = ehci_itd_iommu_to_cpu(ehcip, 975 Get_ITD(curr_itd->itd_next_active_itd)); 976 977 /* 978 * If haven't past the frame number that the ITD was 979 * suppose to be executed, don't touch it. Just in 980 * case it is being processed by the HCD and cause 981 * a race condition. 982 */ 983 itd_frame_number = Get_ITD_FRAME(curr_itd->itd_frame_number); 984 itd_reclaim_number = 985 Get_ITD_FRAME(curr_itd->itd_reclaim_number); 986 987 /* Get the ITD state */ 988 state = Get_ITD(curr_itd->itd_state); 989 990 if (((state == EHCI_ITD_ACTIVE) && 991 (itd_frame_number < current_frame_number)) || 992 ((state == EHCI_ITD_RECLAIM) && 993 (itd_reclaim_number < current_frame_number))) { 994 995 /* Remove this ITD from active ITD list */ 996 ehci_remove_itd_from_active_list(ehcip, curr_itd); 997 998 /* 999 * Create the done list in reverse order, since the 1000 * active list was also created in reverse order. 1001 */ 1002 Set_ITD(curr_itd->itd_next_active_itd, 1003 ehci_itd_cpu_to_iommu(ehcip, done_itd_list)); 1004 done_itd_list = curr_itd; 1005 } 1006 1007 curr_itd = next_itd; 1008 } 1009 1010 return (done_itd_list); 1011 } 1012 1013 1014 /* 1015 * ehci_insert_isoc_to_pfl: 1016 * 1017 * Insert a ITD request into the Host Controller's isochronous list. 1018 * All the ITDs in the ITW will be added the PFL at once. Either all 1019 * of them will make it or none of them will. 1020 */ 1021 int 1022 ehci_insert_isoc_to_pfl( 1023 ehci_state_t *ehcip, 1024 ehci_pipe_private_t *pp, 1025 ehci_isoc_xwrapper_t *itw) 1026 { 1027 usb_isoc_req_t *isoc_reqp = itw->itw_curr_xfer_reqp; 1028 usb_frame_number_t current_frame_number, start_frame_number; 1029 uint_t ddic, pfl_number; 1030 ehci_periodic_frame_list_t *periodic_frame_list = 1031 ehcip->ehci_periodic_frame_list_tablep; 1032 uint32_t addr, port_status; 1033 ehci_itd_t *itd; 1034 1035 USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1036 "ehci_insert_isoc_to_pfl: " 1037 "isoc flags 0x%x itw = 0x%p", 1038 isoc_reqp->isoc_attributes, (void *)itw); 1039 1040 /* 1041 * Enter critical, while programming the usb frame number 1042 * and inserting current isochronous TD into the ED's list. 1043 */ 1044 ddic = ddi_enter_critical(); 1045 1046 /* Get the current frame number */ 1047 current_frame_number = ehci_get_current_frame_number(ehcip); 1048 1049 /* 1050 * Check the given isochronous flags and get the frame number 1051 * to insert the itd into. 1052 */ 1053 switch (isoc_reqp->isoc_attributes & 1054 (USB_ATTRS_ISOC_START_FRAME | USB_ATTRS_ISOC_XFER_ASAP)) { 1055 case USB_ATTRS_ISOC_START_FRAME: 1056 1057 /* Starting frame number is specified */ 1058 if (pp->pp_flag & EHCI_ISOC_XFER_CONTINUE) { 1059 /* Get the starting usb frame number */ 1060 start_frame_number = pp->pp_next_frame_number; 1061 } else { 1062 /* Check for the Starting usb frame number */ 1063 if ((isoc_reqp->isoc_frame_no == 0) || 1064 ((isoc_reqp->isoc_frame_no + 1065 isoc_reqp->isoc_pkts_count) < 1066 current_frame_number)) { 1067 1068 /* Exit the critical */ 1069 ddi_exit_critical(ddic); 1070 1071 USB_DPRINTF_L2(PRINT_MASK_LISTS, 1072 ehcip->ehci_log_hdl, 1073 "ehci_insert_isoc_to_pfl:" 1074 "Invalid starting frame number"); 1075 1076 return (USB_INVALID_START_FRAME); 1077 } 1078 1079 /* Get the starting usb frame number */ 1080 start_frame_number = isoc_reqp->isoc_frame_no; 1081 1082 pp->pp_next_frame_number = 0; 1083 } 1084 break; 1085 case USB_ATTRS_ISOC_XFER_ASAP: 1086 /* ehci has to specify starting frame number */ 1087 if ((pp->pp_next_frame_number) && 1088 (pp->pp_next_frame_number > current_frame_number)) { 1089 /* 1090 * Get the next usb frame number. 1091 */ 1092 start_frame_number = pp->pp_next_frame_number; 1093 } else { 1094 /* 1095 * Add appropriate offset to the current usb 1096 * frame number and use it as a starting frame 1097 * number. 1098 */ 1099 start_frame_number = 1100 current_frame_number + EHCI_FRAME_OFFSET; 1101 } 1102 1103 if (!(pp->pp_flag & EHCI_ISOC_XFER_CONTINUE)) { 1104 isoc_reqp->isoc_frame_no = start_frame_number; 1105 } 1106 break; 1107 default: 1108 /* Exit the critical */ 1109 ddi_exit_critical(ddic); 1110 1111 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1112 "ehci_insert_isoc_to_pfl: Either starting " 1113 "frame number or ASAP flags are not set, attrs = 0x%x", 1114 isoc_reqp->isoc_attributes); 1115 1116 return (USB_NO_FRAME_NUMBER); 1117 } 1118 1119 if (itw->itw_port_status == USBA_HIGH_SPEED_DEV) { 1120 port_status = EHCI_ITD_LINK_REF_ITD; 1121 } else { 1122 port_status = EHCI_ITD_LINK_REF_SITD; 1123 } 1124 1125 itd = itw->itw_itd_head; 1126 while (itd) { 1127 /* Find the appropriate frame list to put the itd into */ 1128 pfl_number = start_frame_number % EHCI_NUM_PERIODIC_FRAME_LISTS; 1129 1130 addr = Get_PFLT(periodic_frame_list-> 1131 ehci_periodic_frame_list_table[pfl_number]); 1132 Set_ITD(itd->itd_link_ptr, addr); 1133 1134 /* Set the link_ref correctly as ITD or SITD. */ 1135 addr = ehci_itd_cpu_to_iommu(ehcip, itd) & EHCI_ITD_LINK_PTR; 1136 addr |= port_status; 1137 1138 Set_PFLT(periodic_frame_list-> 1139 ehci_periodic_frame_list_table[pfl_number], addr); 1140 1141 /* Save which frame the ITD was inserted into */ 1142 Set_ITD_FRAME(itd->itd_frame_number, start_frame_number); 1143 1144 ehci_insert_itd_into_active_list(ehcip, itd); 1145 1146 /* Get the next ITD in the ITW */ 1147 itd = ehci_itd_iommu_to_cpu(ehcip, 1148 Get_ITD(itd->itd_itw_next_itd)); 1149 1150 start_frame_number++; 1151 } 1152 1153 /* Exit the critical */ 1154 ddi_exit_critical(ddic); 1155 1156 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1157 "ehci_insert_isoc_to_pfl: " 1158 "current frame number 0x%llx start frame number 0x%llx num itds %d", 1159 (unsigned long long)current_frame_number, 1160 (unsigned long long)start_frame_number, itw->itw_num_itds); 1161 1162 /* 1163 * Increment this saved frame number by current number 1164 * of data packets needs to be transfer. 1165 */ 1166 pp->pp_next_frame_number = start_frame_number; 1167 1168 /* 1169 * Set EHCI_ISOC_XFER_CONTINUE flag in order to send other 1170 * isochronous packets, part of the current isoch request 1171 * in the subsequent frames. 1172 */ 1173 pp->pp_flag |= EHCI_ISOC_XFER_CONTINUE; 1174 1175 return (USB_SUCCESS); 1176 } 1177 1178 1179 /* 1180 * ehci_remove_isoc_to_pfl: 1181 * 1182 * Remove an ITD request from the Host Controller's isochronous list. 1183 * If we can't find it, something has gone wrong. 1184 */ 1185 void 1186 ehci_remove_isoc_from_pfl( 1187 ehci_state_t *ehcip, 1188 ehci_itd_t *curr_itd) 1189 { 1190 ehci_periodic_frame_list_t *periodic_frame_list; 1191 uint_t pfl_number; 1192 uint32_t next_addr, curr_itd_addr; 1193 uint32_t link_ref; 1194 ehci_itd_t *prev_itd = NULL; 1195 1196 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 1197 "ehci_remove_isoc_from_pfl:"); 1198 1199 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1200 1201 /* Get the address of the current itd */ 1202 curr_itd_addr = ehci_itd_cpu_to_iommu(ehcip, curr_itd); 1203 1204 /* 1205 * Remove this ITD from the PFL 1206 * But first we need to find it in the PFL 1207 */ 1208 periodic_frame_list = ehcip->ehci_periodic_frame_list_tablep; 1209 pfl_number = Get_ITD_FRAME(curr_itd->itd_frame_number) % 1210 EHCI_NUM_PERIODIC_FRAME_LISTS; 1211 1212 USB_DPRINTF_L4(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 1213 "ehci_remove_isoc_from_pfl: itd = 0x%p pfl number 0x%x", 1214 (void *)curr_itd, pfl_number); 1215 1216 next_addr = Get_PFLT(periodic_frame_list-> 1217 ehci_periodic_frame_list_table[pfl_number]); 1218 while ((next_addr & EHCI_ITD_LINK_PTR) != 1219 (curr_itd_addr & EHCI_ITD_LINK_PTR)) { 1220 1221 link_ref = next_addr & EHCI_ITD_LINK_REF; 1222 1223 if ((link_ref == EHCI_ITD_LINK_REF_ITD) || 1224 (link_ref == EHCI_ITD_LINK_REF_SITD)) { 1225 1226 prev_itd = ehci_itd_iommu_to_cpu(ehcip, 1227 (next_addr & EHCI_ITD_LINK_PTR)); 1228 next_addr = Get_ITD(prev_itd->itd_link_ptr); 1229 } else { 1230 1231 break; 1232 } 1233 } 1234 1235 /* 1236 * If the next itd is the current itd, that means we found it. 1237 * Set the previous's ITD link ptr to the Curr_ITD's link ptr. 1238 * But do not touch the Curr_ITD's link ptr. 1239 */ 1240 if ((next_addr & EHCI_ITD_LINK_PTR) == 1241 (curr_itd_addr & EHCI_ITD_LINK_PTR)) { 1242 1243 next_addr = Get_ITD(curr_itd->itd_link_ptr); 1244 1245 if (prev_itd == NULL) { 1246 /* This means PFL points to this ITD */ 1247 Set_PFLT(periodic_frame_list-> 1248 ehci_periodic_frame_list_table[pfl_number], 1249 next_addr); 1250 } else { 1251 /* Set the previous ITD's itd_link_ptr */ 1252 Set_ITD(prev_itd->itd_link_ptr, next_addr); 1253 } 1254 1255 Set_ITD_FRAME(curr_itd->itd_frame_number, 0); 1256 } else { 1257 ASSERT((next_addr & EHCI_ITD_LINK_PTR) == 1258 (curr_itd_addr & EHCI_ITD_LINK_PTR)); 1259 USB_DPRINTF_L3(PRINT_MASK_ALLOC, ehcip->ehci_log_hdl, 1260 "ehci_remove_isoc_from_pfl: Unable to find ITD in PFL"); 1261 } 1262 } 1263 1264 1265 /* 1266 * Isochronous in resource functions 1267 */ 1268 /* 1269 * ehci_allocate_periodic_in_resource 1270 * 1271 * Allocate interrupt request structure for the interrupt IN transfer. 1272 */ 1273 int 1274 ehci_allocate_isoc_in_resource( 1275 ehci_state_t *ehcip, 1276 ehci_pipe_private_t *pp, 1277 ehci_isoc_xwrapper_t *itw, 1278 usb_flags_t flags) 1279 { 1280 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle; 1281 usb_isoc_req_t *orig_isoc_reqp, *clone_isoc_reqp; 1282 1283 USB_DPRINTF_L4(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1284 "ehci_allocate_isoc_in_resource:" 1285 "pp = 0x%p itw = 0x%p flags = 0x%x", (void *)pp, (void *)itw, 1286 flags); 1287 1288 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1289 ASSERT(itw->itw_curr_xfer_reqp == NULL); 1290 1291 /* Get the client periodic in request pointer */ 1292 orig_isoc_reqp = (usb_isoc_req_t *)(pp->pp_client_periodic_in_reqp); 1293 1294 ASSERT(orig_isoc_reqp != NULL); 1295 1296 clone_isoc_reqp = usba_hcdi_dup_isoc_req(ph->p_dip, 1297 orig_isoc_reqp, flags); 1298 1299 if (clone_isoc_reqp == NULL) { 1300 USB_DPRINTF_L2(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1301 "ehci_allocate_isoc_in_resource: Isochronous" 1302 "request structure allocation failed"); 1303 1304 return (USB_NO_RESOURCES); 1305 } 1306 1307 /* 1308 * Save the client's isochronous request pointer and 1309 * length of isochronous transfer in transfer wrapper. 1310 * The dup'ed request is saved in pp_client_periodic_in_reqp 1311 */ 1312 itw->itw_curr_xfer_reqp = orig_isoc_reqp; 1313 1314 pp->pp_client_periodic_in_reqp = (usb_opaque_t)clone_isoc_reqp; 1315 1316 mutex_enter(&ph->p_mutex); 1317 ph->p_req_count++; 1318 mutex_exit(&ph->p_mutex); 1319 1320 pp->pp_state = EHCI_PIPE_STATE_ACTIVE; 1321 1322 return (USB_SUCCESS); 1323 } 1324 1325 1326 /* 1327 * ehci_deallocate_isoc_in_resource 1328 * 1329 * Deallocate interrupt request structure for the interrupt IN transfer. 1330 */ 1331 void 1332 ehci_deallocate_isoc_in_resource( 1333 ehci_state_t *ehcip, 1334 ehci_pipe_private_t *pp, 1335 ehci_isoc_xwrapper_t *itw) 1336 { 1337 usba_pipe_handle_data_t *ph = pp->pp_pipe_handle; 1338 uchar_t ep_attr = ph->p_ep.bmAttributes; 1339 usb_isoc_req_t *isoc_reqp; 1340 1341 USB_DPRINTF_L4(PRINT_MASK_LISTS, 1342 ehcip->ehci_log_hdl, 1343 "ehci_deallocate_isoc_in_resource: " 1344 "pp = 0x%p itw = 0x%p", (void *)pp, (void *)itw); 1345 1346 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1347 ASSERT((ep_attr & USB_EP_ATTR_MASK) == USB_EP_ATTR_ISOCH); 1348 1349 isoc_reqp = itw->itw_curr_xfer_reqp; 1350 1351 /* Check the current periodic in request pointer */ 1352 if (isoc_reqp) { 1353 itw->itw_curr_xfer_reqp = NULL; 1354 itw->itw_curr_isoc_pktp = NULL; 1355 1356 mutex_enter(&ph->p_mutex); 1357 ph->p_req_count--; 1358 mutex_exit(&ph->p_mutex); 1359 1360 usb_free_isoc_req(isoc_reqp); 1361 1362 /* Set periodic in pipe state to idle */ 1363 pp->pp_state = EHCI_PIPE_STATE_IDLE; 1364 } 1365 } 1366 1367 1368 /* 1369 * ehci_itd_cpu_to_iommu: 1370 * 1371 * This function converts for the given Transfer Descriptor (ITD) CPU address 1372 * to IO address. 1373 */ 1374 uint32_t 1375 ehci_itd_cpu_to_iommu( 1376 ehci_state_t *ehcip, 1377 ehci_itd_t *addr) 1378 { 1379 uint32_t td; 1380 1381 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1382 1383 if (addr == NULL) 1384 return (0); 1385 1386 td = (uint32_t)ehcip->ehci_itd_pool_cookie.dmac_address + 1387 (uint32_t)((uintptr_t)addr - 1388 (uintptr_t)(ehcip->ehci_itd_pool_addr)); 1389 1390 ASSERT(((uint32_t) (sizeof (ehci_itd_t) * 1391 (addr - ehcip->ehci_itd_pool_addr))) == 1392 ((uint32_t)((uintptr_t)addr - (uintptr_t) 1393 (ehcip->ehci_itd_pool_addr)))); 1394 1395 ASSERT(td >= ehcip->ehci_itd_pool_cookie.dmac_address); 1396 ASSERT(td <= ehcip->ehci_itd_pool_cookie.dmac_address + 1397 sizeof (ehci_itd_t) * ehci_itd_pool_size); 1398 1399 return (td); 1400 } 1401 1402 1403 /* 1404 * ehci_itd_iommu_to_cpu: 1405 * 1406 * This function converts for the given Transfer Descriptor (ITD) IO address 1407 * to CPU address. 1408 */ 1409 ehci_itd_t * 1410 ehci_itd_iommu_to_cpu( 1411 ehci_state_t *ehcip, 1412 uintptr_t addr) 1413 { 1414 ehci_itd_t *itd; 1415 1416 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1417 1418 if (addr == 0) 1419 return (NULL); 1420 1421 itd = (ehci_itd_t *)((uintptr_t) 1422 (addr - ehcip->ehci_itd_pool_cookie.dmac_address) + 1423 (uintptr_t)ehcip->ehci_itd_pool_addr); 1424 1425 ASSERT(itd >= ehcip->ehci_itd_pool_addr); 1426 ASSERT((uintptr_t)itd <= (uintptr_t)ehcip->ehci_itd_pool_addr + 1427 (uintptr_t)(sizeof (ehci_itd_t) * ehci_itd_pool_size)); 1428 1429 return (itd); 1430 } 1431 1432 1433 /* 1434 * Error parsing functions 1435 */ 1436 void ehci_parse_isoc_error( 1437 ehci_state_t *ehcip, 1438 ehci_isoc_xwrapper_t *itw, 1439 ehci_itd_t *itd) 1440 { 1441 usb_isoc_req_t *isoc_reqp; 1442 usb_cr_t error; 1443 1444 ASSERT(mutex_owned(&ehcip->ehci_int_mutex)); 1445 1446 isoc_reqp = itw->itw_curr_xfer_reqp; 1447 1448 if (itw->itw_port_status == USBA_HIGH_SPEED_DEV) { 1449 error = ehci_parse_itd_error(ehcip, itw, itd); 1450 } else { 1451 error = ehci_parse_sitd_error(ehcip, itw, itd); 1452 1453 if (error != USB_CR_OK) { 1454 isoc_reqp->isoc_error_count++; 1455 1456 USB_DPRINTF_L2(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1457 "ehci_parse_sitd_error: Error %d Device Address %d" 1458 " Endpoint number %d", error, itw->itw_device_addr, 1459 itw->itw_endpoint_num); 1460 } 1461 1462 } 1463 } 1464 1465 1466 /* ARGSUSED */ 1467 static usb_cr_t ehci_parse_itd_error( 1468 ehci_state_t *ehcip, 1469 ehci_isoc_xwrapper_t *itw, 1470 ehci_itd_t *itd) 1471 { 1472 uint32_t status, index; 1473 usb_cr_t error = USB_CR_OK; 1474 uint32_t i; 1475 usb_isoc_req_t *isoc_reqp; 1476 1477 isoc_reqp = itw->itw_curr_xfer_reqp; 1478 1479 for (i = 0; i < EHCI_ITD_CTRL_LIST_SIZE; i++) { 1480 index = Get_ITD_INDEX(itd, i); 1481 if (index == 0xffffffff) { 1482 1483 continue; 1484 } 1485 1486 error = USB_CR_OK; 1487 1488 status = Get_ITD_BODY(itd, EHCI_ITD_CTRL0 + i) & 1489 EHCI_ITD_XFER_STATUS_MASK; 1490 1491 if (status & EHCI_ITD_XFER_DATA_BUFFER_ERR) { 1492 if (itw->itw_direction == USB_EP_DIR_OUT) { 1493 USB_DPRINTF_L3(PRINT_MASK_INTR, 1494 ehcip->ehci_log_hdl, 1495 "ehci_parse_itd_error: BUFFER Underrun"); 1496 1497 error = USB_CR_BUFFER_UNDERRUN; 1498 } else { 1499 USB_DPRINTF_L3(PRINT_MASK_INTR, 1500 ehcip->ehci_log_hdl, 1501 "ehci_parse_itd_error: BUFFER Overrun"); 1502 1503 error = USB_CR_BUFFER_OVERRUN; 1504 } 1505 } 1506 1507 if (status & EHCI_ITD_XFER_BABBLE) { 1508 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1509 "ehci_parse_itd_error: BABBLE DETECTED"); 1510 1511 error = USB_CR_DATA_OVERRUN; 1512 } 1513 1514 if (status & EHCI_ITD_XFER_ERROR) { 1515 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1516 "ehci_parse_itd_error: XACT ERROR"); 1517 1518 error = USB_CR_DEV_NOT_RESP; 1519 } 1520 1521 if (status & EHCI_ITD_XFER_ACTIVE) { 1522 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1523 "ehci_parse_itd_error: NOT ACCESSED"); 1524 1525 error = USB_CR_NOT_ACCESSED; 1526 } 1527 1528 itw->itw_curr_isoc_pktp->isoc_pkt_actual_length = 0; 1529 1530 /* Write the status of isoc data packet */ 1531 itw->itw_curr_isoc_pktp->isoc_pkt_status = error; 1532 1533 /* counts total number of error packets in this req */ 1534 if (error != USB_CR_OK) { 1535 isoc_reqp->isoc_error_count++; 1536 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1537 "ehci_parse_itd_error: Error %d Device Address %d " 1538 "Endpoint number %d", error, itw->itw_device_addr, 1539 itw->itw_endpoint_num); 1540 } 1541 1542 itw->itw_curr_isoc_pktp++; 1543 } 1544 1545 return (error); 1546 } 1547 1548 static usb_cr_t ehci_parse_sitd_error( 1549 ehci_state_t *ehcip, 1550 ehci_isoc_xwrapper_t *itw, 1551 ehci_itd_t *itd) 1552 { 1553 uint32_t status; 1554 usb_cr_t error; 1555 usb_isoc_pkt_descr_t *isoc_pkt_descr; 1556 uint32_t residue; 1557 1558 isoc_pkt_descr = itw->itw_curr_isoc_pktp; 1559 1560 status = Get_ITD_BODY(itd, EHCI_SITD_XFER_STATE) & 1561 EHCI_SITD_XFER_STATUS_MASK; 1562 1563 switch (status) { 1564 case EHCI_SITD_XFER_ACTIVE: 1565 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1566 "ehci_check_for_sitd_error: NOT ACCESSED"); 1567 error = USB_CR_NOT_ACCESSED; 1568 1569 break; 1570 case EHCI_SITD_XFER_ERROR: 1571 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1572 "ehci_check_for_sitd_error: TT ERROR"); 1573 1574 error = USB_CR_UNSPECIFIED_ERR; 1575 1576 break; 1577 case EHCI_SITD_XFER_DATA_BUFFER_ERR: 1578 if (itw->itw_direction == USB_EP_DIR_OUT) { 1579 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1580 "ehci_check_for_sitd_error: BUFFER Underrun"); 1581 error = USB_CR_BUFFER_UNDERRUN; 1582 } else { 1583 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1584 "ehci_check_for_sitd_error: BUFFER Overrun"); 1585 error = USB_CR_BUFFER_OVERRUN; 1586 } 1587 1588 break; 1589 case EHCI_SITD_XFER_BABBLE: 1590 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1591 "ehci_check_for_sitd_error: BABBLE"); 1592 error = USB_CR_DATA_OVERRUN; 1593 1594 break; 1595 case EHCI_SITD_XFER_XACT_ERROR: 1596 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1597 "ehci_check_for_sitd_error: XACT ERROR"); 1598 1599 error = USB_CR_DEV_NOT_RESP; 1600 break; 1601 case EHCI_SITD_XFER_MISSED_UFRAME: 1602 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1603 "ehci_check_for_sitd_error: MISSED UFRAME"); 1604 1605 error = USB_CR_NOT_ACCESSED; 1606 break; 1607 default: 1608 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 1609 "ehci_check_for_sitd_error: NO ERROR"); 1610 error = USB_CR_OK; 1611 1612 break; 1613 } 1614 1615 /* This is HCD specific and may not have this information */ 1616 residue = 1617 (Get_ITD_BODY(itd, EHCI_SITD_XFER_STATE) & 1618 EHCI_SITD_XFER_TOTAL_MASK) >> 1619 EHCI_SITD_XFER_TOTAL_SHIFT; 1620 1621 /* 1622 * Subtract the residue from the isoc_pkt_descr that 1623 * was set when this ITD was inserted. 1624 */ 1625 isoc_pkt_descr->isoc_pkt_actual_length -= residue; 1626 1627 /* Write the status of isoc data packet */ 1628 isoc_pkt_descr->isoc_pkt_status = error; 1629 1630 itw->itw_curr_isoc_pktp++; 1631 1632 return (error); 1633 } 1634 1635 1636 /* 1637 * debug print functions 1638 */ 1639 void 1640 ehci_print_itd( 1641 ehci_state_t *ehcip, 1642 ehci_itd_t *itd) 1643 { 1644 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1645 "ehci_print_itd: itd = 0x%p", (void *)itd); 1646 1647 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1648 "\titd_link_ptr: 0x%x ", Get_ITD(itd->itd_link_ptr)); 1649 1650 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1651 "\titd_ctrl0: 0x%x ", 1652 Get_ITD(itd->itd_body[EHCI_ITD_CTRL0])); 1653 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1654 "\titd_ctrl1: 0x%x ", 1655 Get_ITD(itd->itd_body[EHCI_ITD_CTRL1])); 1656 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1657 "\titd_ctrl2: 0x%x ", 1658 Get_ITD(itd->itd_body[EHCI_ITD_CTRL2])); 1659 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1660 "\titd_ctrl3: 0x%x ", 1661 Get_ITD(itd->itd_body[EHCI_ITD_CTRL3])); 1662 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1663 "\titd_ctrl4: 0x%x ", 1664 Get_ITD(itd->itd_body[EHCI_ITD_CTRL4])); 1665 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1666 "\titd_ctrl5: 0x%x ", 1667 Get_ITD(itd->itd_body[EHCI_ITD_CTRL5])); 1668 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1669 "\titd_ctrl6: 0x%x ", 1670 Get_ITD(itd->itd_body[EHCI_ITD_CTRL6])); 1671 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1672 "\titd_ctrl7: 0x%x ", 1673 Get_ITD(itd->itd_body[EHCI_ITD_CTRL7])); 1674 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1675 "\titd_buffer0: 0x%x ", 1676 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER0])); 1677 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1678 "\titd_buffer1: 0x%x ", 1679 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER1])); 1680 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1681 "\titd_buffer2: 0x%x ", 1682 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER2])); 1683 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1684 "\titd_buffer3: 0x%x ", 1685 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER3])); 1686 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1687 "\titd_buffer4: 0x%x ", 1688 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER4])); 1689 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1690 "\titd_buffer5: 0x%x ", 1691 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER5])); 1692 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1693 "\titd_buffer6: 0x%x ", 1694 Get_ITD(itd->itd_body[EHCI_ITD_BUFFER6])); 1695 1696 /* HCD private fields */ 1697 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1698 "\titd_trans_wrapper: 0x%x ", 1699 Get_ITD(itd->itd_trans_wrapper)); 1700 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1701 "\titd_itw_next_itd: 0x%x ", 1702 Get_ITD(itd->itd_itw_next_itd)); 1703 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1704 "\titd_state: 0x%x ", 1705 Get_ITD(itd->itd_state)); 1706 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1707 "\titd_index: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x ", 1708 Get_ITD_INDEX(itd, 0), Get_ITD_INDEX(itd, 1), 1709 Get_ITD_INDEX(itd, 2), Get_ITD_INDEX(itd, 3), 1710 Get_ITD_INDEX(itd, 4), Get_ITD_INDEX(itd, 5), 1711 Get_ITD_INDEX(itd, 6), Get_ITD_INDEX(itd, 7)); 1712 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1713 "\titd_frame_number: 0x%x ", 1714 Get_ITD(itd->itd_frame_number)); 1715 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1716 "\titd_reclaim_number: 0x%x ", 1717 Get_ITD(itd->itd_reclaim_number)); 1718 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1719 "\titd_next_active_itd: 0x%x ", 1720 Get_ITD(itd->itd_next_active_itd)); 1721 } 1722 1723 1724 void 1725 ehci_print_sitd( 1726 ehci_state_t *ehcip, 1727 ehci_itd_t *itd) 1728 { 1729 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1730 "ehci_print_itd: itd = 0x%p", (void *)itd); 1731 1732 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1733 "\titd_link_ptr: 0x%x ", Get_ITD(itd->itd_link_ptr)); 1734 1735 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1736 "\tsitd_ctrl: 0x%x ", 1737 Get_ITD(itd->itd_body[EHCI_SITD_CTRL])); 1738 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1739 "\tsitd_uframe_sched: 0x%x ", 1740 Get_ITD(itd->itd_body[EHCI_SITD_UFRAME_SCHED])); 1741 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1742 "\tsitd_xfer_state: 0x%x ", 1743 Get_ITD(itd->itd_body[EHCI_SITD_XFER_STATE])); 1744 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1745 "\tsitd_buffer0: 0x%x ", 1746 Get_ITD(itd->itd_body[EHCI_SITD_BUFFER0])); 1747 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1748 "\tsitd_buffer1: 0x%x ", 1749 Get_ITD(itd->itd_body[EHCI_SITD_BUFFER1])); 1750 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1751 "\tsitd_prev_sitd: 0x%x ", 1752 Get_ITD(itd->itd_body[EHCI_SITD_PREV_SITD])); 1753 1754 /* HCD private fields */ 1755 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1756 "\titd_trans_wrapper: 0x%x ", 1757 Get_ITD(itd->itd_trans_wrapper)); 1758 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1759 "\titd_itw_next_itd: 0x%x ", 1760 Get_ITD(itd->itd_itw_next_itd)); 1761 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1762 "\titd_state: 0x%x ", 1763 Get_ITD(itd->itd_state)); 1764 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1765 "\titd_frame_number: 0x%x ", 1766 Get_ITD(itd->itd_frame_number)); 1767 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1768 "\titd_reclaim_number: 0x%x ", 1769 Get_ITD(itd->itd_reclaim_number)); 1770 USB_DPRINTF_L3(PRINT_MASK_LISTS, ehcip->ehci_log_hdl, 1771 "\titd_next_active_itd: 0x%x ", 1772 Get_ITD(itd->itd_next_active_itd)); 1773 } 1774