|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)autoconf.c 1.1 86/02/03 Copyr 1985 Sun Micro";
3: #endif
4:
5: /*
6: * Copyright (c) 1985 by Sun Microsystems, Inc.
7: */
8:
9: /*
10: * Setup the system to run on the current machine.
11: *
12: * Configure() is called at boot time and initializes the Mainbus
13: * device tables and the memory controller monitoring. Available
14: * devices are determined (from possibilities mentioned in ioconf.c),
15: * and the drivers are initialized.
16: */
17:
18: #include "../h/param.h"
19: #include "../h/systm.h"
20: #include "../h/map.h"
21: #include "../h/buf.h"
22: #include "../h/dk.h"
23: #include "../h/vm.h"
24: #include "../h/conf.h"
25: #include "../h/file.h"
26: #include "../h/dir.h"
27: #include "../h/user.h"
28: #include "../h/proc.h"
29:
30: #include "../machine/pte.h"
31: #include "../machine/mmu.h"
32: #include "../machine/cpu.h"
33: #include "../machine/scb.h"
34: #include "../machine/mbvar.h"
35: #include "../machine/zsvar.h"
36: #include "../machine/sunromvec.h"
37: #include "../machine/idprom.h"
38:
39: /*
40: * The following several variables are related to
41: * the configuration process, and are used in initializing
42: * the machine.
43: */
44: int dkn; /* number of iostat dk numbers assigned so far */
45:
46: /*
47: * This allocates the space for the per-Mainbus information.
48: */
49: struct mb_hd mb_hd;
50:
51: /*
52: * Determine mass storage and memory configuration for a machine.
53: * Get cpu type, and then switch out to machine specific procedures
54: * which will probe adaptors to see what is out there.
55: */
56: configure()
57: {
58:
59: idprom();
60: /*
61: * Configure the Mainbus.
62: */
63: mbconfig();
64: #ifdef GENERIC
65: setconf();
66: #endif
67: }
68:
69: static int (*vec_save)(); /* used to save original vector value */
70:
71: /*
72: * Find devices on the Mainbus.
73: * Uses per-driver routine to probe for existence of the device
74: * and then fills in the tables, with help from a per-driver
75: * slave initialization routine.
76: */
77: mbconfig()
78: {
79: register struct mb_device *md;
80: register struct mb_ctlr *mc;
81: u_short *reg;
82: struct mb_driver *mdr;
83: u_short *doprobe();
84:
85: vec_save = scb.scb_user[0]; /* save default trap routine */
86:
87: /*
88: * Grab some memory to record the Mainbus address space in use,
89: * so we can be sure not to place two devices at the same address.
90: * If we run out of kernelmap space, we could reuse the mapped
91: * pages if we did all probes first to determine the target
92: * locations and sizes, and then remucked with the kernelmap to
93: * share spaces, then did all the attaches.
94: *
95: * We could use just 1/8 of this (we only want a 1 bit flag) but
96: * we are going to give it back anyway, and that would make the
97: * code here bigger (which we can't give back), so ...
98: */
99:
100: /*
101: * Check each Mainbus mass storage controller.
102: * See if it is really there, and if it is record it and
103: * then go looking for slaves.
104: */
105: for (mc = mbcinit; mdr = mc->mc_driver; mc++) {
106: if ((reg = doprobe((u_long)mc->mc_addr, (u_long)mc->mc_space,
107: mdr, mdr->mdr_cname, mc->mc_ctlr, mc->mc_intpri,
108: mc->mc_intr)) == 0)
109: continue;
110: mc->mc_alive = 1;
111: mc->mc_mh = &mb_hd;
112: mc->mc_addr = (caddr_t)reg;
113: if (mdr->mdr_cinfo)
114: mdr->mdr_cinfo[mc->mc_ctlr] = mc;
115: for (md = mbdinit; md->md_driver; md++) {
116: if (md->md_driver != mdr || md->md_alive ||
117: md->md_ctlr != mc->mc_ctlr && md->md_ctlr != '?')
118: continue;
119: if ((*mdr->mdr_slave)(md, reg)) {
120: md->md_alive = 1;
121: md->md_ctlr = mc->mc_ctlr;
122: md->md_hd = &mb_hd;
123: md->md_addr = (caddr_t)reg;
124: if (md->md_dk && dkn < DK_NDRIVE)
125: md->md_dk = dkn++;
126: else
127: md->md_dk = -1;
128: md->md_mc = mc;
129: /* md_type comes from driver */
130: if (mdr->mdr_dinfo)
131: mdr->mdr_dinfo[md->md_unit] = md;
132: printf("%s%d at %s%d slave %d\n",
133: mdr->mdr_dname, md->md_unit,
134: mdr->mdr_cname, mc->mc_ctlr, md->md_slave);
135: if (mdr->mdr_attach)
136: (*mdr->mdr_attach)(md);
137: }
138: }
139: }
140:
141: /*
142: * Now look for non-mass storage peripherals.
143: */
144: for (md = mbdinit; mdr = md->md_driver; md++) {
145: if (md->md_alive || md->md_slave != -1)
146: continue;
147: if ((reg = doprobe((u_long)md->md_addr, (u_long)md->md_space,
148: mdr, mdr->mdr_dname, md->md_unit, md->md_intpri,
149: md->md_intr)) == 0)
150: continue;
151: md->md_hd = &mb_hd;
152: md->md_alive = 1;
153: md->md_addr = (caddr_t)reg;
154: md->md_dk = -1;
155: /* md_type comes from driver */
156: if (mdr->mdr_dinfo)
157: mdr->mdr_dinfo[md->md_unit] = md;
158: if (mdr->mdr_attach)
159: (*mdr->mdr_attach)(md);
160: }
161: }
162:
163: /*
164: * Make non-zero if want to be set up to handle
165: * both vectored and auto-vectored interrupts
166: * for the same device at the same time.
167: */
168: int paranoid = 0;
169:
170: /*
171: * Probe for a device or controller at the specified addr.
172: * The space argument give the page type and cpu type for the device.
173: */
174: u_short *
175: doprobe(addr, space, mdr, dname, unit, br, vp)
176: register u_long addr, space;
177: register struct mb_driver *mdr;
178: char *dname;
179: int unit, br;
180: register struct vec *vp;
181: {
182: register u_short *reg = NULL;
183: char *name;
184: long a = 0;
185: int i, extent, machine;
186: u_int pageval;
187:
188: #define SP_MACHMASK 0xFFFF0000 /* space mask for machine type */
189: #define MAKE_MACH(m) ((m)<<16)
190: #define SP_MACH_ALL MAKE_MACH(0)
191:
192: #define SP_BUSMASK 0x0000FFFF /* mask for bus type */
193: #define SP_VIRTUAL 0x00000001
194: #define SP_OBMEM 0x00000002
195: #define SP_OBIO 0x00000004
196: #define SP_VME16D16 0x00000100
197: #define SP_VME24D16 0x00000200
198: #define SP_VME32D16 0x00000400
199: #define SP_VME16D32 0x00001000
200: #define SP_VME24D32 0x00002000
201: #define SP_VME32D32 0x00004000
202:
203: machine = space & SP_MACHMASK;
204:
205: if (machine != SP_MACH_ALL && machine != MAKE_MACH(cpu & CPU_MACH))
206: return(0);
207:
208: switch (space & SP_BUSMASK) {
209:
210: case SP_VIRTUAL:
211: name = "virtual";
212: reg = (u_short *)addr;
213: break;
214:
215: case SP_OBMEM:
216: name = "obmem";
217: pageval = PGT_OBMEM | btop(addr);
218: break;
219:
220: case SP_OBIO:
221: name = "obio";
222: pageval = PGT_OBIO | btop(addr);
223: break;
224:
225: case SP_VME16D16:
226: name = "vme16d16";
227: pageval = PGT_VME_D16 | btop(VME16_BASE | (addr & VME16_MASK));
228: break;
229:
230: case SP_VME24D16:
231: name = "vme24d16";
232: pageval = PGT_VME_D16 | btop(VME24_BASE | (addr & VME24_MASK));
233: break;
234:
235: case SP_VME32D16:
236: name = "vme32d16";
237: pageval = PGT_VME_D16 | btop(addr);
238: break;
239:
240: case SP_VME16D32:
241: name = "vme16d32";
242: pageval = PGT_VME_D32 | btop(VME16_BASE | (addr & VME16_MASK));
243: break;
244:
245: case SP_VME24D32:
246: name = "vme24d32";
247: pageval = PGT_VME_D32 | btop(VME24_BASE | (addr & VME24_MASK));
248: break;
249:
250: case SP_VME32D32:
251: name = "vme32d32";
252: pageval = PGT_VME_D32 | btop(addr);
253: break;
254:
255: default:
256: return (0);
257: }
258:
259: if (reg == NULL) {
260: int offset = addr & PGOFSET;
261:
262: extent = btoc(mdr->mdr_size + offset);
263: if (extent == 0)
264: extent = 1;
265: if ((a = rmalloc(kernelmap, (long)extent)) == 0)
266: panic("out of kernelmap for devices");
267: reg = (u_short *)((int)kmxtob(a) | offset);
268: mapin(&Usrptmap[a], btop(reg), pageval, extent, PG_V | PG_KW);
269: }
270:
271: i = (*mdr->mdr_probe)(reg, unit);
272: if (i == 0) {
273: if (a)
274: rmfree(kernelmap, (long)extent, a);
275: return (0);
276: }
277: printf("%s%d at %s %x ", dname, unit, name, addr);
278: if (br < 0 || br >= 7) {
279: printf("bad priority (%d)\n", br);
280: if (a)
281: rmfree(kernelmap, (long)extent, a);
282: return (0);
283: }
284:
285: /*
286: * If br is 0, then no priority was specified in the
287: * config file and the device cannot use interrupts.
288: */
289: if (br != 0) {
290: /*
291: * If we are paranoid or vectored interrupts are not
292: * going to be used then set up for polling interrupts.
293: */
294: if (paranoid || vp == (struct vec *)0) {
295: printf("pri %d ", br);
296: addintr(br, mdr);
297: }
298:
299: /*
300: * now set up vectored interrupts if conditions are right
301: */
302: if (vp != (struct vec *)0) {
303: for (; vp->v_func; vp++) {
304: printf("vec 0x%x ", vp->v_vec);
305: if (vp->v_vec < VEC_MIN || vp->v_vec > VEC_MAX)
306: panic("bad vector");
307: else if (scb.scb_user[vp->v_vec - VEC_MIN] !=
308: vec_save)
309: panic("duplicate vector");
310: else
311: scb.scb_user[vp->v_vec - VEC_MIN] =
312: vp->v_func;
313: }
314: }
315: }
316: printf("\n");
317: return (reg);
318: }
319:
320: #define SPURIOUS 0x80000000 /* recognized in locore.s */
321:
322: int level2_spurious, level3_spurious, level4_spurious, level6_spurious;
323:
324: not_serviced2()
325: {
326:
327: call_default_intr();
328: if ((level2_spurious++ % 100) == 1)
329: printf("iobus level 2 interrupt not serviced\n");
330: return (SPURIOUS);
331: }
332:
333: not_serviced3()
334: {
335:
336: call_default_intr();
337: if ((level3_spurious++ % 100) == 1)
338: printf("iobus level 3 interrupt not serviced\n");
339: return (SPURIOUS);
340: }
341:
342: not_serviced4()
343: {
344:
345: call_default_intr();
346: if ((level4_spurious++ % 100) == 1)
347: printf("iobus level 4 interrupt not serviced\n");
348: return (SPURIOUS);
349: }
350:
351: not_serviced6()
352: {
353:
354: call_default_intr();
355: if ((level6_spurious++ % 100) == 1)
356: printf("iobus level 6 interrupt not serviced\n");
357: return (SPURIOUS);
358: }
359:
360: typedef int (*func)();
361:
362: #define NVECT 10
363:
364: /*
365: * These vectors are used in locore.s to jump to device interrupt routines.
366: */
367: func level2_vector[NVECT] = {not_serviced2};
368: func level3_vector[NVECT] = {not_serviced3};
369: func level4_vector[NVECT] = {not_serviced4};
370: func level6_vector[NVECT] = {not_serviced6};
371:
372: func *vector[7] = {NULL, NULL, level2_vector, level3_vector,
373: level4_vector, NULL, level6_vector};
374:
375: /*
376: * Arrange for a driver to be called when a particular
377: * auto-vectored interrupt occurs.
378: * NOTE: every device sharing a driver must be on the
379: * same interrupt level for polling interrupts because
380: * there is only one entry made per driver.
381: */
382: addintr(lvl, mdr)
383: struct mb_driver *mdr;
384: {
385: register func f;
386: register func *fp;
387: register int i;
388:
389: switch (lvl) {
390: case 1:
391: return; /* bogus - these devices don't interrupt */
392: case 2:
393: fp = level2_vector;
394: break;
395: case 3:
396: fp = level3_vector;
397: break;
398: case 4:
399: fp = level4_vector;
400: break;
401: case 5:
402: panic("addintr called with level 5");
403: /* NOTREACHED */
404: case 6:
405: fp = level6_vector;
406: break;
407: default:
408: panic("addintr: unknown level");
409: /* NOTREACHED */
410: }
411: if ((f = mdr->mdr_intr) == NULL)
412: return;
413: for (i = 0; i < NVECT; i++) {
414: if (*fp == NULL) /* end of list found */
415: break;
416: if (*fp == f) /* already in list */
417: return;
418: fp++;
419: }
420: if (i >= NVECT)
421: panic("addintr: too many devices");
422: fp[0] = fp[-1]; /* move not_serviced to end */
423: fp[-1] = f; /* add f to list */
424: }
425:
426: /*
427: * This is for crazy devices that don't know when they interrupt.
428: * We just call them at the end after all the sane devices have decided
429: * the interrupt is not their fault.
430: */
431: func default_intrs[NVECT];
432:
433: add_default_intr(f)
434: func f;
435: {
436: register int i;
437: register func *fp;
438:
439: fp = default_intrs;
440: for (i = 0; i < NVECT; i++) {
441: if (*fp == NULL) /* end of list found */
442: break;
443: if (*fp == f) /* already in list */
444: return;
445: fp++;
446: }
447: if (i >= NVECT)
448: panic("add_default_intr: too many devices");
449: *fp = f; /* add f to list */
450: }
451:
452: call_default_intr()
453: {
454: register func *fp;
455:
456: for (fp = default_intrs; *fp; fp++)
457: (*fp)();
458: }
459:
460: /*
461: * Some things, like cputype, are contained in the idprom, but are
462: * needed and obtained earlier; hence they are not set (again) here.
463: */
464: idprom()
465: {
466: register u_char *cp, val = 0;
467: register int i;
468: struct idprom id;
469:
470: getidprom((char *)&id);
471: cp = (u_char *)&id;
472: for (i = 0; i < 16; i++)
473: val ^= *cp++;
474: if (val != 0)
475: printf("WARNING: ID prom checksum error\n");
476: if (id.id_format == 1) {
477: localetheraddr(id.id_ether, NULL);
478: } else
479: printf("INVALID FORMAT CODE IN ID PROM\n");
480: }
481:
482: int cpudelay = 3; /* default to a medium range value here */
483:
484: /*
485: * We set the cpu type and associated variables. Should there get to
486: * be too many variables, they should be collected together in a
487: * structure and indexed by cpu type.
488: */
489: setcputype()
490: {
491: struct idprom id;
492:
493: cpu = -1;
494: getidprom((char *)&id);
495: if (id.id_format == 1) {
496: switch (id.id_machine) {
497: case CPU_SUN3_160:
498: case CPU_SUN3_50:
499: case CPU_SUN3_260:
500: cpu = id.id_machine;
501: break;
502: default:
503: printf("UNKNOWN MACHINE TYPE 0x%x IN ID PROM\n",
504: id.id_machine);
505: break;
506: }
507: } else
508: printf("INVALID FORMAT TYPE IN ID PROM\n");
509:
510: if (cpu == -1) {
511: printf("DEFAULTING MACHINE TYPE TO SUN3_160\n");
512: cpu = CPU_SUN3_160;
513: }
514:
515: /*
516: * Can't use the last segment for DVMA.
517: * The last is for on-board Ethernet scratch,
518: * u area, and miscellanous on-board devices.
519: * On the Sun-3, we can set dvmasize independent
520: * of the implementation.
521: */
522: dvmasize = btoc(DVMASIZE) - NPAGSEG;
523:
524: switch (cpu) {
525: case CPU_SUN3_160:
526: #ifndef SUN3_160
527: panic("not configured for SUN3_160");
528: #endif !SUN3_160
529: cpudelay = 3;
530: break;
531: case CPU_SUN3_50:
532: #ifndef SUN3_50
533: panic("not configured for SUN3_50");
534: #endif !SUN3_50
535: cpudelay = 3;
536: break;
537: case CPU_SUN3_260:
538: #ifndef SUN3_260
539: panic("not configured for SUN3_260");
540: #endif !SUN3_260
541: cpudelay = 2;
542: break;
543: }
544: }
545:
546: machineid()
547: {
548: struct idprom id;
549: register int x;
550:
551: getidprom((char *)&id);
552: x = id.id_machine << 24;
553: x += id.id_serial;
554: return (x);
555: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.