Print this page
MFV: illumos-gate@9a48f6c443e5968307491ba7cc134bbdd0328801
9806 ehci_take_control() can infinite loop due to PCI invalid reads
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Jason King <jason.king@joyent.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Approved by: Richard Lowe <richlowe@richlowe.net>
Author: Robert Mustacchi <rm@joyent.com>
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>


   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 (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.

  24  */
  25 
  26 /*




  27  * EHCI Host Controller Driver (EHCI)
  28  *
  29  * The EHCI driver is a software driver which interfaces to the Universal
  30  * Serial Bus layer (USBA) and the Host Controller (HC). The interface to
  31  * the Host Controller is defined by the EHCI Host Controller Interface.
  32  *
  33  * This module contains the main EHCI driver code which handles all USB
  34  * transfers, bandwidth allocations and other general functionalities.
  35  */
  36 
  37 #include <sys/usb/hcd/ehci/ehcid.h>
  38 #include <sys/usb/hcd/ehci/ehci_isoch.h>
  39 #include <sys/usb/hcd/ehci/ehci_xfer.h>
  40 
  41 /*
  42  * EHCI MSI tunable:
  43  *
  44  * By default MSI is enabled on all supported platforms except for the
  45  * EHCI controller of ULI1575 South bridge.
  46  */


 728          */
 729         if ((ehcip->ehci_vendor_id == PCI_VENDOR_ULi_M1575) &&
 730             (ehcip->ehci_device_id == PCI_DEVICE_ULi_M1575)) {
 731                 ehcip->ehci_msi_enabled = B_FALSE;
 732         } else {
 733                 /* Set the MSI enable flag from the global EHCI MSI tunable */
 734                 ehcip->ehci_msi_enabled = ehci_enable_msi;
 735         }
 736 
 737         /* launch polling thread instead of enabling pci interrupt */
 738         if (ehci_is_polled(ehcip->ehci_dip)) {
 739                 extern pri_t maxclsyspri;
 740 
 741                 USB_DPRINTF_L2(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
 742                     "ehci_register_intrs_and_init_mutex: "
 743                     "running in simulated polled mode");
 744 
 745                 (void) thread_create(NULL, 0, ehci_poll_intr, ehcip, 0, &p0,
 746                     TS_RUN, maxclsyspri);
 747 
 748                 goto skip_intr;
 749         }
 750 
 751 #if defined(__x86)
 752         /*
 753          * Make sure that the interrupt pin is connected to the
 754          * interrupt controller on x86.  Interrupt line 255 means
 755          * "unknown" or "not connected" (PCI spec 6.2.4, footnote 43).
 756          * If we would return failure when interrupt line equals 255, then
 757          * high speed devices will be routed to companion host controllers.
 758          * However, it is not necessary to return failure here, and
 759          * o/uhci codes don't check the interrupt line either.
 760          * But it's good to log a message here for debug purposes.
 761          */
 762         iline = pci_config_get8(ehcip->ehci_config_handle,
 763             PCI_CONF_ILINE);
 764 
 765         if (iline == 255) {
 766                 USB_DPRINTF_L2(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
 767                     "ehci_register_intrs_and_init_mutex: "
 768                     "interrupt line value out of range (%d)",


 802 
 803         if ((!(ehcip->ehci_flags & EHCI_INTR)) &&
 804             (intr_types & DDI_INTR_TYPE_FIXED)) {
 805                 if (ehci_add_intrs(ehcip, DDI_INTR_TYPE_FIXED)
 806                     != DDI_SUCCESS) {
 807                         USB_DPRINTF_L2(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
 808                             "ehci_register_intrs_and_init_mutex: "
 809                             "FIXED interrupt registration failed\n");
 810 
 811                         return (DDI_FAILURE);
 812                 }
 813 
 814                 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
 815                     "ehci_register_intrs_and_init_mutex: "
 816                     "Using FIXED interrupt type\n");
 817 
 818                 ehcip->ehci_intr_type = DDI_INTR_TYPE_FIXED;
 819                 ehcip->ehci_flags |= EHCI_INTR;
 820         }
 821 
 822 skip_intr:
 823         /* Create prototype for advance on async schedule */
 824         cv_init(&ehcip->ehci_async_schedule_advance_cv,
 825             NULL, CV_DRIVER, NULL);
 826 
 827         return (DDI_SUCCESS);
 828 }
 829 
 830 
 831 /*
 832  * ehci_add_intrs:
 833  *
 834  * Register FIXED or MSI interrupts.
 835  */
 836 static int
 837 ehci_add_intrs(ehci_state_t     *ehcip,
 838                 int             intr_type)
 839 {
 840         int     actual, avail, intr_size, count = 0;
 841         int     i, flag, ret;
 842 
 843         USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
 844             "ehci_add_intrs: interrupt type 0x%x", intr_type);
 845 
 846         /* Get number of interrupts */
 847         ret = ddi_intr_get_nintrs(ehcip->ehci_dip, intr_type, &count);
 848         if ((ret != DDI_SUCCESS) || (count == 0)) {
 849                 USB_DPRINTF_L2(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
 850                     "ehci_add_intrs: ddi_intr_get_nintrs() failure, "
 851                     "ret: %d, count: %d", ret, count);
 852 
 853                 return (DDI_FAILURE);
 854         }
 855 
 856         /* Get number of available interrupts */
 857         ret = ddi_intr_get_navail(ehcip->ehci_dip, intr_type, &avail);
 858         if ((ret != DDI_SUCCESS) || (avail == 0)) {


1157                             "Please also refer to www.sun.com/io for");
1158                         USB_DPRINTF_L1(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1159                             "Solaris Ready products and to");
1160                         USB_DPRINTF_L1(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1161                             "www.sun.com/bigadmin/hcl for additional");
1162                         USB_DPRINTF_L1(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1163                             "compatible USB products.");
1164 
1165                         return (DDI_FAILURE);
1166 
1167                         } else if (ehci_vt62x2_workaround) {
1168 
1169                         USB_DPRINTF_L1(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1170                             "Applying VIA workarounds");
1171                 }
1172         }
1173 
1174         return (DDI_SUCCESS);
1175 }
1176 
1177 
1178 /*
1179  * ehci_init_check_status
1180  *
1181  * Check if EHCI host controller is running
1182  */
1183 int
1184 ehci_init_check_status(ehci_state_t     *ehcip)
1185 {
1186         clock_t                 sof_time_wait;
1187 
1188         /*
1189          * Get the number of clock ticks to wait.
1190          * This is based on the maximum time it takes for a frame list rollover
1191          * and maximum time wait for SOFs to begin.
1192          */
1193         sof_time_wait = drv_usectohz((EHCI_NUM_PERIODIC_FRAME_LISTS * 1000) +
1194             EHCI_SOF_TIMEWAIT);
1195 
1196         /* Tell the ISR to broadcast ehci_async_schedule_advance_cv */
1197         ehcip->ehci_flags |= EHCI_CV_INTR;
1198 
1199         /* We need to add a delay to allow the chip time to start running */
1200         (void) cv_reltimedwait(&ehcip->ehci_async_schedule_advance_cv,
1201             &ehcip->ehci_int_mutex, sof_time_wait, TR_CLOCK_TICK);
1202 
1203         /*
1204          * Check EHCI host controller is running, otherwise return failure.
1205          */
1206         if ((ehcip->ehci_flags & EHCI_CV_INTR) ||
1207             (Get_OpReg(ehci_status) & EHCI_STS_HOST_CTRL_HALTED)) {
1208 
1209                 USB_DPRINTF_L0(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1210                     "No SOF interrupts have been received, this USB EHCI host"
1211                     "controller is unusable");
1212 
1213                 /*
1214                  * Route all Root hub ports to Classic host
1215                  * controller, in case this is an unusable ALI M5273
1216                  * EHCI controller.
1217                  */
1218                 if (ehcip->ehci_vendor_id == PCI_VENDOR_ALI) {
1219                         Set_OpReg(ehci_config_flag, EHCI_CONFIG_FLAG_CLASSIC);
1220                 }
1221 
1222                 return (DDI_FAILURE);
1223         }
1224 
1225         return (DDI_SUCCESS);
1226 }
1227 
1228 
1229 /*
1230  * ehci_init_ctlr:
1231  *
1232  * Initialize the Host Controller (HC).
1233  */
1234 int
1235 ehci_init_ctlr(ehci_state_t     *ehcip,
1236                 int             init_type)
1237 {
1238         USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, "ehci_init_ctlr:");
1239 
1240         if (init_type == EHCI_NORMAL_INITIALIZATION) {
1241 
1242                 if (ehci_init_hardware(ehcip) != DDI_SUCCESS) {
1243 
1244                         return (DDI_FAILURE);
1245                 }
1246         }
1247 
1248         /*
1249          * Check for Asynchronous schedule park capability feature. If this
1250          * feature is supported, then, program ehci command register with
1251          * appropriate values..
1252          */
1253         if (Get_Cap(ehci_hcc_params) & EHCI_HCC_ASYNC_SCHED_PARK_CAP) {
1254 
1255                 USB_DPRINTF_L3(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1256                     "ehci_init_ctlr: Async park mode is supported");


1307             EHCI_PERIODIC_LIST_BASE));
1308 
1309         /*
1310          * Set ehci_interrupt to enable all interrupts except Root
1311          * Hub Status change interrupt.
1312          */
1313         Set_OpReg(ehci_interrupt, EHCI_INTR_HOST_SYSTEM_ERROR |
1314             EHCI_INTR_FRAME_LIST_ROLLOVER | EHCI_INTR_USB_ERROR |
1315             EHCI_INTR_USB);
1316 
1317         /*
1318          * Set the desired interrupt threshold and turn on EHCI host controller.
1319          */
1320         Set_OpReg(ehci_command,
1321             ((Get_OpReg(ehci_command) & ~EHCI_CMD_INTR_THRESHOLD) |
1322             (EHCI_CMD_01_INTR | EHCI_CMD_HOST_CTRL_RUN)));
1323 
1324         ASSERT(Get_OpReg(ehci_command) & EHCI_CMD_HOST_CTRL_RUN);
1325 
1326         if (init_type == EHCI_NORMAL_INITIALIZATION) {
1327 
1328                 if (ehci_init_workaround(ehcip) != DDI_SUCCESS) {
1329 
1330                         /* Set host controller soft state to error */
1331                         ehcip->ehci_hc_soft_state = EHCI_CTLR_ERROR_STATE;
1332 
1333                         return (DDI_FAILURE);
1334                 }
1335 
1336                 if (ehci_init_check_status(ehcip) != DDI_SUCCESS) {
1337 
1338                         /* Set host controller soft state to error */
1339                         ehcip->ehci_hc_soft_state = EHCI_CTLR_ERROR_STATE;
1340 
1341                         return (DDI_FAILURE);
1342                 }
1343 
1344                 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1345                     "ehci_init_ctlr: SOF's have started");
1346         }
1347 
1348         /* Route all Root hub ports to EHCI host controller */
1349         Set_OpReg(ehci_config_flag, EHCI_CONFIG_FLAG_EHCI);
1350 
1351         return (DDI_SUCCESS);
1352 }
1353 
1354 /*
1355  * ehci_take_control:
1356  *
1357  * Handshake to take EHCI control from BIOS if necessary.  Its only valid for
1358  * x86 machines, because sparc doesn't have a BIOS.
1359  * On x86 machine, the take control process includes
1360  *    o get the base address of the extended capability list
1361  *    o find out the capability for handoff synchronization in the list.
1362  *    o check if BIOS has owned the host controller.
1363  *    o set the OS Owned semaphore bit, ask the BIOS to release the ownership.
1364  *    o wait for a constant time and check if BIOS has relinquished control.
1365  */
1366 /* ARGSUSED */
1367 static int


1389          * worry about BIOS handoff.
1390          */
1391         if (extended_cap_offset < EHCI_HCC_EECP_MIN_OFFSET) {
1392 
1393                 USB_DPRINTF_L3(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1394                     "ehci_take_control: Hardware doesn't support legacy.");
1395 
1396                 goto success;
1397         }
1398 
1399         /*
1400          * According EHCI Spec 2.1.7, A zero offset indicates the
1401          * end of the extended capability list.
1402          */
1403         while (extended_cap_offset) {
1404 
1405                 /* Get the extended capability value. */
1406                 extended_cap = pci_config_get32(ehcip->ehci_config_handle,
1407                     extended_cap_offset);
1408 













1409                 /* Get the capability ID */
1410                 extended_cap_id = (extended_cap & EHCI_EX_CAP_ID) >>
1411                     EHCI_EX_CAP_ID_SHIFT;
1412 
1413                 /* Check if the card support legacy */
1414                 if (extended_cap_id == EHCI_EX_CAP_ID_BIOS_HANDOFF) {
1415                         break;
1416                 }
1417 
1418                 /* Get the offset of the next capability */
1419                 extended_cap_offset = (extended_cap & EHCI_EX_CAP_NEXT_PTR) >>
1420                     EHCI_EX_CAP_NEXT_PTR_SHIFT;

1421         }
1422 
1423         /*
1424          * Unable to find legacy support in hardware's extended capability list.
1425          * This means we don't need to worry about BIOS handoff.
1426          */
1427         if (extended_cap_id != EHCI_EX_CAP_ID_BIOS_HANDOFF) {
1428 
1429                 USB_DPRINTF_L3(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1430                     "ehci_take_control: Hardware doesn't support legacy");
1431 
1432                 goto success;
1433         }
1434 
1435         /* Check if BIOS has owned it. */
1436         if (!(extended_cap & EHCI_LEGSUP_BIOS_OWNED_SEM)) {
1437 
1438                 USB_DPRINTF_L3(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1439                     "ehci_take_control: BIOS does not own EHCI");
1440 


1914                     EHCI_PFLT_DMA_BOUND) == EHCI_PFLT_DMA_BOUND) {
1915 
1916                         rval = ddi_dma_unbind_handle(
1917                             ehcip->ehci_pflt_dma_handle);
1918 
1919                         ASSERT(rval == DDI_SUCCESS);
1920                 }
1921 
1922                 ddi_dma_mem_free(&ehcip->ehci_pflt_mem_handle);
1923         }
1924 
1925         (void) ehci_isoc_cleanup(ehcip);
1926 
1927         if (ehcip->ehci_pflt_dma_handle) {
1928                 ddi_dma_free_handle(&ehcip->ehci_pflt_dma_handle);
1929         }
1930 
1931         if (flags & EHCI_INTR) {
1932                 /* Destroy the mutex */
1933                 mutex_destroy(&ehcip->ehci_int_mutex);
1934 
1935                 /* Destroy the async schedule advance condition variable */
1936                 cv_destroy(&ehcip->ehci_async_schedule_advance_cv);
1937         }
1938 
1939         /* clean up kstat structs */
1940         ehci_destroy_stats(ehcip);
1941 
1942         /* Free ehci hcdi ops */
1943         if (ehcip->ehci_hcdi_ops) {
1944                 usba_free_hcdi_ops(ehcip->ehci_hcdi_ops);
1945         }
1946 
1947         if (flags & EHCI_ZALLOC) {
1948 
1949                 usb_free_log_hdl(ehcip->ehci_log_hdl);
1950 
1951                 /* Remove all properties that might have been created */
1952                 ddi_prop_remove_all(ehcip->ehci_dip);
1953 
1954                 /* Free the soft state */
1955                 ddi_soft_state_free(ehci_statep,
1956                     ddi_get_instance(ehcip->ehci_dip));


2959  */
2960 static uint_t
2961 ehci_lattice_parent(uint_t node)
2962 {
2963         if ((node % 2) == 0) {
2964 
2965                 return ((node/2) - 1);
2966         } else {
2967 
2968                 return ((node + 1)/2 - 1);
2969         }
2970 }
2971 
2972 
2973 /*
2974  * ehci_find_periodic_node:
2975  *
2976  * Based on the "real" array leaf node and interval, get the periodic node.
2977  */
2978 static uint_t
2979 ehci_find_periodic_node(uint_t leaf, int interval) {

2980         uint_t  lattice_leaf;
2981         uint_t  height = ehci_lattice_height(interval);
2982         uint_t  pnode;
2983         int     i;
2984 
2985         /* Get the leaf number in the lattice */
2986         lattice_leaf = leaf + EHCI_NUM_INTR_QH_LISTS - 1;
2987 
2988         /* Get the node in the lattice based on the height and leaf */
2989         pnode = lattice_leaf;
2990         for (i = 0; i < height; i++) {
2991                 pnode = ehci_lattice_parent(pnode);
2992         }
2993 
2994         return (pnode);
2995 }
2996 
2997 
2998 /*
2999  * ehci_leftmost_leaf:




   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 (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2018, Joyent, Inc.
  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 module contains the main EHCI driver code which handles all USB
  39  * transfers, bandwidth allocations and other general functionalities.
  40  */
  41 
  42 #include <sys/usb/hcd/ehci/ehcid.h>
  43 #include <sys/usb/hcd/ehci/ehci_isoch.h>
  44 #include <sys/usb/hcd/ehci/ehci_xfer.h>
  45 
  46 /*
  47  * EHCI MSI tunable:
  48  *
  49  * By default MSI is enabled on all supported platforms except for the
  50  * EHCI controller of ULI1575 South bridge.
  51  */


 733          */
 734         if ((ehcip->ehci_vendor_id == PCI_VENDOR_ULi_M1575) &&
 735             (ehcip->ehci_device_id == PCI_DEVICE_ULi_M1575)) {
 736                 ehcip->ehci_msi_enabled = B_FALSE;
 737         } else {
 738                 /* Set the MSI enable flag from the global EHCI MSI tunable */
 739                 ehcip->ehci_msi_enabled = ehci_enable_msi;
 740         }
 741 
 742         /* launch polling thread instead of enabling pci interrupt */
 743         if (ehci_is_polled(ehcip->ehci_dip)) {
 744                 extern pri_t maxclsyspri;
 745 
 746                 USB_DPRINTF_L2(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
 747                     "ehci_register_intrs_and_init_mutex: "
 748                     "running in simulated polled mode");
 749 
 750                 (void) thread_create(NULL, 0, ehci_poll_intr, ehcip, 0, &p0,
 751                     TS_RUN, maxclsyspri);
 752 
 753                 return (DDI_SUCCESS);
 754         }
 755 
 756 #if defined(__x86)
 757         /*
 758          * Make sure that the interrupt pin is connected to the
 759          * interrupt controller on x86.  Interrupt line 255 means
 760          * "unknown" or "not connected" (PCI spec 6.2.4, footnote 43).
 761          * If we would return failure when interrupt line equals 255, then
 762          * high speed devices will be routed to companion host controllers.
 763          * However, it is not necessary to return failure here, and
 764          * o/uhci codes don't check the interrupt line either.
 765          * But it's good to log a message here for debug purposes.
 766          */
 767         iline = pci_config_get8(ehcip->ehci_config_handle,
 768             PCI_CONF_ILINE);
 769 
 770         if (iline == 255) {
 771                 USB_DPRINTF_L2(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
 772                     "ehci_register_intrs_and_init_mutex: "
 773                     "interrupt line value out of range (%d)",


 807 
 808         if ((!(ehcip->ehci_flags & EHCI_INTR)) &&
 809             (intr_types & DDI_INTR_TYPE_FIXED)) {
 810                 if (ehci_add_intrs(ehcip, DDI_INTR_TYPE_FIXED)
 811                     != DDI_SUCCESS) {
 812                         USB_DPRINTF_L2(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
 813                             "ehci_register_intrs_and_init_mutex: "
 814                             "FIXED interrupt registration failed\n");
 815 
 816                         return (DDI_FAILURE);
 817                 }
 818 
 819                 USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
 820                     "ehci_register_intrs_and_init_mutex: "
 821                     "Using FIXED interrupt type\n");
 822 
 823                 ehcip->ehci_intr_type = DDI_INTR_TYPE_FIXED;
 824                 ehcip->ehci_flags |= EHCI_INTR;
 825         }
 826 





 827         return (DDI_SUCCESS);
 828 }
 829 
 830 
 831 /*
 832  * ehci_add_intrs:
 833  *
 834  * Register FIXED or MSI interrupts.
 835  */
 836 static int
 837 ehci_add_intrs(ehci_state_t *ehcip, int intr_type)

 838 {
 839         int     actual, avail, intr_size, count = 0;
 840         int     i, flag, ret;
 841 
 842         USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
 843             "ehci_add_intrs: interrupt type 0x%x", intr_type);
 844 
 845         /* Get number of interrupts */
 846         ret = ddi_intr_get_nintrs(ehcip->ehci_dip, intr_type, &count);
 847         if ((ret != DDI_SUCCESS) || (count == 0)) {
 848                 USB_DPRINTF_L2(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
 849                     "ehci_add_intrs: ddi_intr_get_nintrs() failure, "
 850                     "ret: %d, count: %d", ret, count);
 851 
 852                 return (DDI_FAILURE);
 853         }
 854 
 855         /* Get number of available interrupts */
 856         ret = ddi_intr_get_navail(ehcip->ehci_dip, intr_type, &avail);
 857         if ((ret != DDI_SUCCESS) || (avail == 0)) {


1156                             "Please also refer to www.sun.com/io for");
1157                         USB_DPRINTF_L1(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1158                             "Solaris Ready products and to");
1159                         USB_DPRINTF_L1(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1160                             "www.sun.com/bigadmin/hcl for additional");
1161                         USB_DPRINTF_L1(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1162                             "compatible USB products.");
1163 
1164                         return (DDI_FAILURE);
1165 
1166                         } else if (ehci_vt62x2_workaround) {
1167 
1168                         USB_DPRINTF_L1(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1169                             "Applying VIA workarounds");
1170                 }
1171         }
1172 
1173         return (DDI_SUCCESS);
1174 }
1175 

1176 /*



















































1177  * ehci_init_ctlr:
1178  *
1179  * Initialize the Host Controller (HC).
1180  */
1181 int
1182 ehci_init_ctlr(ehci_state_t *ehcip, int init_type)

1183 {
1184         USB_DPRINTF_L4(PRINT_MASK_ATTA, ehcip->ehci_log_hdl, "ehci_init_ctlr:");
1185 
1186         if (init_type == EHCI_NORMAL_INITIALIZATION) {
1187 
1188                 if (ehci_init_hardware(ehcip) != DDI_SUCCESS) {
1189 
1190                         return (DDI_FAILURE);
1191                 }
1192         }
1193 
1194         /*
1195          * Check for Asynchronous schedule park capability feature. If this
1196          * feature is supported, then, program ehci command register with
1197          * appropriate values..
1198          */
1199         if (Get_Cap(ehci_hcc_params) & EHCI_HCC_ASYNC_SCHED_PARK_CAP) {
1200 
1201                 USB_DPRINTF_L3(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1202                     "ehci_init_ctlr: Async park mode is supported");


1253             EHCI_PERIODIC_LIST_BASE));
1254 
1255         /*
1256          * Set ehci_interrupt to enable all interrupts except Root
1257          * Hub Status change interrupt.
1258          */
1259         Set_OpReg(ehci_interrupt, EHCI_INTR_HOST_SYSTEM_ERROR |
1260             EHCI_INTR_FRAME_LIST_ROLLOVER | EHCI_INTR_USB_ERROR |
1261             EHCI_INTR_USB);
1262 
1263         /*
1264          * Set the desired interrupt threshold and turn on EHCI host controller.
1265          */
1266         Set_OpReg(ehci_command,
1267             ((Get_OpReg(ehci_command) & ~EHCI_CMD_INTR_THRESHOLD) |
1268             (EHCI_CMD_01_INTR | EHCI_CMD_HOST_CTRL_RUN)));
1269 
1270         ASSERT(Get_OpReg(ehci_command) & EHCI_CMD_HOST_CTRL_RUN);
1271 
1272         if (init_type == EHCI_NORMAL_INITIALIZATION) {

1273                 if (ehci_init_workaround(ehcip) != DDI_SUCCESS) {
1274 
1275                         /* Set host controller soft state to error */
1276                         ehcip->ehci_hc_soft_state = EHCI_CTLR_ERROR_STATE;
1277 
1278                         return (DDI_FAILURE);
1279                 }







1280         }
1281 




1282         /* Route all Root hub ports to EHCI host controller */
1283         Set_OpReg(ehci_config_flag, EHCI_CONFIG_FLAG_EHCI);
1284 
1285         return (DDI_SUCCESS);
1286 }
1287 
1288 /*
1289  * ehci_take_control:
1290  *
1291  * Handshake to take EHCI control from BIOS if necessary.  Its only valid for
1292  * x86 machines, because sparc doesn't have a BIOS.
1293  * On x86 machine, the take control process includes
1294  *    o get the base address of the extended capability list
1295  *    o find out the capability for handoff synchronization in the list.
1296  *    o check if BIOS has owned the host controller.
1297  *    o set the OS Owned semaphore bit, ask the BIOS to release the ownership.
1298  *    o wait for a constant time and check if BIOS has relinquished control.
1299  */
1300 /* ARGSUSED */
1301 static int


1323          * worry about BIOS handoff.
1324          */
1325         if (extended_cap_offset < EHCI_HCC_EECP_MIN_OFFSET) {
1326 
1327                 USB_DPRINTF_L3(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1328                     "ehci_take_control: Hardware doesn't support legacy.");
1329 
1330                 goto success;
1331         }
1332 
1333         /*
1334          * According EHCI Spec 2.1.7, A zero offset indicates the
1335          * end of the extended capability list.
1336          */
1337         while (extended_cap_offset) {
1338 
1339                 /* Get the extended capability value. */
1340                 extended_cap = pci_config_get32(ehcip->ehci_config_handle,
1341                     extended_cap_offset);
1342 
1343                 /*
1344                  * It's possible that we'll receive an invalid PCI read here due
1345                  * to something going wrong due to platform firmware. This has
1346                  * been observed in the wild depending on the version of ACPI in
1347                  * use. If this happens, we'll assume that the capability does
1348                  * not exist and that we do not need to take control from the
1349                  * BIOS.
1350                  */
1351                 if (extended_cap == PCI_EINVAL32) {
1352                         extended_cap_id = EHCI_EX_CAP_ID_RESERVED;
1353                         break;
1354                 }
1355 
1356                 /* Get the capability ID */
1357                 extended_cap_id = (extended_cap & EHCI_EX_CAP_ID) >>
1358                     EHCI_EX_CAP_ID_SHIFT;
1359 
1360                 /* Check if the card support legacy */
1361                 if (extended_cap_id == EHCI_EX_CAP_ID_BIOS_HANDOFF) {
1362                         break;
1363                 }
1364 
1365                 /* Get the offset of the next capability */
1366                 extended_cap_offset = (extended_cap & EHCI_EX_CAP_NEXT_PTR) >>
1367                     EHCI_EX_CAP_NEXT_PTR_SHIFT;
1368 
1369         }
1370 
1371         /*
1372          * Unable to find legacy support in hardware's extended capability list.
1373          * This means we don't need to worry about BIOS handoff.
1374          */
1375         if (extended_cap_id != EHCI_EX_CAP_ID_BIOS_HANDOFF) {
1376 
1377                 USB_DPRINTF_L3(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1378                     "ehci_take_control: Hardware doesn't support legacy");
1379 
1380                 goto success;
1381         }
1382 
1383         /* Check if BIOS has owned it. */
1384         if (!(extended_cap & EHCI_LEGSUP_BIOS_OWNED_SEM)) {
1385 
1386                 USB_DPRINTF_L3(PRINT_MASK_ATTA, ehcip->ehci_log_hdl,
1387                     "ehci_take_control: BIOS does not own EHCI");
1388 


1862                     EHCI_PFLT_DMA_BOUND) == EHCI_PFLT_DMA_BOUND) {
1863 
1864                         rval = ddi_dma_unbind_handle(
1865                             ehcip->ehci_pflt_dma_handle);
1866 
1867                         ASSERT(rval == DDI_SUCCESS);
1868                 }
1869 
1870                 ddi_dma_mem_free(&ehcip->ehci_pflt_mem_handle);
1871         }
1872 
1873         (void) ehci_isoc_cleanup(ehcip);
1874 
1875         if (ehcip->ehci_pflt_dma_handle) {
1876                 ddi_dma_free_handle(&ehcip->ehci_pflt_dma_handle);
1877         }
1878 
1879         if (flags & EHCI_INTR) {
1880                 /* Destroy the mutex */
1881                 mutex_destroy(&ehcip->ehci_int_mutex);



1882         }
1883 
1884         /* clean up kstat structs */
1885         ehci_destroy_stats(ehcip);
1886 
1887         /* Free ehci hcdi ops */
1888         if (ehcip->ehci_hcdi_ops) {
1889                 usba_free_hcdi_ops(ehcip->ehci_hcdi_ops);
1890         }
1891 
1892         if (flags & EHCI_ZALLOC) {
1893 
1894                 usb_free_log_hdl(ehcip->ehci_log_hdl);
1895 
1896                 /* Remove all properties that might have been created */
1897                 ddi_prop_remove_all(ehcip->ehci_dip);
1898 
1899                 /* Free the soft state */
1900                 ddi_soft_state_free(ehci_statep,
1901                     ddi_get_instance(ehcip->ehci_dip));


2904  */
2905 static uint_t
2906 ehci_lattice_parent(uint_t node)
2907 {
2908         if ((node % 2) == 0) {
2909 
2910                 return ((node/2) - 1);
2911         } else {
2912 
2913                 return ((node + 1)/2 - 1);
2914         }
2915 }
2916 
2917 
2918 /*
2919  * ehci_find_periodic_node:
2920  *
2921  * Based on the "real" array leaf node and interval, get the periodic node.
2922  */
2923 static uint_t
2924 ehci_find_periodic_node(uint_t leaf, int interval)
2925 {
2926         uint_t  lattice_leaf;
2927         uint_t  height = ehci_lattice_height(interval);
2928         uint_t  pnode;
2929         int     i;
2930 
2931         /* Get the leaf number in the lattice */
2932         lattice_leaf = leaf + EHCI_NUM_INTR_QH_LISTS - 1;
2933 
2934         /* Get the node in the lattice based on the height and leaf */
2935         pnode = lattice_leaf;
2936         for (i = 0; i < height; i++) {
2937                 pnode = ehci_lattice_parent(pnode);
2938         }
2939 
2940         return (pnode);
2941 }
2942 
2943 
2944 /*
2945  * ehci_leftmost_leaf: