xref: /original-bsd/sys/pmax/pmax/autoconf.c (revision 313aa166)
1 /*
2  * Copyright (c) 1988 University of Utah.
3  * Copyright (c) 1992, 1993
4  *	The Regents of the University of California.  All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * the Systems Programming Group of the University of Utah Computer
8  * Science Department and Ralph Campbell.
9  *
10  * %sccs.include.redist.c%
11  *
12  * from: Utah $Hdr: autoconf.c 1.31 91/01/21$
13  *
14  *	@(#)autoconf.c	8.1 (Berkeley) 06/10/93
15  */
16 
17 /*
18  * Setup the system to run on the current machine.
19  *
20  * Configure() is called at boot time.  Available
21  * devices are determined (from possibilities mentioned in ioconf.c),
22  * and the drivers are initialized.
23  */
24 
25 #include <sys/param.h>
26 #include <sys/systm.h>
27 #include <sys/map.h>
28 #include <sys/buf.h>
29 #include <sys/dkstat.h>
30 #include <sys/conf.h>
31 #include <sys/dmap.h>
32 #include <sys/reboot.h>
33 
34 #include <machine/cpu.h>
35 #include <pmax/dev/device.h>
36 #include <pmax/pmax/pmaxtype.h>
37 #include <pmax/pmax/turbochannel.h>
38 
39 /*
40  * The following several variables are related to
41  * the configuration process, and are used in initializing
42  * the machine.
43  */
44 int	cold = 1;	/* if 1, still working on cold-start */
45 int	dkn;		/* number of iostat dk numbers assigned so far */
46 int	cpuspeed = 30;	/* approx # instr per usec. */
47 extern	int pmax_boardtype;
48 extern	tc_option_t tc_slot_info[TC_MAX_LOGICAL_SLOTS];
49 
50 /*
51  * Determine mass storage and memory configuration for a machine.
52  * Get cpu type, and then switch out to machine specific procedures
53  * which will probe adaptors to see what is out there.
54  */
55 configure()
56 {
57 	register struct pmax_ctlr *cp;
58 	register struct scsi_device *dp;
59 	register struct driver *drp;
60 	register int i;
61 
62 	/* print what type of CPU and FPU we have */
63 
64 	/*
65 	 * for some reason the Pmax has an R2000 cpu with an implementation
66 	 * level of 2 and DEC's R3000s are level 2 as well?
67 	 */
68 	if (pmax_boardtype == DS_PMAX) {
69 		cpu.cpu.cp_imp = MIPS_R2000;
70 		fpu.cpu.cp_imp = MIPS_R2010;
71 	}
72 
73 	switch (cpu.cpu.cp_imp) {
74 	case MIPS_R2000:
75 		printf("cpu0 (MIPS R2000 revision %d.%d)\n",
76 			cpu.cpu.cp_majrev, cpu.cpu.cp_minrev);
77 		break;
78 
79 	case MIPS_R3000:
80 		printf("cpu0 (MIPS R3000 revision %d.%d)\n",
81 			cpu.cpu.cp_majrev, cpu.cpu.cp_minrev);
82 		break;
83 
84 	case MIPS_R4000:
85 		printf("cpu0 (MIPS R4000 revision %d.%d)\n",
86 			cpu.cpu.cp_majrev, cpu.cpu.cp_minrev);
87 		break;
88 
89 	default:
90 		printf("cpu0 (implementation %d revision %d.%d)\n",
91 			cpu.cpu.cp_imp, cpu.cpu.cp_majrev, cpu.cpu.cp_minrev);
92 	}
93 	switch (fpu.cpu.cp_imp) {
94 	case MIPS_R2010:
95 		printf("fpu0 (MIPS R2010 revision %d.%d)\n",
96 			fpu.cpu.cp_majrev, fpu.cpu.cp_minrev);
97 		break;
98 
99 	case MIPS_R3010:
100 		printf("fpu0 (MIPS R3010 revision %d.%d)\n",
101 			fpu.cpu.cp_majrev, fpu.cpu.cp_minrev);
102 		break;
103 
104 	case MIPS_R4010:
105 		printf("fpu0 (MIPS R4010 revision %d.%d)\n",
106 			fpu.cpu.cp_majrev, fpu.cpu.cp_minrev);
107 		break;
108 
109 	default:
110 		printf("fpu0 (implementation %d revision %d.%d)\n",
111 			fpu.cpu.cp_imp, fpu.cpu.cp_majrev, fpu.cpu.cp_minrev);
112 	}
113 	printf("data cache size %dK inst cache size %dK\n",
114 		machDataCacheSize >> 10, machInstCacheSize >> 10);
115 
116 	/* probe and initialize controllers */
117 	for (cp = pmax_cinit; drp = cp->pmax_driver; cp++) {
118 		switch (pmax_boardtype) {
119 		case DS_PMAX:
120 			if (cp->pmax_addr == (char *)QUES)
121 				continue;
122 			if (!(*drp->d_init)(cp))
123 				continue;
124 			break;
125 #ifdef DS5000
126 		case DS_3MAX:
127 		case DS_3MIN:
128 		case DS_MAXINE:
129 		case DS_3MAXPLUS:
130 			/*
131 			 * If the device is still in an unknown slot,
132 			 * then it was not found by tc_find_all_options().
133 			 */
134 			if (cp->pmax_addr == (char *)QUES)
135 				continue;
136 			if (!(*drp->d_init)(cp)) {
137 				cp->pmax_alive = 0;
138 				continue;
139 			}
140 			if (drp->d_intr && (i = cp->pmax_pri) >= 0) {
141 				if (tc_slot_info[i].intr)
142 					printf("%s: slot %d already in use\n",
143 						drp->d_name, i);
144 				tc_slot_info[i].intr = drp->d_intr;
145 				tc_slot_info[i].unit = cp->pmax_unit;
146 			}
147 			break;
148 #endif /* DS5000 */
149 		};
150 
151 		cp->pmax_alive = 1;
152 
153 		/* probe and initialize devices connected to controller */
154 		for (dp = scsi_dinit; drp = dp->sd_driver; dp++) {
155 			/* might want to get fancier later */
156 			if (dp->sd_cdriver != cp->pmax_driver ||
157 			    dp->sd_ctlr != cp->pmax_unit)
158 				continue;	/* not connected */
159 			if (!(*drp->d_init)(dp))
160 				continue;
161 			dp->sd_alive = 1;
162 			/* if device is a disk, assign number for statistics */
163 			if (dp->sd_dk && dkn < DK_NDRIVE)
164 				dp->sd_dk = dkn++;
165 			else
166 				dp->sd_dk = -1;
167 		}
168 	}
169 
170 #ifdef GENERIC
171 	if ((boothowto & RB_ASKNAME) == 0)
172 		setroot();
173 	setconf();
174 #else
175 	setroot();
176 #endif
177 	swapconf();
178 	cold = 0;
179 }
180 
181 /*
182  * Configure swap space and related parameters.
183  */
184 swapconf()
185 {
186 	register struct swdevt *swp;
187 	register int nblks;
188 
189 	for (swp = swdevt; swp->sw_dev != NODEV; swp++)
190 		if (bdevsw[major(swp->sw_dev)].d_psize) {
191 			nblks =
192 			  (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev);
193 			if (nblks != -1 &&
194 			    (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
195 				swp->sw_nblks = nblks;
196 		}
197 	dumpconf();
198 }
199 
200 #define	DOSWAP			/* Change swdevt and dumpdev too */
201 u_long	bootdev;		/* should be dev_t, but not until 32 bits */
202 
203 static	char devname[][2] = {
204 	'r','z',	/* 0 = rz */
205 };
206 
207 #define	PARTITIONMASK	0x7
208 #define	PARTITIONSHIFT	3
209 
210 /*
211  * Attempt to find the device from which we were booted.
212  * If we can do so, and not instructed not to do so,
213  * change rootdev to correspond to the load device.
214  */
215 setroot()
216 {
217 	register struct scsi_device *dp;
218 	int  majdev, mindev, unit, part, controller;
219 	dev_t temp, orootdev;
220 	struct swdevt *swp;
221 
222 	if (boothowto & RB_DFLTROOT ||
223 	    (bootdev & B_MAGICMASK) != B_DEVMAGIC)
224 		return;
225 	majdev = B_TYPE(bootdev);
226 	if (majdev >= sizeof(devname) / sizeof(devname[0]))
227 		return;
228 	controller = B_CONTROLLER(bootdev);
229 	part = B_PARTITION(bootdev);
230 	unit = B_UNIT(bootdev);
231 
232 	for (dp = scsi_dinit; ; dp++) {
233 		if (dp->sd_driver == 0)
234 			return;
235 		if (dp->sd_alive && dp->sd_drive == unit &&
236 		    dp->sd_ctlr == controller &&
237 		    dp->sd_driver->d_name[0] == devname[majdev][0] &&
238 		    dp->sd_driver->d_name[1] == devname[majdev][1]) {
239 			mindev = dp->sd_unit;
240 		    	break;
241 		}
242 	}
243 	/*
244 	 * Form a new rootdev
245 	 */
246 	mindev = (mindev << PARTITIONSHIFT) + part;
247 	orootdev = rootdev;
248 	rootdev = makedev(majdev, mindev);
249 	/*
250 	 * If the original rootdev is the same as the one
251 	 * just calculated, don't need to adjust the swap configuration.
252 	 */
253 	if (rootdev == orootdev)
254 		return;
255 
256 	printf("Changing root device to %c%c%d%c\n",
257 		devname[majdev][0], devname[majdev][1],
258 		mindev >> PARTITIONSHIFT, part + 'a');
259 
260 #ifdef DOSWAP
261 	mindev &= ~PARTITIONMASK;
262 	for (swp = swdevt; swp->sw_dev != NODEV; swp++) {
263 		if (majdev == major(swp->sw_dev) &&
264 		    mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) {
265 			temp = swdevt[0].sw_dev;
266 			swdevt[0].sw_dev = swp->sw_dev;
267 			swp->sw_dev = temp;
268 			break;
269 		}
270 	}
271 	if (swp->sw_dev == NODEV)
272 		return;
273 
274 	/*
275 	 * If dumpdev was the same as the old primary swap
276 	 * device, move it to the new primary swap device.
277 	 */
278 	if (temp == dumpdev)
279 		dumpdev = swdevt[0].sw_dev;
280 #endif
281 }
282 
283 /*
284  * Look at the string 'cp' and decode the boot device.
285  * Boot names can be something like 'rz(0,0,0)vmunix' or '5/rz0/vmunix'.
286  */
287 void
288 makebootdev(cp)
289 	register char *cp;
290 {
291 	int majdev, unit, part, ctrl;
292 
293 	if (*cp >= '0' && *cp <= '9') {
294 		/* XXX should be able to specify controller */
295 		if (cp[1] != '/' || cp[4] < '0' || cp[4] > '9')
296 			goto defdev;
297 		unit = cp[4] - '0';
298 		if (cp[5] >= 'a' && cp[5] <= 'h')
299 			part = cp[5] - 'a';
300 		else
301 			part = 0;
302 		cp += 2;
303 		for (majdev = 0; majdev < sizeof(devname)/sizeof(devname[0]);
304 		    majdev++) {
305 			if (cp[0] == devname[majdev][0] &&
306 			    cp[1] == devname[majdev][1]) {
307 				bootdev = MAKEBOOTDEV(majdev, 0, 0, unit, part);
308 				return;
309 			}
310 		}
311 		goto defdev;
312 	}
313 	for (majdev = 0; majdev < sizeof(devname)/sizeof(devname[0]); majdev++)
314 		if (cp[0] == devname[majdev][0] &&
315 		    cp[1] == devname[majdev][1] &&
316 		    cp[2] == '(')
317 			goto fndmaj;
318 defdev:
319 	bootdev = B_DEVMAGIC;
320 	return;
321 
322 fndmaj:
323 	for (ctrl = 0, cp += 3; *cp >= '0' && *cp <= '9'; )
324 		ctrl = ctrl * 10 + *cp++ - '0';
325 	if (*cp == ',')
326 		cp++;
327 	for (unit = 0; *cp >= '0' && *cp <= '9'; )
328 		unit = unit * 10 + *cp++ - '0';
329 	if (*cp == ',')
330 		cp++;
331 	for (part = 0; *cp >= '0' && *cp <= '9'; )
332 		part = part * 10 + *cp++ - '0';
333 	if (*cp != ')')
334 		goto defdev;
335 	bootdev = MAKEBOOTDEV(majdev, 0, ctrl, unit, part);
336 }
337