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