xref: /illumos-gate/usr/src/uts/i86pc/io/pciex/npe_misc.c (revision e2738c5e21a9e5d9a6525e48af4738deda3df455)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  *	Library file that has miscellaneous support for npe(7d)
31  */
32 
33 #include <sys/conf.h>
34 #include <sys/pci.h>
35 #include <sys/sunndi.h>
36 #include <sys/acpi/acpi.h>
37 #include <sys/acpi/acpi_pci.h>
38 #include <sys/acpica.h>
39 #include <io/pciex/pcie_nvidia.h>
40 
41 /*
42  * Prototype declaration
43  */
44 void	npe_query_acpi_mcfg(dev_info_t *dip);
45 void	npe_ck804_fix_aer_ptr(dev_info_t *child);
46 int	npe_disable_empty_bridges_workaround(dev_info_t *child);
47 
48 /*
49  * Default ecfga base address
50  */
51 int64_t npe_default_ecfga_base = 0xE0000000;
52 
53 /*
54  * Query the MCFG table using ACPI.  If MCFG is found, setup the
55  * 'ecfga-base-address' (Enhanced Configuration Access base address)
56  * property accordingly.  Otherwise, set the value of the property
57  * to the default value.
58  */
59 void
60 npe_query_acpi_mcfg(dev_info_t *dip)
61 {
62 	MCFG_TABLE *mcfgp;
63 	CFG_BASE_ADDR_ALLOC *cfg_baap;
64 	char *cfg_baa_endp;
65 	uint64_t ecfga_base;
66 
67 	/* Query the MCFG table using ACPI */
68 	if (AcpiGetFirmwareTable(MCFG_SIG, 1, ACPI_LOGICAL_ADDRESSING,
69 	    (ACPI_TABLE_HEADER **)&mcfgp) == AE_OK) {
70 
71 		cfg_baap = (CFG_BASE_ADDR_ALLOC *)mcfgp->CfgBaseAddrAllocList;
72 		cfg_baa_endp = ((char *)mcfgp) + mcfgp->Length;
73 
74 		while ((char *)cfg_baap < cfg_baa_endp) {
75 			ecfga_base = ACPI_GET_ADDRESS(cfg_baap->base_addr);
76 			if (ecfga_base != (uint64_t)0) {
77 				/*
78 				 * Setup the 'ecfga-base-address' property to
79 				 * the base_addr found in the MCFG and return.
80 				 */
81 				(void) ndi_prop_update_int64(DDI_DEV_T_NONE,
82 				    dip, "ecfga-base-address", ecfga_base);
83 				return;
84 			}
85 			cfg_baap++;
86 		}
87 	}
88 	/*
89 	 * If MCFG is not found or ecfga_base is not found in MCFG table,
90 	 * set the 'ecfga-base-address' property to the default value.
91 	 */
92 	(void) ndi_prop_update_int64(DDI_DEV_T_NONE, dip,
93 	    "ecfga-base-address", npe_default_ecfga_base);
94 }
95 
96 
97 /*
98  * Enable reporting of AER capability next pointer.
99  * This needs to be done only for CK8-04 devices
100  * by setting NV_XVR_VEND_CYA1 (offset 0xf40) bit 13
101  * NOTE: BIOS is disabling this, it needs to be enabled temporarily
102  */
103 void
104 npe_ck804_fix_aer_ptr(dev_info_t *child)
105 {
106 	ushort_t		cya1;
107 	ddi_acc_handle_t	config_handle;
108 
109 	if (pci_config_setup(child, &config_handle) != DDI_SUCCESS)
110 		return;
111 
112 	if ((pci_config_get16(config_handle, PCI_CONF_VENID) !=
113 	    NVIDIA_VENDOR_ID) && (pci_config_get16(config_handle,
114 	    PCI_CONF_DEVID) != NVIDIA_CK804_DEVICE_ID)) {
115 		pci_config_teardown(&config_handle);
116 		return;
117 	}
118 
119 	cya1 =  pci_config_get16(config_handle, NVIDIA_CK804_VEND_CYA1_OFF);
120 	if (!(cya1 & ~NVIDIA_CK804_VEND_CYA1_ERPT_MASK))
121 		(void) pci_config_put16(config_handle,
122 		    NVIDIA_CK804_VEND_CYA1_OFF,
123 		    cya1 | NVIDIA_CK804_VEND_CYA1_ERPT_VAL);
124 
125 	pci_config_teardown(&config_handle);
126 }
127 
128 
129 /*
130  * If the bridge is empty, disable it
131  */
132 int
133 npe_disable_empty_bridges_workaround(dev_info_t *child)
134 {
135 	/*
136 	 * Do not bind drivers to empty bridges.
137 	 * Fail above, if the bridge is found to be hotplug capable
138 	 */
139 	if (ddi_driver_major(child) == ddi_name_to_major("pcie_pci") &&
140 	    ddi_get_child(child) == NULL &&
141 	    ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS,
142 	    "pci-hotplug-type", INBAND_HPC_NONE) == INBAND_HPC_NONE)
143 		return (1);
144 
145 	return (0);
146 }
147