1 /* $NetBSD: amd64_mainbus.c,v 1.13 2025/10/20 00:15:31 thorpej Exp $ */ 2 /* NetBSD: mainbus.c,v 1.39 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: amd64_mainbus.c,v 1.13 2025/10/20 00:15:31 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/pci/pcivar.h> 45 46 #include <dev/isa/isareg.h> 47 48 #include "pci.h" 49 #include "isa.h" 50 #include "isadma.h" 51 #include "acpica.h" 52 #include "ipmi.h" 53 #include "pv.h" 54 55 #include "opt_acpi.h" 56 #include "opt_mpbios.h" 57 #include "opt_pcifixup.h" 58 59 #include <machine/cpuvar.h> 60 #include <machine/i82093var.h> 61 #include <machine/mpbiosvar.h> 62 #include <machine/mpacpi.h> 63 64 #if NACPICA > 0 65 #include <dev/acpi/acpivar.h> 66 #endif 67 68 #if NIPMI > 0 69 #include <x86/ipmivar.h> 70 #endif 71 72 #if NPCI > 0 73 #if defined(PCI_BUS_FIXUP) 74 #include <arch/x86/pci/pci_bus_fixup.h> 75 #if defined(PCI_ADDR_FIXUP) 76 #include <arch/x86/pci/pci_addr_fixup.h> 77 #endif 78 #endif 79 #ifdef __HAVE_PCI_MSI_MSIX 80 #include <arch/x86/pci/msipic.h> 81 #endif /* __HAVE_PCI_MSI_MSIX */ 82 #endif 83 #if NPV > 0 84 #include <arch/x86/pv/pvvar.h> 85 #endif 86 87 /* 88 * XXXfvdl ACPI 89 */ 90 91 int amd64_mainbus_match(device_t, cfdata_t, void *); 92 void amd64_mainbus_attach(device_t, device_t, void *); 93 94 union amd64_mainbus_attach_args { 95 struct pcibus_attach_args mba_pba; 96 struct isabus_attach_args mba_iba; 97 struct cpu_attach_args mba_caa; 98 #if NACPICA > 0 99 struct acpibus_attach_args mba_acpi; 100 #endif 101 struct apic_attach_args aaa_caa; 102 #if NIPMI > 0 103 struct ipmi_attach_args mba_ipmi; 104 #endif 105 #if NPV > 0 106 struct pvbus_attach_args mba_pvba; 107 #endif 108 }; 109 110 /* 111 * This is set when the ISA bus is attached. If it's not set by the 112 * time it's checked below, then mainbus attempts to attach an ISA. 113 */ 114 int isa_has_been_seen; 115 struct x86_isa_chipset x86_isa_chipset; 116 #if NISA > 0 117 static const struct isabus_attach_args mba_iba = { 118 ._iba_busname = "isa", 119 .iba_dmat = &isa_bus_dma_tag, 120 .iba_ic = &x86_isa_chipset 121 }; 122 #endif 123 124 #if defined(MPBIOS) || NACPICA > 0 125 struct mp_bus *mp_busses; 126 int mp_nbus; 127 struct mp_intr_map *mp_intrs; 128 int mp_nintr; 129 130 int mp_isa_bus = -1; 131 int mp_eisa_bus = -1; 132 133 extern bool acpi_present; 134 extern bool mpacpi_active; 135 136 # ifdef MPVERBOSE 137 # if MPVERBOSE > 0 138 int mp_verbose = MPVERBOSE; 139 # else 140 int mp_verbose = 1; 141 # endif 142 # else 143 int mp_verbose = 0; 144 # endif 145 #endif 146 147 /* 148 * Probe for the mainbus; always succeeds. 149 */ 150 int 151 amd64_mainbus_match(device_t parent, cfdata_t match, void *aux) 152 { 153 154 return 1; 155 } 156 157 /* 158 * Attach the mainbus. 159 */ 160 void 161 amd64_mainbus_attach(device_t parent, device_t self, void *aux) 162 { 163 #if NISA > 0 || NPCI > 0 || NACPICA > 0 || NIPMI > 0 || NPV > 0 164 union amd64_mainbus_attach_args mba; 165 #endif 166 167 #if NISADMA > 0 && NACPICA > 0 168 /* 169 * ACPI needs ISA DMA initialized before they start probing. 170 */ 171 isa_dmainit(&x86_isa_chipset, x86_bus_space_io, &isa_bus_dma_tag, 172 self); 173 #endif 174 175 #if NACPICA > 0 176 if (acpi_present) { 177 mba.mba_acpi.aa_iot = x86_bus_space_io; 178 mba.mba_acpi.aa_memt = x86_bus_space_mem; 179 mba.mba_acpi.aa_pc = NULL; 180 mba.mba_acpi.aa_pciflags = 181 PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY | 182 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | 183 PCI_FLAGS_MWI_OKAY; 184 mba.mba_acpi.aa_ic = &x86_isa_chipset; 185 mba.mba_acpi.aa_dmat = &pci_bus_dma_tag; 186 mba.mba_acpi.aa_dmat64 = &pci_bus_dma64_tag; 187 config_found(self, &mba.mba_acpi, NULL, 188 CFARGS(.iattr = "acpibus")); 189 } 190 #endif 191 192 #if NIPMI > 0 193 memset(&mba.mba_ipmi, 0, sizeof(mba.mba_ipmi)); 194 mba.mba_ipmi.iaa_iot = x86_bus_space_io; 195 mba.mba_ipmi.iaa_memt = x86_bus_space_mem; 196 if (ipmi_probe(&mba.mba_ipmi)) 197 config_found(self, &mba.mba_ipmi, NULL, 198 CFARGS(.iattr = "ipmibus")); 199 #endif 200 201 #if NPCI > 0 202 if (pci_mode_detect() != 0) { 203 int npcibus = 0; 204 205 mba.mba_pba.pba_iot = x86_bus_space_io; 206 mba.mba_pba.pba_memt = x86_bus_space_mem; 207 mba.mba_pba.pba_dmat = &pci_bus_dma_tag; 208 mba.mba_pba.pba_dmat64 = &pci_bus_dma64_tag; 209 mba.mba_pba.pba_pc = NULL; 210 mba.mba_pba.pba_flags = 211 PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY | 212 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | 213 PCI_FLAGS_MWI_OKAY; 214 mba.mba_pba.pba_bus = 0; 215 mba.mba_pba.pba_bridgetag = NULL; 216 #if NACPICA > 0 && defined(ACPI_SCANPCI) 217 if (npcibus == 0 && mpacpi_active) 218 npcibus = mp_pci_scan(self, &mba.mba_pba, pcibusprint); 219 #endif 220 #if defined(MPBIOS) && defined(MPBIOS_SCANPCI) 221 if (npcibus == 0 && mpbios_scanned != 0) 222 npcibus = mp_pci_scan(self, &mba.mba_pba, pcibusprint); 223 #endif 224 if (npcibus == 0) 225 config_found(self, &mba.mba_pba, pcibusprint, 226 CFARGS(.iattr = "pcibus")); 227 228 #if NACPICA > 0 229 if (mp_verbose) 230 acpi_pci_link_state(); 231 #endif 232 } 233 #endif 234 235 #if NISA > 0 236 if (isa_has_been_seen == 0) { 237 mba.mba_iba = mba_iba; 238 mba.mba_iba.iba_iot = x86_bus_space_io; 239 mba.mba_iba.iba_memt = x86_bus_space_mem; 240 isabus_attach(self, &mba.mba_iba); 241 } 242 #endif 243 244 #if NPV > 0 245 /* add here more VM guests types that would benefit from a pv bus */ 246 switch(vm_guest) { 247 /* FALLTHROUGH */ 248 case VM_GUEST_GENPVH: 249 case VM_GUEST_KVM: 250 case VM_GUEST_NVMM: 251 mba.mba_pvba.pvba_busname = "pvbus"; 252 config_found(self, &mba.mba_pvba.pvba_busname, NULL, 253 CFARGS(.iattr = "pvbus")); 254 break; 255 default: 256 break; 257 } 258 #endif 259 260 if (!pmf_device_register(self, NULL, NULL)) 261 aprint_error_dev(self, "couldn't establish power handler\n"); 262 } 263