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