1 /* $OpenBSD: mainbus.c,v 1.62 2024/08/18 15:50:49 deraadt Exp $ */ 2 /* $NetBSD: mainbus.c,v 1.21 1997/06/06 23:14:20 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 1996 Christopher G. Demetriou. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Christopher G. Demetriou 18 * for the NetBSD Project. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/device.h> 37 38 #include <machine/bus.h> 39 #include <machine/specialreg.h> 40 41 #include <dev/isa/isavar.h> 42 #include <dev/eisa/eisavar.h> 43 #include <dev/pci/pcivar.h> 44 45 #include <dev/isa/isareg.h> /* for IOM_BEGIN */ 46 #include <i386/isa/isa_machdep.h> 47 48 #include "pci.h" 49 #include "eisa.h" 50 #include "isadma.h" 51 #include "bios.h" 52 #include "acpi.h" 53 #include "ipmi.h" 54 #include "esm.h" 55 #include "amdmsr.h" 56 #include "pvbus.h" 57 58 #include <machine/cpuvar.h> 59 #include <machine/i82093var.h> 60 61 #if NBIOS > 0 62 #include <machine/biosvar.h> 63 #endif 64 65 #include <dev/acpi/acpivar.h> 66 67 #if NIPMI > 0 68 #include <dev/ipmivar.h> 69 #endif 70 71 #if NPVBUS > 0 72 #include <dev/pv/pvvar.h> 73 #endif 74 75 #if NAMDMSR > 0 76 #include <machine/amdmsr.h> 77 #endif 78 79 #if NESM > 0 80 #include <arch/i386/i386/esmvar.h> 81 #endif 82 83 int mainbus_match(struct device *, void *, void *); 84 void mainbus_attach(struct device *, struct device *, void *); 85 86 const struct cfattach mainbus_ca = { 87 sizeof(struct device), mainbus_match, mainbus_attach 88 }; 89 90 struct cfdriver mainbus_cd = { 91 NULL, "mainbus", DV_DULL 92 }; 93 94 int mainbus_print(void *, const char *); 95 96 union mainbus_attach_args { 97 const char *mba_busname; /* first elem of all */ 98 struct pcibus_attach_args mba_pba; 99 struct eisabus_attach_args mba_eba; 100 struct isabus_attach_args mba_iba; 101 #if NBIOS > 0 102 struct bios_attach_args mba_bios; 103 #endif 104 struct cpu_attach_args mba_caa; 105 struct apic_attach_args aaa_caa; 106 #if NIPMI > 0 107 struct ipmi_attach_args mba_iaa; 108 #endif 109 #if NESM > 0 110 struct esm_attach_args mba_eaa; 111 #endif 112 #if NPVBUS > 0 113 struct pvbus_attach_args mba_pvba; 114 #endif 115 }; 116 117 /* 118 * This is set when the ISA bus is attached. If it's not set by the 119 * time it's checked below, then mainbus attempts to attach an ISA. 120 */ 121 int isa_has_been_seen; 122 123 /* 124 * Probe for the mainbus; always succeeds. 125 */ 126 int 127 mainbus_match(struct device *parent, void *match, void *aux) 128 { 129 return (1); 130 } 131 132 /* 133 * Attach the mainbus. 134 */ 135 void 136 mainbus_attach(struct device *parent, struct device *self, void *aux) 137 { 138 union mainbus_attach_args mba; 139 extern void (*setperf_setup)(struct cpu_info *); 140 extern void (*cpusensors_setup)(struct cpu_info *); 141 142 printf("\n"); 143 144 #if NPVBUS > 0 145 /* Detect hypervisors early, attach the paravirtual bus later */ 146 if (cpu_ecxfeature & CPUIDECX_HV) 147 pvbus_identify(); 148 #endif 149 150 #if NBIOS > 0 151 { 152 mba.mba_bios.ba_name = "bios"; 153 mba.mba_bios.ba_iot = I386_BUS_SPACE_IO; 154 mba.mba_bios.ba_memt = I386_BUS_SPACE_MEM; 155 config_found(self, &mba.mba_bios, mainbus_print); 156 } 157 #endif 158 159 #if NIPMI > 0 160 { 161 memset(&mba.mba_iaa, 0, sizeof(mba.mba_iaa)); 162 mba.mba_iaa.iaa_name = "ipmi"; 163 mba.mba_iaa.iaa_iot = I386_BUS_SPACE_IO; 164 mba.mba_iaa.iaa_memt = I386_BUS_SPACE_MEM; 165 if (ipmi_probe(&mba.mba_iaa)) 166 config_found(self, &mba.mba_iaa, mainbus_print); 167 } 168 #endif 169 170 if ((cpu_info_primary.ci_flags & CPUF_PRESENT) == 0) { 171 struct cpu_attach_args caa; 172 173 memset(&caa, 0, sizeof(caa)); 174 caa.caa_name = "cpu"; 175 caa.cpu_apicid = 0; 176 caa.cpu_role = CPU_ROLE_SP; 177 caa.cpu_func = 0; 178 caa.cpu_signature = cpu_id; 179 caa.feature_flags = cpu_feature; 180 181 config_found(self, &caa, mainbus_print); 182 } 183 #if NAMDMSR > 0 184 if (amdmsr_probe()) { 185 mba.mba_busname = "amdmsr"; 186 config_found(self, &mba.mba_busname, mainbus_print); 187 } 188 #endif 189 190 #if NACPI > 0 191 if (!acpi_hasprocfvs) 192 #endif 193 { 194 if (setperf_setup != NULL) 195 setperf_setup(&cpu_info_primary); 196 } 197 198 #ifdef MULTIPROCESSOR 199 mp_setperf_init(); 200 #endif 201 202 if (cpusensors_setup != NULL) 203 cpusensors_setup(&cpu_info_primary); 204 205 #if NESM > 0 206 { 207 memset(&mba.mba_eaa, 0, sizeof(mba.mba_eaa)); 208 mba.mba_eaa.eaa_name = "esm"; 209 mba.mba_eaa.eaa_iot = I386_BUS_SPACE_IO; 210 mba.mba_eaa.eaa_memt = I386_BUS_SPACE_MEM; 211 if (esm_probe(&mba.mba_eaa)) 212 config_found(self, &mba.mba_eaa, mainbus_print); 213 } 214 #endif 215 216 #if NPVBUS > 0 217 /* Probe first to hide the "not configured" message */ 218 if (pvbus_probe()) { 219 mba.mba_pvba.pvba_busname = "pvbus"; 220 config_found(self, &mba.mba_pvba.pvba_busname, mainbus_print); 221 } 222 #endif 223 224 /* 225 * XXX Note also that the presence of a PCI bus should 226 * XXX _always_ be checked, and if present the bus should be 227 * XXX 'found'. However, because of the structure of the code, 228 * XXX that's not currently possible. 229 */ 230 #if NPCI > 0 231 if (pci_mode_detect() != 0) { 232 pci_init_extents(); 233 234 bzero(&mba.mba_pba, sizeof(mba.mba_pba)); 235 mba.mba_pba.pba_busname = "pci"; 236 mba.mba_pba.pba_iot = I386_BUS_SPACE_IO; 237 mba.mba_pba.pba_memt = I386_BUS_SPACE_MEM; 238 mba.mba_pba.pba_dmat = &pci_bus_dma_tag; 239 mba.mba_pba.pba_ioex = pciio_ex; 240 mba.mba_pba.pba_memex = pcimem_ex; 241 mba.mba_pba.pba_busex = pcibus_ex; 242 mba.mba_pba.pba_domain = pci_ndomains++; 243 mba.mba_pba.pba_bus = 0; 244 config_found(self, &mba.mba_pba, mainbus_print); 245 #if NACPI > 0 246 acpi_pciroots_attach(self, &mba.mba_pba, mainbus_print); 247 #endif 248 } 249 #endif 250 251 if (!bcmp(ISA_HOLE_VADDR(EISA_ID_PADDR), EISA_ID, EISA_ID_LEN)) { 252 mba.mba_eba.eba_busname = "eisa"; 253 mba.mba_eba.eba_iot = I386_BUS_SPACE_IO; 254 mba.mba_eba.eba_memt = I386_BUS_SPACE_MEM; 255 #if NEISA > 0 256 mba.mba_eba.eba_dmat = &eisa_bus_dma_tag; 257 #endif 258 config_found(self, &mba.mba_eba, mainbus_print); 259 } 260 261 if (isa_has_been_seen == 0) { 262 mba.mba_iba.iba_busname = "isa"; 263 mba.mba_iba.iba_iot = I386_BUS_SPACE_IO; 264 mba.mba_iba.iba_memt = I386_BUS_SPACE_MEM; 265 #if NISADMA > 0 266 mba.mba_iba.iba_dmat = &isa_bus_dma_tag; 267 #endif 268 config_found(self, &mba.mba_iba, mainbus_print); 269 } 270 } 271 272 int 273 mainbus_print(void *aux, const char *pnp) 274 { 275 union mainbus_attach_args *mba = aux; 276 277 if (pnp) 278 printf("%s at %s", mba->mba_busname, pnp); 279 if (!strcmp(mba->mba_busname, "pci")) 280 printf(" bus %d", mba->mba_pba.pba_bus); 281 282 return (UNCONF); 283 } 284