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