1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * EHCI Host Controller Driver (EHCI) 30 * 31 * The EHCI driver is a software driver which interfaces to the Universal 32 * Serial Bus layer (USBA) and the Host Controller (HC). The interface to 33 * the Host Controller is defined by the EHCI Host Controller Interface. 34 * 35 * This file contains code for Auto-configuration and HCDI entry points. 36 * 37 * NOTE: 38 * 39 * Currently EHCI driver does not support the following features 40 * 41 * - Alternate QTD for short xfer condition is only used in Bulk xfers. 42 * - Frame Span Traversal Nodes (FSTN). 43 * - Bandwidth allocation scheme needs to be updated for FSTN and USB2.0 44 * or High speed hub with multiple TT implementation. Currently bandwidth 45 * allocation scheme assumes one TT per USB2.0 or High speed hub. 46 * - 64 bit addressing capability. 47 * - Programmable periodic frame list size like 256, 512, 1024. 48 * It supports only 1024 periodic frame list size. 49 */ 50 51 #include <sys/usb/hcd/ehci/ehcid.h> 52 #include <sys/usb/hcd/ehci/ehci_xfer.h> 53 #include <sys/usb/hcd/ehci/ehci_intr.h> 54 #include <sys/usb/hcd/ehci/ehci_util.h> 55 #include <sys/usb/hcd/ehci/ehci_isoch.h> 56 57 /* Pointer to the state structure */ 58 void *ehci_statep; 59 60 /* Number of instances */ 61 #define EHCI_INSTS 1 62 63 /* Debugging information */ 64 uint_t ehci_errmask = (uint_t)PRINT_MASK_ALL; 65 uint_t ehci_errlevel = USB_LOG_L2; 66 uint_t ehci_instance_debug = (uint_t)-1; 67 68 /* 69 * Tunable to ensure host controller goes off even if a keyboard is attached. 70 */ 71 int force_ehci_off = 1; 72 73 /* Enable all workarounds for VIA VT62x2 */ 74 uint_t ehci_vt62x2_workaround = EHCI_VIA_WORKAROUNDS; 75 76 /* 77 * EHCI Auto-configuration entry points. 78 * 79 * Device operations (dev_ops) entries function prototypes. 80 * 81 * We use the hub cbops since all nexus ioctl operations defined so far will 82 * be executed by the root hub. The following are the Host Controller Driver 83 * (HCD) entry points. 84 * 85 * the open/close/ioctl functions call the corresponding usba_hubdi_* 86 * calls after looking up the dip thru the dev_t. 87 */ 88 static int ehci_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 89 static int ehci_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 90 static int ehci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd); 91 static int ehci_info(dev_info_t *dip, ddi_info_cmd_t infocmd, 92 void *arg, void **result); 93 94 static int ehci_open(dev_t *devp, int flags, int otyp, cred_t *credp); 95 static int ehci_close(dev_t dev, int flag, int otyp, cred_t *credp); 96 static int ehci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, 97 cred_t *credp, int *rvalp); 98 99 int usba_hubdi_root_hub_power(dev_info_t *dip, int comp, int level); 100 101 static struct cb_ops ehci_cb_ops = { 102 ehci_open, /* EHCI */ 103 ehci_close, /* Close */ 104 nodev, /* Strategy */ 105 nodev, /* Print */ 106 nodev, /* Dump */ 107 nodev, /* Read */ 108 nodev, /* Write */ 109 ehci_ioctl, /* Ioctl */ 110 nodev, /* Devmap */ 111 nodev, /* Mmap */ 112 nodev, /* Segmap */ 113 nochpoll, /* Poll */ 114 ddi_prop_op, /* cb_prop_op */ 115 NULL, /* Streamtab */ 116 D_NEW | D_MP | D_HOTPLUG /* Driver compatibility flag */ 117 }; 118 119 static struct dev_ops ehci_ops = { 120 DEVO_REV, /* Devo_rev */ 121 0, /* Refcnt */ 122 ehci_info, /* Info */ 123 nulldev, /* Identify */ 124 nulldev, /* Probe */ 125 ehci_attach, /* Attach */ 126 ehci_detach, /* Detach */ 127 ehci_reset, /* Reset */ 128 &ehci_cb_ops, /* Driver operations */ 129 &usba_hubdi_busops, /* Bus operations */ 130 usba_hubdi_root_hub_power /* Power */ 131 }; 132 133 /* 134 * The USBA library must be loaded for this driver. 135 */ 136 static struct modldrv modldrv = { 137 &mod_driverops, /* Type of module. This one is a driver */ 138 "USB EHCI Driver %I%", /* Name of the module. */ 139 &ehci_ops, /* Driver ops */ 140 }; 141 142 static struct modlinkage modlinkage = { 143 MODREV_1, (void *)&modldrv, NULL 144 }; 145 146 147 int 148 _init(void) 149 { 150 int error; 151 152 /* Initialize the soft state structures */ 153 if ((error = ddi_soft_state_init(&ehci_statep, sizeof (ehci_state_t), 154 EHCI_INSTS)) != 0) { 155 return (error); 156 } 157 158 /* Install the loadable module */ 159 if ((error = mod_install(&modlinkage)) != 0) { 160 ddi_soft_state_fini(&ehci_statep); 161 } 162 163 return (error); 164 } 165 166 167 int 168 _info(struct modinfo *modinfop) 169 { 170 return (mod_info(&modlinkage, modinfop)); 171 } 172 173 174 int 175 _fini(void) 176 { 177 int error; 178 179 if ((error = mod_remove(&modlinkage)) == 0) { 180 181 /* Release per module resources */ 182 ddi_soft_state_fini(&ehci_statep); 183 } 184 185 return (error); 186 } 187 188 189 /* 190 * EHCI Auto configuration entry points. 191 */ 192 193 /* 194 * ehci_attach: 195 * 196 * Description: Attach entry point is called by the Kernel. 197 * Allocates resources for each EHCI host controller instance. 198 * Initializes the EHCI Host Controller. 199 * 200 * Return : DDI_SUCCESS / DDI_FAILURE. 201 */ 202 static int 203 ehci_attach(dev_info_t *dip, 204 ddi_attach_cmd_t cmd) 205 { 206 int instance; 207 ehci_state_t *ehcip = NULL; 208 usba_hcdi_register_args_t hcdi_args; 209 210 switch (cmd) { 211 case DDI_ATTACH: 212 break; 213 case DDI_RESUME: 214 ehcip = ehci_obtain_state(dip); 215 216 return (ehci_cpr_resume(ehcip)); 217 default: 218 return (DDI_FAILURE); 219 } 220 221 /* Get the instance and create soft state */ 222 instance = ddi_get_instance(dip); 223 224 if (ddi_soft_state_zalloc(ehci_statep, instance) != 0) { 225 226 return (DDI_FAILURE); 227 } 228 229 ehcip = ddi_get_soft_state(ehci_statep, instance); 230 if (ehcip == NULL) { 231 232 return (DDI_FAILURE); 233 } 234 235 ehcip->ehci_flags = EHCI_ATTACH; 236 237 ehcip->ehci_log_hdl = usb_alloc_log_hdl(dip, "ehci", &ehci_errlevel, 238 &ehci_errmask, &ehci_instance_debug, 0); 239 240 ehcip->ehci_flags |= EHCI_ZALLOC; 241 242 /* Set host controller soft state to initialization */ 243 ehcip->ehci_hc_soft_state = EHCI_CTLR_INIT_STATE; 244 245 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, 246 "ehcip = 0x%p", (void *)ehcip); 247 248 /* Initialize the DMA attributes */ 249 ehci_set_dma_attributes(ehcip); 250 251 /* Save the dip and instance */ 252 ehcip->ehci_dip = dip; 253 ehcip->ehci_instance = instance; 254 255 /* Initialize the DMA attributes */ 256 ehci_create_stats(ehcip); 257 258 /* Create the qtd and qh pools */ 259 if (ehci_allocate_pools(ehcip) != DDI_SUCCESS) { 260 (void) ehci_cleanup(ehcip); 261 262 return (DDI_FAILURE); 263 } 264 265 /* Initialize the isochronous resources */ 266 if (ehci_isoc_init(ehcip) != DDI_SUCCESS) { 267 (void) ehci_cleanup(ehcip); 268 269 return (DDI_FAILURE); 270 } 271 272 /* Map the registers */ 273 if (ehci_map_regs(ehcip) != DDI_SUCCESS) { 274 (void) ehci_cleanup(ehcip); 275 276 return (DDI_FAILURE); 277 } 278 279 /* Get the ehci chip vendor and device id */ 280 ehcip->ehci_vendor_id = pci_config_get16( 281 ehcip->ehci_config_handle, PCI_CONF_VENID); 282 ehcip->ehci_device_id = pci_config_get16( 283 ehcip->ehci_config_handle, PCI_CONF_DEVID); 284 ehcip->ehci_rev_id = pci_config_get8( 285 ehcip->ehci_config_handle, PCI_CONF_REVID); 286 287 /* Register interrupts */ 288 if (ehci_register_intrs_and_init_mutex(ehcip) != DDI_SUCCESS) { 289 (void) ehci_cleanup(ehcip); 290 291 return (DDI_FAILURE); 292 } 293 294 mutex_enter(&ehcip->ehci_int_mutex); 295 296 /* Initialize the controller */ 297 if (ehci_init_ctlr(ehcip, EHCI_NORMAL_INITIALIZATION) != DDI_SUCCESS) { 298 mutex_exit(&ehcip->ehci_int_mutex); 299 (void) ehci_cleanup(ehcip); 300 301 return (DDI_FAILURE); 302 } 303 304 /* 305 * At this point, the hardware will be okay. 306 * Initialize the usba_hcdi structure 307 */ 308 ehcip->ehci_hcdi_ops = ehci_alloc_hcdi_ops(ehcip); 309 310 mutex_exit(&ehcip->ehci_int_mutex); 311 312 /* 313 * Make this HCD instance known to USBA 314 * (dma_attr must be passed for USBA busctl's) 315 */ 316 hcdi_args.usba_hcdi_register_version = HCDI_REGISTER_VERSION; 317 hcdi_args.usba_hcdi_register_dip = dip; 318 hcdi_args.usba_hcdi_register_ops = ehcip->ehci_hcdi_ops; 319 hcdi_args.usba_hcdi_register_dma_attr = &ehcip->ehci_dma_attr; 320 321 /* 322 * Priority and iblock_cookie are one and the same 323 * (However, retaining hcdi_soft_iblock_cookie for now 324 * assigning it w/ priority. In future all iblock_cookie 325 * could just go) 326 */ 327 hcdi_args.usba_hcdi_register_iblock_cookie = 328 (ddi_iblock_cookie_t)(uintptr_t)ehcip->ehci_intr_pri; 329 330 if (usba_hcdi_register(&hcdi_args, 0) != DDI_SUCCESS) { 331 (void) ehci_cleanup(ehcip); 332 333 return (DDI_FAILURE); 334 } 335 336 ehcip->ehci_flags |= EHCI_USBAREG; 337 338 mutex_enter(&ehcip->ehci_int_mutex); 339 340 if ((ehci_init_root_hub(ehcip)) != USB_SUCCESS) { 341 mutex_exit(&ehcip->ehci_int_mutex); 342 (void) ehci_cleanup(ehcip); 343 344 return (DDI_FAILURE); 345 } 346 347 mutex_exit(&ehcip->ehci_int_mutex); 348 349 /* Finally load the root hub driver */ 350 if (ehci_load_root_hub_driver(ehcip) != USB_SUCCESS) { 351 (void) ehci_cleanup(ehcip); 352 353 return (DDI_FAILURE); 354 } 355 ehcip->ehci_flags |= EHCI_RHREG; 356 357 /* Display information in the banner */ 358 ddi_report_dev(dip); 359 360 mutex_enter(&ehcip->ehci_int_mutex); 361 362 /* Reset the ehci initialization flag */ 363 ehcip->ehci_flags &= ~EHCI_ATTACH; 364 365 /* Print the Host Control's Operational registers */ 366 ehci_print_caps(ehcip); 367 ehci_print_regs(ehcip); 368 369 (void) pci_report_pmcap(dip, PCI_PM_IDLESPEED, (void *)4000); 370 371 mutex_exit(&ehcip->ehci_int_mutex); 372 373 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, 374 "ehci_attach: dip = 0x%p done", (void *)dip); 375 376 return (DDI_SUCCESS); 377 } 378 379 380 /* 381 * ehci_detach: 382 * 383 * Description: Detach entry point is called by the Kernel. 384 * Deallocates all resource allocated. 385 * Unregisters the interrupt handler. 386 * 387 * Return : DDI_SUCCESS / DDI_FAILURE 388 */ 389 int 390 ehci_detach(dev_info_t *dip, 391 ddi_detach_cmd_t cmd) 392 { 393 ehci_state_t *ehcip = ehci_obtain_state(dip); 394 395 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, "ehci_detach:"); 396 397 switch (cmd) { 398 case DDI_DETACH: 399 400 return (ehci_cleanup(ehcip)); 401 case DDI_SUSPEND: 402 403 return (ehci_cpr_suspend(ehcip)); 404 default: 405 406 return (DDI_FAILURE); 407 } 408 } 409 410 /* 411 * ehci_reset: 412 * 413 * Description: Reset entry point - called by the Kernel 414 * on the way down. 415 * Toshiba Tecra laptop has been observed to hang 416 * on soft reboot. The resetting ehci on the way 417 * down solves the problem. 418 * 419 * Return : DDI_SUCCESS / DDI_FAILURE 420 */ 421 /* ARGSUSED */ 422 static int 423 ehci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd) 424 { 425 #if defined(__sparc) 426 /* 427 * Don't reset the host controller on SPARC, for OBP needs Solaris 428 * to continue to provide keyboard support after shutdown of SPARC, 429 * or the keyboard connected to a USB 2.0 port will not work after 430 * that. The incomplete reset problem on Toshiba Tecra laptop is 431 * specific to Tecra laptop or BIOS, not present on SPARC. The SPARC 432 * OBP guarantees good reset behavior during startup. 433 */ 434 return (DDI_SUCCESS); 435 #else 436 ehci_state_t *ehcip = ehci_obtain_state(dip); 437 438 mutex_enter(&ehcip->ehci_int_mutex); 439 440 /* 441 * To reset the host controller, the HCRESET bit should be set to one. 442 * Software should not set this bit to a one when the HCHalted bit in 443 * the USBSTS register is a zero. Attempting to reset an actively 444 * running host controller will result in undefined behavior. 445 * see EHCI SPEC. for more information. 446 */ 447 if (!(Get_OpReg(ehci_status) & EHCI_STS_HOST_CTRL_HALTED)) { 448 449 /* Stop the EHCI host controller */ 450 Set_OpReg(ehci_command, 451 Get_OpReg(ehci_command) & ~EHCI_CMD_HOST_CTRL_RUN); 452 /* 453 * When this bit is set to 0, the Host Controller completes the 454 * current and any actively pipelined transactions on the USB 455 * and then halts. The Host Controller must halt within 16 456 * micro-frames after software clears the Run bit. 457 * The HC Halted bit in the status register indicates when the 458 * Host Controller has finished its pending pipelined 459 * transactions and has entered the stopped state. 460 */ 461 drv_usecwait(EHCI_RESET_TIMEWAIT); 462 } 463 464 /* Reset the EHCI host controller */ 465 Set_OpReg(ehci_command, 466 Get_OpReg(ehci_command) | EHCI_CMD_HOST_CTRL_RESET); 467 468 mutex_exit(&ehcip->ehci_int_mutex); 469 470 return (DDI_SUCCESS); 471 #endif 472 } 473 474 /* 475 * ehci_info: 476 */ 477 /* ARGSUSED */ 478 static int 479 ehci_info(dev_info_t *dip, 480 ddi_info_cmd_t infocmd, 481 void *arg, 482 void **result) 483 { 484 dev_t dev; 485 ehci_state_t *ehcip; 486 int instance; 487 int error = DDI_FAILURE; 488 489 switch (infocmd) { 490 case DDI_INFO_DEVT2DEVINFO: 491 dev = (dev_t)arg; 492 instance = EHCI_UNIT(dev); 493 ehcip = ddi_get_soft_state(ehci_statep, instance); 494 if (ehcip != NULL) { 495 *result = (void *)ehcip->ehci_dip; 496 if (*result != NULL) { 497 error = DDI_SUCCESS; 498 } 499 } else { 500 *result = NULL; 501 } 502 503 break; 504 case DDI_INFO_DEVT2INSTANCE: 505 dev = (dev_t)arg; 506 instance = EHCI_UNIT(dev); 507 *result = (void *)(uintptr_t)instance; 508 error = DDI_SUCCESS; 509 break; 510 default: 511 break; 512 } 513 514 return (error); 515 } 516 517 518 /* 519 * EHCI CB_OPS entry points. 520 */ 521 static dev_info_t * 522 ehci_get_dip(dev_t dev) 523 { 524 int instance = EHCI_UNIT(dev); 525 ehci_state_t *ehcip = ddi_get_soft_state(ehci_statep, instance); 526 527 if (ehcip) { 528 529 return (ehcip->ehci_dip); 530 } else { 531 532 return (NULL); 533 } 534 } 535 536 537 static int 538 ehci_open(dev_t *devp, 539 int flags, 540 int otyp, 541 cred_t *credp) 542 { 543 dev_info_t *dip = ehci_get_dip(*devp); 544 545 return (usba_hubdi_open(dip, devp, flags, otyp, credp)); 546 } 547 548 549 static int 550 ehci_close(dev_t dev, 551 int flag, 552 int otyp, 553 cred_t *credp) 554 { 555 dev_info_t *dip = ehci_get_dip(dev); 556 557 return (usba_hubdi_close(dip, dev, flag, otyp, credp)); 558 } 559 560 561 static int 562 ehci_ioctl(dev_t dev, 563 int cmd, 564 intptr_t arg, 565 int mode, 566 cred_t *credp, 567 int *rvalp) 568 { 569 dev_info_t *dip = ehci_get_dip(dev); 570 571 return (usba_hubdi_ioctl(dip, 572 dev, cmd, arg, mode, credp, rvalp)); 573 } 574 575 /* 576 * EHCI Interrupt Handler entry point. 577 */ 578 579 /* 580 * ehci_intr: 581 * 582 * EHCI (EHCI) interrupt handling routine. 583 */ 584 uint_t 585 ehci_intr(caddr_t arg1, caddr_t arg2) 586 { 587 uint_t intr; 588 ehci_state_t *ehcip = (ehci_state_t *)arg1; 589 590 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 591 "ehci_intr: Interrupt occurred, arg1 0x%p arg2 0x%p", 592 (void *)arg1, (void *)arg2); 593 594 /* Get the ehci global mutex */ 595 mutex_enter(&ehcip->ehci_int_mutex); 596 597 /* Any interrupt is not handled for the suspended device. */ 598 if (ehcip->ehci_hc_soft_state == EHCI_CTLR_SUSPEND_STATE) { 599 mutex_exit(&ehcip->ehci_int_mutex); 600 601 return (DDI_INTR_UNCLAIMED); 602 } 603 604 /* 605 * Now process the actual ehci interrupt events that caused 606 * invocation of this ehci interrupt handler. 607 */ 608 intr = (Get_OpReg(ehci_status) & Get_OpReg(ehci_interrupt)); 609 610 /* Update kstat values */ 611 ehci_do_intrs_stats(ehcip, intr); 612 613 /* 614 * We could have gotten a spurious interrupts. If so, do not 615 * claim it. This is quite possible on some architectures 616 * where more than one PCI slots share the IRQs. If so, the 617 * associated driver's interrupt routine may get called even 618 * if the interrupt is not meant for them. 619 * 620 * By unclaiming the interrupt, the other driver gets chance 621 * to service its interrupt. 622 */ 623 if (!intr) { 624 mutex_exit(&ehcip->ehci_int_mutex); 625 626 return (DDI_INTR_UNCLAIMED); 627 } 628 629 /* Acknowledge the interrupt */ 630 Set_OpReg(ehci_status, intr); 631 632 if (ehcip->ehci_hc_soft_state == EHCI_CTLR_ERROR_STATE) { 633 mutex_exit(&ehcip->ehci_int_mutex); 634 635 return (DDI_INTR_CLAIMED); 636 } 637 638 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 639 "Interrupt status 0x%x", intr); 640 641 /* 642 * If necessary broadcast that an interrupt has occured. This 643 * is only necessary during controller init. 644 */ 645 if (ehcip->ehci_flags & EHCI_CV_INTR) { 646 ehcip->ehci_flags &= ~EHCI_CV_INTR; 647 cv_broadcast(&ehcip->ehci_async_schedule_advance_cv); 648 } 649 650 /* Check for Frame List Rollover */ 651 if (intr & EHCI_INTR_FRAME_LIST_ROLLOVER) { 652 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 653 "ehci_intr: Frame List Rollover"); 654 655 ehci_handle_frame_list_rollover(ehcip); 656 657 /* VIA VT6202 looses EHCI_INTR_USB interrupts, workaround. */ 658 if ((ehcip->ehci_vendor_id == PCI_VENDOR_VIA) && 659 (ehci_vt62x2_workaround & EHCI_VIA_LOST_INTERRUPTS)) { 660 ehcip->ehci_missed_intr_sts |= EHCI_INTR_USB; 661 } 662 } 663 664 /* Check for Advance on Asynchronous Schedule */ 665 if (intr & EHCI_INTR_ASYNC_ADVANCE) { 666 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 667 "ehci_intr: Asynchronous Schedule Advance Notification"); 668 669 /* Disable async list advance interrupt */ 670 Set_OpReg(ehci_interrupt, 671 (Get_OpReg(ehci_interrupt) & ~EHCI_INTR_ASYNC_ADVANCE)); 672 673 /* 674 * Call cv_broadcast on every this interrupt to wakeup 675 * all the threads that are waiting the async list advance 676 * event. 677 */ 678 cv_broadcast(&ehcip->ehci_async_schedule_advance_cv); 679 } 680 681 /* Always process completed itds */ 682 ehci_traverse_active_isoc_list(ehcip); 683 684 /* 685 * Check for any USB transaction completion notification. Also 686 * process any missed USB transaction completion interrupts. 687 */ 688 if ((intr & EHCI_INTR_USB) || (intr & EHCI_INTR_USB_ERROR) || 689 (ehcip->ehci_missed_intr_sts & EHCI_INTR_USB) || 690 (ehcip->ehci_missed_intr_sts & EHCI_INTR_USB_ERROR)) { 691 692 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 693 "ehci_intr: USB Transaction Completion Notification"); 694 695 /* Clear missed interrupts */ 696 if (ehcip->ehci_missed_intr_sts) { 697 ehcip->ehci_missed_intr_sts = 0; 698 } 699 700 /* Process completed qtds */ 701 ehci_traverse_active_qtd_list(ehcip); 702 } 703 704 /* Process endpoint reclamation list */ 705 if (ehcip->ehci_reclaim_list) { 706 ehci_handle_endpoint_reclaimation(ehcip); 707 } 708 709 /* Check for Host System Error */ 710 if (intr & EHCI_INTR_HOST_SYSTEM_ERROR) { 711 USB_DPRINTF_L2(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 712 "ehci_intr: Unrecoverable error"); 713 714 ehci_handle_ue(ehcip); 715 } 716 717 /* 718 * Read interrupt status register to make sure that any PIO 719 * store to clear the ISR has made it on the PCI bus before 720 * returning from its interrupt handler. 721 */ 722 (void) Get_OpReg(ehci_status); 723 724 /* Release the ehci global mutex */ 725 mutex_exit(&ehcip->ehci_int_mutex); 726 727 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 728 "Interrupt handling completed"); 729 730 return (DDI_INTR_CLAIMED); 731 } 732 733 734 /* 735 * EHCI HCDI entry points 736 * 737 * The Host Controller Driver Interfaces (HCDI) are the software interfaces 738 * between the Universal Serial Bus Layer (USBA) and the Host Controller 739 * Driver (HCD). The HCDI interfaces or entry points are subject to change. 740 */ 741 742 /* 743 * ehci_hcdi_pipe_open: 744 * 745 * Member of HCD Ops structure and called during client specific pipe open 746 * Add the pipe to the data structure representing the device and allocate 747 * bandwidth for the pipe if it is a interrupt or isochronous endpoint. 748 */ 749 int 750 ehci_hcdi_pipe_open( 751 usba_pipe_handle_data_t *ph, 752 usb_flags_t flags) 753 { 754 ehci_state_t *ehcip = ehci_obtain_state( 755 ph->p_usba_device->usb_root_hub_dip); 756 usb_ep_descr_t *epdt = &ph->p_ep; 757 int rval, error = USB_SUCCESS; 758 int kmflag = (flags & USB_FLAGS_SLEEP) ? 759 KM_SLEEP : KM_NOSLEEP; 760 uchar_t smask = 0; 761 uchar_t cmask = 0; 762 uint_t pnode = 0; 763 ehci_pipe_private_t *pp; 764 765 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 766 "ehci_hcdi_pipe_open: addr = 0x%x, ep%d", 767 ph->p_usba_device->usb_addr, 768 epdt->bEndpointAddress & USB_EP_NUM_MASK); 769 770 mutex_enter(&ehcip->ehci_int_mutex); 771 rval = ehci_state_is_operational(ehcip); 772 mutex_exit(&ehcip->ehci_int_mutex); 773 774 if (rval != USB_SUCCESS) { 775 776 return (rval); 777 } 778 779 /* 780 * Check and handle root hub pipe open. 781 */ 782 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 783 784 mutex_enter(&ehcip->ehci_int_mutex); 785 error = ehci_handle_root_hub_pipe_open(ph, flags); 786 mutex_exit(&ehcip->ehci_int_mutex); 787 788 return (error); 789 } 790 791 /* 792 * Opening of other pipes excluding root hub pipe are 793 * handled below. Check whether pipe is already opened. 794 */ 795 if (ph->p_hcd_private) { 796 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 797 "ehci_hcdi_pipe_open: Pipe is already opened"); 798 799 return (USB_FAILURE); 800 } 801 802 /* 803 * A portion of the bandwidth is reserved for the non-periodic 804 * transfers, i.e control and bulk transfers in each of one 805 * millisecond frame period & usually it will be 20% of frame 806 * period. Hence there is no need to check for the available 807 * bandwidth before adding the control or bulk endpoints. 808 * 809 * There is a need to check for the available bandwidth before 810 * adding the periodic transfers, i.e interrupt & isochronous, 811 * since all these periodic transfers are guaranteed transfers. 812 * Usually 80% of the total frame time is reserved for periodic 813 * transfers. 814 */ 815 if (EHCI_PERIODIC_ENDPOINT(epdt)) { 816 817 mutex_enter(&ehcip->ehci_int_mutex); 818 mutex_enter(&ph->p_mutex); 819 820 error = ehci_allocate_bandwidth(ehcip, 821 ph, &pnode, &smask, &cmask); 822 823 if (error != USB_SUCCESS) { 824 825 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 826 "ehci_hcdi_pipe_open: Bandwidth allocation failed"); 827 828 mutex_exit(&ph->p_mutex); 829 mutex_exit(&ehcip->ehci_int_mutex); 830 831 return (error); 832 } 833 834 mutex_exit(&ph->p_mutex); 835 mutex_exit(&ehcip->ehci_int_mutex); 836 } 837 838 /* Create the HCD pipe private structure */ 839 pp = kmem_zalloc(sizeof (ehci_pipe_private_t), kmflag); 840 841 /* 842 * Return failure if ehci pipe private 843 * structure allocation fails. 844 */ 845 if (pp == NULL) { 846 847 mutex_enter(&ehcip->ehci_int_mutex); 848 849 /* Deallocate bandwidth */ 850 if (EHCI_PERIODIC_ENDPOINT(epdt)) { 851 852 mutex_enter(&ph->p_mutex); 853 ehci_deallocate_bandwidth(ehcip, 854 ph, pnode, smask, cmask); 855 mutex_exit(&ph->p_mutex); 856 } 857 858 mutex_exit(&ehcip->ehci_int_mutex); 859 860 return (USB_NO_RESOURCES); 861 } 862 863 mutex_enter(&ehcip->ehci_int_mutex); 864 865 /* Save periodic nodes */ 866 pp->pp_pnode = pnode; 867 868 /* Save start and complete split mask values */ 869 pp->pp_smask = smask; 870 pp->pp_cmask = cmask; 871 872 /* Create prototype for xfer completion condition variable */ 873 cv_init(&pp->pp_xfer_cmpl_cv, NULL, CV_DRIVER, NULL); 874 875 /* Set the state of pipe as idle */ 876 pp->pp_state = EHCI_PIPE_STATE_IDLE; 877 878 /* Store a pointer to the pipe handle */ 879 pp->pp_pipe_handle = ph; 880 881 mutex_enter(&ph->p_mutex); 882 883 /* Store the pointer in the pipe handle */ 884 ph->p_hcd_private = (usb_opaque_t)pp; 885 886 /* Store a copy of the pipe policy */ 887 bcopy(&ph->p_policy, &pp->pp_policy, sizeof (usb_pipe_policy_t)); 888 889 mutex_exit(&ph->p_mutex); 890 891 /* Allocate the host controller endpoint descriptor */ 892 pp->pp_qh = ehci_alloc_qh(ehcip, ph, NULL); 893 894 /* Initialize the halting flag */ 895 pp->pp_halt_state = EHCI_HALT_STATE_FREE; 896 897 /* Create prototype for halt completion condition variable */ 898 cv_init(&pp->pp_halt_cmpl_cv, NULL, CV_DRIVER, NULL); 899 900 /* Isoch does not use QH, so ignore this */ 901 if ((pp->pp_qh == NULL) && !(EHCI_ISOC_ENDPOINT(epdt))) { 902 ASSERT(pp->pp_qh == NULL); 903 904 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 905 "ehci_hcdi_pipe_open: QH allocation failed"); 906 907 mutex_enter(&ph->p_mutex); 908 909 /* Deallocate bandwidth */ 910 if (EHCI_PERIODIC_ENDPOINT(epdt)) { 911 912 ehci_deallocate_bandwidth(ehcip, 913 ph, pnode, smask, cmask); 914 } 915 916 /* Destroy the xfer completion condition variable */ 917 cv_destroy(&pp->pp_xfer_cmpl_cv); 918 919 /* 920 * Deallocate the hcd private portion 921 * of the pipe handle. 922 */ 923 kmem_free(ph->p_hcd_private, sizeof (ehci_pipe_private_t)); 924 925 /* 926 * Set the private structure in the 927 * pipe handle equal to NULL. 928 */ 929 ph->p_hcd_private = NULL; 930 931 mutex_exit(&ph->p_mutex); 932 mutex_exit(&ehcip->ehci_int_mutex); 933 934 return (USB_NO_RESOURCES); 935 } 936 937 /* 938 * Isoch does not use QH so no need to 939 * restore data toggle or insert QH 940 */ 941 if (!(EHCI_ISOC_ENDPOINT(epdt))) { 942 /* Restore the data toggle information */ 943 ehci_restore_data_toggle(ehcip, ph); 944 } 945 946 /* 947 * Insert the endpoint onto the host controller's 948 * appropriate endpoint list. The host controller 949 * will not schedule this endpoint and will not have 950 * any QTD's to process. It will also update the pipe count. 951 */ 952 ehci_insert_qh(ehcip, ph); 953 954 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 955 "ehci_hcdi_pipe_open: ph = 0x%p", (void *)ph); 956 957 ehcip->ehci_open_pipe_count++; 958 959 mutex_exit(&ehcip->ehci_int_mutex); 960 961 return (USB_SUCCESS); 962 } 963 964 965 /* 966 * ehci_hcdi_pipe_close: 967 * 968 * Member of HCD Ops structure and called during the client specific pipe 969 * close. Remove the pipe and the data structure representing the device. 970 * Deallocate bandwidth for the pipe if it is a interrupt or isochronous 971 * endpoint. 972 */ 973 /* ARGSUSED */ 974 int 975 ehci_hcdi_pipe_close( 976 usba_pipe_handle_data_t *ph, 977 usb_flags_t flags) 978 { 979 ehci_state_t *ehcip = ehci_obtain_state( 980 ph->p_usba_device->usb_root_hub_dip); 981 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 982 usb_ep_descr_t *eptd = &ph->p_ep; 983 int error = USB_SUCCESS; 984 985 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 986 "ehci_hcdi_pipe_close: addr = 0x%x, ep%d", 987 ph->p_usba_device->usb_addr, 988 eptd->bEndpointAddress & USB_EP_NUM_MASK); 989 990 /* Check and handle root hub pipe close */ 991 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 992 993 mutex_enter(&ehcip->ehci_int_mutex); 994 error = ehci_handle_root_hub_pipe_close(ph); 995 mutex_exit(&ehcip->ehci_int_mutex); 996 997 return (error); 998 } 999 1000 ASSERT(ph->p_hcd_private != NULL); 1001 1002 mutex_enter(&ehcip->ehci_int_mutex); 1003 1004 /* Set pipe state to pipe close */ 1005 pp->pp_state = EHCI_PIPE_STATE_CLOSE; 1006 1007 ehci_pipe_cleanup(ehcip, ph); 1008 1009 /* 1010 * Remove the endpoint descriptor from Host 1011 * Controller's appropriate endpoint list. 1012 */ 1013 ehci_remove_qh(ehcip, pp, B_TRUE); 1014 1015 /* Deallocate bandwidth */ 1016 if (EHCI_PERIODIC_ENDPOINT(eptd)) { 1017 1018 mutex_enter(&ph->p_mutex); 1019 ehci_deallocate_bandwidth(ehcip, ph, pp->pp_pnode, 1020 pp->pp_smask, pp->pp_cmask); 1021 mutex_exit(&ph->p_mutex); 1022 } 1023 1024 mutex_enter(&ph->p_mutex); 1025 1026 /* Destroy the xfer completion condition variable */ 1027 cv_destroy(&pp->pp_xfer_cmpl_cv); 1028 1029 1030 /* Destory halt completion condition variable */ 1031 cv_destroy(&pp->pp_halt_cmpl_cv); 1032 1033 /* 1034 * Deallocate the hcd private portion 1035 * of the pipe handle. 1036 */ 1037 kmem_free(ph->p_hcd_private, sizeof (ehci_pipe_private_t)); 1038 ph->p_hcd_private = NULL; 1039 1040 mutex_exit(&ph->p_mutex); 1041 1042 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1043 "ehci_hcdi_pipe_close: ph = 0x%p", (void *)ph); 1044 1045 ehcip->ehci_open_pipe_count--; 1046 1047 mutex_exit(&ehcip->ehci_int_mutex); 1048 1049 return (error); 1050 } 1051 1052 1053 /* 1054 * ehci_hcdi_pipe_reset: 1055 */ 1056 /* ARGSUSED */ 1057 int 1058 ehci_hcdi_pipe_reset( 1059 usba_pipe_handle_data_t *ph, 1060 usb_flags_t usb_flags) 1061 { 1062 ehci_state_t *ehcip = ehci_obtain_state( 1063 ph->p_usba_device->usb_root_hub_dip); 1064 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 1065 int error = USB_SUCCESS; 1066 1067 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1068 "ehci_hcdi_pipe_reset:"); 1069 1070 /* 1071 * Check and handle root hub pipe reset. 1072 */ 1073 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 1074 1075 error = ehci_handle_root_hub_pipe_reset(ph, usb_flags); 1076 return (error); 1077 } 1078 1079 mutex_enter(&ehcip->ehci_int_mutex); 1080 1081 /* Set pipe state to pipe reset */ 1082 pp->pp_state = EHCI_PIPE_STATE_RESET; 1083 1084 ehci_pipe_cleanup(ehcip, ph); 1085 1086 mutex_exit(&ehcip->ehci_int_mutex); 1087 1088 return (error); 1089 } 1090 1091 /* 1092 * ehci_hcdi_pipe_ctrl_xfer: 1093 */ 1094 int 1095 ehci_hcdi_pipe_ctrl_xfer( 1096 usba_pipe_handle_data_t *ph, 1097 usb_ctrl_req_t *ctrl_reqp, 1098 usb_flags_t usb_flags) 1099 { 1100 ehci_state_t *ehcip = ehci_obtain_state( 1101 ph->p_usba_device->usb_root_hub_dip); 1102 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 1103 int rval; 1104 int error = USB_SUCCESS; 1105 ehci_trans_wrapper_t *tw; 1106 1107 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1108 "ehci_hcdi_pipe_ctrl_xfer: ph = 0x%p reqp = 0x%p flags = %x", 1109 (void *)ph, (void *)ctrl_reqp, usb_flags); 1110 1111 mutex_enter(&ehcip->ehci_int_mutex); 1112 rval = ehci_state_is_operational(ehcip); 1113 mutex_exit(&ehcip->ehci_int_mutex); 1114 1115 if (rval != USB_SUCCESS) { 1116 1117 return (rval); 1118 } 1119 1120 /* 1121 * Check and handle root hub control request. 1122 */ 1123 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 1124 1125 error = ehci_handle_root_hub_request(ehcip, ph, ctrl_reqp); 1126 1127 return (error); 1128 } 1129 1130 mutex_enter(&ehcip->ehci_int_mutex); 1131 1132 /* 1133 * Check whether pipe is in halted state. 1134 */ 1135 if (pp->pp_state == EHCI_PIPE_STATE_ERROR) { 1136 1137 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1138 "ehci_hcdi_pipe_ctrl_xfer: " 1139 "Pipe is in error state, need pipe reset to continue"); 1140 1141 mutex_exit(&ehcip->ehci_int_mutex); 1142 1143 return (USB_FAILURE); 1144 } 1145 1146 /* Allocate a transfer wrapper */ 1147 if ((tw = ehci_allocate_ctrl_resources(ehcip, pp, ctrl_reqp, 1148 usb_flags)) == NULL) { 1149 1150 error = USB_NO_RESOURCES; 1151 } else { 1152 /* Insert the qtd's on the endpoint */ 1153 ehci_insert_ctrl_req(ehcip, ph, ctrl_reqp, tw, usb_flags); 1154 } 1155 1156 mutex_exit(&ehcip->ehci_int_mutex); 1157 1158 return (error); 1159 } 1160 1161 1162 /* 1163 * ehci_hcdi_bulk_transfer_size: 1164 * 1165 * Return maximum bulk transfer size 1166 */ 1167 1168 /* ARGSUSED */ 1169 int 1170 ehci_hcdi_bulk_transfer_size( 1171 usba_device_t *usba_device, 1172 size_t *size) 1173 { 1174 ehci_state_t *ehcip = ehci_obtain_state( 1175 usba_device->usb_root_hub_dip); 1176 int rval; 1177 1178 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1179 "ehci_hcdi_bulk_transfer_size:"); 1180 1181 mutex_enter(&ehcip->ehci_int_mutex); 1182 rval = ehci_state_is_operational(ehcip); 1183 mutex_exit(&ehcip->ehci_int_mutex); 1184 1185 if (rval != USB_SUCCESS) { 1186 1187 return (rval); 1188 } 1189 1190 /* VIA VT6202 may not handle bigger xfers well, workaround. */ 1191 if ((ehcip->ehci_vendor_id == PCI_VENDOR_VIA) && 1192 (ehci_vt62x2_workaround & EHCI_VIA_REDUCED_MAX_BULK_XFER_SIZE)) { 1193 *size = EHCI_VIA_MAX_BULK_XFER_SIZE; 1194 } else { 1195 *size = EHCI_MAX_BULK_XFER_SIZE; 1196 } 1197 1198 return (USB_SUCCESS); 1199 } 1200 1201 1202 /* 1203 * ehci_hcdi_pipe_bulk_xfer: 1204 */ 1205 int 1206 ehci_hcdi_pipe_bulk_xfer( 1207 usba_pipe_handle_data_t *ph, 1208 usb_bulk_req_t *bulk_reqp, 1209 usb_flags_t usb_flags) 1210 { 1211 ehci_state_t *ehcip = ehci_obtain_state( 1212 ph->p_usba_device->usb_root_hub_dip); 1213 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 1214 int rval, error = USB_SUCCESS; 1215 ehci_trans_wrapper_t *tw; 1216 1217 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1218 "ehci_hcdi_pipe_bulk_xfer: ph = 0x%p reqp = 0x%p flags = %x", 1219 (void *)ph, (void *)bulk_reqp, usb_flags); 1220 1221 mutex_enter(&ehcip->ehci_int_mutex); 1222 rval = ehci_state_is_operational(ehcip); 1223 1224 if (rval != USB_SUCCESS) { 1225 mutex_exit(&ehcip->ehci_int_mutex); 1226 1227 return (rval); 1228 } 1229 1230 /* 1231 * Check whether pipe is in halted state. 1232 */ 1233 if (pp->pp_state == EHCI_PIPE_STATE_ERROR) { 1234 1235 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1236 "ehci_hcdi_pipe_bulk_xfer:" 1237 "Pipe is in error state, need pipe reset to continue"); 1238 1239 mutex_exit(&ehcip->ehci_int_mutex); 1240 1241 return (USB_FAILURE); 1242 } 1243 1244 /* Allocate a transfer wrapper */ 1245 if ((tw = ehci_allocate_bulk_resources(ehcip, pp, bulk_reqp, 1246 usb_flags)) == NULL) { 1247 1248 error = USB_NO_RESOURCES; 1249 } else { 1250 /* Add the QTD into the Host Controller's bulk list */ 1251 ehci_insert_bulk_req(ehcip, ph, bulk_reqp, tw, usb_flags); 1252 } 1253 1254 mutex_exit(&ehcip->ehci_int_mutex); 1255 1256 return (error); 1257 } 1258 1259 1260 /* 1261 * ehci_hcdi_pipe_intr_xfer: 1262 */ 1263 int 1264 ehci_hcdi_pipe_intr_xfer( 1265 usba_pipe_handle_data_t *ph, 1266 usb_intr_req_t *intr_reqp, 1267 usb_flags_t usb_flags) 1268 { 1269 ehci_state_t *ehcip = ehci_obtain_state( 1270 ph->p_usba_device->usb_root_hub_dip); 1271 int pipe_dir, rval, error = USB_SUCCESS; 1272 ehci_trans_wrapper_t *tw; 1273 1274 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1275 "ehci_hcdi_pipe_intr_xfer: ph = 0x%p reqp = 0x%p flags = %x", 1276 (void *)ph, (void *)intr_reqp, usb_flags); 1277 1278 mutex_enter(&ehcip->ehci_int_mutex); 1279 rval = ehci_state_is_operational(ehcip); 1280 1281 if (rval != USB_SUCCESS) { 1282 mutex_exit(&ehcip->ehci_int_mutex); 1283 1284 return (rval); 1285 } 1286 1287 /* Get the pipe direction */ 1288 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK; 1289 1290 if (pipe_dir == USB_EP_DIR_IN) { 1291 error = ehci_start_periodic_pipe_polling(ehcip, ph, 1292 (usb_opaque_t)intr_reqp, usb_flags); 1293 } else { 1294 /* Allocate transaction resources */ 1295 if ((tw = ehci_allocate_intr_resources(ehcip, ph, 1296 intr_reqp, usb_flags)) == NULL) { 1297 1298 error = USB_NO_RESOURCES; 1299 } else { 1300 ehci_insert_intr_req(ehcip, 1301 (ehci_pipe_private_t *)ph->p_hcd_private, 1302 tw, usb_flags); 1303 } 1304 } 1305 1306 mutex_exit(&ehcip->ehci_int_mutex); 1307 1308 return (error); 1309 } 1310 1311 /* 1312 * ehci_hcdi_pipe_stop_intr_polling() 1313 */ 1314 int 1315 ehci_hcdi_pipe_stop_intr_polling( 1316 usba_pipe_handle_data_t *ph, 1317 usb_flags_t flags) 1318 { 1319 ehci_state_t *ehcip = ehci_obtain_state( 1320 ph->p_usba_device->usb_root_hub_dip); 1321 int error = USB_SUCCESS; 1322 1323 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1324 "ehci_hcdi_pipe_stop_intr_polling: ph = 0x%p fl = 0x%x", 1325 (void *)ph, flags); 1326 1327 mutex_enter(&ehcip->ehci_int_mutex); 1328 1329 error = ehci_stop_periodic_pipe_polling(ehcip, ph, flags); 1330 1331 mutex_exit(&ehcip->ehci_int_mutex); 1332 1333 return (error); 1334 } 1335 1336 1337 /* 1338 * ehci_hcdi_get_current_frame_number: 1339 * 1340 * Get the current usb frame number. 1341 * Return whether the request is handled successfully. 1342 */ 1343 int 1344 ehci_hcdi_get_current_frame_number( 1345 usba_device_t *usba_device, 1346 usb_frame_number_t *frame_number) 1347 { 1348 ehci_state_t *ehcip = ehci_obtain_state( 1349 usba_device->usb_root_hub_dip); 1350 int rval; 1351 1352 ehcip = ehci_obtain_state(usba_device->usb_root_hub_dip); 1353 1354 mutex_enter(&ehcip->ehci_int_mutex); 1355 rval = ehci_state_is_operational(ehcip); 1356 1357 if (rval != USB_SUCCESS) { 1358 mutex_exit(&ehcip->ehci_int_mutex); 1359 1360 return (rval); 1361 } 1362 1363 *frame_number = ehci_get_current_frame_number(ehcip); 1364 1365 mutex_exit(&ehcip->ehci_int_mutex); 1366 1367 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1368 "ehci_hcdi_get_current_frame_number: " 1369 "Current frame number 0x%llx", (unsigned long long)(*frame_number)); 1370 1371 return (rval); 1372 } 1373 1374 1375 /* 1376 * ehci_hcdi_get_max_isoc_pkts: 1377 * 1378 * Get maximum isochronous packets per usb isochronous request. 1379 * Return whether the request is handled successfully. 1380 */ 1381 int 1382 ehci_hcdi_get_max_isoc_pkts( 1383 usba_device_t *usba_device, 1384 uint_t *max_isoc_pkts_per_request) 1385 { 1386 ehci_state_t *ehcip = ehci_obtain_state( 1387 usba_device->usb_root_hub_dip); 1388 int rval; 1389 1390 mutex_enter(&ehcip->ehci_int_mutex); 1391 rval = ehci_state_is_operational(ehcip); 1392 mutex_exit(&ehcip->ehci_int_mutex); 1393 1394 if (rval != USB_SUCCESS) { 1395 1396 return (rval); 1397 } 1398 1399 *max_isoc_pkts_per_request = EHCI_MAX_ISOC_PKTS_PER_XFER; 1400 1401 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1402 "ehci_hcdi_get_max_isoc_pkts: maximum isochronous" 1403 "packets per usb isochronous request = 0x%x", 1404 *max_isoc_pkts_per_request); 1405 1406 return (rval); 1407 } 1408 1409 1410 /* 1411 * ehci_hcdi_pipe_isoc_xfer: 1412 */ 1413 int 1414 ehci_hcdi_pipe_isoc_xfer( 1415 usba_pipe_handle_data_t *ph, 1416 usb_isoc_req_t *isoc_reqp, 1417 usb_flags_t usb_flags) 1418 { 1419 ehci_state_t *ehcip = ehci_obtain_state( 1420 ph->p_usba_device->usb_root_hub_dip); 1421 1422 int pipe_dir, rval; 1423 ehci_isoc_xwrapper_t *itw; 1424 1425 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1426 "ehci_hcdi_pipe_isoc_xfer: ph = 0x%p reqp = 0x%p flags = 0x%x", 1427 (void *)ph, (void *)isoc_reqp, usb_flags); 1428 1429 mutex_enter(&ehcip->ehci_int_mutex); 1430 rval = ehci_state_is_operational(ehcip); 1431 1432 if (rval != USB_SUCCESS) { 1433 mutex_exit(&ehcip->ehci_int_mutex); 1434 1435 return (rval); 1436 } 1437 1438 /* Get the isochronous pipe direction */ 1439 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK; 1440 1441 if (pipe_dir == USB_EP_DIR_IN) { 1442 rval = ehci_start_periodic_pipe_polling(ehcip, ph, 1443 (usb_opaque_t)isoc_reqp, usb_flags); 1444 } else { 1445 /* Allocate transaction resources */ 1446 if ((itw = ehci_allocate_isoc_resources(ehcip, ph, 1447 isoc_reqp, usb_flags)) == NULL) { 1448 rval = USB_NO_RESOURCES; 1449 } else { 1450 rval = ehci_insert_isoc_req(ehcip, 1451 (ehci_pipe_private_t *)ph->p_hcd_private, 1452 itw, usb_flags); 1453 } 1454 } 1455 1456 mutex_exit(&ehcip->ehci_int_mutex); 1457 1458 return (rval); 1459 } 1460 1461 1462 /* 1463 * ehci_hcdi_pipe_stop_isoc_polling() 1464 */ 1465 /*ARGSUSED*/ 1466 int 1467 ehci_hcdi_pipe_stop_isoc_polling( 1468 usba_pipe_handle_data_t *ph, 1469 usb_flags_t flags) 1470 { 1471 ehci_state_t *ehcip = ehci_obtain_state( 1472 ph->p_usba_device->usb_root_hub_dip); 1473 int rval; 1474 1475 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1476 "ehci_hcdi_pipe_stop_isoc_polling: ph = 0x%p fl = 0x%x", 1477 (void *)ph, flags); 1478 1479 mutex_enter(&ehcip->ehci_int_mutex); 1480 rval = ehci_state_is_operational(ehcip); 1481 1482 if (rval != USB_SUCCESS) { 1483 mutex_exit(&ehcip->ehci_int_mutex); 1484 1485 return (rval); 1486 } 1487 1488 rval = ehci_stop_periodic_pipe_polling(ehcip, ph, flags); 1489 1490 mutex_exit(&ehcip->ehci_int_mutex); 1491 1492 return (rval); 1493 } 1494