xref: /openbsd-src/sys/arch/i386/i386/mainbus.c (revision 46035553bfdd96e63c94e32da0210227ec2e3cf1)
1 /*	$OpenBSD: mainbus.c,v 1.59 2019/01/18 01:34:50 pd Exp $	*/
2 /*	$NetBSD: mainbus.c,v 1.21 1997/06/06 23:14:20 thorpej 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/param.h>
35 #include <sys/systm.h>
36 #include <sys/device.h>
37 
38 #include <machine/bus.h>
39 #include <machine/specialreg.h>
40 
41 #include <dev/isa/isavar.h>
42 #include <dev/eisa/eisavar.h>
43 #include <dev/pci/pcivar.h>
44 
45 #include <dev/isa/isareg.h>		/* for IOM_BEGIN */
46 #include <i386/isa/isa_machdep.h>
47 
48 #include "pci.h"
49 #include "eisa.h"
50 #include "isa.h"
51 #include "apm.h"
52 #include "bios.h"
53 #include "acpi.h"
54 #include "ipmi.h"
55 #include "esm.h"
56 #include "amdmsr.h"
57 #include "pvbus.h"
58 
59 #include <machine/cpuvar.h>
60 #include <machine/i82093var.h>
61 
62 #if NBIOS > 0
63 #include <machine/biosvar.h>
64 #endif
65 
66 #include <dev/acpi/acpivar.h>
67 
68 #if NIPMI > 0
69 #include <dev/ipmivar.h>
70 #endif
71 
72 #if NPVBUS > 0
73 #include <dev/pv/pvvar.h>
74 #endif
75 
76 #if NAMDMSR > 0
77 #include <machine/amdmsr.h>
78 #endif
79 
80 #if NESM > 0
81 #include <arch/i386/i386/esmvar.h>
82 #endif
83 
84 int	mainbus_match(struct device *, void *, void *);
85 void	mainbus_attach(struct device *, struct device *, void *);
86 
87 struct cfattach mainbus_ca = {
88 	sizeof(struct device), mainbus_match, mainbus_attach, NULL,
89 	config_activate_children
90 };
91 
92 struct cfdriver mainbus_cd = {
93 	NULL, "mainbus", DV_DULL
94 };
95 
96 int	mainbus_print(void *, const char *);
97 
98 union mainbus_attach_args {
99 	const char *mba_busname;		/* first elem of all */
100 	struct pcibus_attach_args mba_pba;
101 	struct eisabus_attach_args mba_eba;
102 	struct isabus_attach_args mba_iba;
103 #if NBIOS > 0
104 	struct bios_attach_args mba_bios;
105 #endif
106 	struct cpu_attach_args mba_caa;
107 	struct apic_attach_args	aaa_caa;
108 #if NIPMI > 0
109 	struct ipmi_attach_args mba_iaa;
110 #endif
111 #if NESM > 0
112 	struct esm_attach_args mba_eaa;
113 #endif
114 #if NPVBUS > 0
115 	struct pvbus_attach_args mba_pvba;
116 #endif
117 };
118 
119 /*
120  * This is set when the ISA bus is attached.  If it's not set by the
121  * time it's checked below, then mainbus attempts to attach an ISA.
122  */
123 int     isa_has_been_seen;
124 
125 /*
126  * Probe for the mainbus; always succeeds.
127  */
128 int
129 mainbus_match(struct device *parent, void *match, void *aux)
130 {
131 	return (1);
132 }
133 
134 /*
135  * Attach the mainbus.
136  */
137 void
138 mainbus_attach(struct device *parent, struct device *self, void *aux)
139 {
140 	union mainbus_attach_args	mba;
141 	extern void			(*setperf_setup)(struct cpu_info *);
142 	extern void			(*cpusensors_setup)(struct cpu_info *);
143 
144 	printf("\n");
145 
146 #if NPVBUS > 0
147 	/* Detect hypervisors early, attach the paravirtual bus later */
148 	if (cpu_ecxfeature & CPUIDECX_HV)
149 		pvbus_identify();
150 #endif
151 
152 #if NBIOS > 0
153 	{
154 		mba.mba_bios.ba_name = "bios";
155 		mba.mba_bios.ba_iot = I386_BUS_SPACE_IO;
156 		mba.mba_bios.ba_memt = I386_BUS_SPACE_MEM;
157 		config_found(self, &mba.mba_bios, mainbus_print);
158 	}
159 #endif
160 
161 #if NIPMI > 0
162 	{
163 		memset(&mba.mba_iaa, 0, sizeof(mba.mba_iaa));
164 		mba.mba_iaa.iaa_name = "ipmi";
165 		mba.mba_iaa.iaa_iot  = I386_BUS_SPACE_IO;
166 		mba.mba_iaa.iaa_memt = I386_BUS_SPACE_MEM;
167 		if (ipmi_probe(&mba.mba_iaa))
168 			config_found(self, &mba.mba_iaa, mainbus_print);
169 	}
170 #endif
171 
172 	if ((cpu_info_primary.ci_flags & CPUF_PRESENT) == 0) {
173 		struct cpu_attach_args caa;
174 
175 		memset(&caa, 0, sizeof(caa));
176 		caa.caa_name = "cpu";
177 		caa.cpu_apicid = 0;
178 		caa.cpu_role = CPU_ROLE_SP;
179 		caa.cpu_func = 0;
180 		caa.cpu_signature = cpu_id;
181 		caa.feature_flags = cpu_feature;
182 
183 		config_found(self, &caa, mainbus_print);
184 	}
185 #if NAMDMSR > 0
186 	if (amdmsr_probe()) {
187 		mba.mba_busname = "amdmsr";
188 		config_found(self, &mba.mba_busname, mainbus_print);
189 	}
190 #endif
191 
192 #if NACPI > 0
193 	if (!acpi_hasprocfvs)
194 #endif
195 	{
196 		if (setperf_setup != NULL)
197 			setperf_setup(&cpu_info_primary);
198 	}
199 
200 #ifdef MULTIPROCESSOR
201 	mp_setperf_init();
202 #endif
203 
204 	if (cpusensors_setup != NULL)
205 		cpusensors_setup(&cpu_info_primary);
206 
207 #if NESM > 0
208 	{
209 		memset(&mba.mba_eaa, 0, sizeof(mba.mba_eaa));
210 		mba.mba_eaa.eaa_name = "esm";
211 		mba.mba_eaa.eaa_iot  = I386_BUS_SPACE_IO;
212 		mba.mba_eaa.eaa_memt = I386_BUS_SPACE_MEM;
213 		if (esm_probe(&mba.mba_eaa))
214 			config_found(self, &mba.mba_eaa, mainbus_print);
215 	}
216 #endif
217 
218 #if NPVBUS > 0
219 	/* Probe first to hide the "not configured" message */
220 	if (pvbus_probe()) {
221 		mba.mba_pvba.pvba_busname = "pvbus";
222 		config_found(self, &mba.mba_pvba.pvba_busname, mainbus_print);
223 	}
224 #endif
225 
226 	/*
227 	 * XXX Note also that the presence of a PCI bus should
228 	 * XXX _always_ be checked, and if present the bus should be
229 	 * XXX 'found'.  However, because of the structure of the code,
230 	 * XXX that's not currently possible.
231 	 */
232 #if NPCI > 0
233 	if (pci_mode_detect() != 0) {
234 		pci_init_extents();
235 
236 		bzero(&mba.mba_pba, sizeof(mba.mba_pba));
237 		mba.mba_pba.pba_busname = "pci";
238 		mba.mba_pba.pba_iot = I386_BUS_SPACE_IO;
239 		mba.mba_pba.pba_memt = I386_BUS_SPACE_MEM;
240 		mba.mba_pba.pba_dmat = &pci_bus_dma_tag;
241 		mba.mba_pba.pba_ioex = pciio_ex;
242 		mba.mba_pba.pba_memex = pcimem_ex;
243 		mba.mba_pba.pba_busex = pcibus_ex;
244 		mba.mba_pba.pba_domain = pci_ndomains++;
245 		mba.mba_pba.pba_bus = 0;
246 		config_found(self, &mba.mba_pba, mainbus_print);
247 #if NACPI > 0
248 		acpi_pciroots_attach(self, &mba.mba_pba, mainbus_print);
249 #endif
250 	}
251 #endif
252 
253 	if (!bcmp(ISA_HOLE_VADDR(EISA_ID_PADDR), EISA_ID, EISA_ID_LEN)) {
254 		mba.mba_eba.eba_busname = "eisa";
255 		mba.mba_eba.eba_iot = I386_BUS_SPACE_IO;
256 		mba.mba_eba.eba_memt = I386_BUS_SPACE_MEM;
257 #if NEISA > 0
258 		mba.mba_eba.eba_dmat = &eisa_bus_dma_tag;
259 #endif
260 		config_found(self, &mba.mba_eba, mainbus_print);
261 	}
262 
263 	if (isa_has_been_seen == 0) {
264 		mba.mba_iba.iba_busname = "isa";
265 		mba.mba_iba.iba_iot = I386_BUS_SPACE_IO;
266 		mba.mba_iba.iba_memt = I386_BUS_SPACE_MEM;
267 #if NISADMA > 0
268 		mba.mba_iba.iba_dmat = &isa_bus_dma_tag;
269 #endif
270 		config_found(self, &mba.mba_iba, mainbus_print);
271 	}
272 }
273 
274 int
275 mainbus_print(void *aux, const char *pnp)
276 {
277 	union mainbus_attach_args	*mba = aux;
278 
279 	if (pnp)
280 		printf("%s at %s", mba->mba_busname, pnp);
281 	if (!strcmp(mba->mba_busname, "pci"))
282 		printf(" bus %d", mba->mba_pba.pba_bus);
283 
284 	return (UNCONF);
285 }
286