BSD 4_3 release
[unix-history] / usr / src / sys / vax / autoconf.c
CommitLineData
da7c5cc6 1/*
42b84df5 2 * Copyright (c) 1982,1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
95f51977 6 * @(#)autoconf.c 7.1 (Berkeley) 6/6/86
da7c5cc6 7 */
327f6ec8 8
327f6ec8 9/*
d565635a
BJ
10 * Setup the system to run on the current machine.
11 *
12 * Configure() is called at boot time and initializes the uba and mba
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.
327f6ec8
BJ
16 */
17
47fa50b1 18#include "mba.h"
976a5707 19#include "uba.h"
47fa50b1 20
1884f3f6 21#include "pte.h"
961945a8 22
1884f3f6
JB
23#include "param.h"
24#include "systm.h"
25#include "map.h"
26#include "buf.h"
95f51977 27#include "dk.h"
1884f3f6
JB
28#include "vm.h"
29#include "conf.h"
30#include "dmap.h"
42b84df5 31#include "reboot.h"
cd3da95f 32
1884f3f6
JB
33#include "cpu.h"
34#include "mem.h"
35#include "mtpr.h"
36#include "nexus.h"
37#include "scb.h"
cb4a08d0 38#include "ioa.h"
cd3da95f
BJ
39#include "../vaxmba/mbareg.h"
40#include "../vaxmba/mbavar.h"
41#include "../vaxuba/ubareg.h"
42#include "../vaxuba/ubavar.h"
327f6ec8 43
d565635a
BJ
44/*
45 * The following several variables are related to
46 * the configuration process, and are used in initializing
47 * the machine.
48 */
49int cold; /* if 1, still working on cold-start */
66ca574e 50int nexnum; /* current nexus number */
95f51977 51int nsbi; /* current sbi number */
d565635a 52int dkn; /* number of iostat dk numbers assigned so far */
3327052b 53int cpuspeed = 1; /* relative cpu speed */
327f6ec8 54
d565635a
BJ
55/*
56 * Addresses of the (locore) routines which bootstrap us from
57 * hardware traps to C code. Filled into the system control block
58 * as necessary.
59 */
47fa50b1 60#if NMBA > 0
8d2ea14f 61int (*mbaintv[4])() = { Xmba0int, Xmba1int, Xmba2int, Xmba3int };
cb4a08d0
JB
62#if NMBA > 4
63 Need to expand the table for more than 4 massbus adaptors
47fa50b1 64#endif
cb4a08d0
JB
65#endif
66#if defined(VAX780) || defined(VAX8600)
67int (*ubaintv[])() =
68{
69 Xua0int, Xua1int, Xua2int, Xua3int,
70#if NUBA > 4
71 Xua4int, Xua5int, Xua6int, Xua7int,
72#endif
73#if NUBA > 8
74 Need to expand the table for more than 8 unibus adaptors
75#endif
76};
5aa9d5ea 77#endif
d565635a
BJ
78
79/*
80 * This allocates the space for the per-uba information,
81 * such as buffered data path usage.
82 */
9b95def8 83struct uba_hd uba_hd[NUBA];
327f6ec8
BJ
84
85/*
86 * Determine mass storage and memory configuration for a machine.
87 * Get cpu type, and then switch out to machine specific procedures
88 * which will probe adaptors to see what is out there.
89 */
90configure()
91{
92 union cpusid cpusid;
3f3a34c3 93 register struct percpu *ocp;
a0eab615 94 register int *ip;
3e7ee2db 95 extern char Sysbase[];
327f6ec8
BJ
96
97 cpusid.cpusid = mfpr(SID);
b17fedcd 98 for (ocp = percpu; ocp->pc_cputype; ocp++)
3f3a34c3 99 if (ocp->pc_cputype == cpusid.cpuany.cp_type) {
3327052b 100 cpuspeed = ocp->pc_cpuspeed;
0fe372b3 101 probeio(ocp);
d565635a 102 /*
096eb64d
SL
103 * Write protect the scb and UNIBUS interrupt vectors.
104 * It is strange that this code is here, but this is
105 * as soon as we are done mucking with it, and the
d565635a
BJ
106 * write-enable was done in assembly language
107 * to which we will never return.
108 */
0b1784af 109 ip = (int *)Sysmap + 1; *ip &= ~PG_PROT; *ip |= PG_KR;
096eb64d
SL
110 ip++; *ip &= ~PG_PROT; *ip |= PG_KR;
111#if NUBA > 1
112 ip++; *ip &= ~PG_PROT; *ip |= PG_KR;
113#endif
3e7ee2db 114 mtpr(TBIS, Sysbase);
d565635a 115#if GENERIC
25cfc74b
MK
116 if ((boothowto & RB_ASKNAME) == 0)
117 setroot();
118 setconf();
cd97bee2 119#else
25cfc74b 120 setroot();
d565635a 121#endif
9f0281aa
SL
122 /*
123 * Configure swap area and related system
124 * parameter based on device(s) used.
125 */
126 swapconf();
8d2ea14f 127 cold = 0;
c9e9b65b 128 memenable();
3f3a34c3
BJ
129 return;
130 }
d565635a 131 printf("cpu type %d not configured\n", cpusid.cpuany.cp_type);
327f6ec8
BJ
132 asm("halt");
133}
134
0fe372b3
MK
135/*
136 * Probe the main IO bus(es).
137 * The percpu structure gives us a handle on the addresses and/or types.
138 */
139probeio(pcpu)
140 register struct percpu *pcpu;
cb4a08d0 141{
0fe372b3 142 register struct iobus *iob;
cb4a08d0
JB
143 int ioanum;
144
145 ioanum = 0;
0fe372b3
MK
146 for (iob = pcpu->pc_io; ioanum < pcpu->pc_nioa; ioanum++, iob++) {
147
148 switch (iob->io_type) {
149
95f51977 150#if VAX780 || VAX750 || VAX730 || VAX630
0fe372b3
MK
151 case IO_SBI780:
152 case IO_CMI750:
153 case IO_XXX730:
95f51977 154 case IO_QBUS:
0fe372b3 155 probenexi((struct nexusconnect *)iob->io_details);
cb4a08d0
JB
156 break;
157#endif
0fe372b3 158
cb4a08d0 159#if VAX8600
0fe372b3
MK
160 case IO_ABUS:
161 probe_Abus(ioanum, iob);
cb4a08d0
JB
162 break;
163#endif
164 default:
0fe372b3
MK
165 if (iob->io_addr) {
166 printf(
167 "IO adaptor %d, type %d, at address 0x%x is unsupported\n",
168 ioanum, iob->io_type, iob->io_addr);
cb4a08d0 169 } else
0fe372b3
MK
170 printf("IO adaptor %d, type %d, is unsupported\n",
171 ioanum, iob->io_type);
172 break;
cb4a08d0
JB
173 }
174 }
175}
176
0fe372b3
MK
177#if VAX8600
178probe_Abus(ioanum, iob)
179 register struct iobus *iob;
180{
181 register struct ioa *ioap;
182 union ioacsr ioacsr;
183 int type;
184 struct sbia_regs *sbiaregs;
185
186 ioap = &ioa[ioanum];
121c4a08 187 ioaccess(iob->io_addr, Ioamap[ioanum], iob->io_size);
0fe372b3
MK
188 if (badaddr((caddr_t)ioap, 4))
189 return;
190 ioacsr.ioa_csr = ioap->ioacsr.ioa_csr;
191 type = ioacsr.ioa_type & IOA_TYPMSK;
192
193 switch (type) {
194
195 case IOA_SBIA:
196 printf("SBIA%d at IO adaptor %d address 0x%x\n",
197 nsbi, ioanum, iob->io_addr);
198 probenexi((struct nexusconnect *)iob->io_details);
199 nsbi++;
200 sbiaregs = (struct sbia_regs *)ioap;
201 sbiaregs->sbi_errsum = -1;
202 sbiaregs->sbi_error = 0x1000;
203 sbiaregs->sbi_fltsts = 0xc0000;
204 break;
205
206 default:
207 printf("IOA%d at address 0x%x is unsupported (type = 0x%x)\n",
208 ioanum, iob->io_addr, ioacsr.ioa_type);
209 break;
210 }
211}
212#endif
213
327f6ec8 214/*
b17fedcd
BJ
215 * Probe nexus space, finding the interconnects
216 * and setting up and probing mba's and uba's for devices.
327f6ec8 217 */
a0eab615 218/*ARGSUSED*/
0fe372b3
MK
219probenexi(pnc)
220 register struct nexusconnect *pnc;
327f6ec8
BJ
221{
222 register struct nexus *nxv;
0fe372b3 223 struct nexus *nxp = pnc->psb_nexbase;
327f6ec8 224 union nexcsr nexcsr;
e83ccfd7 225 int i;
327f6ec8 226
cdd3a7e3 227 nexnum = 0, nxv = &nexus[nsbi * NNEXSBI];
0fe372b3 228 for (; nexnum < pnc->psb_nnexus; nexnum++, nxp++, nxv++) {
cdd3a7e3 229 ioaccess((caddr_t)nxp, Nexmap[nsbi * NNEXSBI + nexnum],
0fe372b3 230 sizeof(struct nexus));
327f6ec8
BJ
231 if (badaddr((caddr_t)nxv, 4))
232 continue;
0fe372b3
MK
233 if (pnc->psb_nextype && pnc->psb_nextype[nexnum] != NEX_ANY)
234 nexcsr.nex_csr = pnc->psb_nextype[nexnum];
b17fedcd
BJ
235 else
236 nexcsr = nxv->nexcsr;
327f6ec8
BJ
237 if (nexcsr.nex_csr&NEX_APD)
238 continue;
327f6ec8
BJ
239 switch (nexcsr.nex_type) {
240
241 case NEX_MBA:
8d2ea14f 242 printf("mba%d at tr%d\n", nummba, nexnum);
a7e7fa7e 243 if (nummba >= NMBA) {
9b95def8 244 printf("%d mba's", nummba++);
a0eab615 245 goto unconfig;
a7e7fa7e 246 }
d565635a 247#if NMBA > 0
3f3a34c3 248 mbafind(nxv, nxp);
5aa9d5ea 249 nummba++;
47fa50b1 250#endif
d565635a 251 break;
327f6ec8
BJ
252
253 case NEX_UBA0:
254 case NEX_UBA1:
255 case NEX_UBA2:
256 case NEX_UBA3:
d565635a 257 printf("uba%d at tr%d\n", numuba, nexnum);
e870748a 258#if VAX750
9b95def8
MK
259 if (numuba >= 2 && cpu == VAX_750) {
260 printf("More than 2 UBA's");
3f3a34c3
BJ
261 goto unsupp;
262 }
9b95def8
MK
263#endif
264 if (numuba >= NUBA) {
cb4a08d0 265 printf("%d uba's", ++numuba);
9b95def8
MK
266 goto unconfig;
267 }
cb4a08d0
JB
268#if defined(VAX780) || defined(VAX8600)
269 if ((cpu == VAX_780) || (cpu == VAX_8600))
e83ccfd7
BJ
270 setscbnex(ubaintv[numuba]);
271#endif
3f3a34c3 272 i = nexcsr.nex_type - NEX_UBA0;
66ca574e 273 unifind((struct uba_regs *)nxv, (struct uba_regs *)nxp,
95f51977
C
274 umem[numuba], pnc->psb_umaddr[i], UMEMmap[numuba],
275 pnc->psb_haveubasr);
276#if defined(VAX780) || defined(VAX8600)
277 if ((cpu == VAX_780) || (cpu == VAX_8600))
66ca574e
C
278 ((struct uba_regs *)nxv)->uba_cr =
279 UBACR_IFS|UBACR_BRIE|
280 UBACR_USEFIE|UBACR_SUEFIE|
281 (((struct uba_regs *)nxv)->uba_cr&0x7c000000);
282#endif
283 numuba++;
327f6ec8
BJ
284 break;
285
286 case NEX_DR32:
5aa9d5ea 287 /* there can be more than one... are there other codes??? */
327f6ec8
BJ
288 printf("dr32");
289 goto unsupp;
290
291 case NEX_MEM4:
292 case NEX_MEM4I:
293 case NEX_MEM16:
294 case NEX_MEM16I:
2d192058
MK
295 printf("mcr%d at tr%d\n", nmcr, nexnum);
296 if (nmcr >= 4) {
297 printf("5 mcr's");
298 goto unsupp;
299 }
300 switch (cpu) {
301 case VAX_780:
302 mcrtype[nmcr] = M780C;
303 break;
304 case VAX_750:
305 mcrtype[nmcr] = M750;
306 break;
307 case VAX_730:
308 mcrtype[nmcr] = M730;
309 break;
310 }
311 mcraddr[nmcr++] = (struct mcr *)nxv;
312 break;
313
314 case NEX_MEM64I:
096eb64d
SL
315 case NEX_MEM64L:
316 case NEX_MEM64LI:
96f412b7
JB
317 case NEX_MEM256I:
318 case NEX_MEM256L:
319 case NEX_MEM256LI:
2d192058
MK
320 printf("mcr%d (el) at tr%d\n", nmcr, nexnum);
321 if (nmcr >= 4) {
322 printf("5 mcr's");
323 goto unsupp;
324 }
325 if (cpu == VAX_780)
326 mcrtype[nmcr] = M780EL;
327 mcraddr[nmcr++] = (struct mcr *)nxv;
96f412b7
JB
328 if (nexcsr.nex_type != NEX_MEM64I &&
329 nexcsr.nex_type != NEX_MEM256I)
2d192058
MK
330 break;
331 /* fall into ... */
332
096eb64d
SL
333 case NEX_MEM64U:
334 case NEX_MEM64UI:
96f412b7
JB
335 case NEX_MEM256U:
336 case NEX_MEM256UI:
2d192058 337 printf("mcr%d (eu) at tr%d\n", nmcr, nexnum);
30d13fef 338 if (nmcr >= 4) {
d565635a 339 printf("5 mcr's");
3f3a34c3
BJ
340 goto unsupp;
341 }
2d192058
MK
342 if (cpu == VAX_780)
343 mcrtype[nmcr] = M780EU;
3f3a34c3 344 mcraddr[nmcr++] = (struct mcr *)nxv;
327f6ec8
BJ
345 break;
346
347 case NEX_MPM0:
348 case NEX_MPM1:
349 case NEX_MPM2:
350 case NEX_MPM3:
351 printf("mpm");
352 goto unsupp;
353
096eb64d
SL
354 case NEX_CI:
355 printf("ci");
356 goto unsupp;
357
327f6ec8
BJ
358 default:
359 printf("nexus type %x", nexcsr.nex_type);
30d13fef 360unsupp:
3f3a34c3 361 printf(" unsupported (at tr %d)\n", nexnum);
327f6ec8 362 continue;
d565635a
BJ
363unconfig:
364 printf(" not configured\n");
365 continue;
327f6ec8
BJ
366 }
367 }
9b95def8
MK
368 if (nummba > NMBA)
369 nummba = NMBA;
370 if (numuba > NUBA)
371 numuba = NUBA;
327f6ec8 372}
30d13fef 373
47fa50b1 374#if NMBA > 0
b721b0ed 375struct mba_device *mbaconfig();
327f6ec8
BJ
376/*
377 * Find devices attached to a particular mba
378 * and look for each device found in the massbus
379 * initialization tables.
380 */
3f3a34c3 381mbafind(nxv, nxp)
30d13fef 382 struct nexus *nxv, *nxp;
327f6ec8
BJ
383{
384 register struct mba_regs *mdp;
385 register struct mba_drv *mbd;
b721b0ed
BJ
386 register struct mba_device *mi;
387 register struct mba_slave *ms;
299100bf 388 int dn, dt, sn;
a0eab615 389 struct mba_device fnd;
327f6ec8 390
3f3a34c3 391 mdp = (struct mba_regs *)nxv;
5aa9d5ea
RE
392 mba_hd[nummba].mh_mba = mdp;
393 mba_hd[nummba].mh_physmba = (struct mba_regs *)nxp;
a0eab615 394 setscbnex(mbaintv[nummba]);
327f6ec8 395 fnd.mi_mba = mdp;
5aa9d5ea 396 fnd.mi_mbanum = nummba;
327f6ec8 397 for (mbd = mdp->mba_drv, dn = 0; mbd < &mdp->mba_drv[8]; mbd++, dn++) {
0cf493bf
BJ
398 if ((mbd->mbd_ds&MBDS_DPR) == 0)
399 continue;
51ee2ebf 400 mdp->mba_sr |= MBSR_NED; /* si kludge */
327f6ec8
BJ
401 dt = mbd->mbd_dt & 0xffff;
402 if (dt == 0)
403 continue;
51ee2ebf
BJ
404 if (mdp->mba_sr&MBSR_NED)
405 continue; /* si kludge */
327f6ec8
BJ
406 if (dt == MBDT_MOH)
407 continue;
408 fnd.mi_drive = dn;
299100bf
RE
409#define qeq(a, b) ( a == b || a == '?' )
410 if ((mi = mbaconfig(&fnd, dt)) && (dt & MBDT_TAP))
411 for (sn = 0; sn < 8; sn++) {
412 mbd->mbd_tc = sn;
413 for (ms = mbsinit; ms->ms_driver; ms++)
414 if (ms->ms_driver == mi->mi_driver &&
415 ms->ms_alive == 0 &&
416 qeq(ms->ms_ctlr, mi->mi_unit) &&
417 qeq(ms->ms_slave, sn) &&
418 (*ms->ms_driver->md_slave)(mi, ms, sn)) {
419 printf("%s%d at %s%d slave %d\n"
420 , ms->ms_driver->md_sname
421 , ms->ms_unit
422 , mi->mi_driver->md_dname
423 , mi->mi_unit
424 , sn
425 );
d565635a
BJ
426 ms->ms_alive = 1;
427 ms->ms_ctlr = mi->mi_unit;
299100bf 428 ms->ms_slave = sn;
b721b0ed 429 }
299100bf 430 }
327f6ec8 431 }
66ca574e
C
432 mdp->mba_cr = MBCR_INIT;
433 mdp->mba_cr = MBCR_IE;
327f6ec8
BJ
434}
435
436/*
437 * Have found a massbus device;
438 * see if it is in the configuration table.
439 * If so, fill in its data.
440 */
b721b0ed 441struct mba_device *
327f6ec8 442mbaconfig(ni, type)
b721b0ed 443 register struct mba_device *ni;
327f6ec8
BJ
444 register int type;
445{
b721b0ed 446 register struct mba_device *mi;
327f6ec8 447 register short *tp;
71236e46 448 register struct mba_hd *mh;
327f6ec8 449
b721b0ed 450 for (mi = mbdinit; mi->mi_driver; mi++) {
327f6ec8
BJ
451 if (mi->mi_alive)
452 continue;
453 tp = mi->mi_driver->md_type;
454 for (mi->mi_type = 0; *tp; tp++, mi->mi_type++)
295446f8 455 if (*tp == (type&MBDT_TYPE))
327f6ec8
BJ
456 goto found;
457 continue;
458found:
459#define match(fld) (ni->fld == mi->fld || mi->fld == '?')
b721b0ed 460 if (!match(mi_drive) || !match(mi_mbanum))
327f6ec8 461 continue;
66ca574e 462 printf("%s%d at mba%d drive %d\n",
b721b0ed
BJ
463 mi->mi_driver->md_dname, mi->mi_unit,
464 ni->mi_mbanum, ni->mi_drive);
327f6ec8 465 mi->mi_alive = 1;
71236e46
BJ
466 mh = &mba_hd[ni->mi_mbanum];
467 mi->mi_hd = mh;
468 mh->mh_mbip[ni->mi_drive] = mi;
469 mh->mh_ndrive++;
327f6ec8
BJ
470 mi->mi_mba = ni->mi_mba;
471 mi->mi_drv = &mi->mi_mba->mba_drv[ni->mi_drive];
327f6ec8
BJ
472 mi->mi_mbanum = ni->mi_mbanum;
473 mi->mi_drive = ni->mi_drive;
0d7a9a27
SL
474 /*
475 * If drive has never been seen before,
476 * give it a dkn for statistics.
477 */
478 if (mi->mi_driver->md_info[mi->mi_unit] == 0) {
479 mi->mi_driver->md_info[mi->mi_unit] = mi;
480 if (mi->mi_dk && dkn < DK_NDRIVE)
481 mi->mi_dk = dkn++;
482 else
483 mi->mi_dk = -1;
484 }
b721b0ed
BJ
485 (*mi->mi_driver->md_attach)(mi);
486 return (mi);
327f6ec8 487 }
b721b0ed 488 return (0);
327f6ec8 489}
47fa50b1 490#endif
327f6ec8 491
3f3a34c3 492/*
30d13fef
BJ
493 * Fixctlrmask fixes the masks of the driver ctlr routines
494 * which otherwise save r10 and r11 where the interrupt and br
495 * level are passed through.
496 */
497fixctlrmask()
498{
b721b0ed
BJ
499 register struct uba_ctlr *um;
500 register struct uba_device *ui;
30d13fef
BJ
501 register struct uba_driver *ud;
502#define phys(a,b) ((b)(((int)(a))&0x7fffffff))
503
504 for (um = ubminit; ud = phys(um->um_driver, struct uba_driver *); um++)
71236e46 505 *phys(ud->ud_probe, short *) &= ~0xc00;
30d13fef 506 for (ui = ubdinit; ud = phys(ui->ui_driver, struct uba_driver *); ui++)
71236e46 507 *phys(ud->ud_probe, short *) &= ~0xc00;
30d13fef
BJ
508}
509
510/*
511 * Find devices on a UNIBUS.
512 * Uses per-driver routine to set <br,cvec> into <r11,r10>,
513 * and then fills in the tables, with help from a per-driver
514 * slave initialization routine.
3f3a34c3 515 */
95f51977 516unifind(vubp, pubp, vumem, pumem, memmap, haveubasr)
66ca574e
C
517 struct uba_regs *vubp, *pubp;
518 caddr_t vumem, pumem;
519 struct pte *memmap;
95f51977 520 int haveubasr;
327f6ec8 521{
a0eab615 522#ifndef lint
30d13fef 523 register int br, cvec; /* MUST BE r11, r10 */
a0eab615
BJ
524#else
525 /*
526 * Lint doesn't realize that these
527 * can be initialized asynchronously
528 * when devices interrupt.
529 */
530 register int br = 0, cvec = 0;
531#endif
b721b0ed
BJ
532 register struct uba_device *ui;
533 register struct uba_ctlr *um;
299100bf 534 u_short *reg, *ap, addr;
66ca574e 535 struct uba_hd *uhp;
327f6ec8 536 struct uba_driver *udp;
cb4a08d0 537 int i, (**ivec)();
299100bf 538 caddr_t ualloc, zmemall();
46a2d5b2 539 extern int catcher[256];
03d3d455 540
95f51977
C
541#if VAX630
542 /*
543 * The map registers start right at 20088000 on the
544 * ka630, so we have to subtract out the 2k offset to make the
545 * pointers work..
546 */
547 if (cpu == VAX_630) {
548 vubp = (struct uba_regs *)(((u_long)vubp)-0x800);
549 pubp = (struct uba_regs *)(((u_long)pubp)-0x800);
550 }
551#endif
30d13fef
BJ
552 /*
553 * Initialize the UNIBUS, by freeing the map
554 * registers and the buffered data path registers
555 */
66ca574e 556 uhp = &uba_hd[numuba];
30d13fef 557 uhp->uh_map = (struct map *)calloc(UAMSIZ * sizeof (struct map));
9305c2b9 558 ubainitmaps(uhp);
327f6ec8 559
30d13fef 560 /*
66ca574e
C
561 * Save virtual and physical addresses
562 * of adaptor, and allocate and initialize
563 * the UNIBUS interrupt vector.
564 */
565 uhp->uh_uba = vubp;
566 uhp->uh_physuba = pubp;
95f51977 567 /*
121c4a08
MK
568 * On the 8600, can't use UNIvec;
569 * the vectors for the second SBI overlap it.
570 */
cb4a08d0
JB
571 if (cpu == VAX_8600)
572 uhp->uh_vec = (int(**)())calloc(512);
95f51977 573 else if (numuba == 0)
30d13fef 574 uhp->uh_vec = UNIvec;
096eb64d
SL
575#if NUBA > 1
576 else if (numuba == 1)
577 uhp->uh_vec = UNI1vec;
9b95def8
MK
578 else
579 uhp->uh_vec = (int(**)())calloc(512);
096eb64d 580#endif
30d13fef
BJ
581 for (i = 0; i < 128; i++)
582 uhp->uh_vec[i] =
583 scbentry(&catcher[i*2], SCB_ISTACK);
64614526
BJ
584 /*
585 * Set last free interrupt vector for devices with
586 * programmable interrupt vectors. Use is to decrement
587 * this number and use result as interrupt vector.
588 */
589 uhp->uh_lastiv = 0x200;
590
95f51977
C
591#if VAX630
592 /*
593 * Kludge time again. The q22 memory and device reg. address spaces
594 * are not physically contiguous, so we need 2 loops to map them
595 * into contiguous virtual space.
596 */
597 if (cpu == VAX_630) {
598 ioaccess(pumem, memmap, (UBAPAGES-16)*NBPG);
599 ioaccess(0x20000000, memmap+(UBAPAGES-16), 16*NBPG);
600 } else
601#endif
602 ioaccess(pumem, memmap, UBAPAGES * NBPG);
603#if defined(VAX780) || defined(VAX8600)
66ca574e 604 if (haveubasr) {
30d13fef 605 vubp->uba_sr = vubp->uba_sr;
b721b0ed 606 vubp->uba_cr = UBACR_IFS|UBACR_BRIE;
327f6ec8 607 }
327f6ec8 608#endif
e870748a
MK
609 /*
610 * First configure devices that have unibus memory,
611 * allowing them to allocate the correct map registers.
612 */
613 ubameminit(numuba);
299100bf
RE
614 /*
615 * Grab some memory to record the umem address space we allocate,
616 * so we can be sure not to place two devices at the same address.
617 *
618 * We could use just 1/8 of this (we only want a 1 bit flag) but
619 * we are going to give it back anyway, and that would make the
620 * code here bigger (which we can't give back), so ...
621 *
622 * One day, someone will make a unibus with something other than
623 * an 8K i/o address space, & screw this totally.
624 */
625 ualloc = zmemall(memall, 8*1024);
626 if (ualloc == (caddr_t)0)
627 panic("no mem for unifind");
628
30d13fef
BJ
629 /*
630 * Map the first page of UNIBUS i/o
631 * space to the first page of memory
632 * for devices which will need to dma
633 * output to produce an interrupt.
634 */
66ca574e 635 *(int *)(&vubp->uba_map[0]) = UBAMR_MRV;
30d13fef 636
66ca574e
C
637#define ubaoff(off) ((off)&0x1fff)
638#define ubaddr(off) (u_short *)((int)vumem + (ubaoff(off)|0x3e000))
30d13fef
BJ
639 /*
640 * Check each unibus mass storage controller.
641 * For each one which is potentially on this uba,
642 * see if it is really there, and if it is record it and
643 * then go looking for slaves.
644 */
645 for (um = ubminit; udp = um->um_driver; um++) {
646 if (um->um_ubanum != numuba && um->um_ubanum != '?')
647 continue;
648 addr = (u_short)um->um_addr;
299100bf
RE
649 /*
650 * use the particular address specified first,
651 * or if it is given as "0", of there is no device
652 * at that address, try all the standard addresses
653 * in the driver til we find it
654 */
655 for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) {
656
66ca574e 657 if (ualloc[ubaoff(addr)])
299100bf 658 continue;
66ca574e 659 reg = ubaddr(addr);
30d13fef 660 if (badaddr((caddr_t)reg, 2))
327f6ec8 661 continue;
95f51977 662#if defined(VAX780) || defined(VAX8600)
66ca574e 663 if (haveubasr && vubp->uba_sr) {
8d2ea14f
BJ
664 vubp->uba_sr = vubp->uba_sr;
665 continue;
30d13fef 666 }
327f6ec8 667#endif
30d13fef 668 cvec = 0x200;
e870748a 669 i = (*udp->ud_probe)(reg, um->um_ctlr, um);
95f51977 670#if defined(VAX780) || defined(VAX8600)
66ca574e 671 if (haveubasr && vubp->uba_sr) {
8d2ea14f
BJ
672 vubp->uba_sr = vubp->uba_sr;
673 continue;
30d13fef 674 }
327f6ec8 675#endif
30d13fef
BJ
676 if (i == 0)
677 continue;
8d2ea14f
BJ
678 printf("%s%d at uba%d csr %o ",
679 udp->ud_mname, um->um_ctlr, numuba, addr);
30d13fef
BJ
680 if (cvec == 0) {
681 printf("zero vector\n");
682 continue;
683 }
684 if (cvec == 0x200) {
685 printf("didn't interrupt\n");
686 continue;
687 }
8d2ea14f 688 printf("vec %o, ipl %x\n", cvec, br);
30d13fef
BJ
689 um->um_alive = 1;
690 um->um_ubanum = numuba;
691 um->um_hd = &uba_hd[numuba];
692 um->um_addr = (caddr_t)reg;
693 udp->ud_minfo[um->um_ctlr] = um;
694 for (ivec = um->um_intr; *ivec; ivec++) {
695 um->um_hd->uh_vec[cvec/4] =
696 scbentry(*ivec, SCB_ISTACK);
697 cvec += 4;
698 }
699 for (ui = ubdinit; ui->ui_driver; ui++) {
700 if (ui->ui_driver != udp || ui->ui_alive ||
701 ui->ui_ctlr != um->um_ctlr && ui->ui_ctlr != '?' ||
702 ui->ui_ubanum != numuba && ui->ui_ubanum != '?')
327f6ec8 703 continue;
8d2ea14f 704 if ((*udp->ud_slave)(ui, reg)) {
30d13fef
BJ
705 ui->ui_alive = 1;
706 ui->ui_ctlr = um->um_ctlr;
707 ui->ui_ubanum = numuba;
708 ui->ui_hd = &uba_hd[numuba];
709 ui->ui_addr = (caddr_t)reg;
ddbbb5fb 710 ui->ui_physaddr = pumem + ubdevreg(addr);
8d2ea14f 711 if (ui->ui_dk && dkn < DK_NDRIVE)
0801d37f 712 ui->ui_dk = dkn++;
8d2ea14f
BJ
713 else
714 ui->ui_dk = -1;
30d13fef
BJ
715 ui->ui_mi = um;
716 /* ui_type comes from driver */
717 udp->ud_dinfo[ui->ui_unit] = ui;
8d2ea14f
BJ
718 printf("%s%d at %s%d slave %d\n",
719 udp->ud_dname, ui->ui_unit,
720 udp->ud_mname, um->um_ctlr, ui->ui_slave);
71236e46 721 (*udp->ud_attach)(ui);
327f6ec8 722 }
30d13fef 723 }
299100bf
RE
724 break;
725 }
30d13fef
BJ
726 }
727 /*
728 * Now look for non-mass storage peripherals.
729 */
730 for (ui = ubdinit; udp = ui->ui_driver; ui++) {
731 if (ui->ui_ubanum != numuba && ui->ui_ubanum != '?' ||
732 ui->ui_alive || ui->ui_slave != -1)
733 continue;
734 addr = (u_short)ui->ui_addr;
299100bf
RE
735
736 for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) {
737
66ca574e 738 if (ualloc[ubaoff(addr)])
299100bf 739 continue;
66ca574e 740 reg = ubaddr(addr);
30d13fef
BJ
741 if (badaddr((caddr_t)reg, 2))
742 continue;
95f51977 743#if defined(VAX780) || defined(VAX8600)
66ca574e 744 if (haveubasr && vubp->uba_sr) {
8d2ea14f
BJ
745 vubp->uba_sr = vubp->uba_sr;
746 continue;
30d13fef
BJ
747 }
748#endif
749 cvec = 0x200;
e870748a 750 i = (*udp->ud_probe)(reg, ui);
95f51977 751#if defined(VAX780) || defined(VAX8600)
66ca574e 752 if (haveubasr && vubp->uba_sr) {
8d2ea14f
BJ
753 vubp->uba_sr = vubp->uba_sr;
754 continue;
327f6ec8 755 }
30d13fef
BJ
756#endif
757 if (i == 0)
758 continue;
8d2ea14f
BJ
759 printf("%s%d at uba%d csr %o ",
760 ui->ui_driver->ud_dname, ui->ui_unit, numuba, addr);
30d13fef
BJ
761 if (cvec == 0) {
762 printf("zero vector\n");
763 continue;
764 }
765 if (cvec == 0x200) {
766 printf("didn't interrupt\n");
767 continue;
768 }
8d2ea14f 769 printf("vec %o, ipl %x\n", cvec, br);
66ca574e
C
770 while (--i >= 0)
771 ualloc[ubaoff(addr+i)] = 1;
30d13fef
BJ
772 ui->ui_hd = &uba_hd[numuba];
773 for (ivec = ui->ui_intr; *ivec; ivec++) {
774 ui->ui_hd->uh_vec[cvec/4] =
775 scbentry(*ivec, SCB_ISTACK);
776 cvec += 4;
777 }
778 ui->ui_alive = 1;
779 ui->ui_ubanum = numuba;
780 ui->ui_addr = (caddr_t)reg;
ddbbb5fb 781 ui->ui_physaddr = pumem + ubdevreg(addr);
8d2ea14f 782 ui->ui_dk = -1;
30d13fef
BJ
783 /* ui_type comes from driver */
784 udp->ud_dinfo[ui->ui_unit] = ui;
71236e46 785 (*udp->ud_attach)(ui);
299100bf
RE
786 break;
787 }
327f6ec8 788 }
299100bf
RE
789
790#ifdef AUTO_DEBUG
791 printf("Unibus allocation map");
792 for (i = 0; i < 8*1024; ) {
793 register n, m;
794
795 if ((i % 128) == 0) {
796 printf("\n%6o:", i);
797 for (n = 0; n < 128; n++)
798 if (ualloc[i+n])
799 break;
800 if (n == 128) {
801 i += 128;
802 continue;
803 }
804 }
805
806 for (n = m = 0; n < 16; n++) {
807 m <<= 1;
808 m |= ualloc[i++];
809 }
810
811 printf(" %4x", m);
812 }
813 printf("\n");
814#endif
815
816 wmemfree(ualloc, 8*1024);
327f6ec8
BJ
817}
818
66ca574e
C
819setscbnex(fn)
820 int (*fn)();
7e949ce2 821{
66ca574e
C
822 register struct scb *scbp = &scb;
823
95f51977 824 scbp = (struct scb *)((caddr_t)scbp + nsbi * 512);
66ca574e
C
825 scbp->scb_ipl14[nexnum] = scbp->scb_ipl15[nexnum] =
826 scbp->scb_ipl16[nexnum] = scbp->scb_ipl17[nexnum] =
827 scbentry(fn, SCB_ISTACK);
7e949ce2
MK
828}
829
327f6ec8 830/*
0fe372b3 831 * Make an IO register area accessible at physical address physa
327f6ec8 832 * by mapping kernel ptes starting at pte.
327f6ec8 833 */
121c4a08 834ioaccess(physa, pte, size)
0fe372b3 835 caddr_t physa;
327f6ec8 836 register struct pte *pte;
cb4a08d0 837 int size;
327f6ec8 838{
95f51977 839 register int i = btop(size);
30d13fef 840 register unsigned v = btop(physa);
327f6ec8
BJ
841
842 do
843 *(int *)pte++ = PG_V|PG_KW|v++;
a0eab615 844 while (--i > 0);
327f6ec8
BJ
845 mtpr(TBIA, 0);
846}
1c1f6ecf 847
9f0281aa
SL
848/*
849 * Configure swap space and related parameters.
850 */
851swapconf()
852{
853 register struct swdevt *swp;
220ebf99 854 register int nblks;
9f0281aa
SL
855
856 for (swp = swdevt; swp->sw_dev; swp++) {
e766bd61 857 if (bdevsw[major(swp->sw_dev)].d_psize) {
220ebf99 858 nblks =
e766bd61 859 (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev);
95f51977 860 if (swp->sw_nblks == 0 || swp->sw_nblks > nblks)
e766bd61
MK
861 swp->sw_nblks = nblks;
862 }
9f0281aa
SL
863 }
864 if (!cold) /* in case called for mba device */
865 return;
6348b4d1 866 if (dumplo == 0 && bdevsw[major(dumpdev)].d_psize)
e766bd61 867 dumplo = (*bdevsw[major(dumpdev)].d_psize)(dumpdev) - physmem;
9f0281aa
SL
868 if (dumplo < 0)
869 dumplo = 0;
9f0281aa 870}
42b84df5
MK
871
872#define DOSWAP /* Change swdevt, argdev, and dumpdev too */
873u_long bootdev; /* should be dev_t, but not until 32 bits */
874
875static char devname[][2] = {
876 'h','p', /* 0 = hp */
877 0,0, /* 1 = ht */
878 'u','p', /* 2 = up */
879 'r','k', /* 3 = hk */
880 0,0, /* 4 = sw */
881 0,0, /* 5 = tm */
882 0,0, /* 6 = ts */
883 0,0, /* 7 = mt */
884 0,0, /* 8 = tu */
885 'r','a', /* 9 = ra */
886 0,0, /* 10 = ut */
887 'r','b', /* 11 = rb */
888 0,0, /* 12 = uu */
889 0,0, /* 13 = rx */
890 'r','l', /* 14 = rl */
891};
892
893#define PARTITIONMASK 0x7
894#define PARTITIONSHIFT 3
895
896/*
897 * Attempt to find the device from which we were booted.
898 * If we can do so, and not instructed not to do so,
899 * change rootdev to correspond to the load device.
900 */
901setroot()
902{
30012337 903 int majdev, mindev, unit, part, adaptor;
42b84df5
MK
904 dev_t temp, orootdev;
905 struct swdevt *swp;
906
90dc7048
BK
907 if (boothowto & RB_DFLTROOT ||
908 (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
25cfc74b 909 return;
42b84df5
MK
910 majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
911 if (majdev > sizeof(devname) / sizeof(devname[0]))
25cfc74b 912 return;
42b84df5
MK
913 adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
914 part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
915 unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
916 if (majdev == 0) { /* MBA device */
cd97bee2 917#if NMBA > 0
42b84df5 918 register struct mba_device *mbap;
cd97bee2 919 int mask;
42b84df5 920
cd97bee2
MK
921/*
922 * The MBA number used at boot time is not necessarily the same as the
923 * MBA number used by the kernel. In order to change the rootdev we need to
924 * convert the boot MBA number to the kernel MBA number. The address space
925 * for an MBA used by the boot code is 0x20010000 + 0x2000 * MBA_number
926 * on the 78? and 86?0, 0xf28000 + 0x2000 * MBA_number on the 750.
927 * Therefore we can search the mba_hd table for the MBA that has the physical
928 * address corresponding to the boot MBA number.
929 */
930#define PHYSADRSHFT 13
931#define PHYSMBAMASK780 0x7
932#define PHYSMBAMASK750 0x3
933
934 switch (cpu) {
935
936 case VAX_780:
937 case VAX_8600:
938 default:
939 mask = PHYSMBAMASK780;
940 break;
941
942 case VAX_750:
943 mask = PHYSMBAMASK750;
944 break;
945 }
42b84df5
MK
946 for (mbap = mbdinit; mbap->mi_driver; mbap++)
947 if (mbap->mi_alive && mbap->mi_drive == unit &&
cd97bee2
MK
948 (((long)mbap->mi_hd->mh_physmba >> PHYSADRSHFT)
949 & mask) == adaptor)
42b84df5
MK
950 break;
951 if (mbap->mi_driver == 0)
25cfc74b 952 return;
42b84df5 953 mindev = mbap->mi_unit;
cd97bee2 954#else
25cfc74b 955 return;
c5c7e511 956#endif
cd97bee2 957 } else {
42b84df5
MK
958 register struct uba_device *ubap;
959
960 for (ubap = ubdinit; ubap->ui_driver; ubap++)
961 if (ubap->ui_alive && ubap->ui_slave == unit &&
962 ubap->ui_ubanum == adaptor &&
963 ubap->ui_driver->ud_dname[0] == devname[majdev][0] &&
964 ubap->ui_driver->ud_dname[1] == devname[majdev][1])
965 break;
966
967 if (ubap->ui_driver == 0)
25cfc74b 968 return;
42b84df5
MK
969 mindev = ubap->ui_unit;
970 }
971 mindev = (mindev << PARTITIONSHIFT) + part;
972 orootdev = rootdev;
973 rootdev = makedev(majdev, mindev);
42b84df5
MK
974 /*
975 * If the original rootdev is the same as the one
976 * just calculated, don't need to adjust the swap configuration.
977 */
978 if (rootdev == orootdev)
25cfc74b 979 return;
42b84df5 980
76eb3c51
MK
981 printf("Changing root device to %c%c%d%c\n",
982 devname[majdev][0], devname[majdev][1],
983 mindev >> PARTITIONSHIFT, part + 'a');
2254a193
MK
984
985#ifdef DOSWAP
42b84df5
MK
986 mindev &= ~PARTITIONMASK;
987 for (swp = swdevt; swp->sw_dev; swp++) {
988 if (majdev == major(swp->sw_dev) &&
989 mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) {
990 temp = swdevt[0].sw_dev;
991 swdevt[0].sw_dev = swp->sw_dev;
992 swp->sw_dev = temp;
993 break;
994 }
995 }
996 if (swp->sw_dev == 0)
25cfc74b 997 return;
42b84df5
MK
998
999 /*
1000 * If argdev and dumpdev were the same as the old primary swap
1001 * device, move them to the new primary swap device.
1002 */
1003 if (temp == dumpdev)
1004 dumpdev = swdevt[0].sw_dev;
1005 if (temp == argdev)
1006 argdev = swdevt[0].sw_dev;
1007#endif
1008}