s/HZ/hz/
[unix-history] / usr / src / sys / vax / vax / autoconf.c
CommitLineData
a7e7fa7e 1/* autoconf.c 4.16 81/02/27 */
327f6ec8 2
327f6ec8 3/*
5aa9d5ea 4 * Configure the system for the current machine.
327f6ec8
BJ
5 */
6
47fa50b1
BJ
7#include "mba.h"
8
327f6ec8 9#include "../h/param.h"
3f3a34c3 10#include "../h/systm.h"
327f6ec8
BJ
11#include "../h/map.h"
12#include "../h/nexus.h"
13#include "../h/pte.h"
14#include "../h/buf.h"
15#include "../h/mba.h"
8d2ea14f
BJ
16#include "../h/dk.h"
17#include "../h/vm.h"
3f3a34c3 18#include "../h/uba.h"
327f6ec8
BJ
19#include "../h/mtpr.h"
20#include "../h/cpu.h"
21#include "../h/scb.h"
3f3a34c3 22#include "../h/mem.h"
327f6ec8 23
8d2ea14f 24int cold;
327f6ec8 25int nexnum; /* current nexus number */
8d2ea14f 26int dkn; /* number of dk numbers assigned so far */
327f6ec8 27
47fa50b1 28#if NMBA > 0
8d2ea14f 29int (*mbaintv[4])() = { Xmba0int, Xmba1int, Xmba2int, Xmba3int };
47fa50b1 30#endif
5aa9d5ea 31#if VAX780
8d2ea14f 32int (*ubaintv[4])() = { Xua0int, Xua1int, Xua2int, Xua3int };
5aa9d5ea 33caddr_t umaddr780[4] = {
30d13fef
BJ
34 (caddr_t) 0x2013e000, (caddr_t) 0x2017e000,
35 (caddr_t) 0x201be000, (caddr_t) 0x201fe000
3f3a34c3 36};
5aa9d5ea 37#endif
327f6ec8 38
47fa50b1
BJ
39#if VAX780
40int c780();
41#endif
42#if VAX750
43int c750();
44#endif
3f3a34c3
BJ
45
46struct percpu percpu[] = {
47#if VAX780
30d13fef 48 c780, VAX_780,
3f3a34c3
BJ
49#endif
50#if VAX750
30d13fef 51 c750, VAX_750,
3f3a34c3
BJ
52#endif
53};
54#define NCPU (sizeof(percpu)/sizeof(struct percpu))
55
327f6ec8
BJ
56/*
57 * Determine mass storage and memory configuration for a machine.
58 * Get cpu type, and then switch out to machine specific procedures
59 * which will probe adaptors to see what is out there.
60 */
61configure()
62{
63 union cpusid cpusid;
3f3a34c3 64 register struct percpu *ocp;
3e7ee2db
BJ
65 register int i, *ip;
66 extern char Sysbase[];
327f6ec8
BJ
67
68 cpusid.cpusid = mfpr(SID);
3f3a34c3
BJ
69 for (ocp = percpu; ocp < &percpu[NCPU]; ocp++)
70 if (ocp->pc_cputype == cpusid.cpuany.cp_type) {
3f3a34c3 71 (*ocp->pc_config)(ocp);
16acfbd5 72#if VAXANY
30d13fef 73 setconf();
5aa9d5ea 74#endif
3e7ee2db
BJ
75 ip = (int *)Sysmap; *ip &= ~PG_PROT; *ip |= PG_KR;
76 mtpr(TBIS, Sysbase);
8d2ea14f 77 cold = 0;
3f3a34c3
BJ
78 return;
79 }
80 printf("cpu type %d unsupported\n", cpusid.cpuany.cp_type);
327f6ec8
BJ
81 asm("halt");
82}
83
3f3a34c3 84#if VAX780
327f6ec8
BJ
85/*
86 * Build configuration table for a 780, by looking
87 * at the things (mbas and ubas) in the nexus slots
88 * and initialzing each appropriately.
89 */
3f3a34c3
BJ
90c780(pcpu)
91 register struct percpu *pcpu;
327f6ec8
BJ
92{
93 register struct nexus *nxv;
5aa9d5ea 94 register struct uba_hd *uhp;
30d13fef 95 struct nexus *nxp = NEX780;
327f6ec8 96 union nexcsr nexcsr;
3cda891a 97 int i, ubawatch();
327f6ec8 98
30d13fef 99 for (nexnum = 0,nxv = nexus; nexnum < NNEX780; nexnum++,nxp++,nxv++) {
327f6ec8
BJ
100 nxaccess((caddr_t)nxp, Nexmap[nexnum]);
101 if (badaddr((caddr_t)nxv, 4))
102 continue;
103 nexcsr = nxv->nexcsr;
104 if (nexcsr.nex_csr&NEX_APD)
105 continue;
327f6ec8
BJ
106 switch (nexcsr.nex_type) {
107
108 case NEX_MBA:
47fa50b1 109#if NMBA > 0
8d2ea14f 110 printf("mba%d at tr%d\n", nummba, nexnum);
a7e7fa7e
BJ
111 if (nummba >= NMBA) {
112 printf("%d mba's not configured\n", nummba+1);
113 continue;
114 }
3f3a34c3 115 mbafind(nxv, nxp);
5aa9d5ea 116 nummba++;
47fa50b1
BJ
117#else
118 printf("mba's");
119 goto unsupp;
120#endif
327f6ec8
BJ
121
122 case NEX_UBA0:
123 case NEX_UBA1:
124 case NEX_UBA2:
125 case NEX_UBA3:
30d13fef
BJ
126 if (numuba >= 4) {
127 printf("5 uba's");
3f3a34c3
BJ
128 goto unsupp;
129 }
8d2ea14f
BJ
130 printf("uba%d at tr%d\n", numuba, nexnum);
131 setscbnex(nexnum, ubaintv[numuba]);
3f3a34c3 132 i = nexcsr.nex_type - NEX_UBA0;
30d13fef
BJ
133 unifind((struct uba_regs *)nxv, (struct uba_regs *)nxp,
134 umem[i], umaddr780[i]);
30d13fef
BJ
135 ((struct uba_regs *)nxv)->uba_cr =
136 UBA_IFS|UBA_BRIE|UBA_USEFIE|UBA_SUEFIE;
3f3a34c3 137 numuba++;
327f6ec8
BJ
138 break;
139
140 case NEX_DR32:
5aa9d5ea 141 /* there can be more than one... are there other codes??? */
327f6ec8
BJ
142 printf("dr32");
143 goto unsupp;
144
145 case NEX_MEM4:
146 case NEX_MEM4I:
147 case NEX_MEM16:
148 case NEX_MEM16I:
30d13fef
BJ
149 if (nmcr >= 4) {
150 printf("%d mcr's", 4);
3f3a34c3
BJ
151 goto unsupp;
152 }
3e7ee2db 153 printf("mcr%d at tr%d\n", nmcr, nexnum);
3f3a34c3 154 mcraddr[nmcr++] = (struct mcr *)nxv;
327f6ec8
BJ
155 break;
156
157 case NEX_MPM0:
158 case NEX_MPM1:
159 case NEX_MPM2:
160 case NEX_MPM3:
161 printf("mpm");
162 goto unsupp;
163
164 default:
165 printf("nexus type %x", nexcsr.nex_type);
30d13fef 166unsupp:
3f3a34c3 167 printf(" unsupported (at tr %d)\n", nexnum);
327f6ec8
BJ
168 continue;
169 }
170 }
3cda891a 171 timeout(ubawatch, 0, HZ);
327f6ec8
BJ
172}
173#endif
174
30d13fef
BJ
175#if VAX750
176/*
177 * Configure a 750. There are four possible mba's,
178 * one standard UNIBUS, and a memory controller.
179 */
180c750(pcpu)
181 struct percpu *pcpu;
182{
183 register struct nexus *nxv = nexus;
184 struct nexus *nxp = NEX750;
185
3e7ee2db
BJ
186 printf("mcr at %x\n", MCR_750);
187 nxaccess((caddr_t)MCR_750, Nexmap[nexnum]);
47fa50b1
BJ
188 mcraddr[nmcr++] = (struct mcr *)nxv;
189#if NMBA > 0
30d13fef
BJ
190 for (nexnum = 0; nexnum < NNEX750; nexnum++, nxp++, nxv++) {
191 nxaccess((caddr_t)nxp, Nexmap[nexnum]);
192 if (badaddr((caddr_t)nxv, 4))
193 continue;
3e7ee2db 194 printf("mba%d at %x\n", nummba, nxp);
a7e7fa7e
BJ
195 if (nummba >= NMBA)
196 printf("%d mba's not configured\n", nummba+1);
197 else {
198 mbafind(nxv, nxp);
199 nummba++;
200 }
30d13fef 201 }
47fa50b1 202#endif
3e7ee2db 203 printf("uba at %x\n", nxp);
30d13fef
BJ
204 nxaccess((caddr_t)nxp, Nexmap[nexnum++]);
205 unifind((struct uba_regs *)nxv++, (struct uba_regs *)nxp,
8d2ea14f 206 umem[0], UMEM750);
30d13fef 207 numuba = 1;
30d13fef
BJ
208}
209#endif
210
47fa50b1 211#if NMBA > 0
327f6ec8
BJ
212/*
213 * Find devices attached to a particular mba
214 * and look for each device found in the massbus
215 * initialization tables.
216 */
3f3a34c3 217mbafind(nxv, nxp)
30d13fef 218 struct nexus *nxv, *nxp;
327f6ec8
BJ
219{
220 register struct mba_regs *mdp;
221 register struct mba_drv *mbd;
222 int dn, dt, sn, ds;
223 struct mba_info fnd;
224
3f3a34c3 225 mdp = (struct mba_regs *)nxv;
5aa9d5ea
RE
226 mba_hd[nummba].mh_mba = mdp;
227 mba_hd[nummba].mh_physmba = (struct mba_regs *)nxp;
228 setscbnex(nexnum, mbaintv[nummba]);
327f6ec8 229 fnd.mi_mba = mdp;
5aa9d5ea 230 fnd.mi_mbanum = nummba;
327f6ec8
BJ
231 for (mbd = mdp->mba_drv, dn = 0; mbd < &mdp->mba_drv[8]; mbd++, dn++) {
232 dt = mbd->mbd_dt & 0xffff;
233 if (dt == 0)
234 continue;
327f6ec8
BJ
235 if ((dt&MBDT_TYPE) == MBDT_TU78) {
236 printf("tm04/tu78 unsupported\n");
237 continue;
238 }
239 if (dt == MBDT_MOH)
240 continue;
241 fnd.mi_drive = dn;
242 if (dt & MBDT_TAP) {
243 for (sn = 0; sn < 8; sn++) {
244 mbd->mbd_tc = sn;
245 dt = mbd->mbd_dt;
246 if ((dt & MBDT_SPR) == 0)
247 continue;
248 dt &= MBDT_TYPE;
249 fnd.mi_slave = sn;
250 mbaconfig(&fnd, dt);
251 }
252 } else {
253 fnd.mi_slave = -1;
254 mbaconfig(&fnd, dt&MBDT_TYPE);
255 }
256 }
3f3a34c3
BJ
257 mdp->mba_cr = MBAINIT;
258 mdp->mba_cr = MBAIE;
327f6ec8
BJ
259}
260
261/*
262 * Have found a massbus device;
263 * see if it is in the configuration table.
264 * If so, fill in its data.
265 */
266mbaconfig(ni, type)
267 register struct mba_info *ni;
268 register int type;
269{
270 register struct mba_info *mi;
271 register short *tp;
71236e46 272 register struct mba_hd *mh;
327f6ec8 273
327f6ec8
BJ
274 for (mi = mbinit; mi->mi_driver; mi++) {
275 if (mi->mi_alive)
276 continue;
277 tp = mi->mi_driver->md_type;
278 for (mi->mi_type = 0; *tp; tp++, mi->mi_type++)
279 if (*tp == type)
280 goto found;
281 continue;
282found:
283#define match(fld) (ni->fld == mi->fld || mi->fld == '?')
284 if (!match(mi_slave) || !match(mi_drive) || !match(mi_mbanum))
285 continue;
8d2ea14f
BJ
286 printf("%c%d at mba%d drive %d\n",
287 mi->mi_name, mi->mi_unit, ni->mi_mbanum, ni->mi_drive);
327f6ec8 288 mi->mi_alive = 1;
71236e46
BJ
289 mh = &mba_hd[ni->mi_mbanum];
290 mi->mi_hd = mh;
291 mh->mh_mbip[ni->mi_drive] = mi;
292 mh->mh_ndrive++;
327f6ec8
BJ
293 mi->mi_mba = ni->mi_mba;
294 mi->mi_drv = &mi->mi_mba->mba_drv[ni->mi_drive];
295 mi->mi_driver->md_info[mi->mi_unit] = mi;
296 mi->mi_mbanum = ni->mi_mbanum;
297 mi->mi_drive = ni->mi_drive;
298 mi->mi_slave = ni->mi_slave;
8d2ea14f
BJ
299 if (mi->mi_dk && dkn < DK_NDRIVE)
300 mi->mi_dk = dkn++;
301 else
302 mi->mi_dk = -1;
71236e46 303 (*mi->mi_driver->md_dkinit)(mi);
327f6ec8
BJ
304 }
305}
47fa50b1 306#endif
327f6ec8 307
3f3a34c3 308/*
30d13fef
BJ
309 * Fixctlrmask fixes the masks of the driver ctlr routines
310 * which otherwise save r10 and r11 where the interrupt and br
311 * level are passed through.
312 */
313fixctlrmask()
314{
315 register struct uba_minfo *um;
316 register struct uba_dinfo *ui;
317 register struct uba_driver *ud;
318#define phys(a,b) ((b)(((int)(a))&0x7fffffff))
319
320 for (um = ubminit; ud = phys(um->um_driver, struct uba_driver *); um++)
71236e46 321 *phys(ud->ud_probe, short *) &= ~0xc00;
30d13fef 322 for (ui = ubdinit; ud = phys(ui->ui_driver, struct uba_driver *); ui++)
71236e46 323 *phys(ud->ud_probe, short *) &= ~0xc00;
30d13fef
BJ
324}
325
326/*
327 * Find devices on a UNIBUS.
328 * Uses per-driver routine to set <br,cvec> into <r11,r10>,
329 * and then fills in the tables, with help from a per-driver
330 * slave initialization routine.
3f3a34c3 331 */
30d13fef
BJ
332unifind(vubp, pubp, vumem, pumem)
333 struct uba_regs *vubp, *pubp;
334 caddr_t vumem, pumem;
327f6ec8 335{
30d13fef 336 register int br, cvec; /* MUST BE r11, r10 */
3f3a34c3 337 register struct uba_dinfo *ui;
30d13fef
BJ
338 register struct uba_minfo *um;
339 u_short *umem = (u_short *)vumem, *sp, *reg, addr;
340 struct uba_hd *uhp;
327f6ec8 341 struct uba_driver *udp;
8d2ea14f 342 int i, (**ivec)(), haveubasr = 0;
30d13fef
BJ
343
344 /*
345 * Initialize the UNIBUS, by freeing the map
346 * registers and the buffered data path registers
347 */
348 uhp = &uba_hd[numuba];
349 uhp->uh_map = (struct map *)calloc(UAMSIZ * sizeof (struct map));
350 mfree(uhp->uh_map, NUBMREG, 1);
351 switch (cpu) {
352#if VAX780
353 case VAX_780:
8d2ea14f
BJ
354 uhp->uh_bdpfree = (1<<NBDP780) - 1;
355 haveubasr = 1;
30d13fef
BJ
356 break;
357#endif
358#if VAX750
359 case VAX_750:
8d2ea14f 360 uhp->uh_bdpfree = (1<<NBDP750) - 1;
30d13fef
BJ
361 break;
362#endif
363 }
327f6ec8 364
30d13fef
BJ
365 /*
366 * Save virtual and physical addresses
367 * of adaptor, and allocate and initialize
368 * the UNIBUS interrupt vector.
369 */
370 uhp->uh_uba = vubp;
371 uhp->uh_physuba = pubp;
372 if (numuba == 0)
373 uhp->uh_vec = UNIvec;
374 else
375 uhp->uh_vec = (int(**)())calloc(512);
376 for (i = 0; i < 128; i++)
377 uhp->uh_vec[i] =
378 scbentry(&catcher[i*2], SCB_ISTACK);
379 nxaccess((struct nexus *)pumem, UMEMmap[numuba]);
3f3a34c3 380#if VAX780
8d2ea14f 381 if (haveubasr) {
30d13fef 382 vubp->uba_sr = vubp->uba_sr;
8d2ea14f 383 vubp->uba_cr = UBA_IFS|UBA_BRIE;
327f6ec8 384 }
327f6ec8 385#endif
30d13fef
BJ
386 /*
387 * Map the first page of UNIBUS i/o
388 * space to the first page of memory
389 * for devices which will need to dma
390 * output to produce an interrupt.
391 */
392 *(int *)(&vubp->uba_map[0]) = UBA_MRV;
393
394#define ubaddr(off) (u_short *)((int)vumem + ((off)&0x1fff))
395 /*
396 * Check each unibus mass storage controller.
397 * For each one which is potentially on this uba,
398 * see if it is really there, and if it is record it and
399 * then go looking for slaves.
400 */
401 for (um = ubminit; udp = um->um_driver; um++) {
402 if (um->um_ubanum != numuba && um->um_ubanum != '?')
403 continue;
404 addr = (u_short)um->um_addr;
405 reg = ubaddr(addr);
406 if (badaddr((caddr_t)reg, 2))
327f6ec8 407 continue;
3f3a34c3 408#if VAX780
8d2ea14f
BJ
409 if (haveubasr && vubp->uba_sr) {
410 vubp->uba_sr = vubp->uba_sr;
411 continue;
30d13fef 412 }
327f6ec8 413#endif
30d13fef 414 cvec = 0x200;
71236e46 415 i = (*udp->ud_probe)(reg);
3f3a34c3 416#if VAX780
8d2ea14f
BJ
417 if (haveubasr && vubp->uba_sr) {
418 vubp->uba_sr = vubp->uba_sr;
419 continue;
30d13fef 420 }
327f6ec8 421#endif
30d13fef
BJ
422 if (i == 0)
423 continue;
8d2ea14f
BJ
424 printf("%s%d at uba%d csr %o ",
425 udp->ud_mname, um->um_ctlr, numuba, addr);
30d13fef
BJ
426 if (cvec == 0) {
427 printf("zero vector\n");
428 continue;
429 }
430 if (cvec == 0x200) {
431 printf("didn't interrupt\n");
432 continue;
433 }
8d2ea14f 434 printf("vec %o, ipl %x\n", cvec, br);
30d13fef
BJ
435 um->um_alive = 1;
436 um->um_ubanum = numuba;
437 um->um_hd = &uba_hd[numuba];
438 um->um_addr = (caddr_t)reg;
439 udp->ud_minfo[um->um_ctlr] = um;
440 for (ivec = um->um_intr; *ivec; ivec++) {
441 um->um_hd->uh_vec[cvec/4] =
442 scbentry(*ivec, SCB_ISTACK);
443 cvec += 4;
444 }
445 for (ui = ubdinit; ui->ui_driver; ui++) {
446 if (ui->ui_driver != udp || ui->ui_alive ||
447 ui->ui_ctlr != um->um_ctlr && ui->ui_ctlr != '?' ||
448 ui->ui_ubanum != numuba && ui->ui_ubanum != '?')
327f6ec8 449 continue;
8d2ea14f 450 if ((*udp->ud_slave)(ui, reg)) {
30d13fef
BJ
451 ui->ui_alive = 1;
452 ui->ui_ctlr = um->um_ctlr;
453 ui->ui_ubanum = numuba;
454 ui->ui_hd = &uba_hd[numuba];
455 ui->ui_addr = (caddr_t)reg;
456 ui->ui_physaddr = pumem + (addr&0x1fff);
8d2ea14f 457 if (ui->ui_dk && dkn < DK_NDRIVE)
0801d37f 458 ui->ui_dk = dkn++;
8d2ea14f
BJ
459 else
460 ui->ui_dk = -1;
30d13fef
BJ
461 ui->ui_mi = um;
462 /* ui_type comes from driver */
463 udp->ud_dinfo[ui->ui_unit] = ui;
8d2ea14f
BJ
464 printf("%s%d at %s%d slave %d\n",
465 udp->ud_dname, ui->ui_unit,
466 udp->ud_mname, um->um_ctlr, ui->ui_slave);
71236e46 467 (*udp->ud_attach)(ui);
327f6ec8 468 }
30d13fef
BJ
469 }
470 }
471 /*
472 * Now look for non-mass storage peripherals.
473 */
474 for (ui = ubdinit; udp = ui->ui_driver; ui++) {
475 if (ui->ui_ubanum != numuba && ui->ui_ubanum != '?' ||
476 ui->ui_alive || ui->ui_slave != -1)
477 continue;
478 addr = (u_short)ui->ui_addr;
479 reg = ubaddr(addr);
480 if (badaddr((caddr_t)reg, 2))
481 continue;
482#if VAX780
8d2ea14f
BJ
483 if (haveubasr && vubp->uba_sr) {
484 vubp->uba_sr = vubp->uba_sr;
485 continue;
30d13fef
BJ
486 }
487#endif
488 cvec = 0x200;
71236e46 489 i = (*udp->ud_probe)(reg);
30d13fef 490#if VAX780
8d2ea14f
BJ
491 if (haveubasr && vubp->uba_sr) {
492 vubp->uba_sr = vubp->uba_sr;
493 continue;
327f6ec8 494 }
30d13fef
BJ
495#endif
496 if (i == 0)
497 continue;
8d2ea14f
BJ
498 printf("%s%d at uba%d csr %o ",
499 ui->ui_driver->ud_dname, ui->ui_unit, numuba, addr);
30d13fef
BJ
500 if (cvec == 0) {
501 printf("zero vector\n");
502 continue;
503 }
504 if (cvec == 0x200) {
505 printf("didn't interrupt\n");
506 continue;
507 }
8d2ea14f 508 printf("vec %o, ipl %x\n", cvec, br);
30d13fef
BJ
509 ui->ui_hd = &uba_hd[numuba];
510 for (ivec = ui->ui_intr; *ivec; ivec++) {
511 ui->ui_hd->uh_vec[cvec/4] =
512 scbentry(*ivec, SCB_ISTACK);
513 cvec += 4;
514 }
515 ui->ui_alive = 1;
516 ui->ui_ubanum = numuba;
517 ui->ui_addr = (caddr_t)reg;
518 ui->ui_physaddr = pumem + (addr&0x1fff);
8d2ea14f 519 ui->ui_dk = -1;
30d13fef
BJ
520 /* ui_type comes from driver */
521 udp->ud_dinfo[ui->ui_unit] = ui;
71236e46 522 (*udp->ud_attach)(ui);
327f6ec8
BJ
523 }
524}
525
327f6ec8 526setscbnex(nexnum, fn)
8d2ea14f 527 int nexnum, (*fn)();
327f6ec8 528{
71236e46 529 register struct scb *scbp = &scb;
327f6ec8 530
71236e46
BJ
531 scbp->scb_ipl14[nexnum] = scbp->scb_ipl15[nexnum] =
532 scbp->scb_ipl16[nexnum] = scbp->scb_ipl17[nexnum] =
327f6ec8
BJ
533 scbentry(fn, SCB_ISTACK);
534}
535
536/*
537 * Make a nexus accessible at physical address phys
538 * by mapping kernel ptes starting at pte.
539 *
540 * WE LEAVE ALL NEXI MAPPED; THIS IS PERHAPS UNWISE
541 * SINCE MISSING NEXI DONT RESPOND. BUT THEN AGAIN
542 * PRESENT NEXI DONT RESPOND TO ALL OF THEIR ADDRESS SPACE.
543 */
30d13fef
BJ
544nxaccess(physa, pte)
545 caddr_t physa;
327f6ec8
BJ
546 register struct pte *pte;
547{
548 register int cnt = btop(sizeof (struct nexus));
30d13fef 549 register unsigned v = btop(physa);
327f6ec8
BJ
550
551 do
552 *(int *)pte++ = PG_V|PG_KW|v++;
553 while (--cnt > 0);
554 mtpr(TBIA, 0);
555}