1 /* $NetBSD: i386_mainbus.c,v 1.13 2025/10/20 00:14:22 thorpej Exp $ */ 2 /* NetBSD: mainbus.c,v 1.104 2018/12/02 08:19:44 cherry 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/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: i386_mainbus.c,v 1.13 2025/10/20 00:14:22 thorpej Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/systm.h> 39 #include <sys/device.h> 40 #include <sys/reboot.h> 41 #include <sys/bus.h> 42 43 #include <dev/isa/isavar.h> 44 #include <dev/eisa/eisavar.h> 45 #include <dev/pci/pcivar.h> 46 47 #include <dev/isa/isareg.h> /* for ISA_HOLE_VADDR */ 48 49 #include "pci.h" 50 #include "eisa.h" 51 #include "isa.h" 52 #include "isadma.h" 53 #include "mca.h" 54 #include "pnpbios.h" 55 #include "acpica.h" 56 #include "ipmi.h" 57 #include "pv.h" 58 59 #include "opt_acpi.h" 60 #include "opt_mpbios.h" 61 #include "opt_pcifixup.h" 62 63 #include <machine/cpuvar.h> 64 #include <machine/i82093var.h> 65 #include <machine/mpbiosvar.h> 66 #include <machine/mpacpi.h> 67 68 #if NPNPBIOS > 0 69 #include <arch/i386/pnpbios/pnpbiosvar.h> 70 #endif 71 72 #if NACPICA > 0 73 #include <dev/acpi/acpivar.h> 74 #endif 75 76 #if NMCA > 0 77 #include <dev/mca/mcavar.h> 78 #endif 79 80 #include <x86/autoconf.h> 81 82 #if NIPMI > 0 83 #include <x86/ipmivar.h> 84 #endif 85 86 #if NPCI > 0 87 #if defined(PCI_BUS_FIXUP) 88 #include <arch/x86/pci/pci_bus_fixup.h> 89 #if defined(PCI_ADDR_FIXUP) 90 #include <arch/x86/pci/pci_addr_fixup.h> 91 #endif /* PCI_ADDR_FIXUP */ 92 #endif /* PCI_BUS_FIXUP */ 93 #endif /* NPCI > 0 */ 94 #if NPV > 0 95 #include <arch/x86/pv/pvvar.h> 96 #endif 97 98 void i386_mainbus_childdetached(device_t, device_t); 99 int i386_mainbus_match(device_t, cfdata_t, void *); 100 void i386_mainbus_attach(device_t, device_t, void *); 101 int i386_mainbus_rescan(device_t, const char *, const int *); 102 103 union i386_mainbus_attach_args { 104 const char *mba_busname; /* first elem of all */ 105 struct pcibus_attach_args mba_pba; 106 struct eisabus_attach_args mba_eba; 107 struct isabus_attach_args mba_iba; 108 #if NMCA > 0 109 struct mcabus_attach_args mba_mba; 110 #endif 111 #if NPNPBIOS > 0 112 struct pnpbios_attach_args mba_paa; 113 #endif 114 struct cpu_attach_args mba_caa; 115 struct apic_attach_args aaa_caa; 116 #if NACPICA > 0 117 struct acpibus_attach_args mba_acpi; 118 #endif 119 #if NIPMI > 0 120 struct ipmi_attach_args mba_ipmi; 121 #endif 122 #if NPV > 0 123 struct pvbus_attach_args mba_pvba; 124 #endif 125 }; 126 127 /* 128 * This is set when the ISA bus is attached. If it's not set by the 129 * time it's checked below, then mainbus attempts to attach an ISA. 130 */ 131 int isa_has_been_seen; 132 struct x86_isa_chipset x86_isa_chipset; 133 #if NISA > 0 134 static const struct isabus_attach_args mba_iba = { 135 ._iba_busname = "isa", 136 .iba_dmat = &isa_bus_dma_tag, 137 .iba_ic = &x86_isa_chipset 138 }; 139 #endif 140 141 /* 142 * Same as above, but for EISA. 143 */ 144 int eisa_has_been_seen; 145 146 #if defined(MPBIOS) || NACPICA > 0 147 struct mp_bus *mp_busses; 148 int mp_nbus; 149 struct mp_intr_map *mp_intrs; 150 int mp_nintr; 151 152 int mp_isa_bus = -1; /* XXX */ 153 int mp_eisa_bus = -1; /* XXX */ 154 155 extern bool acpi_present; 156 extern bool mpacpi_active; 157 158 # ifdef MPVERBOSE 159 # if MPVERBOSE > 0 160 int mp_verbose = MPVERBOSE; 161 # else 162 int mp_verbose = 1; 163 # endif 164 # else 165 int mp_verbose = 0; 166 # endif 167 #endif 168 169 void 170 i386_mainbus_childdetached(device_t self, device_t child) 171 { 172 struct mainbus_softc *sc = device_private(self); 173 174 if (sc->sc_acpi == child) 175 sc->sc_acpi = NULL; 176 if (sc->sc_ipmi == child) 177 sc->sc_ipmi = NULL; 178 if (sc->sc_mca == child) 179 sc->sc_mca = NULL; 180 if (sc->sc_pnpbios == child) 181 sc->sc_pnpbios = NULL; 182 if (sc->sc_pci == child) 183 sc->sc_pci = NULL; 184 185 #if NPCI > 0 && (defined(MPBIOS) || NACPICA > 0) 186 mp_pci_childdetached(self, child); 187 #endif 188 } 189 190 /* 191 * Probe for the mainbus; always succeeds. 192 */ 193 int 194 i386_mainbus_match(device_t parent, cfdata_t match, void *aux) 195 { 196 197 return 1; 198 } 199 200 /* 201 * Attach the mainbus. 202 */ 203 void 204 i386_mainbus_attach(device_t parent, device_t self, void *aux) 205 { 206 struct mainbus_softc *sc = device_private(self); 207 union i386_mainbus_attach_args mba; 208 209 sc->sc_dev = self; 210 211 #if NISADMA > 0 && (NACPICA > 0 || NPNPBIOS > 0) 212 /* 213 * ACPI and PNPBIOS need ISA DMA initialized before they start probing. 214 */ 215 isa_dmainit(&x86_isa_chipset, x86_bus_space_io, &isa_bus_dma_tag, 216 self); 217 #endif 218 219 i386_mainbus_rescan(self, "acpibus", NULL); 220 221 i386_mainbus_rescan(self, "pnpbiosbus", NULL); 222 223 i386_mainbus_rescan(self, "ipmibus", NULL); 224 225 i386_mainbus_rescan(self, "pcibus", NULL); 226 227 i386_mainbus_rescan(self, "mcabus", NULL); 228 229 if (memcmp(ISA_HOLE_VADDR(EISA_ID_PADDR), EISA_ID, EISA_ID_LEN) == 0 && 230 eisa_has_been_seen == 0) { 231 mba.mba_eba.eba_iot = x86_bus_space_io; 232 mba.mba_eba.eba_memt = x86_bus_space_mem; 233 #if NEISA > 0 234 mba.mba_eba.eba_dmat = &eisa_bus_dma_tag; 235 #endif 236 eisabus_attach(self, &mba.mba_eba); 237 } 238 239 #if NISA > 0 240 if (isa_has_been_seen == 0) { 241 mba.mba_iba = mba_iba; 242 mba.mba_iba.iba_iot = x86_bus_space_io; 243 mba.mba_iba.iba_memt = x86_bus_space_mem; 244 isabus_attach(self, &mba.mba_iba); 245 } 246 #endif 247 248 #if NPV > 0 249 /* add here more VM guests types that would benefit from a pv bus */ 250 switch(vm_guest) { 251 /* FALLTHROUGH */ 252 case VM_GUEST_GENPVH: 253 case VM_GUEST_KVM: 254 case VM_GUEST_NVMM: 255 mba.mba_pvba.pvba_busname = "pvbus"; 256 config_found(self, &mba.mba_pvba.pvba_busname, NULL, 257 CFARGS(.iattr = "pvbus")); 258 break; 259 default: 260 break; 261 } 262 #endif 263 if (!pmf_device_register(self, NULL, NULL)) 264 aprint_error_dev(self, "couldn't establish power handler\n"); 265 } 266 267 /* scan for new children */ 268 int 269 i386_mainbus_rescan(device_t self, const char *ifattr, const int *locators) 270 { 271 struct mainbus_softc *sc = device_private(self); 272 #if NACPICA > 0 || NIPMI > 0 || NMCA > 0 || NPCI > 0 || NPNPBIOS > 0 273 union i386_mainbus_attach_args mba; 274 #endif 275 276 if (ifattr_match(ifattr, "acpibus") && sc->sc_acpi == NULL && 277 acpi_present) { 278 #if NACPICA > 0 279 mba.mba_acpi.aa_iot = x86_bus_space_io; 280 mba.mba_acpi.aa_memt = x86_bus_space_mem; 281 mba.mba_acpi.aa_pc = NULL; 282 mba.mba_acpi.aa_pciflags = 283 PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY | 284 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | 285 PCI_FLAGS_MWI_OKAY; 286 mba.mba_acpi.aa_ic = &x86_isa_chipset; 287 mba.mba_acpi.aa_dmat = &pci_bus_dma_tag; 288 mba.mba_acpi.aa_dmat64 = NULL; 289 sc->sc_acpi = config_found(self, &mba.mba_acpi, NULL, 290 CFARGS(.iattr = "acpibus")); 291 #if 0 /* XXXJRT not yet */ 292 if (acpi_active) { 293 /* 294 * ACPI already did all the work for us, there 295 * is nothing more for us to do. 296 */ 297 return; 298 } 299 #endif 300 #endif 301 } 302 303 if (ifattr_match(ifattr, "pnpbiosbus") && sc->sc_pnpbios == NULL) { 304 #if NPNPBIOS > 0 305 #if NACPICA > 0 306 if (acpi_active == 0) 307 #endif 308 if (pnpbios_probe()) { 309 mba.mba_paa.paa_ic = &x86_isa_chipset; 310 sc->sc_pnpbios = config_found(self, &mba.mba_paa, NULL, 311 CFARGS(.iattr = "pnpbiosbus")); 312 } 313 #endif 314 } 315 316 if (ifattr_match(ifattr, "ipmibus") && sc->sc_ipmi == NULL) { 317 #if NIPMI > 0 318 memset(&mba.mba_ipmi, 0, sizeof(mba.mba_ipmi)); 319 mba.mba_ipmi.iaa_iot = x86_bus_space_io; 320 mba.mba_ipmi.iaa_memt = x86_bus_space_mem; 321 if (ipmi_probe(&mba.mba_ipmi)) { 322 sc->sc_ipmi = config_found(self, &mba.mba_ipmi, NULL, 323 CFARGS(.iattr = "ipmibus")); 324 } 325 #endif 326 } 327 328 /* 329 * XXX Note also that the presence of a PCI bus should 330 * XXX _always_ be checked, and if present the bus should be 331 * XXX 'found'. However, because of the structure of the code, 332 * XXX that's not currently possible. 333 */ 334 #if NPCI > 0 335 if (pci_mode_detect() != 0 && ifattr_match(ifattr, "pcibus")) { 336 int npcibus = 0; 337 338 mba.mba_pba.pba_iot = x86_bus_space_io; 339 mba.mba_pba.pba_memt = x86_bus_space_mem; 340 mba.mba_pba.pba_dmat = &pci_bus_dma_tag; 341 mba.mba_pba.pba_dmat64 = NULL; 342 mba.mba_pba.pba_pc = NULL; 343 mba.mba_pba.pba_flags = 344 PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY | 345 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | 346 PCI_FLAGS_MWI_OKAY; 347 mba.mba_pba.pba_bus = 0; 348 /* XXX On those machines with >1 Host-PCI bridge, 349 * XXX not every bus > pba_bus is subordinate to pba_bus, 350 * XXX but this works on many machines, and pba_sub is 351 * XXX not used today by any critical code, so it is safe 352 * XXX to be so inclusive at this time. 353 */ 354 mba.mba_pba.pba_sub = 255; 355 mba.mba_pba.pba_bridgetag = NULL; 356 #if NACPICA > 0 && defined(ACPI_SCANPCI) 357 if (npcibus == 0 && mpacpi_active) 358 npcibus = mp_pci_scan(self, &mba.mba_pba, pcibusprint); 359 #endif 360 #if defined(MPBIOS) && defined(MPBIOS_SCANPCI) 361 if (npcibus == 0 && mpbios_scanned != 0) 362 npcibus = mp_pci_scan(self, &mba.mba_pba, pcibusprint); 363 #endif 364 if (npcibus == 0 && sc->sc_pci == NULL) { 365 sc->sc_pci = 366 config_found(self, &mba.mba_pba, pcibusprint, 367 CFARGS(.iattr = "pcibus")); 368 } 369 #if NACPICA > 0 370 if (mp_verbose) 371 acpi_pci_link_state(); 372 #endif 373 } 374 #endif 375 376 377 if (ifattr_match(ifattr, "mcabus") && sc->sc_mca == NULL) { 378 #if NMCA > 0 379 /* Note: MCA bus probe is done in i386/machdep.c */ 380 if (MCA_system) { 381 mba.mba_mba.mba_iot = x86_bus_space_io; 382 mba.mba_mba.mba_memt = x86_bus_space_mem; 383 mba.mba_mba.mba_dmat = &mca_bus_dma_tag; 384 mba.mba_mba.mba_mc = NULL; 385 mba.mba_mba.mba_bus = 0; 386 sc->sc_mca = mcabus_attach(self, &mba.mba_mba); 387 } 388 #endif 389 } 390 return 0; 391 } 392 393