1 /* $NetBSD: amd64_mainbus.c,v 1.8 2025/01/02 10:34:33 imil 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.8 2025/01/02 10:34:33 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/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 "pvbus.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 NPVBUS > 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 int amd64_mainbus_print(void *, const char *); 94 95 union amd64_mainbus_attach_args { 96 const char *mba_busname; /* first elem of all */ 97 struct pcibus_attach_args mba_pba; 98 struct isabus_attach_args mba_iba; 99 struct cpu_attach_args mba_caa; 100 #if NACPICA > 0 101 struct acpibus_attach_args mba_acpi; 102 #endif 103 struct apic_attach_args aaa_caa; 104 #if NIPMI > 0 105 struct ipmi_attach_args mba_ipmi; 106 #endif 107 #if NPVBUS > 0 108 struct pvbus_attach_args mba_pvba; 109 #endif 110 }; 111 112 /* 113 * This is set when the ISA bus is attached. If it's not set by the 114 * time it's checked below, then mainbus attempts to attach an ISA. 115 */ 116 int isa_has_been_seen; 117 struct x86_isa_chipset x86_isa_chipset; 118 #if NISA > 0 119 static const struct isabus_attach_args mba_iba = { 120 ._iba_busname = "isa", 121 .iba_dmat = &isa_bus_dma_tag, 122 .iba_ic = &x86_isa_chipset 123 }; 124 #endif 125 126 #if defined(MPBIOS) || NACPICA > 0 127 struct mp_bus *mp_busses; 128 int mp_nbus; 129 struct mp_intr_map *mp_intrs; 130 int mp_nintr; 131 132 int mp_isa_bus = -1; 133 int mp_eisa_bus = -1; 134 135 extern bool acpi_present; 136 extern bool mpacpi_active; 137 138 # ifdef MPVERBOSE 139 # if MPVERBOSE > 0 140 int mp_verbose = MPVERBOSE; 141 # else 142 int mp_verbose = 1; 143 # endif 144 # else 145 int mp_verbose = 0; 146 # endif 147 #endif 148 149 /* 150 * Probe for the mainbus; always succeeds. 151 */ 152 int 153 amd64_mainbus_match(device_t parent, cfdata_t match, void *aux) 154 { 155 156 return 1; 157 } 158 159 /* 160 * Attach the mainbus. 161 */ 162 void 163 amd64_mainbus_attach(device_t parent, device_t self, void *aux) 164 { 165 #if NISA > 0 || NPCI > 0 || NACPICA > 0 || NIPMI > 0 || NPVBUS > 0 166 union amd64_mainbus_attach_args mba; 167 #endif 168 169 #if NISADMA > 0 && NACPICA > 0 170 /* 171 * ACPI needs ISA DMA initialized before they start probing. 172 */ 173 isa_dmainit(&x86_isa_chipset, x86_bus_space_io, &isa_bus_dma_tag, 174 self); 175 #endif 176 177 #if NACPICA > 0 178 if (acpi_present) { 179 mba.mba_acpi.aa_iot = x86_bus_space_io; 180 mba.mba_acpi.aa_memt = x86_bus_space_mem; 181 mba.mba_acpi.aa_pc = NULL; 182 mba.mba_acpi.aa_pciflags = 183 PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY | 184 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | 185 PCI_FLAGS_MWI_OKAY; 186 mba.mba_acpi.aa_ic = &x86_isa_chipset; 187 mba.mba_acpi.aa_dmat = &pci_bus_dma_tag; 188 mba.mba_acpi.aa_dmat64 = &pci_bus_dma64_tag; 189 config_found(self, &mba.mba_acpi, NULL, 190 CFARGS(.iattr = "acpibus")); 191 } 192 #endif 193 194 #if NIPMI > 0 195 memset(&mba.mba_ipmi, 0, sizeof(mba.mba_ipmi)); 196 mba.mba_ipmi.iaa_iot = x86_bus_space_io; 197 mba.mba_ipmi.iaa_memt = x86_bus_space_mem; 198 if (ipmi_probe(&mba.mba_ipmi)) 199 config_found(self, &mba.mba_ipmi, NULL, 200 CFARGS(.iattr = "ipmibus")); 201 #endif 202 203 #if NPCI > 0 204 if (pci_mode_detect() != 0) { 205 int npcibus = 0; 206 207 mba.mba_pba.pba_iot = x86_bus_space_io; 208 mba.mba_pba.pba_memt = x86_bus_space_mem; 209 mba.mba_pba.pba_dmat = &pci_bus_dma_tag; 210 mba.mba_pba.pba_dmat64 = &pci_bus_dma64_tag; 211 mba.mba_pba.pba_pc = NULL; 212 mba.mba_pba.pba_flags = 213 PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY | 214 PCI_FLAGS_MRL_OKAY | PCI_FLAGS_MRM_OKAY | 215 PCI_FLAGS_MWI_OKAY; 216 mba.mba_pba.pba_bus = 0; 217 mba.mba_pba.pba_bridgetag = NULL; 218 #if NACPICA > 0 && defined(ACPI_SCANPCI) 219 if (npcibus == 0 && mpacpi_active) 220 npcibus = mp_pci_scan(self, &mba.mba_pba, pcibusprint); 221 #endif 222 #if defined(MPBIOS) && defined(MPBIOS_SCANPCI) 223 if (npcibus == 0 && mpbios_scanned != 0) 224 npcibus = mp_pci_scan(self, &mba.mba_pba, pcibusprint); 225 #endif 226 if (npcibus == 0) 227 config_found(self, &mba.mba_pba, pcibusprint, 228 CFARGS(.iattr = "pcibus")); 229 230 #if NACPICA > 0 231 if (mp_verbose) 232 acpi_pci_link_state(); 233 #endif 234 } 235 #endif 236 237 #if NISA > 0 238 if (isa_has_been_seen == 0) { 239 mba.mba_iba = mba_iba; 240 mba.mba_iba.iba_iot = x86_bus_space_io; 241 mba.mba_iba.iba_memt = x86_bus_space_mem; 242 config_found(self, &mba.mba_iba, isabusprint, 243 CFARGS(.iattr = "isabus")); 244 } 245 #endif 246 247 #if NPVBUS > 0 248 /* add here more VM guests types that would benefit from a pv bus */ 249 switch(vm_guest) { 250 /* FALLTHROUGH */ 251 case VM_GUEST_GENPVH: 252 case VM_GUEST_KVM: 253 mba.mba_pvba.pvba_busname = "pvbus"; 254 config_found(self, &mba.mba_pvba.pvba_busname, NULL, 255 CFARGS(.iattr = "pvbus")); 256 break; 257 default: 258 break; 259 } 260 #endif 261 262 if (!pmf_device_register(self, NULL, NULL)) 263 aprint_error_dev(self, "couldn't establish power handler\n"); 264 } 265 266 int 267 amd64_mainbus_print(void *aux, const char *pnp) 268 { 269 union amd64_mainbus_attach_args *mba = aux; 270 271 if (pnp) 272 aprint_normal("%s at %s", mba->mba_busname, pnp); 273 return UNCONF; 274 } 275