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 2005 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 * PCI configuration space access routines 31 */ 32 33 #include <sys/systm.h> 34 #include <sys/psw.h> 35 #include <sys/bootconf.h> 36 #include <sys/reboot.h> 37 #include <sys/pci_impl.h> 38 #include <sys/pci_cfgspace.h> 39 #include <sys/pci_cfgspace_impl.h> 40 41 int pci_bios_cfg_type = PCI_MECHANISM_UNKNOWN; 42 int pci_bios_nbus; 43 int pci_bios_mech; 44 int pci_bios_vers; 45 46 /* 47 * These two variables can be used to force a configuration mechanism or 48 * to force which function is used to probe for the presence of the PCI bus. 49 */ 50 int PCI_CFG_TYPE = 0; 51 int PCI_PROBE_TYPE = 0; 52 53 /* 54 * These function pointers lead to the actual implementation routines 55 * for configuration space access. Normally they lead to either the 56 * pci_mech1_* or pci_mech2_* routines, but they can also lead to 57 * routines that work around chipset bugs. 58 */ 59 uint8_t (*pci_getb_func)(int bus, int dev, int func, int reg); 60 uint16_t (*pci_getw_func)(int bus, int dev, int func, int reg); 61 uint32_t (*pci_getl_func)(int bus, int dev, int func, int reg); 62 void (*pci_putb_func)(int bus, int dev, int func, int reg, uint8_t val); 63 void (*pci_putw_func)(int bus, int dev, int func, int reg, uint16_t val); 64 void (*pci_putl_func)(int bus, int dev, int func, int reg, uint32_t val); 65 66 /* 67 * Internal routines 68 */ 69 static int pci_check(void); 70 static int pci_check_bios(void); 71 static int pci_get_cfg_type(void); 72 73 /* all config-space access routines share this one... */ 74 kmutex_t pcicfg_mutex; 75 76 /* ..except Orion and Neptune, which have to have their own */ 77 kmutex_t pcicfg_chipset_mutex; 78 79 void 80 pci_cfgspace_init(void) 81 { 82 mutex_init(&pcicfg_mutex, NULL, MUTEX_DEFAULT, 0); 83 mutex_init(&pcicfg_chipset_mutex, NULL, MUTEX_DEFAULT, 0); 84 if (!pci_check()) { 85 mutex_destroy(&pcicfg_mutex); 86 mutex_destroy(&pcicfg_chipset_mutex); 87 } 88 } 89 90 /* 91 * This code determines if this system supports PCI and which 92 * type of configuration access method is used 93 */ 94 95 static int 96 pci_check(void) 97 { 98 /* 99 * Only do this once. NB: If this is not a PCI system, and we 100 * get called twice, we can't detect it and will probably die 101 * horribly when we try to ask the BIOS whether PCI is present. 102 * This code is safe *ONLY* during system startup when the 103 * BIOS is still available. 104 */ 105 if (pci_bios_cfg_type != PCI_MECHANISM_UNKNOWN) 106 return (TRUE); 107 108 pci_bios_cfg_type = pci_check_bios(); 109 110 if (pci_bios_cfg_type == PCI_MECHANISM_NONE) 111 return (FALSE); 112 113 switch (pci_get_cfg_type()) { 114 case PCI_MECHANISM_1: 115 if (pci_is_broken_orion()) { 116 pci_getb_func = pci_orion_getb; 117 pci_getw_func = pci_orion_getw; 118 pci_getl_func = pci_orion_getl; 119 pci_putb_func = pci_orion_putb; 120 pci_putw_func = pci_orion_putw; 121 pci_putl_func = pci_orion_putl; 122 } else { 123 pci_getb_func = pci_mech1_getb; 124 pci_getw_func = pci_mech1_getw; 125 pci_getl_func = pci_mech1_getl; 126 pci_putb_func = pci_mech1_putb; 127 pci_putw_func = pci_mech1_putw; 128 pci_putl_func = pci_mech1_putl; 129 } 130 break; 131 132 case PCI_MECHANISM_2: 133 if (pci_check_neptune()) { 134 /* 135 * The BIOS for some systems with the Intel 136 * Neptune chipset seem to default to #2 even 137 * though the chipset can do #1. Override 138 * the BIOS so that MP systems will work 139 * correctly. 140 */ 141 142 pci_getb_func = pci_neptune_getb; 143 pci_getw_func = pci_neptune_getw; 144 pci_getl_func = pci_neptune_getl; 145 pci_putb_func = pci_neptune_putb; 146 pci_putw_func = pci_neptune_putw; 147 pci_putl_func = pci_neptune_putl; 148 } else { 149 pci_getb_func = pci_mech2_getb; 150 pci_getw_func = pci_mech2_getw; 151 pci_getl_func = pci_mech2_getl; 152 pci_putb_func = pci_mech2_putb; 153 pci_putw_func = pci_mech2_putw; 154 pci_putl_func = pci_mech2_putl; 155 } 156 break; 157 158 default: 159 return (FALSE); 160 } 161 162 return (TRUE); 163 } 164 165 166 static int 167 pci_check_bios(void) 168 { 169 struct bop_regs regs; 170 uint32_t carryflag; 171 uint16_t ax, dx; 172 173 bzero(®s, sizeof (regs)); 174 regs.eax.word.ax = (PCI_FUNCTION_ID << 8) | PCI_BIOS_PRESENT; 175 176 BOP_DOINT(bootops, 0x1a, ®s); 177 carryflag = regs.eflags & PS_C; 178 ax = regs.eax.word.ax; 179 dx = regs.edx.word.dx; 180 181 /* the carry flag must not be set */ 182 if (carryflag != 0) 183 return (PCI_MECHANISM_NONE); 184 185 if (dx != ('P' | 'C'<<8)) 186 return (PCI_MECHANISM_NONE); 187 188 /* ah (the high byte of ax) must be zero */ 189 if ((ax & 0xff00) != 0) 190 return (PCI_MECHANISM_NONE); 191 192 pci_bios_mech = (ax & 0x3); 193 pci_bios_vers = regs.ebx.word.bx; 194 pci_bios_nbus = (regs.ecx.word.cx & 0xff); 195 196 switch (pci_bios_mech) { 197 default: /* ?!? */ 198 case 0: /* supports neither? */ 199 return (PCI_MECHANISM_NONE); 200 201 case 1: 202 case 3: /* supports both */ 203 return (PCI_MECHANISM_1); 204 205 case 2: 206 return (PCI_MECHANISM_2); 207 } 208 } 209 210 static int 211 pci_get_cfg_type(void) 212 { 213 /* Check to see if the config mechanism has been set in /etc/system */ 214 switch (PCI_CFG_TYPE) { 215 default: 216 case 0: 217 break; 218 case 1: 219 return (PCI_MECHANISM_1); 220 case 2: 221 return (PCI_MECHANISM_2); 222 case -1: 223 return (PCI_MECHANISM_NONE); 224 } 225 226 /* call one of the PCI detection algorithms */ 227 switch (PCI_PROBE_TYPE) { 228 default: 229 case 0: 230 /* From pci_check() and pci_check_bios() */ 231 return (pci_bios_cfg_type); 232 case -1: 233 return (PCI_MECHANISM_NONE); 234 } 235 } 236