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