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, 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 /* Save the dip and instance */ 249 ehcip->ehci_dip = dip; 250 ehcip->ehci_instance = instance; 251 252 /* Map the registers */ 253 if (ehci_map_regs(ehcip) != DDI_SUCCESS) { 254 (void) ehci_cleanup(ehcip); 255 256 return (DDI_FAILURE); 257 } 258 259 /* Get the ehci chip vendor and device id */ 260 ehcip->ehci_vendor_id = pci_config_get16( 261 ehcip->ehci_config_handle, PCI_CONF_VENID); 262 ehcip->ehci_device_id = pci_config_get16( 263 ehcip->ehci_config_handle, PCI_CONF_DEVID); 264 ehcip->ehci_rev_id = pci_config_get8( 265 ehcip->ehci_config_handle, PCI_CONF_REVID); 266 267 /* Initialize the DMA attributes */ 268 ehci_set_dma_attributes(ehcip); 269 270 /* Initialize kstat structures */ 271 ehci_create_stats(ehcip); 272 273 /* Create the qtd and qh pools */ 274 if (ehci_allocate_pools(ehcip) != DDI_SUCCESS) { 275 (void) ehci_cleanup(ehcip); 276 277 return (DDI_FAILURE); 278 } 279 280 /* Initialize the isochronous resources */ 281 if (ehci_isoc_init(ehcip) != DDI_SUCCESS) { 282 (void) ehci_cleanup(ehcip); 283 284 return (DDI_FAILURE); 285 } 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, ddi_detach_cmd_t cmd) 391 { 392 ehci_state_t *ehcip = ehci_obtain_state(dip); 393 394 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, "ehci_detach:"); 395 396 switch (cmd) { 397 case DDI_DETACH: 398 399 return (ehci_cleanup(ehcip)); 400 case DDI_SUSPEND: 401 402 return (ehci_cpr_suspend(ehcip)); 403 default: 404 405 return (DDI_FAILURE); 406 } 407 } 408 409 /* 410 * ehci_reset: 411 * 412 * Description: Reset entry point - called by the Kernel 413 * on the way down. 414 * Toshiba Tecra laptop has been observed to hang 415 * on soft reboot. The resetting ehci on the way 416 * down solves the problem. 417 * 418 * Return : DDI_SUCCESS / DDI_FAILURE 419 */ 420 /* ARGSUSED */ 421 static int 422 ehci_reset(dev_info_t *dip, ddi_reset_cmd_t cmd) 423 { 424 #if defined(__sparc) 425 /* 426 * Don't reset the host controller on SPARC, for OBP needs Solaris 427 * to continue to provide keyboard support after shutdown of SPARC, 428 * or the keyboard connected to a USB 2.0 port will not work after 429 * that. The incomplete reset problem on Toshiba Tecra laptop is 430 * specific to Tecra laptop or BIOS, not present on SPARC. The SPARC 431 * OBP guarantees good reset behavior during startup. 432 */ 433 return (DDI_SUCCESS); 434 #else 435 ehci_state_t *ehcip = ehci_obtain_state(dip); 436 437 mutex_enter(&ehcip->ehci_int_mutex); 438 439 /* 440 * To reset the host controller, the HCRESET bit should be set to one. 441 * Software should not set this bit to a one when the HCHalted bit in 442 * the USBSTS register is a zero. Attempting to reset an actively 443 * running host controller will result in undefined behavior. 444 * see EHCI SPEC. for more information. 445 */ 446 if (!(Get_OpReg(ehci_status) & EHCI_STS_HOST_CTRL_HALTED)) { 447 448 /* Stop the EHCI host controller */ 449 Set_OpReg(ehci_command, 450 Get_OpReg(ehci_command) & ~EHCI_CMD_HOST_CTRL_RUN); 451 /* 452 * When this bit is set to 0, the Host Controller completes the 453 * current and any actively pipelined transactions on the USB 454 * and then halts. The Host Controller must halt within 16 455 * micro-frames after software clears the Run bit. 456 * The HC Halted bit in the status register indicates when the 457 * Host Controller has finished its pending pipelined 458 * transactions and has entered the stopped state. 459 */ 460 drv_usecwait(EHCI_RESET_TIMEWAIT); 461 } 462 463 /* Reset the EHCI host controller */ 464 Set_OpReg(ehci_command, 465 Get_OpReg(ehci_command) | EHCI_CMD_HOST_CTRL_RESET); 466 467 mutex_exit(&ehcip->ehci_int_mutex); 468 469 return (DDI_SUCCESS); 470 #endif 471 } 472 473 /* 474 * quiesce(9E) entry point. 475 * 476 * This function is called when the system is single-threaded at high 477 * PIL with preemption disabled. Therefore, this function must not be 478 * blocked. 479 * 480 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 481 * DDI_FAILURE indicates an error condition and should almost never happen. 482 */ 483 static int 484 ehci_quiesce(dev_info_t *dip) 485 { 486 ehci_state_t *ehcip = ehci_obtain_state(dip); 487 488 if (ehcip == NULL) 489 return (DDI_FAILURE); 490 491 #ifndef lint 492 _NOTE(NO_COMPETING_THREADS_NOW); 493 #endif 494 /* 495 * To reset the host controller, the HCRESET bit should be set to one. 496 * Software should not set this bit to a one when the HCHalted bit in 497 * the USBSTS register is a zero. Attempting to reset an actively 498 * running host controller will result in undefined behavior. 499 * see EHCI SPEC. for more information. 500 */ 501 if (!(Get_OpReg(ehci_status) & EHCI_STS_HOST_CTRL_HALTED)) { 502 503 /* Stop the EHCI host controller */ 504 Set_OpReg(ehci_command, 505 Get_OpReg(ehci_command) & ~EHCI_CMD_HOST_CTRL_RUN); 506 /* 507 * When this bit is set to 0, the Host Controller completes the 508 * current and any actively pipelined transactions on the USB 509 * and then halts. The Host Controller must halt within 16 510 * micro-frames after software clears the Run bit. 511 * The HC Halted bit in the status register indicates when the 512 * Host Controller has finished its pending pipelined 513 * transactions and has entered the stopped state. 514 */ 515 drv_usecwait(EHCI_RESET_TIMEWAIT); 516 } 517 518 /* Reset the EHCI host controller */ 519 Set_OpReg(ehci_command, 520 Get_OpReg(ehci_command) | EHCI_CMD_HOST_CTRL_RESET); 521 522 #ifndef lint 523 _NOTE(COMPETING_THREADS_NOW); 524 #endif 525 return (DDI_SUCCESS); 526 } 527 528 529 /* 530 * ehci_info: 531 */ 532 /* ARGSUSED */ 533 static int 534 ehci_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 535 { 536 dev_t dev; 537 ehci_state_t *ehcip; 538 int instance; 539 int error = DDI_FAILURE; 540 541 switch (infocmd) { 542 case DDI_INFO_DEVT2DEVINFO: 543 dev = (dev_t)arg; 544 instance = EHCI_UNIT(dev); 545 ehcip = ddi_get_soft_state(ehci_statep, instance); 546 if (ehcip != NULL) { 547 *result = (void *)ehcip->ehci_dip; 548 if (*result != NULL) { 549 error = DDI_SUCCESS; 550 } 551 } else { 552 *result = NULL; 553 } 554 555 break; 556 case DDI_INFO_DEVT2INSTANCE: 557 dev = (dev_t)arg; 558 instance = EHCI_UNIT(dev); 559 *result = (void *)(uintptr_t)instance; 560 error = DDI_SUCCESS; 561 break; 562 default: 563 break; 564 } 565 566 return (error); 567 } 568 569 570 /* 571 * EHCI CB_OPS entry points. 572 */ 573 static dev_info_t * 574 ehci_get_dip(dev_t dev) 575 { 576 int instance = EHCI_UNIT(dev); 577 ehci_state_t *ehcip = ddi_get_soft_state(ehci_statep, instance); 578 579 if (ehcip) { 580 581 return (ehcip->ehci_dip); 582 } else { 583 584 return (NULL); 585 } 586 } 587 588 589 static int 590 ehci_open(dev_t *devp, int flags, int otyp, cred_t *credp) 591 { 592 dev_info_t *dip = ehci_get_dip(*devp); 593 594 return (usba_hubdi_open(dip, devp, flags, otyp, credp)); 595 } 596 597 598 static int 599 ehci_close(dev_t dev, int flag, int otyp, cred_t *credp) 600 { 601 dev_info_t *dip = ehci_get_dip(dev); 602 603 return (usba_hubdi_close(dip, dev, flag, otyp, credp)); 604 } 605 606 607 static int 608 ehci_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, 609 int *rvalp) 610 { 611 dev_info_t *dip = ehci_get_dip(dev); 612 613 return (usba_hubdi_ioctl(dip, 614 dev, cmd, arg, mode, credp, rvalp)); 615 } 616 617 /* 618 * EHCI Interrupt Handler entry point. 619 */ 620 621 /* 622 * ehci_intr: 623 * 624 * EHCI (EHCI) interrupt handling routine. 625 */ 626 uint_t 627 ehci_intr(caddr_t arg1, caddr_t arg2) 628 { 629 uint_t intr; 630 ehci_state_t *ehcip = (void *)arg1; 631 632 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 633 "ehci_intr: Interrupt occurred, arg1 0x%p arg2 0x%p", 634 (void *)arg1, (void *)arg2); 635 636 /* Get the ehci global mutex */ 637 mutex_enter(&ehcip->ehci_int_mutex); 638 639 /* Any interrupt is not handled for the suspended device. */ 640 if (ehcip->ehci_hc_soft_state == EHCI_CTLR_SUSPEND_STATE) { 641 mutex_exit(&ehcip->ehci_int_mutex); 642 643 return (DDI_INTR_UNCLAIMED); 644 } 645 646 /* 647 * Now process the actual ehci interrupt events that caused 648 * invocation of this ehci interrupt handler. 649 */ 650 intr = (Get_OpReg(ehci_status) & Get_OpReg(ehci_interrupt)); 651 652 /* Update kstat values */ 653 ehci_do_intrs_stats(ehcip, intr); 654 655 /* 656 * We could have gotten a spurious interrupts. If so, do not 657 * claim it. This is quite possible on some architectures 658 * where more than one PCI slots share the IRQs. If so, the 659 * associated driver's interrupt routine may get called even 660 * if the interrupt is not meant for them. 661 * 662 * By unclaiming the interrupt, the other driver gets chance 663 * to service its interrupt. 664 */ 665 if (!intr) { 666 mutex_exit(&ehcip->ehci_int_mutex); 667 668 return (DDI_INTR_UNCLAIMED); 669 } 670 671 /* Acknowledge the interrupt */ 672 Set_OpReg(ehci_status, intr); 673 674 if (ehcip->ehci_hc_soft_state == EHCI_CTLR_ERROR_STATE) { 675 mutex_exit(&ehcip->ehci_int_mutex); 676 677 return (DDI_INTR_CLAIMED); 678 } 679 680 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 681 "Interrupt status 0x%x", intr); 682 683 /* 684 * If necessary broadcast that an interrupt has occured. This 685 * is only necessary during controller init. 686 */ 687 if (ehcip->ehci_flags & EHCI_CV_INTR) { 688 ehcip->ehci_flags &= ~EHCI_CV_INTR; 689 cv_broadcast(&ehcip->ehci_async_schedule_advance_cv); 690 } 691 692 /* Check for Frame List Rollover */ 693 if (intr & EHCI_INTR_FRAME_LIST_ROLLOVER) { 694 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 695 "ehci_intr: Frame List Rollover"); 696 697 ehci_handle_frame_list_rollover(ehcip); 698 699 /* VIA VT6202 looses EHCI_INTR_USB interrupts, workaround. */ 700 if ((ehcip->ehci_vendor_id == PCI_VENDOR_VIA) && 701 (ehci_vt62x2_workaround & EHCI_VIA_LOST_INTERRUPTS)) { 702 ehcip->ehci_missed_intr_sts |= EHCI_INTR_USB; 703 } 704 } 705 706 /* Check for Advance on Asynchronous Schedule */ 707 if (intr & EHCI_INTR_ASYNC_ADVANCE) { 708 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 709 "ehci_intr: Asynchronous Schedule Advance Notification"); 710 711 /* Disable async list advance interrupt */ 712 Set_OpReg(ehci_interrupt, 713 (Get_OpReg(ehci_interrupt) & ~EHCI_INTR_ASYNC_ADVANCE)); 714 715 /* 716 * Call cv_broadcast on every this interrupt to wakeup 717 * all the threads that are waiting the async list advance 718 * event. 719 */ 720 cv_broadcast(&ehcip->ehci_async_schedule_advance_cv); 721 } 722 723 /* Always process completed itds */ 724 ehci_traverse_active_isoc_list(ehcip); 725 726 /* 727 * Check for any USB transaction completion notification. Also 728 * process any missed USB transaction completion interrupts. 729 */ 730 if ((intr & EHCI_INTR_USB) || (intr & EHCI_INTR_USB_ERROR) || 731 (ehcip->ehci_missed_intr_sts & EHCI_INTR_USB) || 732 (ehcip->ehci_missed_intr_sts & EHCI_INTR_USB_ERROR)) { 733 734 USB_DPRINTF_L3(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 735 "ehci_intr: USB Transaction Completion Notification"); 736 737 /* Clear missed interrupts */ 738 if (ehcip->ehci_missed_intr_sts) { 739 ehcip->ehci_missed_intr_sts = 0; 740 } 741 742 /* Process completed qtds */ 743 ehci_traverse_active_qtd_list(ehcip); 744 } 745 746 /* Process endpoint reclamation list */ 747 if (ehcip->ehci_reclaim_list) { 748 ehci_handle_endpoint_reclaimation(ehcip); 749 } 750 751 /* Check for Host System Error */ 752 if (intr & EHCI_INTR_HOST_SYSTEM_ERROR) { 753 USB_DPRINTF_L2(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 754 "ehci_intr: Unrecoverable error"); 755 756 ehci_handle_ue(ehcip); 757 } 758 759 /* 760 * Read interrupt status register to make sure that any PIO 761 * store to clear the ISR has made it on the PCI bus before 762 * returning from its interrupt handler. 763 */ 764 (void) Get_OpReg(ehci_status); 765 766 /* Release the ehci global mutex */ 767 mutex_exit(&ehcip->ehci_int_mutex); 768 769 USB_DPRINTF_L4(PRINT_MASK_INTR, ehcip->ehci_log_hdl, 770 "Interrupt handling completed"); 771 772 return (DDI_INTR_CLAIMED); 773 } 774 775 776 /* 777 * EHCI HCDI entry points 778 * 779 * The Host Controller Driver Interfaces (HCDI) are the software interfaces 780 * between the Universal Serial Bus Layer (USBA) and the Host Controller 781 * Driver (HCD). The HCDI interfaces or entry points are subject to change. 782 */ 783 784 /* 785 * ehci_hcdi_pipe_open: 786 * 787 * Member of HCD Ops structure and called during client specific pipe open 788 * Add the pipe to the data structure representing the device and allocate 789 * bandwidth for the pipe if it is a interrupt or isochronous endpoint. 790 */ 791 int 792 ehci_hcdi_pipe_open( 793 usba_pipe_handle_data_t *ph, 794 usb_flags_t flags) 795 { 796 ehci_state_t *ehcip = ehci_obtain_state( 797 ph->p_usba_device->usb_root_hub_dip); 798 usb_ep_descr_t *epdt = &ph->p_ep; 799 int rval, error = USB_SUCCESS; 800 int kmflag = (flags & USB_FLAGS_SLEEP) ? 801 KM_SLEEP : KM_NOSLEEP; 802 uchar_t smask = 0; 803 uchar_t cmask = 0; 804 uint_t pnode = 0; 805 ehci_pipe_private_t *pp; 806 807 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 808 "ehci_hcdi_pipe_open: addr = 0x%x, ep%d", 809 ph->p_usba_device->usb_addr, 810 epdt->bEndpointAddress & USB_EP_NUM_MASK); 811 812 mutex_enter(&ehcip->ehci_int_mutex); 813 rval = ehci_state_is_operational(ehcip); 814 mutex_exit(&ehcip->ehci_int_mutex); 815 816 if (rval != USB_SUCCESS) { 817 818 return (rval); 819 } 820 821 /* 822 * Check and handle root hub pipe open. 823 */ 824 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 825 826 mutex_enter(&ehcip->ehci_int_mutex); 827 error = ehci_handle_root_hub_pipe_open(ph, flags); 828 mutex_exit(&ehcip->ehci_int_mutex); 829 830 return (error); 831 } 832 833 /* 834 * Opening of other pipes excluding root hub pipe are 835 * handled below. Check whether pipe is already opened. 836 */ 837 if (ph->p_hcd_private) { 838 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 839 "ehci_hcdi_pipe_open: Pipe is already opened"); 840 841 return (USB_FAILURE); 842 } 843 844 /* 845 * A portion of the bandwidth is reserved for the non-periodic 846 * transfers, i.e control and bulk transfers in each of one 847 * millisecond frame period & usually it will be 20% of frame 848 * period. Hence there is no need to check for the available 849 * bandwidth before adding the control or bulk endpoints. 850 * 851 * There is a need to check for the available bandwidth before 852 * adding the periodic transfers, i.e interrupt & isochronous, 853 * since all these periodic transfers are guaranteed transfers. 854 * Usually 80% of the total frame time is reserved for periodic 855 * transfers. 856 */ 857 if (EHCI_PERIODIC_ENDPOINT(epdt)) { 858 859 mutex_enter(&ehcip->ehci_int_mutex); 860 mutex_enter(&ph->p_mutex); 861 862 error = ehci_allocate_bandwidth(ehcip, 863 ph, &pnode, &smask, &cmask); 864 865 if (error != USB_SUCCESS) { 866 867 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 868 "ehci_hcdi_pipe_open: Bandwidth allocation failed"); 869 870 mutex_exit(&ph->p_mutex); 871 mutex_exit(&ehcip->ehci_int_mutex); 872 873 return (error); 874 } 875 876 mutex_exit(&ph->p_mutex); 877 mutex_exit(&ehcip->ehci_int_mutex); 878 } 879 880 /* Create the HCD pipe private structure */ 881 pp = kmem_zalloc(sizeof (ehci_pipe_private_t), kmflag); 882 883 /* 884 * Return failure if ehci pipe private 885 * structure allocation fails. 886 */ 887 if (pp == NULL) { 888 889 mutex_enter(&ehcip->ehci_int_mutex); 890 891 /* Deallocate bandwidth */ 892 if (EHCI_PERIODIC_ENDPOINT(epdt)) { 893 894 mutex_enter(&ph->p_mutex); 895 ehci_deallocate_bandwidth(ehcip, 896 ph, pnode, smask, cmask); 897 mutex_exit(&ph->p_mutex); 898 } 899 900 mutex_exit(&ehcip->ehci_int_mutex); 901 902 return (USB_NO_RESOURCES); 903 } 904 905 mutex_enter(&ehcip->ehci_int_mutex); 906 907 /* Save periodic nodes */ 908 pp->pp_pnode = pnode; 909 910 /* Save start and complete split mask values */ 911 pp->pp_smask = smask; 912 pp->pp_cmask = cmask; 913 914 /* Create prototype for xfer completion condition variable */ 915 cv_init(&pp->pp_xfer_cmpl_cv, NULL, CV_DRIVER, NULL); 916 917 /* Set the state of pipe as idle */ 918 pp->pp_state = EHCI_PIPE_STATE_IDLE; 919 920 /* Store a pointer to the pipe handle */ 921 pp->pp_pipe_handle = ph; 922 923 mutex_enter(&ph->p_mutex); 924 925 /* Store the pointer in the pipe handle */ 926 ph->p_hcd_private = (usb_opaque_t)pp; 927 928 /* Store a copy of the pipe policy */ 929 bcopy(&ph->p_policy, &pp->pp_policy, sizeof (usb_pipe_policy_t)); 930 931 mutex_exit(&ph->p_mutex); 932 933 /* Allocate the host controller endpoint descriptor */ 934 pp->pp_qh = ehci_alloc_qh(ehcip, ph, EHCI_INTERRUPT_MODE_FLAG); 935 936 /* Initialize the halting flag */ 937 pp->pp_halt_state = EHCI_HALT_STATE_FREE; 938 939 /* Create prototype for halt completion condition variable */ 940 cv_init(&pp->pp_halt_cmpl_cv, NULL, CV_DRIVER, NULL); 941 942 /* Isoch does not use QH, so ignore this */ 943 if ((pp->pp_qh == NULL) && !(EHCI_ISOC_ENDPOINT(epdt))) { 944 ASSERT(pp->pp_qh == NULL); 945 946 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 947 "ehci_hcdi_pipe_open: QH allocation failed"); 948 949 mutex_enter(&ph->p_mutex); 950 951 /* Deallocate bandwidth */ 952 if (EHCI_PERIODIC_ENDPOINT(epdt)) { 953 954 ehci_deallocate_bandwidth(ehcip, 955 ph, pnode, smask, cmask); 956 } 957 958 /* Destroy the xfer completion condition variable */ 959 cv_destroy(&pp->pp_xfer_cmpl_cv); 960 961 /* 962 * Deallocate the hcd private portion 963 * of the pipe handle. 964 */ 965 kmem_free(ph->p_hcd_private, sizeof (ehci_pipe_private_t)); 966 967 /* 968 * Set the private structure in the 969 * pipe handle equal to NULL. 970 */ 971 ph->p_hcd_private = NULL; 972 973 mutex_exit(&ph->p_mutex); 974 mutex_exit(&ehcip->ehci_int_mutex); 975 976 return (USB_NO_RESOURCES); 977 } 978 979 /* 980 * Isoch does not use QH so no need to 981 * restore data toggle or insert QH 982 */ 983 if (!(EHCI_ISOC_ENDPOINT(epdt))) { 984 /* Restore the data toggle information */ 985 ehci_restore_data_toggle(ehcip, ph); 986 } 987 988 /* 989 * Insert the endpoint onto the host controller's 990 * appropriate endpoint list. The host controller 991 * will not schedule this endpoint and will not have 992 * any QTD's to process. It will also update the pipe count. 993 */ 994 ehci_insert_qh(ehcip, ph); 995 996 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 997 "ehci_hcdi_pipe_open: ph = 0x%p", (void *)ph); 998 999 ehcip->ehci_open_pipe_count++; 1000 1001 mutex_exit(&ehcip->ehci_int_mutex); 1002 1003 return (USB_SUCCESS); 1004 } 1005 1006 1007 /* 1008 * ehci_hcdi_pipe_close: 1009 * 1010 * Member of HCD Ops structure and called during the client specific pipe 1011 * close. Remove the pipe and the data structure representing the device. 1012 * Deallocate bandwidth for the pipe if it is a interrupt or isochronous 1013 * endpoint. 1014 */ 1015 /* ARGSUSED */ 1016 int 1017 ehci_hcdi_pipe_close( 1018 usba_pipe_handle_data_t *ph, 1019 usb_flags_t flags) 1020 { 1021 ehci_state_t *ehcip = ehci_obtain_state( 1022 ph->p_usba_device->usb_root_hub_dip); 1023 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 1024 usb_ep_descr_t *eptd = &ph->p_ep; 1025 int error = USB_SUCCESS; 1026 1027 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1028 "ehci_hcdi_pipe_close: addr = 0x%x, ep%d", 1029 ph->p_usba_device->usb_addr, 1030 eptd->bEndpointAddress & USB_EP_NUM_MASK); 1031 1032 /* Check and handle root hub pipe close */ 1033 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 1034 1035 mutex_enter(&ehcip->ehci_int_mutex); 1036 error = ehci_handle_root_hub_pipe_close(ph); 1037 mutex_exit(&ehcip->ehci_int_mutex); 1038 1039 return (error); 1040 } 1041 1042 ASSERT(ph->p_hcd_private != NULL); 1043 1044 mutex_enter(&ehcip->ehci_int_mutex); 1045 1046 /* Set pipe state to pipe close */ 1047 pp->pp_state = EHCI_PIPE_STATE_CLOSE; 1048 1049 ehci_pipe_cleanup(ehcip, ph); 1050 1051 /* 1052 * Remove the endpoint descriptor from Host 1053 * Controller's appropriate endpoint list. 1054 */ 1055 ehci_remove_qh(ehcip, pp, B_TRUE); 1056 1057 /* Deallocate bandwidth */ 1058 if (EHCI_PERIODIC_ENDPOINT(eptd)) { 1059 1060 mutex_enter(&ph->p_mutex); 1061 ehci_deallocate_bandwidth(ehcip, ph, pp->pp_pnode, 1062 pp->pp_smask, pp->pp_cmask); 1063 mutex_exit(&ph->p_mutex); 1064 } 1065 1066 mutex_enter(&ph->p_mutex); 1067 1068 /* Destroy the xfer completion condition variable */ 1069 cv_destroy(&pp->pp_xfer_cmpl_cv); 1070 1071 1072 /* Destory halt completion condition variable */ 1073 cv_destroy(&pp->pp_halt_cmpl_cv); 1074 1075 /* 1076 * Deallocate the hcd private portion 1077 * of the pipe handle. 1078 */ 1079 kmem_free(ph->p_hcd_private, sizeof (ehci_pipe_private_t)); 1080 ph->p_hcd_private = NULL; 1081 1082 mutex_exit(&ph->p_mutex); 1083 1084 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1085 "ehci_hcdi_pipe_close: ph = 0x%p", (void *)ph); 1086 1087 ehcip->ehci_open_pipe_count--; 1088 1089 mutex_exit(&ehcip->ehci_int_mutex); 1090 1091 return (error); 1092 } 1093 1094 1095 /* 1096 * ehci_hcdi_pipe_reset: 1097 */ 1098 /* ARGSUSED */ 1099 int 1100 ehci_hcdi_pipe_reset( 1101 usba_pipe_handle_data_t *ph, 1102 usb_flags_t usb_flags) 1103 { 1104 ehci_state_t *ehcip = ehci_obtain_state( 1105 ph->p_usba_device->usb_root_hub_dip); 1106 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 1107 int error = USB_SUCCESS; 1108 1109 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1110 "ehci_hcdi_pipe_reset:"); 1111 1112 /* 1113 * Check and handle root hub pipe reset. 1114 */ 1115 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 1116 1117 error = ehci_handle_root_hub_pipe_reset(ph, usb_flags); 1118 return (error); 1119 } 1120 1121 mutex_enter(&ehcip->ehci_int_mutex); 1122 1123 /* Set pipe state to pipe reset */ 1124 pp->pp_state = EHCI_PIPE_STATE_RESET; 1125 1126 ehci_pipe_cleanup(ehcip, ph); 1127 1128 mutex_exit(&ehcip->ehci_int_mutex); 1129 1130 return (error); 1131 } 1132 1133 /* 1134 * ehci_hcdi_pipe_reset_data_toggle: 1135 */ 1136 void 1137 ehci_hcdi_pipe_reset_data_toggle( 1138 usba_pipe_handle_data_t *ph) 1139 { 1140 ehci_state_t *ehcip = ehci_obtain_state( 1141 ph->p_usba_device->usb_root_hub_dip); 1142 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 1143 1144 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1145 "ehci_hcdi_pipe_reset_data_toggle:"); 1146 1147 mutex_enter(&ehcip->ehci_int_mutex); 1148 1149 mutex_enter(&ph->p_mutex); 1150 usba_hcdi_set_data_toggle(ph->p_usba_device, ph->p_ep.bEndpointAddress, 1151 DATA0); 1152 mutex_exit(&ph->p_mutex); 1153 1154 Set_QH(pp->pp_qh->qh_status, 1155 Get_QH(pp->pp_qh->qh_status) & (~EHCI_QH_STS_DATA_TOGGLE)); 1156 mutex_exit(&ehcip->ehci_int_mutex); 1157 1158 } 1159 1160 /* 1161 * ehci_hcdi_pipe_ctrl_xfer: 1162 */ 1163 int 1164 ehci_hcdi_pipe_ctrl_xfer( 1165 usba_pipe_handle_data_t *ph, 1166 usb_ctrl_req_t *ctrl_reqp, 1167 usb_flags_t usb_flags) 1168 { 1169 ehci_state_t *ehcip = ehci_obtain_state( 1170 ph->p_usba_device->usb_root_hub_dip); 1171 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 1172 int rval; 1173 int error = USB_SUCCESS; 1174 ehci_trans_wrapper_t *tw; 1175 1176 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1177 "ehci_hcdi_pipe_ctrl_xfer: ph = 0x%p reqp = 0x%p flags = %x", 1178 (void *)ph, (void *)ctrl_reqp, usb_flags); 1179 1180 mutex_enter(&ehcip->ehci_int_mutex); 1181 rval = ehci_state_is_operational(ehcip); 1182 mutex_exit(&ehcip->ehci_int_mutex); 1183 1184 if (rval != USB_SUCCESS) { 1185 1186 return (rval); 1187 } 1188 1189 /* 1190 * Check and handle root hub control request. 1191 */ 1192 if (ph->p_usba_device->usb_addr == ROOT_HUB_ADDR) { 1193 1194 error = ehci_handle_root_hub_request(ehcip, ph, ctrl_reqp); 1195 1196 return (error); 1197 } 1198 1199 mutex_enter(&ehcip->ehci_int_mutex); 1200 1201 /* 1202 * Check whether pipe is in halted state. 1203 */ 1204 if (pp->pp_state == EHCI_PIPE_STATE_ERROR) { 1205 1206 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1207 "ehci_hcdi_pipe_ctrl_xfer: " 1208 "Pipe is in error state, need pipe reset to continue"); 1209 1210 mutex_exit(&ehcip->ehci_int_mutex); 1211 1212 return (USB_FAILURE); 1213 } 1214 1215 /* Allocate a transfer wrapper */ 1216 if ((tw = ehci_allocate_ctrl_resources(ehcip, pp, ctrl_reqp, 1217 usb_flags)) == NULL) { 1218 1219 error = USB_NO_RESOURCES; 1220 } else { 1221 /* Insert the qtd's on the endpoint */ 1222 ehci_insert_ctrl_req(ehcip, ph, ctrl_reqp, tw, usb_flags); 1223 } 1224 1225 mutex_exit(&ehcip->ehci_int_mutex); 1226 1227 return (error); 1228 } 1229 1230 1231 /* 1232 * ehci_hcdi_bulk_transfer_size: 1233 * 1234 * Return maximum bulk transfer size 1235 */ 1236 1237 /* ARGSUSED */ 1238 int 1239 ehci_hcdi_bulk_transfer_size( 1240 usba_device_t *usba_device, 1241 size_t *size) 1242 { 1243 ehci_state_t *ehcip = ehci_obtain_state( 1244 usba_device->usb_root_hub_dip); 1245 int rval; 1246 1247 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1248 "ehci_hcdi_bulk_transfer_size:"); 1249 1250 mutex_enter(&ehcip->ehci_int_mutex); 1251 rval = ehci_state_is_operational(ehcip); 1252 mutex_exit(&ehcip->ehci_int_mutex); 1253 1254 if (rval != USB_SUCCESS) { 1255 1256 return (rval); 1257 } 1258 1259 /* VIA VT6202 may not handle bigger xfers well, workaround. */ 1260 if ((ehcip->ehci_vendor_id == PCI_VENDOR_VIA) && 1261 (ehci_vt62x2_workaround & EHCI_VIA_REDUCED_MAX_BULK_XFER_SIZE)) { 1262 *size = EHCI_VIA_MAX_BULK_XFER_SIZE; 1263 } else { 1264 *size = EHCI_MAX_BULK_XFER_SIZE; 1265 } 1266 1267 return (USB_SUCCESS); 1268 } 1269 1270 1271 /* 1272 * ehci_hcdi_pipe_bulk_xfer: 1273 */ 1274 int 1275 ehci_hcdi_pipe_bulk_xfer( 1276 usba_pipe_handle_data_t *ph, 1277 usb_bulk_req_t *bulk_reqp, 1278 usb_flags_t usb_flags) 1279 { 1280 ehci_state_t *ehcip = ehci_obtain_state( 1281 ph->p_usba_device->usb_root_hub_dip); 1282 ehci_pipe_private_t *pp = (ehci_pipe_private_t *)ph->p_hcd_private; 1283 int rval, error = USB_SUCCESS; 1284 ehci_trans_wrapper_t *tw; 1285 1286 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1287 "ehci_hcdi_pipe_bulk_xfer: ph = 0x%p reqp = 0x%p flags = %x", 1288 (void *)ph, (void *)bulk_reqp, usb_flags); 1289 1290 mutex_enter(&ehcip->ehci_int_mutex); 1291 rval = ehci_state_is_operational(ehcip); 1292 1293 if (rval != USB_SUCCESS) { 1294 mutex_exit(&ehcip->ehci_int_mutex); 1295 1296 return (rval); 1297 } 1298 1299 /* 1300 * Check whether pipe is in halted state. 1301 */ 1302 if (pp->pp_state == EHCI_PIPE_STATE_ERROR) { 1303 1304 USB_DPRINTF_L2(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1305 "ehci_hcdi_pipe_bulk_xfer:" 1306 "Pipe is in error state, need pipe reset to continue"); 1307 1308 mutex_exit(&ehcip->ehci_int_mutex); 1309 1310 return (USB_FAILURE); 1311 } 1312 1313 /* Allocate a transfer wrapper */ 1314 if ((tw = ehci_allocate_bulk_resources(ehcip, pp, bulk_reqp, 1315 usb_flags)) == NULL) { 1316 1317 error = USB_NO_RESOURCES; 1318 } else { 1319 /* Add the QTD into the Host Controller's bulk list */ 1320 ehci_insert_bulk_req(ehcip, ph, bulk_reqp, tw, usb_flags); 1321 } 1322 1323 mutex_exit(&ehcip->ehci_int_mutex); 1324 1325 return (error); 1326 } 1327 1328 1329 /* 1330 * ehci_hcdi_pipe_intr_xfer: 1331 */ 1332 int 1333 ehci_hcdi_pipe_intr_xfer( 1334 usba_pipe_handle_data_t *ph, 1335 usb_intr_req_t *intr_reqp, 1336 usb_flags_t usb_flags) 1337 { 1338 ehci_state_t *ehcip = ehci_obtain_state( 1339 ph->p_usba_device->usb_root_hub_dip); 1340 int pipe_dir, rval, error = USB_SUCCESS; 1341 ehci_trans_wrapper_t *tw; 1342 1343 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1344 "ehci_hcdi_pipe_intr_xfer: ph = 0x%p reqp = 0x%p flags = %x", 1345 (void *)ph, (void *)intr_reqp, usb_flags); 1346 1347 mutex_enter(&ehcip->ehci_int_mutex); 1348 rval = ehci_state_is_operational(ehcip); 1349 1350 if (rval != USB_SUCCESS) { 1351 mutex_exit(&ehcip->ehci_int_mutex); 1352 1353 return (rval); 1354 } 1355 1356 /* Get the pipe direction */ 1357 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK; 1358 1359 if (pipe_dir == USB_EP_DIR_IN) { 1360 error = ehci_start_periodic_pipe_polling(ehcip, ph, 1361 (usb_opaque_t)intr_reqp, usb_flags); 1362 } else { 1363 /* Allocate transaction resources */ 1364 if ((tw = ehci_allocate_intr_resources(ehcip, ph, 1365 intr_reqp, usb_flags)) == NULL) { 1366 1367 error = USB_NO_RESOURCES; 1368 } else { 1369 ehci_insert_intr_req(ehcip, 1370 (ehci_pipe_private_t *)ph->p_hcd_private, 1371 tw, usb_flags); 1372 } 1373 } 1374 1375 mutex_exit(&ehcip->ehci_int_mutex); 1376 1377 return (error); 1378 } 1379 1380 /* 1381 * ehci_hcdi_pipe_stop_intr_polling() 1382 */ 1383 int 1384 ehci_hcdi_pipe_stop_intr_polling( 1385 usba_pipe_handle_data_t *ph, 1386 usb_flags_t flags) 1387 { 1388 ehci_state_t *ehcip = ehci_obtain_state( 1389 ph->p_usba_device->usb_root_hub_dip); 1390 int error = USB_SUCCESS; 1391 1392 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1393 "ehci_hcdi_pipe_stop_intr_polling: ph = 0x%p fl = 0x%x", 1394 (void *)ph, flags); 1395 1396 mutex_enter(&ehcip->ehci_int_mutex); 1397 1398 error = ehci_stop_periodic_pipe_polling(ehcip, ph, flags); 1399 1400 mutex_exit(&ehcip->ehci_int_mutex); 1401 1402 return (error); 1403 } 1404 1405 1406 /* 1407 * ehci_hcdi_get_current_frame_number: 1408 * 1409 * Get the current usb frame number. 1410 * Return whether the request is handled successfully. 1411 */ 1412 int 1413 ehci_hcdi_get_current_frame_number( 1414 usba_device_t *usba_device, 1415 usb_frame_number_t *frame_number) 1416 { 1417 ehci_state_t *ehcip = ehci_obtain_state( 1418 usba_device->usb_root_hub_dip); 1419 int rval; 1420 1421 ehcip = ehci_obtain_state(usba_device->usb_root_hub_dip); 1422 1423 mutex_enter(&ehcip->ehci_int_mutex); 1424 rval = ehci_state_is_operational(ehcip); 1425 1426 if (rval != USB_SUCCESS) { 1427 mutex_exit(&ehcip->ehci_int_mutex); 1428 1429 return (rval); 1430 } 1431 1432 *frame_number = ehci_get_current_frame_number(ehcip); 1433 1434 mutex_exit(&ehcip->ehci_int_mutex); 1435 1436 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1437 "ehci_hcdi_get_current_frame_number: " 1438 "Current frame number 0x%llx", (unsigned long long)(*frame_number)); 1439 1440 return (rval); 1441 } 1442 1443 1444 /* 1445 * ehci_hcdi_get_max_isoc_pkts: 1446 * 1447 * Get maximum isochronous packets per usb isochronous request. 1448 * Return whether the request is handled successfully. 1449 */ 1450 int 1451 ehci_hcdi_get_max_isoc_pkts( 1452 usba_device_t *usba_device, 1453 uint_t *max_isoc_pkts_per_request) 1454 { 1455 ehci_state_t *ehcip = ehci_obtain_state( 1456 usba_device->usb_root_hub_dip); 1457 int rval; 1458 1459 mutex_enter(&ehcip->ehci_int_mutex); 1460 rval = ehci_state_is_operational(ehcip); 1461 mutex_exit(&ehcip->ehci_int_mutex); 1462 1463 if (rval != USB_SUCCESS) { 1464 1465 return (rval); 1466 } 1467 1468 *max_isoc_pkts_per_request = EHCI_MAX_ISOC_PKTS_PER_XFER; 1469 1470 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1471 "ehci_hcdi_get_max_isoc_pkts: maximum isochronous" 1472 "packets per usb isochronous request = 0x%x", 1473 *max_isoc_pkts_per_request); 1474 1475 return (rval); 1476 } 1477 1478 1479 /* 1480 * ehci_hcdi_pipe_isoc_xfer: 1481 */ 1482 int 1483 ehci_hcdi_pipe_isoc_xfer( 1484 usba_pipe_handle_data_t *ph, 1485 usb_isoc_req_t *isoc_reqp, 1486 usb_flags_t usb_flags) 1487 { 1488 ehci_state_t *ehcip = ehci_obtain_state( 1489 ph->p_usba_device->usb_root_hub_dip); 1490 1491 int pipe_dir, rval; 1492 ehci_isoc_xwrapper_t *itw; 1493 1494 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1495 "ehci_hcdi_pipe_isoc_xfer: ph = 0x%p reqp = 0x%p flags = 0x%x", 1496 (void *)ph, (void *)isoc_reqp, usb_flags); 1497 1498 mutex_enter(&ehcip->ehci_int_mutex); 1499 rval = ehci_state_is_operational(ehcip); 1500 1501 if (rval != USB_SUCCESS) { 1502 mutex_exit(&ehcip->ehci_int_mutex); 1503 1504 return (rval); 1505 } 1506 1507 /* Get the isochronous pipe direction */ 1508 pipe_dir = ph->p_ep.bEndpointAddress & USB_EP_DIR_MASK; 1509 1510 if (pipe_dir == USB_EP_DIR_IN) { 1511 rval = ehci_start_periodic_pipe_polling(ehcip, ph, 1512 (usb_opaque_t)isoc_reqp, usb_flags); 1513 } else { 1514 /* Allocate transaction resources */ 1515 if ((itw = ehci_allocate_isoc_resources(ehcip, ph, 1516 isoc_reqp, usb_flags)) == NULL) { 1517 rval = USB_NO_RESOURCES; 1518 } else { 1519 rval = ehci_insert_isoc_req(ehcip, 1520 (ehci_pipe_private_t *)ph->p_hcd_private, 1521 itw, usb_flags); 1522 } 1523 } 1524 1525 mutex_exit(&ehcip->ehci_int_mutex); 1526 1527 return (rval); 1528 } 1529 1530 1531 /* 1532 * ehci_hcdi_pipe_stop_isoc_polling() 1533 */ 1534 /*ARGSUSED*/ 1535 int 1536 ehci_hcdi_pipe_stop_isoc_polling( 1537 usba_pipe_handle_data_t *ph, 1538 usb_flags_t flags) 1539 { 1540 ehci_state_t *ehcip = ehci_obtain_state( 1541 ph->p_usba_device->usb_root_hub_dip); 1542 int rval; 1543 1544 USB_DPRINTF_L4(PRINT_MASK_HCDI, ehcip->ehci_log_hdl, 1545 "ehci_hcdi_pipe_stop_isoc_polling: ph = 0x%p fl = 0x%x", 1546 (void *)ph, flags); 1547 1548 mutex_enter(&ehcip->ehci_int_mutex); 1549 rval = ehci_state_is_operational(ehcip); 1550 1551 if (rval != USB_SUCCESS) { 1552 mutex_exit(&ehcip->ehci_int_mutex); 1553 1554 return (rval); 1555 } 1556 1557 rval = ehci_stop_periodic_pipe_polling(ehcip, ph, flags); 1558 1559 mutex_exit(&ehcip->ehci_int_mutex); 1560 1561 return (rval); 1562 } 1563