FreeBSD/Linux Kernel Cross Reference
sys/sqt/autoconf.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991 Carnegie Mellon University
4 * Copyright (c) 1991 Sequent Computer Systems
5 * All Rights Reserved.
6 *
7 * Permission to use, copy, modify and distribute this software and its
8 * documentation is hereby granted, provided that both the copyright
9 * notice and this permission notice appear in all copies of the
10 * software, derivative works or modified versions, and any portions
11 * thereof, and that both notices appear in supporting documentation.
12 *
13 * CARNEGIE MELLON AND SEQUENT COMPUTER SYSTEMS ALLOW FREE USE OF
14 * THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON AND
15 * SEQUENT COMPUTER SYSTEMS DISCLAIM ANY LIABILITY OF ANY KIND FOR
16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 *
18 * Carnegie Mellon requests users of this software to return to
19 *
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
24 *
25 * any improvements or extensions that they make and grant Carnegie Mellon
26 * the rights to redistribute these changes.
27 */
28
29 /*
30 * HISTORY
31 * $Log: autoconf.c,v $
32 * Revision 2.3 91/07/31 17:59:27 dbg
33 * Changed copyright.
34 * [91/07/31 dbg]
35 *
36 * Revision 2.2 91/05/08 12:52:16 dbg
37 * Adapted for pure Mach kernel. No conditionals. Removed ns32000
38 * and KXX support.
39 * [91/04/26 14:47:41 dbg]
40 *
41 */
42
43 #ifndef lint
44 static char rcsid[] = "$Header: autoconf.c,v 2.3 91/07/31 17:59:27 dbg Exp $";
45 #endif
46
47 /*
48 * autoconf.c
49 * Auto-configuration.
50 */
51
52 /*
53 * Revision 1.2 89/07/20 18:05:40 kak
54 * moved balance includes
55 *
56 * Revision 1.1 89/07/05 13:15:26 kak
57 * Initial revision
58 *
59 * Revision 2.26 88/11/10 08:25:49 djg
60 * bak242
61 *
62 * Revision 2.25 88/03/18 11:54:24 dilip
63 * moved init of dmmin, dmmax, zdmap to vm_drum.c. Also, drop maxdmap
64 * init, call init_dmap() instead.
65 *
66 */
67
68 #include <sys/reboot.h>
69
70 #include <mach/machine.h>
71
72 #include <kern/assert.h>
73 #include <kern/cpu_number.h>
74
75 #include <sqt/vm_defs.h>
76
77 #include <sqt/intctl.h>
78 #include <sqt/ioconf.h>
79 #include <sqt/mutex.h>
80
81 #include <sqt/SGSproc.h>
82 #include <sqt/cfg.h>
83 #include <sqt/slic.h>
84 #include <sqt/slicreg.h>
85 #include <sqt/clkarb.h>
86 #include <sqt/clock.h>
87 #include <sqt/engine.h>
88
89 /*
90 * Address of configuration table set by PROM loader.
91 */
92 struct config_desc *va_CD_LOC;
93
94 unsigned Nengine; /* # processors */
95 struct engine *engine; /* base of engine array */
96 struct engine *engine_Nengine; /* end of engine array */
97 int NFPA = 0; /* # processors with FPA's */
98 int mono_P_slic = -1; /* no mono_P drivers == -1 */
99 short fp_lights; /* Front panel lights */
100 u_char cons_scsi = 0; /* 26 */ /* console SCSI's SLIC id */
101 extern int cpurate; /* used for delays */
102
103 int boothowto; /* boot flags */
104 unsigned sys_clock_rate; /* # Mega Hz system runs at */
105
106 struct bin_header int_bin_table[SLICBINS]; /* Interrupt Bin Table */
107 int bin_alloc[SLICBINS]; /* for allocating vectors */
108
109 /*
110 * slic_to_config[] maps SLIC number to configuration information about
111 * that SLIC.
112 */
113
114 struct ctlr_desc *slic_to_config[MAX_NUM_SLIC];
115
116 /*
117 * slic_to_cpu maps SLIC number to logical processor id
118 */
119
120 char slic_to_cpu[MAX_NUM_SLIC];
121
122 /*
123 * sec0eaddr encodes a system unique 24-bit number. Name is historic.
124 * This value is the low-order 24-bits of the ether address on SCED[0] for
125 * a B8k; on a B21k it's the system-ID value from the backplane (readable thru
126 * the CADM). After system is up and /etc/init has the magic system ID number,
127 * sec0eaddr holds the number of users the system can legally support.
128 */
129
130 unsigned sec0eaddr = -1; /* system ID number */
131
132 extern char * calloc();
133 int strayint();
134
135
136 /*
137 * configure()
138 * Scan the HW configuration information, do probes, etc,
139 * all in the name of determining what's out there.
140 */
141
142 configure()
143 {
144 register struct ctlr_desc *cd;
145 register struct cntlrs *b8k;
146
147 /*
148 * Force io to this slic
149 */
150 mono_P_slic = va_slic->sl_procid;
151
152 /*
153 * Determine boot flags and system clock rate.
154 */
155
156 boothowto = va_CD_LOC->c_boot_flag;
157 sys_clock_rate = va_CD_LOC->c_clock_rate;
158
159 /*
160 * Build slic to config information map.
161 */
162
163 for (cd = PHYSTOKV(va_CD_LOC->c_ctlrs, struct ctlr_desc *);
164 cd < PHYSTOKV(va_CD_LOC->c_end_ctlrs, struct ctlr_desc *);
165 cd++)
166 slic_to_config[cd->cd_slic] = cd;
167
168 /*
169 * Do configuration/allocation of basic system components.
170 */
171
172 conf_console();
173 conf_clkarb();
174 conf_proc();
175 conf_mem();
176
177 for (b8k = b8k_cntlrs; b8k->conf_b8k != NULL; b8k++)
178 (*b8k->conf_b8k)();
179
180 /*
181 * Allocate interrupt table, set up pseudo devices, and
182 * probe IO controllers (includes MBAd's, SCED's, ZDC's, etc).
183 */
184
185 conf_intr();
186 conf_pseudo();
187
188 for (b8k = b8k_cntlrs; b8k->conf_b8k != NULL; b8k++)
189 (*b8k->probe_b8k_devs)();
190 setconf();
191 }
192
193 /*
194 * conf_console()
195 * Determine Console SCSI card for putchar()'s and "boot" console device.
196 */
197
198 conf_console()
199 {
200 register struct ctlr_desc *cd;
201
202 cd = PHYSTOKV(va_CD_LOC->c_cons, struct ctlr_desc *);
203 cons_scsi = cd->cd_slic;
204 }
205
206 /*
207 * conf_clkarb()
208 * Determine if clock arbiter is present. If present,
209 * set flag for front panel lights. And determine bus priority
210 * for slots 16-20. If all are processors then set priority to low
211 * otherwise set high (default).
212 */
213
214 conf_clkarb()
215 {
216 register struct ctlr_toc *toc =
217 PHYSTOKV(&va_CD_LOC->c_toc[SLB_CLKARBBOARD], struct ctlr_toc *);
218 register struct ctlr_desc *cd;
219 extern int light_show;
220
221 if (toc->ct_count == 0) {
222 return;
223 }
224
225 /*
226 * We're a B21k ==> set up to use front-panel LED's and get system ID
227 * from clock-arbiter board.
228 */
229
230 cd = PHYSTOKV(&va_CD_LOC->c_ctlrs[toc->ct_start],
231 struct ctlr_desc *); /* clkarb ctlr_desc */
232
233 fp_lights = 1; /* use front panel LEDs */
234 if (light_show > 1)
235 fp_lights = -1; /* use front-panel and processor LEDs */
236 FP_IO_ONLINE; /* ASSUME all drives online */
237
238 sec0eaddr = cd->cd_ca_sysid & 0x00FFFFFF;
239
240 }
241
242 /*
243 * conf_proc()
244 * Configure processors.
245 *
246 * Allocate engine table for all possible processors, but only remember
247 * alive and configured processors.
248 *
249 * We only fill out the slic addresses in the engine structures;
250 * sysinit() fills out the rest.
251 *
252 * We also set `Nengine' here to the # of desired processors.
253 */
254
255 conf_proc()
256 {
257 extern int lcpuspeed; /* configured value */
258 register struct ctlr_toc *toc;
259 register struct ctlr_desc *cd;
260 register struct engine *eng;
261 register int i;
262
263 /*
264 * Get table of contents pointer for processor board.
265 */
266
267 toc = PHYSTOKV(&va_CD_LOC->c_toc[SLB_SGSPROCBOARD],
268 struct ctlr_toc *); /* SGS processors */
269
270 engine = (struct engine *)
271 calloc((int)toc->ct_count * sizeof(struct engine));
272
273 printf("%d processors; slic", toc->ct_count);
274
275 cd = PHYSTOKV(&va_CD_LOC->c_ctlrs[toc->ct_start], struct ctlr_desc *);
276 for (i = 0; i < toc->ct_count; i++, cd++) {
277 printf(" %d", cd->cd_slic);
278 if (cd->cd_diag_flag & (CFG_FAIL|CFG_DECONF))
279 continue;
280 eng = &engine[Nengine];
281 eng->e_diag_flag = cd->cd_diag_flag;
282 eng->e_slicaddr = cd->cd_slic;
283 eng->e_cpu_speed = cd->cd_p_speed;
284
285 slic_to_cpu[cd->cd_slic] = Nengine;
286
287 machine_slot[Nengine].is_cpu = TRUE;
288 machine_slot[Nengine].cpu_type = CPU_TYPE_I386;
289 machine_slot[Nengine].cpu_subtype = CPU_SUBTYPE_SYMMETRY;
290 machine_slot[Nengine].running = FALSE;
291
292 /*
293 * Set the engine rate and find the slowest proccesor
294 * if not set assume minimum.
295 * Note: cpurate is recalulated to be in MIPS at the
296 * end of this routine.
297 */
298 if (eng->e_cpu_speed == 0 )
299 eng->e_cpu_speed = cpurate;
300 if (eng->e_cpu_speed < cpurate)
301 cpurate = eng->e_cpu_speed;
302 #ifdef E_FPU387
303 /*
304 * Set E_FPU387 and E_FPA in e_flags as appropriate.
305 * Bump NFPA for those available processors that have FPA's.
306 * Only set E_FPA if there is an FPA and it passed diagnostics.
307 */
308 if (cd->cd_p_fp & SLP_387)
309 eng->e_flags |= E_FPU387;
310 if (cd->cd_p_fp & SLP_FPA) {
311 if ((cd->cd_diag_flag & CFG_SP_FPA) == 0) {
312 eng->e_flags |= E_FPA;
313 ++NFPA;
314 }
315 }
316 #endif E_FPU387
317 Nengine++;
318
319 }
320 engine_Nengine = &engine[Nengine];
321 printf(".\n");
322
323 if (Nengine < toc->ct_count) {
324 printf("Not using processors: slic");
325 cd = PHYSTOKV(&va_CD_LOC->c_ctlrs[toc->ct_start],
326 struct ctlr_desc *);
327 for (i = 0; i < toc->ct_count; i++, cd++) {
328 if (cd->cd_diag_flag & (CFG_FAIL|CFG_DECONF))
329 printf(" %d", cd->cd_slic);
330 }
331 printf(".\n");
332 }
333 /*
334 * compute cpurate for delay loops. The value should
335 * correspond to the "mips" rating for the processor
336 * at its running rate.
337 * cd_p_speed: is an actual boards running rate
338 * e_cpu_speed: is the number of mips if
339 * sys_clock_rate = 100
340 * cpurate is only used for probe routines running on the
341 * "boot" processor.
342 */
343 cpurate = (lcpuspeed * cpurate) / 100;
344 }
345
346 /*
347 * conf_intr()
348 * Allocate and initialize interrupt vector table.
349 *
350 * Sysinit() already set up master HW vector table.
351 * Don't allocate anything for bin[0] (SW -- doesn't use this table).
352 */
353
354 conf_intr()
355 {
356 register int i;
357 register int vec;
358 extern todclock(); /* tod clock handler */
359 extern hardclock();
360
361 /*
362 * Add in local clock, tod clock to appropriate bins.
363 */
364
365 ivecres(LCLKBIN, 1);
366 ivecres(TODCLKBIN, 1);
367
368 /*
369 * Allocate int_bin_table, init all entries to point at strayint().
370 */
371
372 for (i = 1; i < SLICBINS; i++) {
373 if (bin_intr[i] == 0)
374 continue;
375 assert(bin_intr[i] <= MSGSPERBIN);
376 int_bin_table[i].bh_size = bin_intr[i];
377 int_bin_table[i].bh_hdlrtab =
378 (int(**)())calloc(bin_intr[i]*sizeof(int (*)()));
379 for (vec = 0; vec < int_bin_table[i].bh_size; vec++)
380 ivecinit(i, vec, strayint);
381 }
382
383 /*
384 * Set up vectors for local clock and tod clock.
385 * Must do LCLKBIN first, to insure it gets vector 0.
386 */
387
388 ivecinit(LCLKBIN, ivecall(LCLKBIN), hardclock);
389 ivecinit(TODCLKBIN, ivecall(TODCLKBIN), todclock);
390 }
391
392 /*
393 * conf_pseudo()
394 * Call the boot procedures of pseudo-devices.
395 */
396
397 conf_pseudo()
398 {
399 register struct pseudo_dev *pd;
400
401 printf("Pseudo devices:");
402 for (pd = pseudo_dev; pd->pd_name; pd++) {
403 printf(" %d %s", pd->pd_flags, pd->pd_name);
404 (*pd->pd_boot)(pd->pd_flags);
405 }
406 printf(".\n");
407 }
408
409 /*
410 * ivecall()
411 * Allocate a vector from a given bin.
412 *
413 * Insures sequential values returned per bin.
414 */
415
416 u_char
417 ivecall(bin)
418 u_char bin;
419 {
420 if (bin_alloc[bin] >= int_bin_table[bin].bh_size) {
421 printf("Too many vectors in bin %d.\n", bin);
422 panic("ivecall");
423 /*NOTREACHED*/
424 }
425 return(bin_alloc[bin]++);
426 }
427
428 /*
429 * strayint()
430 * Stray interrupt catcher.
431 *
432 * Doesn't report bin #; instead reports current value of SLIC local
433 * mask which allows inference of interrupting bin.
434 */
435
436 strayint(vec)
437 int vec; /* vector number within bin */
438 {
439 printf("Stray intr, vector %d ipl 0x%x.\n", vec, va_slic->sl_lmask);
440 }
441
442 /*
443 * bogusint()
444 * Called from locore.s when bad vector number presented
445 * from SLIC.
446 */
447
448 bogusint(bin, vec)
449 unsigned bin;
450 unsigned vec;
451 {
452 printf("Bogus interrupt vector %d on bin %d.\n", vec, bin);
453 }
Cache object: aea916d1b870115cb7498f518eeb4900
|