|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)autoconf.c 7.4 (Berkeley) 6/28/90
7: */
8:
9: /*
10: * Setup the system to run on the current machine.
11: *
12: * Configure() is called at boot time and initializes the vba
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: #include "param.h"
18: #include "systm.h"
19: #include "map.h"
20: #include "buf.h"
21: #include "dkstat.h"
22: #include "vm.h"
23: #include "conf.h"
24: #include "dmap.h"
25: #include "reboot.h"
26: #include "malloc.h"
27:
28: #include "pte.h"
29: #include "mem.h"
30: #include "mtpr.h"
31: #include "scb.h"
32:
33: #include "vba.h"
34:
35: #include "../tahoevba/vbavar.h"
36: #include "../tahoevba/vbaparam.h"
37:
38: /*
39: * The following several variables are related to
40: * the configuration process, and are used in initializing
41: * the machine.
42: */
43: int dkn; /* number of iostat dk numbers assigned so far */
44: int cold; /* cold start flag initialized in locore.s */
45:
46: /*
47: * This allocates the space for the per-vba information.
48: */
49: struct vba_hd vba_hd[NVBA];
50:
51: /*
52: * Determine i/o configuration for a machine.
53: */
54: configure()
55: {
56: register int *ip;
57: extern caddr_t Sysbase;
58:
59: vbafind(numvba, (caddr_t)vmem, VMEMmap);
60: numvba++;
61: /*
62: * Write protect the scb. It is strange
63: * that this code is here, but this is as soon
64: * as we are done mucking with it, and the
65: * write-enable was done in assembly language
66: * to which we will never return.
67: */
68: ip = (int *)&Sysmap[2]; *ip &= ~PG_PROT; *ip |= PG_KR;
69: mtpr(TBIS, Sysbase+2*NBPG);
70: #if GENERIC
71: if ((boothowto & RB_ASKNAME) == 0)
72: setroot();
73: setconf();
74: #else
75: setroot();
76: #endif
77: /*
78: * Configure swap area and related system
79: * parameter based on device(s) used.
80: */
81: swapconf();
82: cold = 0;
83: }
84:
85: /*
86: * Make the controllers accessible at physical address phys
87: * by mapping kernel ptes starting at pte.
88: */
89: vbaccess(pte, iobase, n)
90: register struct pte *pte;
91: caddr_t iobase;
92: register int n;
93: {
94: register unsigned v = btop(iobase);
95:
96: do
97: *(int *)pte++ = PG_V|PG_KW|v++;
98: while (--n > 0);
99: mtpr(TBIA, 0);
100: }
101:
102: /*
103: * Fixctlrmask fixes the masks of the driver ctlr routines
104: * which otherwise save r11 and r12 where the interrupt and br
105: * level are passed through.
106: */
107: fixctlrmask()
108: {
109: register struct vba_ctlr *vm;
110: register struct vba_device *vi;
111: register struct vba_driver *vd;
112: #define phys(a,b) ((b)(((int)(a))&~0xc0000000))
113:
114: vm = phys(vbminit, struct vba_ctlr *);
115: for (; vd = phys(vm->um_driver, struct vba_driver *); vm++)
116: *phys(vd->ud_probe, short *) &= ~0x1800;
117: vi = phys(vbdinit, struct vba_device *);
118: for (; vd = phys(vi->ui_driver, struct vba_driver *); vi++)
119: *phys(vd->ud_probe, short *) &= ~0x1800;
120: }
121:
122: /*
123: * Find devices on the VERSAbus.
124: * Uses per-driver routine to see who is on the bus
125: * and then fills in the tables, with help from a per-driver
126: * slave initialization routine.
127: */
128: vbafind(vban, vumem, memmap)
129: int vban;
130: caddr_t vumem;
131: struct pte memmap[];
132: {
133: register int br, cvec; /* must be r12, r11 */
134: register struct vba_device *ui;
135: register struct vba_ctlr *um;
136: u_short *reg;
137: long addr, *ap;
138: struct vba_hd *vhp;
139: struct vba_driver *udp;
140: int i, octlr, (**ivec)();
141: caddr_t valloc;
142: extern quad catcher[SCB_LASTIV];
143:
144: #ifdef lint
145: br = 0; cvec = 0;
146: #endif
147: vhp = &vba_hd[vban];
148: /*
149: * Make the controllers accessible at physical address phys
150: * by mapping kernel ptes starting at pte.
151: */
152: vbaccess(memmap, (caddr_t)VBIOBASE, (int)VBIOSIZE);
153: printf("vba%d at %x\n", vban, VBIOBASE);
154: /*
155: * Setup scb device entries to point into catcher array.
156: */
157: for (i = 0; i < SCB_LASTIV; i++)
158: scb.scb_devint[i] = (int (*)())((int)&catcher[i]);
159: /*
160: * Set last free interrupt vector for devices with
161: * programmable interrupt vectors. Use is to decrement
162: * this number and use result as interrupt vector.
163: */
164: vhp->vh_lastiv = SCB_LASTIV;
165: /*
166: * Grab some memory to record the address space we allocate,
167: * so we can be sure not to place two devices at the same address.
168: * Register I/O space is allocated in 256-byte sections,
169: * and memory I/O space is in 4Kb sections. We record allocations
170: * in 256-byte sections.
171: *
172: * We could use just 1/8 of this (we only want a 1 bit flag) but
173: * we are going to give it back anyway, and that would make the
174: * code here bigger (which we can't give back), so ...
175: */
176: #define VSECT(a) ((a) / 0x100)
177: #define VSIZE(s) (((s) + 0xff) / 0x100)
178: #define VALLOC(a) (valloc[VSECT(vboff(a))])
179: #define VMAPSIZE VSIZE(ctob(VBIOSIZE))
180: valloc = (caddr_t)malloc((u_long)(VMAPSIZE), M_TEMP, M_NOWAIT);
181: if (valloc == (caddr_t)0)
182: panic("no mem for vbafind");
183: bzero(valloc, VMAPSIZE);
184:
185: /*
186: * Check each VERSAbus mass storage controller.
187: * For each one which is potentially on this vba,
188: * see if it is really there, and if it is record it and
189: * then go looking for slaves.
190: */
191: #define vbaddr(off) (u_short *)(vumem + vboff(off))
192: for (um = vbminit; udp = um->um_driver; um++) {
193: if (um->um_vbanum != vban && um->um_vbanum != '?')
194: continue;
195: /*
196: * Use the particular address specified first,
197: * or if it is given as "0", if there is no device
198: * at that address, try all the standard addresses
199: * in the driver until we find it.
200: */
201: addr = (long)um->um_addr;
202: for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) {
203: if (VBIOMAPPED(addr)) {
204: if (VALLOC(addr))
205: continue;
206: reg = vbaddr(addr);
207: } else
208: reg = (u_short *)addr;
209: um->um_hd = vhp;
210: cvec = SCB_LASTIV, cold &= ~0x2;
211: i = (*udp->ud_probe)(reg, um);
212: cold |= 0x2;
213: if (i == 0)
214: continue;
215: printf("%s%d at vba%d csr %x ",
216: udp->ud_mname, um->um_ctlr, vban, addr);
217: if (cvec < 0 && vhp->vh_lastiv == cvec) {
218: printf("no space for vector(s)\n");
219: continue;
220: }
221: if (cvec == SCB_LASTIV) {
222: printf("didn't interrupt\n");
223: continue;
224: }
225: printf("vec %x, ipl %x\n", cvec, br);
226: csralloc(valloc, addr, i);
227: um->um_alive = 1;
228: um->um_vbanum = vban;
229: um->um_addr = (caddr_t)reg;
230: udp->ud_minfo[um->um_ctlr] = um;
231: for (ivec = um->um_intr; *ivec; ivec++)
232: ((long *)&scb)[cvec++] = (long)*ivec;
233: for (ui = vbdinit; ui->ui_driver; ui++) {
234: if (ui->ui_driver != udp || ui->ui_alive ||
235: ui->ui_ctlr != um->um_ctlr && ui->ui_ctlr != '?' ||
236: ui->ui_vbanum != vban && ui->ui_vbanum != '?')
237: continue;
238: octlr = ui->ui_ctlr, ui->ui_ctlr = um->um_ctlr;
239: if ((*udp->ud_slave)(ui, reg)) {
240: ui->ui_alive = 1;
241: ui->ui_ctlr = um->um_ctlr;
242: ui->ui_vbanum = vban;
243: ui->ui_addr = (caddr_t)reg;
244: ui->ui_physaddr = (caddr_t)addr;
245: if (ui->ui_dk && dkn < DK_NDRIVE)
246: ui->ui_dk = dkn++;
247: else
248: ui->ui_dk = -1;
249: ui->ui_mi = um;
250: ui->ui_hd = vhp;
251: /* ui_type comes from driver */
252: udp->ud_dinfo[ui->ui_unit] = ui;
253: printf("%s%d at %s%d slave %d",
254: udp->ud_dname, ui->ui_unit,
255: udp->ud_mname, um->um_ctlr,
256: ui->ui_slave);
257: (*udp->ud_attach)(ui);
258: printf("\n");
259: } else
260: ui->ui_ctlr = octlr;
261: }
262: break;
263: }
264: }
265: /*
266: * Now look for non-mass storage peripherals.
267: */
268: for (ui = vbdinit; udp = ui->ui_driver; ui++) {
269: if (ui->ui_vbanum != vban && ui->ui_vbanum != '?' ||
270: ui->ui_alive || ui->ui_slave != -1)
271: continue;
272: addr = (long)ui->ui_addr;
273: for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) {
274: if (VBIOMAPPED(addr)) {
275: if (VALLOC(addr))
276: continue;
277: reg = vbaddr(addr);
278: } else
279: reg = (u_short *)addr;
280: ui->ui_hd = vhp;
281: cvec = SCB_LASTIV, cold &= ~0x2;
282: i = (*udp->ud_probe)(reg, ui);
283: cold |= 0x2;
284: if (i == 0)
285: continue;
286: printf("%s%d at vba%d csr %x ",
287: ui->ui_driver->ud_dname, ui->ui_unit, vban, addr);
288: if (ui->ui_intr) {
289: if (cvec < 0 && vhp->vh_lastiv == cvec) {
290: printf("no space for vector(s)\n");
291: continue;
292: }
293: if (cvec == SCB_LASTIV) {
294: printf("didn't interrupt\n");
295: continue;
296: }
297: printf("vec %x, ipl %x\n", cvec, br);
298: for (ivec = ui->ui_intr; *ivec; ivec++)
299: ((long *)&scb)[cvec++] = (long)*ivec;
300: } else
301: printf("no interrupts\n");
302: csralloc(valloc, addr, i);
303: ui->ui_alive = 1;
304: ui->ui_vbanum = vban;
305: if (VBIOMAPPED(addr))
306: ui->ui_addr = (caddr_t)reg;
307: ui->ui_physaddr = (caddr_t)addr;
308: ui->ui_dk = -1;
309: /* ui_type comes from driver */
310: udp->ud_dinfo[ui->ui_unit] = ui;
311: (*udp->ud_attach)(ui);
312: break;
313: }
314: }
315: free(valloc, M_TEMP);
316: }
317:
318: /*
319: * Mark addresses starting at addr and continuing
320: * size bytes as allocated in the map.
321: * Warn if the new allocation overlaps a previous allocation.
322: */
323: csralloc(valloc, addr, size)
324: caddr_t valloc;
325: long addr;
326: register int size;
327: {
328: register caddr_t p;
329: int warned = 0;
330:
331: if (!VBIOMAPPED(addr))
332: return;
333: size = VSIZE(size);
334: p = &VALLOC(addr) + size;
335: while (--size >= 0) {
336: if (*--p && !warned) {
337: printf(
338: "WARNING: device registers overlap those for a previous device\n");
339: warned = 1;
340: }
341: *p = 1;
342: }
343: }
344:
345: /*
346: * Tahoe VERSAbus adapator support routines.
347: */
348:
349: caddr_t vbcur = (caddr_t)&vbbase;
350: int vbx = 0;
351: /*
352: * Allocate page tables for mapping intermediate i/o buffers.
353: * Called by device drivers during autoconfigure.
354: */
355: vbmapalloc(npf, ppte, putl)
356: int npf;
357: struct pte **ppte;
358: caddr_t *putl;
359: {
360:
361: if (vbcur + npf*NBPG > (caddr_t)&vbend)
362: return (0);
363: *ppte = &VBmap[vbx];
364: *putl = vbcur;
365: vbx += npf;
366: vbcur += npf*NBPG;
367: return (1);
368: }
369:
370: caddr_t vbmcur = (caddr_t)&vmem1;
371: int vbmx = 0;
372: /*
373: * Allocate page tables and map VERSAbus i/o space.
374: * Called by device drivers during autoconfigure.
375: */
376: vbmemalloc(npf, addr, ppte, putl)
377: int npf;
378: caddr_t addr;
379: struct pte **ppte;
380: caddr_t *putl;
381: {
382:
383: if (vbmcur + npf*NBPG > (caddr_t)&vmemend)
384: return (0);
385: *ppte = &VMEMmap1[vbmx];
386: *putl = vbmcur;
387: vbmx += npf;
388: vbmcur += npf*NBPG;
389: vbaccess(*ppte, addr, npf); /* map i/o space */
390: return (1);
391: }
392:
393: /*
394: * Configure swap space and related parameters.
395: */
396: swapconf()
397: {
398: register struct swdevt *swp;
399: register int nblks;
400:
401: for (swp = swdevt; swp->sw_dev; swp++)
402: if (bdevsw[major(swp->sw_dev)].d_psize) {
403: nblks =
404: (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev);
405: if (nblks != -1 &&
406: (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
407: swp->sw_nblks = nblks;
408: }
409: dumpconf();
410: }
411:
412: #define DOSWAP /* change swdevt, argdev, and dumpdev too */
413: u_long bootdev; /* should be dev_t, but not until 32 bits */
414:
415: static char devname[][2] = {
416: 0,0, /* 0 = ud */
417: 'd','k', /* 1 = vd */
418: 0,0, /* 2 = xp */
419: };
420:
421: #define PARTITIONMASK 0x7
422: #define PARTITIONSHIFT 3
423:
424: /*
425: * Attempt to find the device from which we were booted.
426: * If we can do so, and not instructed not to do so,
427: * change rootdev to correspond to the load device.
428: */
429: setroot()
430: {
431: int majdev, mindev, unit, part, controller, adaptor;
432: dev_t temp, orootdev;
433: struct swdevt *swp;
434:
435: if (boothowto & RB_DFLTROOT ||
436: (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
437: return;
438: majdev = B_TYPE(bootdev);
439: if (majdev >= sizeof(devname) / sizeof(devname[0]))
440: return;
441: adaptor = B_ADAPTOR(bootdev);
442: controller = B_CONTROLLER(bootdev);
443: part = B_PARTITION(bootdev);
444: unit = B_UNIT(bootdev);
445: /*
446: * Search Versabus devices.
447: *
448: * WILL HAVE TO DISTINGUISH VME/VERSABUS SOMETIME
449: */
450: {
451: register struct vba_device *vbap;
452:
453: for (vbap = vbdinit; vbap->ui_driver; vbap++)
454: if (vbap->ui_alive && vbap->ui_slave == unit &&
455: vbap->ui_ctlr == controller &&
456: vbap->ui_vbanum == adaptor &&
457: vbap->ui_driver->ud_dname[0] == devname[majdev][0] &&
458: vbap->ui_driver->ud_dname[1] == devname[majdev][1])
459: break;
460: if (vbap->ui_driver == 0)
461: return;
462: mindev = vbap->ui_unit;
463: }
464: mindev = (mindev << PARTITIONSHIFT) + part;
465: orootdev = rootdev;
466: rootdev = makedev(majdev, mindev);
467: /*
468: * If the original rootdev is the same as the one
469: * just calculated, don't need to adjust the swap configuration.
470: */
471: if (rootdev == orootdev)
472: return;
473: printf("changing root device to %c%c%d%c\n",
474: devname[majdev][0], devname[majdev][1],
475: mindev >> PARTITIONSHIFT, part + 'a');
476: #ifdef DOSWAP
477: mindev &= ~PARTITIONMASK;
478: for (swp = swdevt; swp->sw_dev; swp++) {
479: if (majdev == major(swp->sw_dev) &&
480: mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) {
481: temp = swdevt[0].sw_dev;
482: swdevt[0].sw_dev = swp->sw_dev;
483: swp->sw_dev = temp;
484: break;
485: }
486: }
487: if (swp->sw_dev == 0)
488: return;
489: /*
490: * If argdev and dumpdev were the same as the old primary swap
491: * device, move them to the new primary swap device.
492: */
493: if (temp == dumpdev)
494: dumpdev = swdevt[0].sw_dev;
495: if (temp == argdev)
496: argdev = swdevt[0].sw_dev;
497: #endif
498: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.