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