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