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