xref: /original-bsd/sys/vax/vax/autoconf.c (revision 2c107824)
1991299c1Sbostic /*-
2991299c1Sbostic  * Copyright (c) 1982, 1986 The Regents of the University of California.
3991299c1Sbostic  * All rights reserved.
4e93b0568Smckusick  *
5991299c1Sbostic  * %sccs.include.redist.c%
6991299c1Sbostic  *
7*2c107824Storek  *	@(#)autoconf.c	7.21 (Berkeley) 04/19/93
8e93b0568Smckusick  */
909e5bb10Swnj 
10b8054636Swnj /*
1184badb11Swnj  * Setup the system to run on the current machine.
1284badb11Swnj  *
1384badb11Swnj  * Configure() is called at boot time and initializes the uba and mba
1484badb11Swnj  * device tables and the memory controller monitoring.  Available
1584badb11Swnj  * devices are determined (from possibilities mentioned in ioconf.c),
1684badb11Swnj  * and the drivers are initialized.
17b8054636Swnj  */
18b8054636Swnj 
19b96bb200Swnj #include "mba.h"
20b79931fcSsam #include "uba.h"
21762ff349Skarels #include "kra.h"		/* XXX wrong file */
2264577cdeSbostic #include "bi.h"
23b96bb200Swnj 
2464577cdeSbostic #include "sys/param.h"
2564577cdeSbostic #include "sys/systm.h"
2664577cdeSbostic #include "sys/map.h"
2764577cdeSbostic #include "sys/buf.h"
2864577cdeSbostic #include "sys/dkstat.h"
2964577cdeSbostic #include "sys/vm.h"
3064577cdeSbostic #include "sys/malloc.h"
3164577cdeSbostic #include "sys/conf.h"
3264577cdeSbostic #include "sys/dmap.h"
3364577cdeSbostic #include "sys/reboot.h"
34a486872dSroot 
3564577cdeSbostic #include "../include/pte.h"
3664577cdeSbostic #include "../include/cpu.h"
37c3ba2265Sbloom #include "mem.h"
3864577cdeSbostic #include "../include/mtpr.h"
39c3ba2265Sbloom #include "nexus.h"
40c3ba2265Sbloom #include "scb.h"
41a089c9d9Sbloom #include "ioa.h"
4264577cdeSbostic #include "../bi/bireg.h"
4364577cdeSbostic #include "../mba/mbareg.h"
4464577cdeSbostic #include "../mba/mbavar.h"
4564577cdeSbostic #include "../uba/ubareg.h"
4664577cdeSbostic #include "../uba/ubavar.h"
47b8054636Swnj 
4884badb11Swnj /*
4984badb11Swnj  * The following several variables are related to
5084badb11Swnj  * the configuration process, and are used in initializing
5184badb11Swnj  * the machine.
5284badb11Swnj  */
5384badb11Swnj int	cold;		/* if 1, still working on cold-start */
5484badb11Swnj int	dkn;		/* number of iostat dk numbers assigned so far */
55f7b6795bSkarels int	cpuspeed = 1;	/* relative cpu speed */
56b8054636Swnj 
5784badb11Swnj /*
5884badb11Swnj  * Addresses of the (locore) routines which bootstrap us from
5984badb11Swnj  * hardware traps to C code.  Filled into the system control block
6084badb11Swnj  * as necessary.
61762ff349Skarels  *
62762ff349Skarels  * RIDICULOUS!  CONFIG SHOULD GENERATE AN ioconf.h FOR US, with
63762ff349Skarels  * mba glue also in `glue.s'.  (Unibus adapter glue is special, though.)
6484badb11Swnj  */
65b96bb200Swnj #if NMBA > 0
668a75d5d5Swnj int	(*mbaintv[4])() =	{ Xmba0int, Xmba1int, Xmba2int, Xmba3int };
67a089c9d9Sbloom #if NMBA > 4
68a089c9d9Sbloom 	Need to expand the table for more than 4 massbus adaptors
69b96bb200Swnj #endif
70a089c9d9Sbloom #endif
71a089c9d9Sbloom #if defined(VAX780) || defined(VAX8600)
72a089c9d9Sbloom int	(*ubaintv[])() =
73a089c9d9Sbloom {
74a089c9d9Sbloom 	Xua0int, Xua1int, Xua2int, Xua3int,
75a089c9d9Sbloom #if NUBA > 4
76a089c9d9Sbloom 	Xua4int, Xua5int, Xua6int, Xua7int,
77a089c9d9Sbloom #endif
78a089c9d9Sbloom #if NUBA > 8
79a089c9d9Sbloom 	Need to expand the table for more than 8 unibus adaptors
80a089c9d9Sbloom #endif
81a089c9d9Sbloom };
82e8b91158Skre #endif
83762ff349Skarels #if NKDB > 0
84762ff349Skarels /* kdb50 driver does not appear in udminit[] (not without csr!) */
85762ff349Skarels int	Xkdbintr0();		/* generated by autoconf */
86762ff349Skarels int	(*kdbintv[])() = { Xkdbintr0 };
87762ff349Skarels #if NKDB > 1
88762ff349Skarels 	Need to expand the table for more than 1 KDB adapter
89762ff349Skarels #endif
90762ff349Skarels #endif
9184badb11Swnj 
9284badb11Swnj /*
9384badb11Swnj  * This allocates the space for the per-uba information,
9484badb11Swnj  * such as buffered data path usage.
9584badb11Swnj  */
96cdfb934eSkarels struct	uba_hd uba_hd[NUBA];
9709e5bb10Swnj 
9884badb11Swnj /*
99b8054636Swnj  * Determine mass storage and memory configuration for a machine.
100b8054636Swnj  * Get cpu type, and then switch out to machine specific procedures
101b8054636Swnj  * which will probe adaptors to see what is out there.
102b8054636Swnj  */
configure()103b8054636Swnj configure()
104b8054636Swnj {
105b8054636Swnj 	union cpusid cpusid;
10609e5bb10Swnj 	register struct percpu *ocp;
107762ff349Skarels 	register struct pte *ip;
108b8054636Swnj 
109b8054636Swnj 	cpusid.cpusid = mfpr(SID);
110762ff349Skarels 	switch (cpusid.cpuany.cp_type) {
111762ff349Skarels #if VAX8600
112762ff349Skarels 	case VAX_8600:
113762ff349Skarels 		printf("VAX 8600, serial# %d(%d), hardware ECO level %d(%d)\n",
1145fe25887Stef 			cpusid.cpu8600.cp_sno, cpusid.cpu8600.cp_plant,
1155fe25887Stef 			cpusid.cpu8600.cp_eco >> 4, cpusid.cpu8600.cp_eco);
116762ff349Skarels 		break;
117762ff349Skarels #endif
118762ff349Skarels #if VAX8200
119762ff349Skarels 	case VAX_8200:
120762ff349Skarels 		printf("\
121762ff349Skarels VAX 82%c0, hardware rev %d, ucode patch rev %d, sec patch %d, ucode rev %d\n",
122762ff349Skarels 			cpusid.cpu8200.cp_5 ? '5' : '0',
123762ff349Skarels 			cpusid.cpu8200.cp_hrev, cpusid.cpu8200.cp_patch,
124762ff349Skarels 			cpusid.cpu8200.cp_secp, cpusid.cpu8200.cp_urev);
125762ff349Skarels 		mastercpu = mfpr(BINID);
126762ff349Skarels 		break;
127762ff349Skarels #endif
128762ff349Skarels #if VAX780
129762ff349Skarels 	case VAX_780:
130762ff349Skarels 		printf("\
131762ff349Skarels VAX 11/78%c, serial# %d(%d), hardware ECO level %d(%d)\n",
132762ff349Skarels 			cpusid.cpu780.cp_5 ? '5' : '0',
133762ff349Skarels 			cpusid.cpu780.cp_sno, cpusid.cpu780.cp_plant,
134762ff349Skarels 			cpusid.cpu780.cp_eco >> 4, cpusid.cpu780.cp_eco);
135762ff349Skarels 		break;
136762ff349Skarels #endif
137762ff349Skarels #if VAX750
138762ff349Skarels 	case VAX_750:
139762ff349Skarels 		printf("VAX 11/750, hardware rev %d, ucode rev %d\n",
140762ff349Skarels 			cpusid.cpu750.cp_hrev, cpusid.cpu750.cp_urev);
141762ff349Skarels 		break;
142762ff349Skarels #endif
143762ff349Skarels #if VAX730
144762ff349Skarels 	case VAX_730:
145762ff349Skarels 		printf("VAX 11/730, ucode rev %d\n", cpusid.cpu730.cp_urev);
146762ff349Skarels 		break;
147762ff349Skarels #endif
148762ff349Skarels #if VAX630
149762ff349Skarels 	case VAX_630:
150762ff349Skarels 		printf("MicroVAX-II\n");
151762ff349Skarels 		break;
152762ff349Skarels #endif
15316fb909cStef #if VAX650
15416fb909cStef 	case VAX_650:
15516fb909cStef 		printf("MicroVAX 3000, ucode rev %d\n", cpusid.cpu650.cp_urev);
15616fb909cStef 		break;
15716fb909cStef #endif
158762ff349Skarels 	}
1590b04a93bSwnj 	for (ocp = percpu; ocp->pc_cputype; ocp++)
16009e5bb10Swnj 		if (ocp->pc_cputype == cpusid.cpuany.cp_type) {
161f7b6795bSkarels 			cpuspeed = ocp->pc_cpuspeed;
162762ff349Skarels 			cpuops = ocp->pc_ops;
163762ff349Skarels 			if (cpuops->cpu_init != NULL)
164762ff349Skarels 				(*cpuops->cpu_init)();
165a8b6ec1fSkarels 			probeio(ocp);
16684badb11Swnj 			/*
167e4f0ff2bSsam 			 * Write protect the scb and UNIBUS interrupt vectors.
168e4f0ff2bSsam 			 * It is strange that this code is here, but this is
169e4f0ff2bSsam 			 * as soon as we are done mucking with it, and the
17084badb11Swnj 			 * write-enable was done in assembly language
17184badb11Swnj 			 * to which we will never return.
17284badb11Swnj 			 */
173762ff349Skarels 			for (ip = kvtopte(scb); ip < kvtopte(eUNIvec); ip++) {
174762ff349Skarels 				*(int *)ip &= ~PG_PROT;
175762ff349Skarels 				*(int *)ip |= PG_KR;
176762ff349Skarels 			}
177762ff349Skarels 			mtpr(TBIA, 0);
17884badb11Swnj #if GENERIC
179cdd5ba0eSkarels 			if ((boothowto & RB_ASKNAME) == 0)
180cdd5ba0eSkarels 				setroot();
18184badb11Swnj 			setconf();
18214e1df5dSkarels #else
183cdd5ba0eSkarels 			setroot();
18484badb11Swnj #endif
18501cdfd67Ssam 			/*
18601cdfd67Ssam 			 * Configure swap area and related system
18701cdfd67Ssam 			 * parameter based on device(s) used.
18801cdfd67Ssam 			 */
18901cdfd67Ssam 			swapconf();
1908a75d5d5Swnj 			cold = 0;
191dfa84b8fSwnj 			memenable();
19209e5bb10Swnj 			return;
193b8054636Swnj 		}
19484badb11Swnj 	printf("cpu type %d not configured\n", cpusid.cpuany.cp_type);
195b8054636Swnj 	asm("halt");
196b8054636Swnj }
197b8054636Swnj 
198b3a411d4Skarels #if VAX8600 || VAX780 || VAX750 || VAX730
199b3a411d4Skarels int	nexnum;		/* current nexus number */
200b3a411d4Skarels int	nsbi;		/* current sbi number */
201b3a411d4Skarels #endif
202762ff349Skarels #if VAX8200
203762ff349Skarels int	numkdb;		/* current ``kdb'' number */
204762ff349Skarels int	bi_nodes;	/* XXX remembers found bi nodes */
205762ff349Skarels #endif
206b3a411d4Skarels 
207a8b6ec1fSkarels /*
208a8b6ec1fSkarels  * Probe the main IO bus(es).
209a8b6ec1fSkarels  * The percpu structure gives us a handle on the addresses and/or types.
210a8b6ec1fSkarels  */
probeio(pcpu)211a8b6ec1fSkarels probeio(pcpu)
212a089c9d9Sbloom 	register struct percpu *pcpu;
213a089c9d9Sbloom {
214a8b6ec1fSkarels 	register struct iobus *iob;
215a089c9d9Sbloom 	int ioanum;
216a089c9d9Sbloom 
217a089c9d9Sbloom 	ioanum = 0;
218a8b6ec1fSkarels 	for (iob = pcpu->pc_io; ioanum < pcpu->pc_nioa; ioanum++, iob++) {
219a8b6ec1fSkarels 
220a8b6ec1fSkarels 		switch (iob->io_type) {
221a8b6ec1fSkarels 
22216fb909cStef #if VAX630 || VAX650
223b3a411d4Skarels 		case IO_QBUS:
224b3a411d4Skarels 			probeqbus((struct qbus *)iob->io_details);
225b3a411d4Skarels 			break;
226b3a411d4Skarels #endif
227b3a411d4Skarels 
228b3a411d4Skarels #if VAX780 || VAX750 || VAX730
229a8b6ec1fSkarels 		case IO_SBI780:
230a8b6ec1fSkarels 		case IO_CMI750:
231a8b6ec1fSkarels 		case IO_XXX730:
232a8b6ec1fSkarels 			probenexi((struct nexusconnect *)iob->io_details);
233a8b6ec1fSkarels 			break;
234a8b6ec1fSkarels #endif
235a8b6ec1fSkarels 
236a8b6ec1fSkarels #if VAX8600
237a8b6ec1fSkarels 		case IO_ABUS:
238a8b6ec1fSkarels 			probe_Abus(ioanum, iob);
239a8b6ec1fSkarels 			break;
240a8b6ec1fSkarels #endif
241762ff349Skarels 
242762ff349Skarels #if VAX8200
243762ff349Skarels 		case IO_BI:
244762ff349Skarels 			probe_bi((struct bibus *)iob->io_details);
245762ff349Skarels 			break;
246762ff349Skarels #endif
247762ff349Skarels 
248a8b6ec1fSkarels 		default:
249a8b6ec1fSkarels 			if (iob->io_addr) {
250a8b6ec1fSkarels 			    printf(
251a8b6ec1fSkarels 		"IO adaptor %d, type %d, at address 0x%x is unsupported\n",
252a8b6ec1fSkarels 				ioanum, iob->io_type, iob->io_addr);
253a8b6ec1fSkarels 			} else
254a8b6ec1fSkarels 			    printf("IO adaptor %d, type %d, is unsupported\n",
255a8b6ec1fSkarels 				ioanum, iob->io_type);
256a8b6ec1fSkarels 			break;
257a8b6ec1fSkarels 		}
258a8b6ec1fSkarels 	}
259a8b6ec1fSkarels }
260a8b6ec1fSkarels 
261a8b6ec1fSkarels #if VAX8600
probe_Abus(ioanum,iob)262a8b6ec1fSkarels probe_Abus(ioanum, iob)
263a8b6ec1fSkarels 	register struct iobus *iob;
264a8b6ec1fSkarels {
265a8b6ec1fSkarels 	register struct ioa *ioap;
266a8b6ec1fSkarels 	union ioacsr ioacsr;
267a8b6ec1fSkarels 	int type;
268a8b6ec1fSkarels 	struct sbia_regs *sbiaregs;
269762ff349Skarels #ifdef notyet
270762ff349Skarels 	int sbi1fail(), sbi1alert(), sbi1fault(), sbi1err();
271762ff349Skarels #endif
272a8b6ec1fSkarels 
273a8b6ec1fSkarels 	ioap = &ioa[ioanum];
27432e110b5Skarels 	ioaccess(iob->io_addr, Ioamap[ioanum], iob->io_size);
275a8b6ec1fSkarels 	if (badaddr((caddr_t)ioap, 4))
276a8b6ec1fSkarels 		return;
277a089c9d9Sbloom 	ioacsr.ioa_csr = ioap->ioacsr.ioa_csr;
278a089c9d9Sbloom 	type = ioacsr.ioa_type & IOA_TYPMSK;
279a8b6ec1fSkarels 
280a089c9d9Sbloom 	switch (type) {
281a8b6ec1fSkarels 
282a089c9d9Sbloom 	case IOA_SBIA:
283a089c9d9Sbloom 		printf("SBIA%d at IO adaptor %d address 0x%x\n",
284a8b6ec1fSkarels 		    nsbi, ioanum, iob->io_addr);
285762ff349Skarels #ifdef notyet
286762ff349Skarels 		/* I AM NOT SURE THESE ARE IN THE SAME PLACES */
287762ff349Skarels 		if (nscb == 1) {
288762ff349Skarels 			scb[1].scb_sbifail = scbentry(sbi1fail, SCB_ISTACK);
289762ff349Skarels 			/* maybe not sbifail, maybe scb1.scb_cmrd */
290762ff349Skarels 			/* but how can I find out without a broken SBIA1? */
291762ff349Skarels 			scb[1].scb_sbialert = scbentry(sbi1alert, SCB_ISTACK);
292762ff349Skarels 			scb[1].scb_sbifault = scbentry(sbi1fault, SCB_ISTACK);
293762ff349Skarels 			scb[1].scb_sbierr = scbentry(sbi1err, SCB_ISTACK);
294762ff349Skarels 		}
295762ff349Skarels #endif
296a8b6ec1fSkarels 		probenexi((struct nexusconnect *)iob->io_details);
297a089c9d9Sbloom 		nsbi++;
298a089c9d9Sbloom 		sbiaregs = (struct sbia_regs *)ioap;
299a089c9d9Sbloom 		sbiaregs->sbi_errsum = -1;
300a089c9d9Sbloom 		sbiaregs->sbi_error = 0x1000;
301a089c9d9Sbloom 		sbiaregs->sbi_fltsts = 0xc0000;
302a089c9d9Sbloom 		break;
303a8b6ec1fSkarels 
304a089c9d9Sbloom 	default:
305a8b6ec1fSkarels 		printf("IOA%d at address 0x%x is unsupported (type = 0x%x)\n",
306a8b6ec1fSkarels 		    ioanum, iob->io_addr, ioacsr.ioa_type);
307a8b6ec1fSkarels 		break;
308a089c9d9Sbloom 	}
309a089c9d9Sbloom }
310a8b6ec1fSkarels #endif
311a089c9d9Sbloom 
312b3a411d4Skarels #if VAX8600 || VAX780 || VAX750 || VAX730
313b8054636Swnj /*
3140b04a93bSwnj  * Probe nexus space, finding the interconnects
3150b04a93bSwnj  * and setting up and probing mba's and uba's for devices.
316b8054636Swnj  */
probenexi(pnc)317a8b6ec1fSkarels probenexi(pnc)
318a8b6ec1fSkarels 	register struct nexusconnect *pnc;
319b8054636Swnj {
320b8054636Swnj 	register struct nexus *nxv;
321a8b6ec1fSkarels 	struct nexus *nxp = pnc->psb_nexbase;
322b8054636Swnj 	union nexcsr nexcsr;
323ce6a472bSwnj 	int i;
324b8054636Swnj 
325762ff349Skarels 	ioaccess((caddr_t)nxp, Nexmap[nsbi * NNEXSBI],
326762ff349Skarels 	    pnc->psb_nnexus * sizeof(struct nexus));
327762ff349Skarels 	nxv = &nexus[nsbi * NNEXSBI];
328762ff349Skarels 	for (nexnum = 0; nexnum < pnc->psb_nnexus; nexnum++, nxp++, nxv++) {
329b8054636Swnj 		if (badaddr((caddr_t)nxv, 4))
330b8054636Swnj 			continue;
331a8b6ec1fSkarels 		if (pnc->psb_nextype && pnc->psb_nextype[nexnum] != NEX_ANY)
332a8b6ec1fSkarels 			nexcsr.nex_csr = pnc->psb_nextype[nexnum];
3330b04a93bSwnj 		else
334b8054636Swnj 			nexcsr = nxv->nexcsr;
335b8054636Swnj 		if (nexcsr.nex_csr&NEX_APD)
336b8054636Swnj 			continue;
337b8054636Swnj 		switch (nexcsr.nex_type) {
338b8054636Swnj 
339b8054636Swnj 		case NEX_MBA:
3408a75d5d5Swnj 			printf("mba%d at tr%d\n", nummba, nexnum);
341b874d253Swnj 			if (nummba >= NMBA) {
342762ff349Skarels 				printf("%d mba's", ++nummba);
3436d315329Swnj 				goto unconfig;
344b874d253Swnj 			}
34584badb11Swnj #if NMBA > 0
34609e5bb10Swnj 			mbafind(nxv, nxp);
347e8b91158Skre 			nummba++;
348b96bb200Swnj #endif
34984badb11Swnj 			break;
350b8054636Swnj 
351b8054636Swnj 		case NEX_UBA0:
352b8054636Swnj 		case NEX_UBA1:
353b8054636Swnj 		case NEX_UBA2:
354b8054636Swnj 		case NEX_UBA3:
35584badb11Swnj 			printf("uba%d at tr%d\n", numuba, nexnum);
356762ff349Skarels 			if (numuba >= NUBA) {
357762ff349Skarels 				printf("%d uba's", ++numuba);
358762ff349Skarels 				goto unconfig;
359762ff349Skarels 			}
360762ff349Skarels #if NUBA > 0
361b14355dbSkarels #if VAX750
362cdfb934eSkarels 			if (numuba >= 2 && cpu == VAX_750) {
363cdfb934eSkarels 				printf("More than 2 UBA's");
36409e5bb10Swnj 				goto unsupp;
365b8054636Swnj 			}
366cdfb934eSkarels #endif
367a089c9d9Sbloom #if defined(VAX780) || defined(VAX8600)
368762ff349Skarels 			if (cpu == VAX_780 || cpu == VAX_8600)
3696d315329Swnj 				setscbnex(ubaintv[numuba]);
370ce6a472bSwnj #endif
37109e5bb10Swnj 			i = nexcsr.nex_type - NEX_UBA0;
372b3a411d4Skarels 			probeuba((struct uba_regs *)nxv, (struct uba_regs *)nxp,
373b3a411d4Skarels 			    pnc->psb_umaddr[i]);
374762ff349Skarels #endif /* NUBA */
375b8054636Swnj 			break;
376b8054636Swnj 
377b8054636Swnj 		case NEX_DR32:
378e8b91158Skre 		/* there can be more than one... are there other codes??? */
379b8054636Swnj 			printf("dr32");
380b8054636Swnj 			goto unsupp;
381b8054636Swnj 
382b8054636Swnj 		case NEX_MEM4:
383b8054636Swnj 		case NEX_MEM4I:
384b8054636Swnj 		case NEX_MEM16:
385b8054636Swnj 		case NEX_MEM16I:
38684badb11Swnj 			printf("mcr%d at tr%d\n", nmcr, nexnum);
387762ff349Skarels 			if (nmcr >= MAXNMCR) {
388762ff349Skarels 				printf("%d mcr's", ++nmcr);
389762ff349Skarels 				goto unconfig;
39009e5bb10Swnj 			}
3912f548fb0Skarels 			switch (cpu) {
392762ff349Skarels #if VAX780
3932f548fb0Skarels 			case VAX_780:
394762ff349Skarels 				/* only ka780 code looks at type */
3952f548fb0Skarels 				mcrtype[nmcr] = M780C;
3962f548fb0Skarels 				break;
397762ff349Skarels #endif
398762ff349Skarels 			default:
3992f548fb0Skarels 				break;
4002f548fb0Skarels 			}
401762ff349Skarels 			mcraddr[nmcr++] = (caddr_t)nxv;
4022f548fb0Skarels 			break;
4032f548fb0Skarels 
404762ff349Skarels #if VAX780
4052f548fb0Skarels 		case NEX_MEM64I:
4062f548fb0Skarels 		case NEX_MEM64L:
4072f548fb0Skarels 		case NEX_MEM64LI:
40864c859b5Sbloom 		case NEX_MEM256I:
40964c859b5Sbloom 		case NEX_MEM256L:
41064c859b5Sbloom 		case NEX_MEM256LI:
4112f548fb0Skarels 			printf("mcr%d (el) at tr%d\n", nmcr, nexnum);
412762ff349Skarels 			if (nmcr >= MAXNMCR) {
413762ff349Skarels 				printf("%d mcr's", ++nmcr);
414762ff349Skarels 				goto unconfig;
4152f548fb0Skarels 			}
4162f548fb0Skarels 			mcrtype[nmcr] = M780EL;
417762ff349Skarels 			mcraddr[nmcr++] = (caddr_t)nxv;
41864c859b5Sbloom 			if (nexcsr.nex_type != NEX_MEM64I &&
41964c859b5Sbloom 			    nexcsr.nex_type != NEX_MEM256I)
4202f548fb0Skarels 				break;
4212f548fb0Skarels 			/* fall into ... */
4222f548fb0Skarels 
4232f548fb0Skarels 		case NEX_MEM64U:
4242f548fb0Skarels 		case NEX_MEM64UI:
42564c859b5Sbloom 		case NEX_MEM256U:
42664c859b5Sbloom 		case NEX_MEM256UI:
4272f548fb0Skarels 			printf("mcr%d (eu) at tr%d\n", nmcr, nexnum);
428762ff349Skarels 			if (nmcr >= MAXNMCR) {
429762ff349Skarels 				printf("%d mcr's", ++nmcr);
430762ff349Skarels 				goto unconfig;
4312f548fb0Skarels 			}
4322f548fb0Skarels 			mcrtype[nmcr] = M780EU;
433762ff349Skarels 			mcraddr[nmcr++] = (caddr_t)nxv;
434b8054636Swnj 			break;
435762ff349Skarels #endif
436b8054636Swnj 
437b8054636Swnj 		case NEX_MPM0:
438b8054636Swnj 		case NEX_MPM1:
439b8054636Swnj 		case NEX_MPM2:
440b8054636Swnj 		case NEX_MPM3:
441b8054636Swnj 			printf("mpm");
442b8054636Swnj 			goto unsupp;
443b8054636Swnj 
444e4f0ff2bSsam 		case NEX_CI:
445e4f0ff2bSsam 			printf("ci");
446e4f0ff2bSsam 			goto unsupp;
447e4f0ff2bSsam 
448b8054636Swnj 		default:
449b8054636Swnj 			printf("nexus type %x", nexcsr.nex_type);
450b8054636Swnj unsupp:
45109e5bb10Swnj 			printf(" unsupported (at tr %d)\n", nexnum);
452b8054636Swnj 			continue;
45384badb11Swnj unconfig:
45484badb11Swnj 			printf(" not configured\n");
45584badb11Swnj 			continue;
456b8054636Swnj 		}
457b8054636Swnj 	}
458cdfb934eSkarels 	if (nummba > NMBA)
459cdfb934eSkarels 		nummba = NMBA;
460cdfb934eSkarels 	if (numuba > NUBA)
461cdfb934eSkarels 		numuba = NUBA;
462762ff349Skarels 	if (nmcr > MAXNMCR)
463762ff349Skarels 		nmcr = MAXNMCR;
464b8054636Swnj }
465d9a5e0b6Swnj 
466b3a411d4Skarels setscbnex(fn)
467b3a411d4Skarels 	int (*fn)();
468b3a411d4Skarels {
469762ff349Skarels 	register struct scb *scbp = &scb[nsbi];
470b3a411d4Skarels 
471b3a411d4Skarels 	scbp->scb_ipl14[nexnum] = scbp->scb_ipl15[nexnum] =
472b3a411d4Skarels 	    scbp->scb_ipl16[nexnum] = scbp->scb_ipl17[nexnum] =
473b3a411d4Skarels 		scbentry(fn, SCB_ISTACK);
474b3a411d4Skarels }
475b3a411d4Skarels #endif
476b3a411d4Skarels 
477762ff349Skarels #if NBI > 0
478762ff349Skarels /*
479762ff349Skarels  * Probe BI node space.
480762ff349Skarels  *
481762ff349Skarels  * THIS DEPENDS ON BI SPACE == NEXUS SPACE
482762ff349Skarels  * THIS WILL NOT WORK FOR MULTIPLE BIs
483762ff349Skarels  */
probe_bi(p)484762ff349Skarels probe_bi(p)
485762ff349Skarels 	register struct bibus *p;
486762ff349Skarels {
487762ff349Skarels 	register struct bi_node *biv, *bip;
488762ff349Skarels 	register int node;
489762ff349Skarels 	short dtype;
490762ff349Skarels 
491762ff349Skarels 	/* must ignore BI errors while configuring */
492762ff349Skarels 	bip = p->pbi_base;
493762ff349Skarels 	ioaccess((caddr_t)bip, Nexmap[0], sizeof(*bip) * NNODEBI);/* XXX */
494762ff349Skarels 	printf("vaxbi0 at address 0x%x\n", bip);
495762ff349Skarels 	biv = (struct bi_node *) &nexus[0];	/* XXX */
496762ff349Skarels 	for (node = 0; node < NNODEBI; node++, bip++, biv++) {
497762ff349Skarels 		if (badaddr((caddr_t)biv, 4))
498762ff349Skarels 			continue;
499762ff349Skarels 		bi_nodes |= 1 << node;		/* XXX */
500762ff349Skarels 		dtype = biv->biic.bi_dtype;
501762ff349Skarels 		/* clear bus errors */
502762ff349Skarels 		biv->biic.bi_ber = ~(BIBER_MBZ|BIBER_NMR|BIBER_UPEN);
503762ff349Skarels 		switch (dtype) {
504762ff349Skarels 
505762ff349Skarels 		case BIDT_KA820: {
506762ff349Skarels 			/* is this right?? */
507762ff349Skarels 			int cp5 = biv->biic.bi_revs & 0x8000 ? '5' : '0';
508762ff349Skarels 
509762ff349Skarels 			if (node != mastercpu) {
510762ff349Skarels 				printf("slave ka82%c cpu", cp5);
511762ff349Skarels 				goto unsupp;
512762ff349Skarels 			}
513762ff349Skarels 			printf("ka82%c cpu at node %x\n", cp5, node);
514762ff349Skarels 			biv->biic.bi_intrdes = 1 << mastercpu;
515762ff349Skarels 			biv->biic.bi_csr |= BICSR_SEIE | BICSR_HEIE;
516762ff349Skarels 			break;
517762ff349Skarels 		}
518762ff349Skarels 
519762ff349Skarels 		case BIDT_DWBUA:
520762ff349Skarels 			if (numuba >= NUBA || /*XXX*/numuba > 2) {
521762ff349Skarels 				printf("%d uba's", ++numuba);
522762ff349Skarels 				goto unconfig;
523762ff349Skarels 			}
524762ff349Skarels #if NUBA > 0
525762ff349Skarels 			printf("uba%d at node %x\n", numuba, node);
526762ff349Skarels 
527762ff349Skarels 			/*
528762ff349Skarels 			 * Run a self test reset to drop any `old' errors,
529762ff349Skarels 			 * so that they cannot cause a BI bus error.
530762ff349Skarels 			 */
531762ff349Skarels 			(void) bi_selftest(&biv->biic);
532762ff349Skarels 
533762ff349Skarels 			/*
534762ff349Skarels 			 * Enable interrupts.  DWBUAs must have
535762ff349Skarels 			 * high priority.
536762ff349Skarels 			 */
537762ff349Skarels 			biv->biic.bi_intrdes = 1 << mastercpu;
538762ff349Skarels 			biv->biic.bi_csr = (biv->biic.bi_csr&~BICSR_ARB_MASK) |
539762ff349Skarels 				BICSR_ARB_HIGH;
540762ff349Skarels 			probeuba((struct uba_regs *)biv, (struct uba_regs *)bip,
541762ff349Skarels 				(caddr_t)UMEM8200(node));
542762ff349Skarels #endif /* NUBA */
543762ff349Skarels 			break;
544762ff349Skarels 
545762ff349Skarels 		case BIDT_MS820:
546762ff349Skarels 			printf("mcr%d at node %x\n", nmcr, node);
547762ff349Skarels 			if (nmcr >= MAXNMCR) {
548762ff349Skarels 				printf("%d mcr's", ++nmcr);
549762ff349Skarels 				goto unconfig;
550762ff349Skarels 			}
551762ff349Skarels 			mcraddr[nmcr++] = (caddr_t)biv;
552762ff349Skarels 			biv->biic.bi_intrdes = 1 << mastercpu;
553762ff349Skarels 			biv->biic.bi_csr |= BICSR_SEIE | BICSR_HEIE;
554762ff349Skarels 			break;
555762ff349Skarels 
556762ff349Skarels 		case BIDT_KDB50:
557762ff349Skarels 			if (numkdb >= NKDB) {
558762ff349Skarels 				printf("%d kdb's", ++numkdb);
559762ff349Skarels 				goto unconfig;
560762ff349Skarels 			}
561762ff349Skarels #if NKDB > 0
562762ff349Skarels 			printf("kdb%d at node %x\n", numkdb, node);
563762ff349Skarels 			kdbconfig(numkdb, (struct biiregs *)biv,
564762ff349Skarels 				(struct biiregs *)bip,
565762ff349Skarels 				(int)&scb[0].scb_ipl15[node] - (int)&scb[0]);
566762ff349Skarels 			scb[0].scb_ipl15[node] =
567762ff349Skarels 				scbentry(kdbintv[numkdb], SCB_ISTACK);
568762ff349Skarels 			kdbfind(numkdb);
569762ff349Skarels #endif
570762ff349Skarels 			numkdb++;
571762ff349Skarels 			break;
572762ff349Skarels 
573762ff349Skarels 		case BIDT_DEBNA:
574762ff349Skarels 		case BIDT_DEBNK:
575762ff349Skarels 			printf("debna/debnk ethernet");
576762ff349Skarels 			goto unsupp;
577762ff349Skarels 
578762ff349Skarels 		default:
579762ff349Skarels 			printf("node type 0x%x ", dtype);
580762ff349Skarels unsupp:
581762ff349Skarels 			printf(" unsupported (at node %x)\n", node);
582762ff349Skarels 			break;
583762ff349Skarels unconfig:
584762ff349Skarels 			printf(" not configured (at node %x)\n", node);
585762ff349Skarels 			continue;
586762ff349Skarels 		}
587762ff349Skarels #ifdef DO_EINTRCSR
588762ff349Skarels 		biv->biic.bi_eintrcsr = BIEIC_IPL17 |
589762ff349Skarels 			(int)&scb[0].scb_bierr - (int)&scb[0];
590762ff349Skarels 		/* but bi reset will need to restore this */
591762ff349Skarels #endif
592762ff349Skarels 	}
593762ff349Skarels 	if (numuba > NUBA)
594762ff349Skarels 		numuba = NUBA;
595762ff349Skarels 	if (numkdb > NKDB)
596762ff349Skarels 		numkdb = NKDB;
597762ff349Skarels 	if (nmcr > MAXNMCR)
598762ff349Skarels 		nmcr = MAXNMCR;
599762ff349Skarels }
600762ff349Skarels 
601762ff349Skarels #if NKDB > 0
602762ff349Skarels /*
603762ff349Skarels  * Find drives attached to a particular KDB50.
604762ff349Skarels  */
kdbfind(kdbnum)605762ff349Skarels kdbfind(kdbnum)
606762ff349Skarels 	int kdbnum;
607762ff349Skarels {
608762ff349Skarels 	extern struct uba_driver kdbdriver;
609762ff349Skarels 	register struct uba_device *ui;
610762ff349Skarels 	register struct uba_driver *udp = &kdbdriver;
611762ff349Skarels 	int t;
612762ff349Skarels 
613762ff349Skarels 	for (ui = ubdinit; ui->ui_driver; ui++) {
614762ff349Skarels 		/* ui->ui_ubanum is trash */
615762ff349Skarels 		if (ui->ui_driver != udp || ui->ui_alive ||
616762ff349Skarels 		    ui->ui_ctlr != kdbnum && ui->ui_ctlr != '?')
617762ff349Skarels 			continue;
618762ff349Skarels 		t = ui->ui_ctlr;
619762ff349Skarels 		ui->ui_ctlr = kdbnum;
620762ff349Skarels 		if ((*udp->ud_slave)(ui) == 0) {
621762ff349Skarels 			ui->ui_ctlr = t;
622762ff349Skarels 			continue;
623762ff349Skarels 		}
624762ff349Skarels 		ui->ui_alive = 1;
625762ff349Skarels 		ui->ui_ubanum = -1;
626762ff349Skarels 
627762ff349Skarels 		/* make these invalid so we can see if someone uses them */
628762ff349Skarels 		/* might as well make each one different too */
629762ff349Skarels 		ui->ui_hd = (struct uba_hd *)0xc0000010;
630762ff349Skarels 		ui->ui_addr = (caddr_t)0xc0000014;
631762ff349Skarels 		ui->ui_physaddr = (caddr_t)0xc0000018;
632762ff349Skarels 		ui->ui_mi = (struct uba_ctlr *)0xc000001c;
633762ff349Skarels 
634762ff349Skarels 		if (ui->ui_dk && dkn < DK_NDRIVE)
635762ff349Skarels 			ui->ui_dk = dkn++;
636762ff349Skarels 		else
637762ff349Skarels 			ui->ui_dk = -1;
638762ff349Skarels 		/* ui_type comes from driver */
639762ff349Skarels 		udp->ud_dinfo[ui->ui_unit] = ui;
640762ff349Skarels 		printf("%s%d at %s%d slave %d\n",
641762ff349Skarels 		    udp->ud_dname, ui->ui_unit,
642762ff349Skarels 		    udp->ud_mname, ui->ui_ctlr, ui->ui_slave);
643762ff349Skarels 		(*udp->ud_attach)(ui);
644762ff349Skarels 	}
645762ff349Skarels }
646762ff349Skarels #endif /* NKDB > 0 */
647762ff349Skarels #endif /* NBI > 0 */
648762ff349Skarels 
649b96bb200Swnj #if NMBA > 0
650701f53b0Swnj struct	mba_device *mbaconfig();
651b8054636Swnj /*
652b8054636Swnj  * Find devices attached to a particular mba
653b8054636Swnj  * and look for each device found in the massbus
654b8054636Swnj  * initialization tables.
655b8054636Swnj  */
65609e5bb10Swnj mbafind(nxv, nxp)
657d9a5e0b6Swnj 	struct nexus *nxv, *nxp;
658b8054636Swnj {
659b8054636Swnj 	register struct mba_regs *mdp;
660b8054636Swnj 	register struct mba_drv *mbd;
661701f53b0Swnj 	register struct mba_device *mi;
662701f53b0Swnj 	register struct mba_slave *ms;
6632101e181Skre 	int dn, dt, sn;
664701f53b0Swnj 	struct mba_device fnd;
665b8054636Swnj 
66609e5bb10Swnj 	mdp = (struct mba_regs *)nxv;
667e8b91158Skre 	mba_hd[nummba].mh_mba = mdp;
668e8b91158Skre 	mba_hd[nummba].mh_physmba = (struct mba_regs *)nxp;
6696d315329Swnj 	setscbnex(mbaintv[nummba]);
670e8887a6eSkarels 	mdp->mba_cr = MBCR_INIT;
671e8887a6eSkarels 	mdp->mba_cr = MBCR_IE;
672b8054636Swnj 	fnd.mi_mba = mdp;
673e8b91158Skre 	fnd.mi_mbanum = nummba;
674b8054636Swnj 	for (mbd = mdp->mba_drv, dn = 0; mbd < &mdp->mba_drv[8]; mbd++, dn++) {
675f939c6feSwnj 		if ((mbd->mbd_ds&MBDS_DPR) == 0)
676f939c6feSwnj 			continue;
6770c0ba551Sroot 		mdp->mba_sr |= MBSR_NED;		/* si kludge */
678b8054636Swnj 		dt = mbd->mbd_dt & 0xffff;
679b8054636Swnj 		if (dt == 0)
680b8054636Swnj 			continue;
6810c0ba551Sroot 		if (mdp->mba_sr&MBSR_NED)
6820c0ba551Sroot 			continue;			/* si kludge */
683b8054636Swnj 		if (dt == MBDT_MOH)
684b8054636Swnj 			continue;
685b8054636Swnj 		fnd.mi_drive = dn;
6862101e181Skre #define	qeq(a, b)	( a == b || a == '?' )
6872101e181Skre 		if ((mi = mbaconfig(&fnd, dt)) && (dt & MBDT_TAP))
6882101e181Skre 		    for (sn = 0; sn < 8; sn++) {
6892101e181Skre 			mbd->mbd_tc = sn;
690701f53b0Swnj 		        for (ms = mbsinit; ms->ms_driver; ms++)
6912101e181Skre 			    if (ms->ms_driver == mi->mi_driver &&
6922101e181Skre 				ms->ms_alive == 0 &&
6932101e181Skre 				qeq(ms->ms_ctlr, mi->mi_unit) &&
6942101e181Skre 				qeq(ms->ms_slave, sn) &&
6952101e181Skre 				(*ms->ms_driver->md_slave)(mi, ms, sn)) {
6962101e181Skre 					printf("%s%d at %s%d slave %d\n"
6972101e181Skre 					    , ms->ms_driver->md_sname
6982101e181Skre 					    , ms->ms_unit
6992101e181Skre 					    , mi->mi_driver->md_dname
7002101e181Skre 					    , mi->mi_unit
7012101e181Skre 					    , sn
7022101e181Skre 					);
70384badb11Swnj 					ms->ms_alive = 1;
70484badb11Swnj 					ms->ms_ctlr = mi->mi_unit;
7052101e181Skre 					ms->ms_slave = sn;
706bb45087dSmckusick 					break;
707701f53b0Swnj 				}
708b8054636Swnj 		    }
709b8054636Swnj 	}
710b8054636Swnj }
711b8054636Swnj 
712b8054636Swnj /*
713b8054636Swnj  * Have found a massbus device;
714b8054636Swnj  * see if it is in the configuration table.
715b8054636Swnj  * If so, fill in its data.
716b8054636Swnj  */
717701f53b0Swnj struct mba_device *
mbaconfig(ni,type)718b8054636Swnj mbaconfig(ni, type)
719701f53b0Swnj 	register struct mba_device *ni;
720b8054636Swnj 	register int type;
721b8054636Swnj {
722701f53b0Swnj 	register struct mba_device *mi;
723b8054636Swnj 	register short *tp;
724884ec674Swnj 	register struct mba_hd *mh;
725b8054636Swnj 
726701f53b0Swnj 	for (mi = mbdinit; mi->mi_driver; mi++) {
727b8054636Swnj 		if (mi->mi_alive)
728b8054636Swnj 			continue;
729b8054636Swnj 		tp = mi->mi_driver->md_type;
730b8054636Swnj 		for (mi->mi_type = 0; *tp; tp++, mi->mi_type++)
731ae520bf5Swnj 			if (*tp == (type&MBDT_TYPE))
732b8054636Swnj 				goto found;
733b8054636Swnj 		continue;
734b8054636Swnj found:
735b8054636Swnj #define	match(fld)	(ni->fld == mi->fld || mi->fld == '?')
736701f53b0Swnj 		if (!match(mi_drive) || !match(mi_mbanum))
737b8054636Swnj 			continue;
738c0ffcddcSkarels 		printf("%s%d at mba%d drive %d",
739701f53b0Swnj 		    mi->mi_driver->md_dname, mi->mi_unit,
740701f53b0Swnj 		    ni->mi_mbanum, ni->mi_drive);
741b8054636Swnj 		mi->mi_alive = 1;
742884ec674Swnj 		mh = &mba_hd[ni->mi_mbanum];
743884ec674Swnj 		mi->mi_hd = mh;
744884ec674Swnj 		mh->mh_mbip[ni->mi_drive] = mi;
745884ec674Swnj 		mh->mh_ndrive++;
746b8054636Swnj 		mi->mi_mba = ni->mi_mba;
747b8054636Swnj 		mi->mi_drv = &mi->mi_mba->mba_drv[ni->mi_drive];
748b8054636Swnj 		mi->mi_mbanum = ni->mi_mbanum;
749b8054636Swnj 		mi->mi_drive = ni->mi_drive;
75043668a85Ssam 		/*
75143668a85Ssam 		 * If drive has never been seen before,
75243668a85Ssam 		 * give it a dkn for statistics.
75343668a85Ssam 		 */
75443668a85Ssam 		if (mi->mi_driver->md_info[mi->mi_unit] == 0) {
75543668a85Ssam 			mi->mi_driver->md_info[mi->mi_unit] = mi;
7568a75d5d5Swnj 			if (mi->mi_dk && dkn < DK_NDRIVE)
7578a75d5d5Swnj 				mi->mi_dk = dkn++;
7588a75d5d5Swnj 			else
7598a75d5d5Swnj 				mi->mi_dk = -1;
76043668a85Ssam 		}
761701f53b0Swnj 		(*mi->mi_driver->md_attach)(mi);
762c0ffcddcSkarels 		printf("\n");
763701f53b0Swnj 		return (mi);
764b8054636Swnj 	}
765701f53b0Swnj 	return (0);
766b8054636Swnj }
767b96bb200Swnj #endif
768b8054636Swnj 
76909e5bb10Swnj /*
770d9a5e0b6Swnj  * Fixctlrmask fixes the masks of the driver ctlr routines
771d9a5e0b6Swnj  * which otherwise save r10 and r11 where the interrupt and br
772d9a5e0b6Swnj  * level are passed through.
77309e5bb10Swnj  */
fixctlrmask()774d9a5e0b6Swnj fixctlrmask()
775b8054636Swnj {
776701f53b0Swnj 	register struct uba_ctlr *um;
777701f53b0Swnj 	register struct uba_device *ui;
778d9a5e0b6Swnj 	register struct uba_driver *ud;
779d9a5e0b6Swnj #define	phys(a,b) ((b)(((int)(a))&0x7fffffff))
780b8054636Swnj 
781d9a5e0b6Swnj 	for (um = ubminit; ud = phys(um->um_driver, struct uba_driver *); um++)
782884ec674Swnj 		*phys(ud->ud_probe, short *) &= ~0xc00;
783d9a5e0b6Swnj 	for (ui = ubdinit; ud = phys(ui->ui_driver, struct uba_driver *); ui++)
784884ec674Swnj 		*phys(ud->ud_probe, short *) &= ~0xc00;
785d9a5e0b6Swnj }
786d9a5e0b6Swnj 
787762ff349Skarels #ifdef QBA
788b3a411d4Skarels /*
789b3a411d4Skarels  * Configure a Q-bus.
790b3a411d4Skarels  */
791b3a411d4Skarels probeqbus(qb)
792b3a411d4Skarels 	struct qbus *qb;
793b3a411d4Skarels {
794b3a411d4Skarels 	register struct uba_hd *uhp = &uba_hd[numuba];
795b3a411d4Skarels 
796762ff349Skarels 	ioaccess((caddr_t)qb->qb_map, Nexmap[0],
797762ff349Skarels 		qb->qb_memsize * sizeof (struct pte));
798b3a411d4Skarels 	uhp->uh_type = qb->qb_type;
799b3a411d4Skarels 	uhp->uh_uba = (struct uba_regs *)0xc0000000;   /* no uba adaptor regs */
800b3a411d4Skarels 	uhp->uh_mr = (struct pte *)&nexus[0];
801b3a411d4Skarels 	/*
802b3a411d4Skarels 	 * The map registers start right at 20088000 on the
803b3a411d4Skarels 	 * ka630, so we have to subtract out the 2k offset to make the
804b3a411d4Skarels 	 * pointers work..
805b3a411d4Skarels 	 */
806b3a411d4Skarels 	uhp->uh_physuba = (struct uba_regs *)(((u_long)qb->qb_map)-0x800);
807b3a411d4Skarels 
808b3a411d4Skarels 	uhp->uh_memsize = qb->qb_memsize;
809b3a411d4Skarels 	ioaccess(qb->qb_maddr, UMEMmap[numuba], uhp->uh_memsize * NBPG);
810b3a411d4Skarels 	uhp->uh_mem = umem[numuba];
811b3a411d4Skarels 
812b3a411d4Skarels 	/*
813b3a411d4Skarels 	 * The I/O page is mapped to the 8K of the umem address space
814b3a411d4Skarels 	 * immediately after the memory section that is mapped.
815b3a411d4Skarels 	 */
816b3a411d4Skarels 	ioaccess(qb->qb_iopage, UMEMmap[numuba] + uhp->uh_memsize,
817b3a411d4Skarels 	    UBAIOPAGES * NBPG);
818b3a411d4Skarels 	uhp->uh_iopage = umem[numuba] + (uhp->uh_memsize * NBPG);
819b3a411d4Skarels 
820b3a411d4Skarels 	unifind(uhp, qb->qb_iopage);
821b3a411d4Skarels }
822b3a411d4Skarels #endif
823b3a411d4Skarels 
824762ff349Skarels #if NUBA > 0
825b3a411d4Skarels probeuba(vubp, pubp, pumem)
826b3a411d4Skarels 	struct uba_regs *vubp, *pubp;
827b3a411d4Skarels 	caddr_t pumem;
828b3a411d4Skarels {
829b3a411d4Skarels 	register struct uba_hd *uhp = &uba_hd[numuba];
830b3a411d4Skarels 
831b3a411d4Skarels 	/*
832b3a411d4Skarels 	 * Save virtual and physical addresses of adaptor.
833b3a411d4Skarels 	 */
834b3a411d4Skarels 	switch (cpu) {
835b3a411d4Skarels #ifdef DW780
836b3a411d4Skarels 	case VAX_8600:
837b3a411d4Skarels 	case VAX_780:
838b3a411d4Skarels 		uhp->uh_type = DW780;
839b3a411d4Skarels 		break;
840b3a411d4Skarels #endif
841b3a411d4Skarels #ifdef DW750
842b3a411d4Skarels 	case VAX_750:
843b3a411d4Skarels 		uhp->uh_type = DW750;
844b3a411d4Skarels 		break;
845b3a411d4Skarels #endif
846b3a411d4Skarels #ifdef DW730
847b3a411d4Skarels 	case VAX_730:
848b3a411d4Skarels 		uhp->uh_type = DW730;
849b3a411d4Skarels 		break;
850b3a411d4Skarels #endif
851762ff349Skarels #ifdef DWBUA
852762ff349Skarels 	case VAX_8200:
853762ff349Skarels 		uhp->uh_type = DWBUA;
854762ff349Skarels 		break;
855762ff349Skarels #endif
856b3a411d4Skarels 	default:
857b3a411d4Skarels 		panic("unknown UBA type");
858b3a411d4Skarels 		/*NOTREACHED*/
859b3a411d4Skarels 	}
860b3a411d4Skarels 	uhp->uh_uba = vubp;
861b3a411d4Skarels 	uhp->uh_physuba = pubp;
862b3a411d4Skarels 	uhp->uh_mr = vubp->uba_map;
863b3a411d4Skarels 	uhp->uh_memsize = UBAPAGES;
864b3a411d4Skarels 
865b3a411d4Skarels 	ioaccess(pumem, UMEMmap[numuba], (UBAPAGES + UBAIOPAGES) * NBPG);
866b3a411d4Skarels 	uhp->uh_mem = umem[numuba];
867b3a411d4Skarels 	uhp->uh_iopage = umem[numuba] + (uhp->uh_memsize * NBPG);
868b3a411d4Skarels 
869b3a411d4Skarels 	unifind(uhp, pumem + (uhp->uh_memsize * NBPG));
870b3a411d4Skarels }
871b3a411d4Skarels 
872d9a5e0b6Swnj /*
873d9a5e0b6Swnj  * Find devices on a UNIBUS.
874d9a5e0b6Swnj  * Uses per-driver routine to set <br,cvec> into <r11,r10>,
875d9a5e0b6Swnj  * and then fills in the tables, with help from a per-driver
876d9a5e0b6Swnj  * slave initialization routine.
877d9a5e0b6Swnj  */
878b3a411d4Skarels unifind(uhp0, pumem)
879b3a411d4Skarels 	struct uba_hd *uhp0;
880b3a411d4Skarels 	caddr_t pumem;
881d9a5e0b6Swnj {
8826d315329Swnj #ifndef lint
883d70b5589Skarels 	register int rbr, rcvec;			/* MUST BE r11, r10 */
8846d315329Swnj #else
8856d315329Swnj 	/*
8866d315329Swnj 	 * Lint doesn't realize that these
8876d315329Swnj 	 * can be initialized asynchronously
8886d315329Swnj 	 * when devices interrupt.
8896d315329Swnj 	 */
890d70b5589Skarels 	register int rbr = 0, rcvec = 0;
8916d315329Swnj #endif
892701f53b0Swnj 	register struct uba_device *ui;
893701f53b0Swnj 	register struct uba_ctlr *um;
894b3a411d4Skarels 	register struct uba_hd *uhp = uhp0;
8952101e181Skre 	u_short *reg, *ap, addr;
896d9a5e0b6Swnj 	struct uba_driver *udp;
897a089c9d9Sbloom 	int i, (**ivec)();
898c2f959ceSmckusick 	caddr_t ualloc;
899762ff349Skarels 	extern quad catcher[128];
900d70b5589Skarels 	extern int br, cvec;
901762ff349Skarels #if DW780 || DWBUA
902b3a411d4Skarels 	struct uba_regs *vubp = uhp->uh_uba;
903de0dda68Skridle #endif
904b3a411d4Skarels 
905d9a5e0b6Swnj 	/*
906d9a5e0b6Swnj 	 * Initialize the UNIBUS, by freeing the map
907d9a5e0b6Swnj 	 * registers and the buffered data path registers
908d9a5e0b6Swnj 	 */
909a3746146Smckusick 	uhp->uh_map = (struct map *)
91069ae479aSkarels 		malloc((u_long)(UAMSIZ * sizeof (struct map)), M_DEVBUF,
91169ae479aSkarels 		    M_NOWAIT);
912366b9158Smckusick 	if (uhp->uh_map == 0)
913366b9158Smckusick 		panic("no mem for unibus map");
91469ae479aSkarels 	bzero((caddr_t)uhp->uh_map, (unsigned)(UAMSIZ * sizeof (struct map)));
9150df6cb74Swnj 	ubainitmaps(uhp);
916d9a5e0b6Swnj 
917d9a5e0b6Swnj 	/*
918762ff349Skarels 	 * Initialize space for the UNIBUS interrupt vectors.
919762ff349Skarels 	 * On the 8600, can't use first slot in UNIvec
920762ff349Skarels 	 * (the vectors for the second SBI overlap it);
921762ff349Skarels 	 * move each set of vectors forward.
92232e110b5Skarels 	 */
923b3a411d4Skarels #if	VAX8600
924a089c9d9Sbloom 	if (cpu == VAX_8600)
925762ff349Skarels 		uhp->uh_vec = UNIvec[numuba + 1];
926b3a411d4Skarels 	else
927b3a411d4Skarels #endif
928762ff349Skarels 		uhp->uh_vec = UNIvec[numuba];
929d9a5e0b6Swnj 	for (i = 0; i < 128; i++)
930762ff349Skarels 		uhp->uh_vec[i] = scbentry(&catcher[i], SCB_ISTACK);
931a9c12ad0Swnj 	/*
932a9c12ad0Swnj 	 * Set last free interrupt vector for devices with
933a9c12ad0Swnj 	 * programmable interrupt vectors.  Use is to decrement
934a9c12ad0Swnj 	 * this number and use result as interrupt vector.
935a9c12ad0Swnj 	 */
936a9c12ad0Swnj 	uhp->uh_lastiv = 0x200;
937a9c12ad0Swnj 
938762ff349Skarels #ifdef DWBUA
939762ff349Skarels 	if (uhp->uh_type == DWBUA)
940762ff349Skarels 		BUA(vubp)->bua_offset = (int)uhp->uh_vec - (int)&scb[0];
941762ff349Skarels #endif
942762ff349Skarels 
943b3a411d4Skarels #ifdef DW780
944b3a411d4Skarels 	if (uhp->uh_type == DW780) {
945d9a5e0b6Swnj 		vubp->uba_sr = vubp->uba_sr;
946701f53b0Swnj 		vubp->uba_cr = UBACR_IFS|UBACR_BRIE;
947b8054636Swnj 	}
948b8054636Swnj #endif
949d9a5e0b6Swnj 	/*
950b14355dbSkarels 	 * First configure devices that have unibus memory,
951b14355dbSkarels 	 * allowing them to allocate the correct map registers.
952b14355dbSkarels 	 */
953b14355dbSkarels 	ubameminit(numuba);
954b14355dbSkarels 	/*
9552101e181Skre 	 * Grab some memory to record the umem address space we allocate,
9562101e181Skre 	 * so we can be sure not to place two devices at the same address.
9572101e181Skre 	 *
9582101e181Skre 	 * We could use just 1/8 of this (we only want a 1 bit flag) but
9592101e181Skre 	 * we are going to give it back anyway, and that would make the
9602101e181Skre 	 * code here bigger (which we can't give back), so ...
9612101e181Skre 	 *
9622101e181Skre 	 * One day, someone will make a unibus with something other than
9632101e181Skre 	 * an 8K i/o address space, & screw this totally.
9642101e181Skre 	 */
96569ae479aSkarels 	ualloc = (caddr_t)malloc((u_long)(8 * 1024), M_TEMP, M_NOWAIT);
9662101e181Skre 	if (ualloc == (caddr_t)0)
9672101e181Skre 		panic("no mem for unifind");
96839b1d096Skre 	bzero(ualloc, 8*1024);
9692101e181Skre 
9702101e181Skre 	/*
971d9a5e0b6Swnj 	 * Map the first page of UNIBUS i/o
972d9a5e0b6Swnj 	 * space to the first page of memory
973d9a5e0b6Swnj 	 * for devices which will need to dma
974d9a5e0b6Swnj 	 * output to produce an interrupt.
975d9a5e0b6Swnj 	 */
976b3a411d4Skarels 	*(int *)(&uhp->uh_mr[0]) = UBAMR_MRV;
977d9a5e0b6Swnj 
978b3a411d4Skarels #define	ubaddr(uhp, off)    (u_short *)((int)(uhp)->uh_iopage + ubdevreg(off))
979d9a5e0b6Swnj 	/*
980d9a5e0b6Swnj 	 * Check each unibus mass storage controller.
981d9a5e0b6Swnj 	 * For each one which is potentially on this uba,
982d9a5e0b6Swnj 	 * see if it is really there, and if it is record it and
983d9a5e0b6Swnj 	 * then go looking for slaves.
984d9a5e0b6Swnj 	 */
985d9a5e0b6Swnj 	for (um = ubminit; udp = um->um_driver; um++) {
986762ff349Skarels 		if (um->um_ubanum != numuba && um->um_ubanum != '?' ||
987762ff349Skarels 		    um->um_alive)
988b8054636Swnj 			continue;
989d9a5e0b6Swnj 		addr = (u_short)um->um_addr;
9902101e181Skre 		/*
9912101e181Skre 		 * use the particular address specified first,
9922101e181Skre 		 * or if it is given as "0", of there is no device
9932101e181Skre 		 * at that address, try all the standard addresses
9942101e181Skre 		 * in the driver til we find it
9952101e181Skre 		 */
9962101e181Skre 	    for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) {
9972101e181Skre 
998b3a411d4Skarels 		if (ualloc[ubdevreg(addr)])
9992101e181Skre 			continue;
1000b3a411d4Skarels 		reg = ubaddr(uhp, addr);
1001b8054636Swnj 		if (badaddr((caddr_t)reg, 2))
1002b8054636Swnj 			continue;
1003b3a411d4Skarels #ifdef DW780
1004b3a411d4Skarels 		if (uhp->uh_type == DW780 && vubp->uba_sr) {
1005d9a5e0b6Swnj 			vubp->uba_sr = vubp->uba_sr;
1006b8054636Swnj 			continue;
1007b8054636Swnj 		}
1008b8054636Swnj #endif
1009b8054636Swnj 		cvec = 0x200;
1010d70b5589Skarels 		rcvec = 0x200;
1011b14355dbSkarels 		i = (*udp->ud_probe)(reg, um->um_ctlr, um);
1012b3a411d4Skarels #ifdef DW780
1013b3a411d4Skarels 		if (uhp->uh_type == DW780 && vubp->uba_sr) {
1014d9a5e0b6Swnj 			vubp->uba_sr = vubp->uba_sr;
1015b8054636Swnj 			continue;
1016b8054636Swnj 		}
1017b8054636Swnj #endif
1018b8054636Swnj 		if (i == 0)
1019b8054636Swnj 			continue;
10208a75d5d5Swnj 		printf("%s%d at uba%d csr %o ",
10218a75d5d5Swnj 		    udp->ud_mname, um->um_ctlr, numuba, addr);
1022d70b5589Skarels 		if (rcvec == 0) {
1023d9a5e0b6Swnj 			printf("zero vector\n");
1024b8054636Swnj 			continue;
1025b8054636Swnj 		}
1026d70b5589Skarels 		if (rcvec == 0x200) {
1027d9a5e0b6Swnj 			printf("didn't interrupt\n");
1028b8054636Swnj 			continue;
1029b8054636Swnj 		}
1030d70b5589Skarels 		printf("vec %o, ipl %x\n", rcvec, rbr);
1031628b8f95Skarels 		csralloc(ualloc, addr, i);
1032d9a5e0b6Swnj 		um->um_alive = 1;
1033d9a5e0b6Swnj 		um->um_ubanum = numuba;
1034762ff349Skarels 		um->um_hd = uhp;
1035d9a5e0b6Swnj 		um->um_addr = (caddr_t)reg;
1036d9a5e0b6Swnj 		udp->ud_minfo[um->um_ctlr] = um;
1037d70b5589Skarels 		for (rcvec /= 4, ivec = um->um_intr; *ivec; rcvec++, ivec++)
1038d70b5589Skarels 			uhp->uh_vec[rcvec] = scbentry(*ivec, SCB_ISTACK);
1039d9a5e0b6Swnj 		for (ui = ubdinit; ui->ui_driver; ui++) {
1040762ff349Skarels 			int t;
1041762ff349Skarels 
1042d9a5e0b6Swnj 			if (ui->ui_driver != udp || ui->ui_alive ||
1043d9a5e0b6Swnj 			    ui->ui_ctlr != um->um_ctlr && ui->ui_ctlr != '?' ||
1044d9a5e0b6Swnj 			    ui->ui_ubanum != numuba && ui->ui_ubanum != '?')
1045d9a5e0b6Swnj 				continue;
1046762ff349Skarels 			t = ui->ui_ctlr;
1047d9a5e0b6Swnj 			ui->ui_ctlr = um->um_ctlr;
1048762ff349Skarels 			if ((*udp->ud_slave)(ui, reg) == 0)
1049762ff349Skarels 				ui->ui_ctlr = t;
1050762ff349Skarels 			else {
1051762ff349Skarels 				ui->ui_alive = 1;
105209e5bb10Swnj 				ui->ui_ubanum = numuba;
1053762ff349Skarels 				ui->ui_hd = uhp;
1054b8054636Swnj 				ui->ui_addr = (caddr_t)reg;
105500b653fcSfeldman 				ui->ui_physaddr = pumem + ubdevreg(addr);
10568a75d5d5Swnj 				if (ui->ui_dk && dkn < DK_NDRIVE)
1057c5a2c486Swnj 					ui->ui_dk = dkn++;
10588a75d5d5Swnj 				else
10598a75d5d5Swnj 					ui->ui_dk = -1;
1060d9a5e0b6Swnj 				ui->ui_mi = um;
106109e5bb10Swnj 				/* ui_type comes from driver */
1062d9a5e0b6Swnj 				udp->ud_dinfo[ui->ui_unit] = ui;
1063762ff349Skarels 				printf("%s%d at %s%d slave %d",
10648a75d5d5Swnj 				    udp->ud_dname, ui->ui_unit,
10658a75d5d5Swnj 				    udp->ud_mname, um->um_ctlr, ui->ui_slave);
1066884ec674Swnj 				(*udp->ud_attach)(ui);
1067762ff349Skarels 				printf("\n");
1068d9a5e0b6Swnj 			}
1069d9a5e0b6Swnj 		}
10702101e181Skre 		break;
10712101e181Skre 	    }
1072d9a5e0b6Swnj 	}
1073d9a5e0b6Swnj 	/*
1074d9a5e0b6Swnj 	 * Now look for non-mass storage peripherals.
1075d9a5e0b6Swnj 	 */
1076d9a5e0b6Swnj 	for (ui = ubdinit; udp = ui->ui_driver; ui++) {
1077d9a5e0b6Swnj 		if (ui->ui_ubanum != numuba && ui->ui_ubanum != '?' ||
1078d9a5e0b6Swnj 		    ui->ui_alive || ui->ui_slave != -1)
1079d9a5e0b6Swnj 			continue;
1080d9a5e0b6Swnj 		addr = (u_short)ui->ui_addr;
10812101e181Skre 
10822101e181Skre 	    for (ap = udp->ud_addr; addr || (addr = *ap++); addr = 0) {
10832101e181Skre 
1084b3a411d4Skarels 		if (ualloc[ubdevreg(addr)])
10852101e181Skre 			continue;
1086b3a411d4Skarels 		reg = ubaddr(uhp, addr);
1087d9a5e0b6Swnj 		if (badaddr((caddr_t)reg, 2))
1088d9a5e0b6Swnj 			continue;
1089b3a411d4Skarels #ifdef DW780
1090b3a411d4Skarels 		if (uhp->uh_type == DW780 && vubp->uba_sr) {
1091d9a5e0b6Swnj 			vubp->uba_sr = vubp->uba_sr;
1092d9a5e0b6Swnj 			continue;
1093d9a5e0b6Swnj 		}
1094d9a5e0b6Swnj #endif
1095d70b5589Skarels 		rcvec = 0x200;
1096d9a5e0b6Swnj 		cvec = 0x200;
1097b14355dbSkarels 		i = (*udp->ud_probe)(reg, ui);
1098b3a411d4Skarels #ifdef DW780
1099b3a411d4Skarels 		if (uhp->uh_type == DW780 && vubp->uba_sr) {
1100d9a5e0b6Swnj 			vubp->uba_sr = vubp->uba_sr;
1101d9a5e0b6Swnj 			continue;
1102d9a5e0b6Swnj 		}
1103d9a5e0b6Swnj #endif
1104d9a5e0b6Swnj 		if (i == 0)
1105d9a5e0b6Swnj 			continue;
11068a75d5d5Swnj 		printf("%s%d at uba%d csr %o ",
11078a75d5d5Swnj 		    ui->ui_driver->ud_dname, ui->ui_unit, numuba, addr);
1108d70b5589Skarels 		if (rcvec == 0) {
1109d9a5e0b6Swnj 			printf("zero vector\n");
1110d9a5e0b6Swnj 			continue;
1111d9a5e0b6Swnj 		}
1112d70b5589Skarels 		if (rcvec == 0x200) {
1113d9a5e0b6Swnj 			printf("didn't interrupt\n");
1114d9a5e0b6Swnj 			continue;
1115d9a5e0b6Swnj 		}
1116d70b5589Skarels 		printf("vec %o, ipl %x\n", rcvec, rbr);
1117628b8f95Skarels 		csralloc(ualloc, addr, i);
1118762ff349Skarels 		ui->ui_hd = uhp;
1119d70b5589Skarels 		for (rcvec /= 4, ivec = ui->ui_intr; *ivec; rcvec++, ivec++)
1120d70b5589Skarels 			uhp->uh_vec[rcvec] = scbentry(*ivec, SCB_ISTACK);
1121d9a5e0b6Swnj 		ui->ui_alive = 1;
1122d9a5e0b6Swnj 		ui->ui_ubanum = numuba;
1123d9a5e0b6Swnj 		ui->ui_addr = (caddr_t)reg;
112400b653fcSfeldman 		ui->ui_physaddr = pumem + ubdevreg(addr);
11258a75d5d5Swnj 		ui->ui_dk = -1;
1126d9a5e0b6Swnj 		/* ui_type comes from driver */
1127d9a5e0b6Swnj 		udp->ud_dinfo[ui->ui_unit] = ui;
1128884ec674Swnj 		(*udp->ud_attach)(ui);
11292101e181Skre 		break;
1130b8054636Swnj 	    }
1131b8054636Swnj 	}
1132b8054636Swnj 
1133b3a411d4Skarels #ifdef DW780
1134b3a411d4Skarels 	if (uhp->uh_type == DW780)
1135b3a411d4Skarels 		uhp->uh_uba->uba_cr = UBACR_IFS | UBACR_BRIE |
1136b3a411d4Skarels 		    UBACR_USEFIE | UBACR_SUEFIE |
1137b3a411d4Skarels 		    (uhp->uh_uba->uba_cr & 0x7c000000);
1138b3a411d4Skarels #endif
1139b3a411d4Skarels 	numuba++;
1140b3a411d4Skarels 
11412101e181Skre #ifdef	AUTO_DEBUG
11422101e181Skre 	printf("Unibus allocation map");
11432101e181Skre 	for (i = 0; i < 8*1024; ) {
11442101e181Skre 		register n, m;
11452101e181Skre 
11462101e181Skre 		if ((i % 128) == 0) {
11472101e181Skre 			printf("\n%6o:", i);
11482101e181Skre 			for (n = 0; n < 128; n++)
11492101e181Skre 				if (ualloc[i+n])
11502101e181Skre 					break;
11512101e181Skre 			if (n == 128) {
11522101e181Skre 				i += 128;
11532101e181Skre 				continue;
11542101e181Skre 			}
11552101e181Skre 		}
11562101e181Skre 
11572101e181Skre 		for (n = m = 0; n < 16; n++) {
11582101e181Skre 			m <<= 1;
11592101e181Skre 			m |= ualloc[i++];
11602101e181Skre 		}
11612101e181Skre 
11622101e181Skre 		printf(" %4x", m);
11632101e181Skre 	}
11642101e181Skre 	printf("\n");
11652101e181Skre #endif
11662101e181Skre 
1167c2f959ceSmckusick 	free(ualloc, M_TEMP);
11682101e181Skre }
1169762ff349Skarels #endif /* NUBA */
11702101e181Skre 
1171b8054636Swnj /*
1172628b8f95Skarels  * Mark addresses starting at "addr" and continuing
1173628b8f95Skarels  * "size" bytes as allocated in the map "ualloc".
1174628b8f95Skarels  * Warn if the new allocation overlaps a previous allocation.
1175628b8f95Skarels  */
1176628b8f95Skarels static
csralloc(ualloc,addr,size)1177628b8f95Skarels csralloc(ualloc, addr, size)
1178628b8f95Skarels 	caddr_t ualloc;
1179628b8f95Skarels 	u_short addr;
1180628b8f95Skarels 	register int size;
1181628b8f95Skarels {
1182628b8f95Skarels 	register caddr_t p;
1183628b8f95Skarels 	int warned = 0;
1184628b8f95Skarels 
1185628b8f95Skarels 	p = &ualloc[ubdevreg(addr+size)];
1186628b8f95Skarels 	while (--size >= 0) {
1187628b8f95Skarels 		if (*--p && !warned) {
1188628b8f95Skarels 			printf(
1189628b8f95Skarels 	"WARNING: device registers overlap those for a previous device!\n");
1190628b8f95Skarels 			warned = 1;
1191628b8f95Skarels 		}
1192628b8f95Skarels 		*p = 1;
1193628b8f95Skarels 	}
1194628b8f95Skarels }
1195628b8f95Skarels 
1196628b8f95Skarels /*
1197a8b6ec1fSkarels  * Make an IO register area accessible at physical address physa
1198b8054636Swnj  * by mapping kernel ptes starting at pte.
1199b8054636Swnj  */
ioaccess(physa,pte,size)120032e110b5Skarels ioaccess(physa, pte, size)
1201a8b6ec1fSkarels 	caddr_t physa;
1202b8054636Swnj 	register struct pte *pte;
1203a089c9d9Sbloom 	int size;
1204b8054636Swnj {
1205b3a411d4Skarels 	register int i = btoc(size);
1206d9a5e0b6Swnj 	register unsigned v = btop(physa);
1207b8054636Swnj 
1208b8054636Swnj 	do
1209b8054636Swnj 		*(int *)pte++ = PG_V|PG_KW|v++;
12106d315329Swnj 	while (--i > 0);
1211b8054636Swnj 	mtpr(TBIA, 0);
1212b8054636Swnj }
1213b404ff6cSfeldman 
121401cdfd67Ssam /*
121501cdfd67Ssam  * Configure swap space and related parameters.
121601cdfd67Ssam  */
swapconf()121701cdfd67Ssam swapconf()
121801cdfd67Ssam {
121901cdfd67Ssam 	register struct swdevt *swp;
122088df6acbSsam 	register int nblks;
122101cdfd67Ssam 
1222*2c107824Storek 	for (swp = swdevt; swp->sw_dev != NODEV; swp++)
1223f55d1ae0Skarels 		if (bdevsw[major(swp->sw_dev)].d_psize) {
122488df6acbSsam 			nblks =
122501cdfd67Ssam 			  (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev);
1226e8887a6eSkarels 			if (nblks != -1 &&
1227e8887a6eSkarels 			    (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
122888df6acbSsam 				swp->sw_nblks = nblks;
122901cdfd67Ssam 		}
1230d70b5589Skarels 	dumpconf();
123101cdfd67Ssam }
1232f187dfb0Skarels 
1233f187dfb0Skarels #define	DOSWAP			/* Change swdevt, argdev, and dumpdev too */
1234f187dfb0Skarels u_long	bootdev;		/* should be dev_t, but not until 32 bits */
1235f187dfb0Skarels 
1236f187dfb0Skarels static	char devname[][2] = {
1237f187dfb0Skarels 	'h','p',	/* 0 = hp */
1238f187dfb0Skarels 	0,0,		/* 1 = ht */
1239f187dfb0Skarels 	'u','p',	/* 2 = up */
1240f187dfb0Skarels 	'r','k',	/* 3 = hk */
1241f187dfb0Skarels 	0,0,		/* 4 = sw */
1242f187dfb0Skarels 	0,0,		/* 5 = tm */
1243f187dfb0Skarels 	0,0,		/* 6 = ts */
1244f187dfb0Skarels 	0,0,		/* 7 = mt */
1245f187dfb0Skarels 	0,0,		/* 8 = tu */
1246f187dfb0Skarels 	'r','a',	/* 9 = ra */
1247f187dfb0Skarels 	0,0,		/* 10 = ut */
1248f187dfb0Skarels 	'r','b',	/* 11 = rb */
1249f187dfb0Skarels 	0,0,		/* 12 = uu */
1250f187dfb0Skarels 	0,0,		/* 13 = rx */
1251f187dfb0Skarels 	'r','l',	/* 14 = rl */
1252762ff349Skarels 	0,0,		/* 15 = tmscp */
1253762ff349Skarels 	'k','r',	/* 16 = ra on kdb50 */
1254f187dfb0Skarels };
1255f187dfb0Skarels 
1256f187dfb0Skarels #define	PARTITIONMASK	0x7
1257f187dfb0Skarels #define	PARTITIONSHIFT	3
1258f187dfb0Skarels 
1259f187dfb0Skarels /*
1260f187dfb0Skarels  * Attempt to find the device from which we were booted.
1261f187dfb0Skarels  * If we can do so, and not instructed not to do so,
1262f187dfb0Skarels  * change rootdev to correspond to the load device.
1263f187dfb0Skarels  */
setroot()1264f187dfb0Skarels setroot()
1265f187dfb0Skarels {
12668c011102Skarels 	int  majdev, mindev, unit, part, controller, adaptor;
1267f187dfb0Skarels 	dev_t temp, orootdev;
1268f187dfb0Skarels 	struct swdevt *swp;
1269f187dfb0Skarels 
1270de0dda68Skridle 	if (boothowto & RB_DFLTROOT ||
1271de0dda68Skridle 	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
1272cdd5ba0eSkarels 		return;
12738c011102Skarels 	majdev = B_TYPE(bootdev);
12748c011102Skarels 	if (majdev >= sizeof(devname) / sizeof(devname[0]))
1275cdd5ba0eSkarels 		return;
12768c011102Skarels 	adaptor = B_ADAPTOR(bootdev);
12778c011102Skarels 	controller = B_CONTROLLER(bootdev);
12788c011102Skarels 	part = B_PARTITION(bootdev);
12798c011102Skarels 	unit = B_UNIT(bootdev);
1280f187dfb0Skarels 	if (majdev == 0) {	/* MBA device */
128114e1df5dSkarels #if NMBA > 0
1282f187dfb0Skarels 		register struct mba_device *mbap;
128314e1df5dSkarels 		int mask;
1284f187dfb0Skarels 
128514e1df5dSkarels /*
128614e1df5dSkarels  * The MBA number used at boot time is not necessarily the same as the
128714e1df5dSkarels  * MBA number used by the kernel.  In order to change the rootdev we need to
128814e1df5dSkarels  * convert the boot MBA number to the kernel MBA number.  The address space
128914e1df5dSkarels  * for an MBA used by the boot code is 0x20010000 + 0x2000 * MBA_number
129014e1df5dSkarels  * on the 78? and 86?0, 0xf28000 + 0x2000 * MBA_number on the 750.
129114e1df5dSkarels  * Therefore we can search the mba_hd table for the MBA that has the physical
129214e1df5dSkarels  * address corresponding to the boot MBA number.
129314e1df5dSkarels  */
129414e1df5dSkarels #define	PHYSADRSHFT	13
129514e1df5dSkarels #define	PHYSMBAMASK780	0x7
129614e1df5dSkarels #define	PHYSMBAMASK750	0x3
129714e1df5dSkarels 
129814e1df5dSkarels 		switch (cpu) {
129914e1df5dSkarels 
130014e1df5dSkarels 		case VAX_780:
130114e1df5dSkarels 		case VAX_8600:
130214e1df5dSkarels 		default:
130314e1df5dSkarels 			mask = PHYSMBAMASK780;
130414e1df5dSkarels 			break;
130514e1df5dSkarels 
130614e1df5dSkarels 		case VAX_750:
130714e1df5dSkarels 			mask = PHYSMBAMASK750;
130814e1df5dSkarels 			break;
130914e1df5dSkarels 		}
1310f187dfb0Skarels 		for (mbap = mbdinit; mbap->mi_driver; mbap++)
1311f187dfb0Skarels 			if (mbap->mi_alive && mbap->mi_drive == unit &&
131214e1df5dSkarels 			    (((long)mbap->mi_hd->mh_physmba >> PHYSADRSHFT)
131314e1df5dSkarels 			      & mask) == adaptor)
1314f187dfb0Skarels 			    	break;
1315f187dfb0Skarels 		if (mbap->mi_driver == 0)
1316cdd5ba0eSkarels 			return;
1317f187dfb0Skarels 		mindev = mbap->mi_unit;
131814e1df5dSkarels #else
1319cdd5ba0eSkarels 		return;
13205c841cf1Skarels #endif
132114e1df5dSkarels 	} else {
1322f187dfb0Skarels 		register struct uba_device *ubap;
1323f187dfb0Skarels 
1324f187dfb0Skarels 		for (ubap = ubdinit; ubap->ui_driver; ubap++)
1325f187dfb0Skarels 			if (ubap->ui_alive && ubap->ui_slave == unit &&
13268c011102Skarels 			   ubap->ui_ctlr == controller &&
1327f187dfb0Skarels 			   ubap->ui_ubanum == adaptor &&
1328f187dfb0Skarels 			   ubap->ui_driver->ud_dname[0] == devname[majdev][0] &&
1329f187dfb0Skarels 			   ubap->ui_driver->ud_dname[1] == devname[majdev][1])
1330f187dfb0Skarels 			    	break;
1331f187dfb0Skarels 
1332f187dfb0Skarels 		if (ubap->ui_driver == 0)
1333cdd5ba0eSkarels 			return;
1334f187dfb0Skarels 		mindev = ubap->ui_unit;
1335f187dfb0Skarels 	}
1336f187dfb0Skarels 	mindev = (mindev << PARTITIONSHIFT) + part;
1337f187dfb0Skarels 	orootdev = rootdev;
1338f187dfb0Skarels 	rootdev = makedev(majdev, mindev);
1339f187dfb0Skarels 	/*
1340f187dfb0Skarels 	 * If the original rootdev is the same as the one
1341f187dfb0Skarels 	 * just calculated, don't need to adjust the swap configuration.
1342f187dfb0Skarels 	 */
1343f187dfb0Skarels 	if (rootdev == orootdev)
1344cdd5ba0eSkarels 		return;
1345f187dfb0Skarels 
13464eec7f0eSkarels 	printf("Changing root device to %c%c%d%c\n",
13474eec7f0eSkarels 		devname[majdev][0], devname[majdev][1],
13484eec7f0eSkarels 		mindev >> PARTITIONSHIFT, part + 'a');
13499a448baeSkarels 
13509a448baeSkarels #ifdef DOSWAP
1351f187dfb0Skarels 	mindev &= ~PARTITIONMASK;
1352*2c107824Storek 	for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
1353f187dfb0Skarels 		if (majdev == major(swp->sw_dev) &&
1354f187dfb0Skarels 		    mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) {
1355f187dfb0Skarels 			temp = swdevt[0].sw_dev;
1356f187dfb0Skarels 			swdevt[0].sw_dev = swp->sw_dev;
1357f187dfb0Skarels 			swp->sw_dev = temp;
1358f187dfb0Skarels 			break;
1359f187dfb0Skarels 		}
1360f187dfb0Skarels 	}
1361*2c107824Storek 	if (swp->sw_dev == NODEV)
1362cdd5ba0eSkarels 		return;
1363f187dfb0Skarels 
1364f187dfb0Skarels 	/*
1365f187dfb0Skarels 	 * If argdev and dumpdev were the same as the old primary swap
1366f187dfb0Skarels 	 * device, move them to the new primary swap device.
1367f187dfb0Skarels 	 */
1368f187dfb0Skarels 	if (temp == dumpdev)
1369f187dfb0Skarels 		dumpdev = swdevt[0].sw_dev;
1370f187dfb0Skarels 	if (temp == argdev)
1371f187dfb0Skarels 		argdev = swdevt[0].sw_dev;
1372f187dfb0Skarels #endif
1373f187dfb0Skarels }
1374