1 /* $NetBSD: i386_mainbus.c,v 1.10 2025/07/08 11:06:13 imil 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.10 2025/07/08 11:06:13 imil 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 config_found(self, &mba.mba_eba, eisabusprint, 237 CFARGS(.iattr = "eisabus")); 238 } 239 240 #if NISA > 0 241 if (isa_has_been_seen == 0) { 242 mba.mba_iba = mba_iba; 243 mba.mba_iba.iba_iot = x86_bus_space_io; 244 mba.mba_iba.iba_memt = x86_bus_space_mem; 245 config_found(self, &mba.mba_iba, isabusprint, 246 CFARGS(.iattr = "isabus")); 247 } 248 #endif 249 250 #if NPV > 0 251 /* add here more VM guests types that would benefit from a pv bus */ 252 switch(vm_guest) { 253 /* FALLTHROUGH */ 254 case VM_GUEST_GENPVH: 255 case VM_GUEST_KVM: 256 case VM_GUEST_NVMM: 257 mba.mba_pvba.pvba_busname = "pvbus"; 258 config_found(self, &mba.mba_pvba.pvba_busname, NULL, 259 CFARGS(.iattr = "pvbus")); 260 break; 261 default: 262 break; 263 } 264 #endif 265 if (!pmf_device_register(self, NULL, NULL)) 266 aprint_error_dev(self, "couldn't establish power handler\n"); 267 } 268 269 /* scan for new children */ 270 int 271 i386_mainbus_rescan(device_t self, const char *ifattr, const int *locators) 272 { 273 struct mainbus_softc *sc = device_private(self); 274 #if NACPICA > 0 || NIPMI > 0 || NMCA > 0 || NPCI > 0 || NPNPBIOS > 0 275 union i386_mainbus_attach_args mba; 276 #endif 277 278 if (ifattr_match(ifattr, "acpibus") && sc->sc_acpi == NULL && 279 acpi_present) { 280 #if NACPICA > 0 281 mba.mba_acpi.aa_iot = x86_bus_space_io; 282 mba.mba_acpi.aa_memt = x86_bus_space_mem; 283 mba.mba_acpi.aa_pc = NULL; 284 mba.mba_acpi.aa_pciflags = 285 PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY | 286 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | 287 PCI_FLAGS_MWI_OKAY; 288 mba.mba_acpi.aa_ic = &x86_isa_chipset; 289 mba.mba_acpi.aa_dmat = &pci_bus_dma_tag; 290 mba.mba_acpi.aa_dmat64 = NULL; 291 sc->sc_acpi = config_found(self, &mba.mba_acpi, NULL, 292 CFARGS(.iattr = "acpibus")); 293 #if 0 /* XXXJRT not yet */ 294 if (acpi_active) { 295 /* 296 * ACPI already did all the work for us, there 297 * is nothing more for us to do. 298 */ 299 return; 300 } 301 #endif 302 #endif 303 } 304 305 if (ifattr_match(ifattr, "pnpbiosbus") && sc->sc_pnpbios == NULL) { 306 #if NPNPBIOS > 0 307 #if NACPICA > 0 308 if (acpi_active == 0) 309 #endif 310 if (pnpbios_probe()) { 311 mba.mba_paa.paa_ic = &x86_isa_chipset; 312 sc->sc_pnpbios = config_found(self, &mba.mba_paa, NULL, 313 CFARGS(.iattr = "pnpbiosbus")); 314 } 315 #endif 316 } 317 318 if (ifattr_match(ifattr, "ipmibus") && sc->sc_ipmi == NULL) { 319 #if NIPMI > 0 320 memset(&mba.mba_ipmi, 0, sizeof(mba.mba_ipmi)); 321 mba.mba_ipmi.iaa_iot = x86_bus_space_io; 322 mba.mba_ipmi.iaa_memt = x86_bus_space_mem; 323 if (ipmi_probe(&mba.mba_ipmi)) { 324 sc->sc_ipmi = config_found(self, &mba.mba_ipmi, NULL, 325 CFARGS(.iattr = "ipmibus")); 326 } 327 #endif 328 } 329 330 /* 331 * XXX Note also that the presence of a PCI bus should 332 * XXX _always_ be checked, and if present the bus should be 333 * XXX 'found'. However, because of the structure of the code, 334 * XXX that's not currently possible. 335 */ 336 #if NPCI > 0 337 if (pci_mode_detect() != 0 && ifattr_match(ifattr, "pcibus")) { 338 int npcibus = 0; 339 340 mba.mba_pba.pba_iot = x86_bus_space_io; 341 mba.mba_pba.pba_memt = x86_bus_space_mem; 342 mba.mba_pba.pba_dmat = &pci_bus_dma_tag; 343 mba.mba_pba.pba_dmat64 = NULL; 344 mba.mba_pba.pba_pc = NULL; 345 mba.mba_pba.pba_flags = 346 PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY | 347 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | 348 PCI_FLAGS_MWI_OKAY; 349 mba.mba_pba.pba_bus = 0; 350 /* XXX On those machines with >1 Host-PCI bridge, 351 * XXX not every bus > pba_bus is subordinate to pba_bus, 352 * XXX but this works on many machines, and pba_sub is 353 * XXX not used today by any critical code, so it is safe 354 * XXX to be so inclusive at this time. 355 */ 356 mba.mba_pba.pba_sub = 255; 357 mba.mba_pba.pba_bridgetag = NULL; 358 #if NACPICA > 0 && defined(ACPI_SCANPCI) 359 if (npcibus == 0 && mpacpi_active) 360 npcibus = mp_pci_scan(self, &mba.mba_pba, pcibusprint); 361 #endif 362 #if defined(MPBIOS) && defined(MPBIOS_SCANPCI) 363 if (npcibus == 0 && mpbios_scanned != 0) 364 npcibus = mp_pci_scan(self, &mba.mba_pba, pcibusprint); 365 #endif 366 if (npcibus == 0 && sc->sc_pci == NULL) { 367 sc->sc_pci = 368 config_found(self, &mba.mba_pba, pcibusprint, 369 CFARGS(.iattr = "pcibus")); 370 } 371 #if NACPICA > 0 372 if (mp_verbose) 373 acpi_pci_link_state(); 374 #endif 375 } 376 #endif 377 378 379 if (ifattr_match(ifattr, "mcabus") && sc->sc_mca == NULL) { 380 #if NMCA > 0 381 /* Note: MCA bus probe is done in i386/machdep.c */ 382 if (MCA_system) { 383 mba.mba_mba.mba_iot = x86_bus_space_io; 384 mba.mba_mba.mba_memt = x86_bus_space_mem; 385 mba.mba_mba.mba_dmat = &mca_bus_dma_tag; 386 mba.mba_mba.mba_mc = NULL; 387 mba.mba_mba.mba_bus = 0; 388 sc->sc_mca = config_found(self, 389 &mba.mba_mba, mcabusprint, 390 CFARGS(.iattr = "mcabus")); 391 } 392 #endif 393 } 394 return 0; 395 } 396 397