xref: /original-bsd/sys/sparc/sparc/autoconf.c (revision 3efa343e)
1 /*
2  * Copyright (c) 1992 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This software was developed by the Computer Systems Engineering group
6  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7  * contributed to Berkeley.
8  *
9  * %sccs.include.redist.c%
10  *
11  *	@(#)autoconf.c	7.1 (Berkeley) 07/13/92
12  *
13  * from: $Header: autoconf.c,v 1.23 92/07/10 22:35:23 torek Exp $ (LBL)
14  */
15 
16 #include "sys/param.h"
17 #include "sys/map.h"
18 #include "sys/buf.h"
19 #include "sys/disklabel.h"
20 #include "sys/device.h"
21 #include "sys/dkstat.h"
22 #include "sys/conf.h"
23 #include "sys/dmap.h"
24 #include "sys/reboot.h"
25 #include "sys/socket.h"
26 #include "sys/systm.h"
27 
28 #include "net/if.h"
29 
30 #include "machine/autoconf.h"
31 #include "machine/bsd_openprom.h"
32 #include "machine/cpu.h"
33 
34 #ifndef	FS_NFS		/* XXX */
35 #define	FS_NFS	100	/* XXX */
36 #endif			/* XXX */
37 
38 /*
39  * The following several variables are related to
40  * the configuration process, and are used in initializing
41  * the machine.
42  */
43 int	cold;		/* if 1, still working on cold-start */
44 int	dkn;		/* number of iostat dk numbers assigned so far */
45 int	cpuspeed = 10;	/* relative cpu speed */
46 int	fbnode;		/* node ID of ROM's console frame buffer */
47 int	optionsnode;	/* node ID of ROM's options */
48 
49 extern struct promvec *promvec;
50 
51 static	int rootnode;
52 int	findroot();
53 static	struct	bootinfo *findbootdev();
54 
55 static	struct bootinfo {
56 	char	name[16];	/* device name */
57 	int	val[3];		/* up to 3 values */
58 	int	type;		/* FS type */
59 	caddr_t	data;		/* FS dependant info */
60 } bootinfo;
61 
62 
63 /*
64  * Most configuration on the SPARC is done by matching OPENPROM Forth
65  * device names with our internal names.
66  */
67 int
68 matchbyname(parent, cf, aux)
69 	struct device *parent;
70 	struct cfdata *cf;
71 	void *aux;
72 {
73 
74 	return (strcmp(cf->cf_driver->cd_name, *(char **)aux) == 0);
75 }
76 
77 /*
78  * Convert hex ASCII string to a value.  Returns updated pointer.
79  * Depends on ASCII order (this *is* machine-dependent code, you know).
80  */
81 static char *
82 str2hex(str, vp)
83 	register char *str;
84 	register int *vp;
85 {
86 	register int v, c;
87 
88 	for (v = 0;; v = v * 16 + c, str++) {
89 		c = *(u_char *)str;
90 		if (c <= '9') {
91 			if ((c -= '0') < 0)
92 				break;
93 		} else if (c <= 'F') {
94 			if ((c -= 'A' - 10) < 10)
95 				break;
96 		} else if (c <= 'f') {
97 			if ((c -= 'a' - 10) < 10)
98 				break;
99 		} else
100 			break;
101 	}
102 	*vp = v;
103 	return (str);
104 }
105 
106 /*
107  * locore.s code calls bootstrap() just before calling main(), after double
108  * mapping the kernel to high memory and setting up the trap base register.
109  * We must finish mapping the kernel properly and glean any bootstrap info.
110  */
111 void
112 bootstrap()
113 {
114 	register char *cp, *bp, *ep;
115 	register int i;
116 	int nmmu, ncontext, node;
117 #ifdef KGDB
118 	extern int kgdb_debug_panic;
119 #endif
120 	extern char *rindex(const char *, int);
121 
122 	node = findroot();
123 	nmmu = getpropint(node, "mmu-npmg", 128);
124 	ncontext = getpropint(node, "mmu-nctx", 8);
125 	pmap_bootstrap(nmmu, ncontext);
126 #ifdef KGDB
127 	zs_kgdb_init();			/* XXX */
128 #endif
129 	/*
130 	 * On SS1s, promvec->pv_v0bootargs->ba_argv[1] contains the flags
131 	 * that were given after the boot command.  On SS2s, pv_v0bootargs
132 	 * is NULL but *promvec->pv_v2bootargs.v2_bootargs points to
133 	 * "vmunix -s" or whatever.
134 	 * ###	DO THIS BEFORE pmap_boostrap?
135 	 */
136 	if (promvec->pv_romvec_vers < 2) {
137 		/* Grab boot device name and values. */
138 		cp = (*promvec->pv_v0bootargs)->ba_argv[0];
139 		if (cp != NULL) {
140 			bp = bootinfo.name;
141 			ep = &bootinfo.name[sizeof(bootinfo.name)];
142 			while (*cp != '(' && *cp != '\0' && bp < ep - 1)
143 				*bp++ = *cp++;
144 			*bp = '\0';
145 
146 			if (*cp == '(' &&
147 			    *(cp = str2hex(++cp, &bootinfo.val[0])) == ',' &&
148 			    *(cp = str2hex(++cp, &bootinfo.val[1])) == ',')
149 				(void)str2hex(++cp, &bootinfo.val[2]);
150 		}
151 
152 		/* Setup pointer to boot flags */
153 		cp = (*promvec->pv_v0bootargs)->ba_argv[1];
154 		if (cp == NULL || *cp != '-')
155 			return;
156 	} else {
157 		/* Grab boot device name and values. */
158 		cp = *promvec->pv_v2bootargs.v2_bootpath;
159 		if (cp != NULL && (cp = rindex(cp, '/')) != NULL) {
160 			++cp;
161 			bp = bootinfo.name;
162 			ep = &bootinfo.name[sizeof(bootinfo.name)];
163 			while (*cp != '@' && *cp != '\0' && bp < ep - 1)
164 				*bp++ = *cp++;
165 			*bp = '\0';
166 
167 			if (*cp == '@' &&
168 			    *(cp = str2hex(++cp, &bootinfo.val[0])) == ',' &&
169 			    *(cp = str2hex(++cp, &bootinfo.val[1])) == ',')
170 				(void)str2hex(++cp, &bootinfo.val[2]);
171 		}
172 
173 		/* Setup pointer to boot flags */
174 		cp = *promvec->pv_v2bootargs.v2_bootargs;
175 		if (cp == NULL)
176 			return;
177 		while (*cp != '-')
178 			if (*cp++ == '\0')
179 				return;
180 	}
181 	for (;;) {
182 		switch (*++cp) {
183 
184 		case '\0':
185 			return;
186 
187 		case 'a':
188 			boothowto |= RB_ASKNAME;
189 			break;
190 
191 		case 'b':
192 			boothowto |= RB_DFLTROOT;
193 			break;
194 
195 		case 'd':	/* kgdb - always on zs	XXX */
196 #ifdef KGDB
197 			boothowto |= RB_KDB;	/* XXX unused */
198 			kgdb_debug_panic = 1;
199 			kgdb_connect(1);
200 #else
201 			printf("kernel not compiled with KGDB\n");
202 #endif
203 			break;
204 
205 		case 's':
206 			boothowto |= RB_SINGLE;
207 			break;
208 		}
209 	}
210 }
211 
212 /*
213  * Determine mass storage and memory configuration for a machine.
214  * We get the PROM's root device and make sure we understand it, then
215  * attach it as `mainbus0'.  We also set up to handle the PROM `sync'
216  * command.
217  */
218 configure()
219 {
220 	register int node;
221 	register char *cp;
222 	struct romaux ra;
223 	void sync_crash();
224 #ifdef NFS
225 	register struct bootinfo *bi;
226 	extern int (*mountroot)(), nfs_mountroot();
227 #endif
228 
229 	node = findroot();
230 	cp = getpropstring(node, "device_type");
231 	if (strcmp(cp, "cpu") != 0) {
232 		printf("PROM root device type = %s\n", cp);
233 		panic("need CPU as root");
234 	}
235 	*promvec->pv_synchook = sync_crash;
236 	ra.ra_node = node;
237 	ra.ra_name = cp = "mainbus";
238 	if (!config_rootfound(cp, (void *)&ra))
239 		panic("mainbus not configured");
240 	(void) spl0();
241 	cold = 0;
242 #ifdef NFS
243 	if (boothowto & RB_ASKNAME) {
244 		char ans[100];
245 
246 		printf("nfs root? (y/n) [n] ");
247 		gets(ans);
248 		if (ans[0] == 'y')
249 			mountroot = nfs_mountroot;
250 	} else if ((bi = findbootdev()) != NULL && bi->type == FS_NFS) {
251 		mountroot = nfs_mountroot;
252 #ifdef LBL
253 		lbl_diskless_setup();
254 #endif /* LBL */
255 	}
256 #endif /* NFS */
257 #if GENERIC
258 	if ((boothowto & RB_ASKNAME) == 0)
259 		setroot();
260 	setconf();
261 #else
262 	setroot();
263 #endif
264 	swapconf();
265 }
266 
267 /*
268  * Console `sync' command.  SunOS just does a `panic: zero' so I guess
269  * no one really wants anything fancy...
270  */
271 void
272 sync_crash()
273 {
274 
275 	panic("PROM sync command");
276 }
277 
278 char *
279 clockfreq(freq)
280 	register int freq;
281 {
282 	register char *p;
283 	static char buf[10];
284 
285 	freq /= 1000;
286 	sprintf(buf, "%d", freq / 1000);
287 	freq %= 1000;
288 	if (freq) {
289 		freq += 1000;	/* now in 1000..1999 */
290 		p = buf + strlen(buf);
291 		sprintf(p, "%d", freq);
292 		*p = '.';	/* now buf = %d.%3d */
293 	}
294 	return (buf);
295 }
296 
297 /* ARGSUSED */
298 static int
299 mbprint(aux, name)
300 	void *aux;
301 	char *name;
302 {
303 	register struct romaux *ra = aux;
304 
305 	if (name)
306 		printf("%s at %s", ra->ra_name, name);
307 	if (ra->ra_paddr)
308 		printf(" %saddr 0x%x", ra->ra_iospace ? "io" : "",
309 		    (int)ra->ra_paddr);
310 	return (UNCONF);
311 }
312 
313 int
314 findroot()
315 {
316 	register int node;
317 
318 	if ((node = rootnode) == 0 && (node = nextsibling(0)) == 0)
319 		panic("no PROM root device");
320 	rootnode = node;
321 	return (node);
322 }
323 
324 /*
325  * Given a `first child' node number, locate the node with the given name.
326  * Return the node number, or 0 if not found.
327  */
328 int
329 findnode(first, name)
330 	int first;
331 	register char *name;
332 {
333 	register int node;
334 
335 	for (node = first; node; node = nextsibling(node))
336 		if (strcmp(getpropstring(node, "name"), name) == 0)
337 			return (node);
338 	return (0);
339 }
340 
341 /*
342  * Fill in a romaux.  Returns 1 on success, 0 if the register property
343  * was not the right size.
344  */
345 int
346 romprop(rp, cp, node)
347 	register struct romaux *rp;
348 	const char *cp;
349 	register int node;
350 {
351 	register int len;
352 	union { char regbuf[64]; int ireg[3]; } u;
353 	static const char pl[] = "property length";
354 
355 	len = getprop(node, "reg", (void *)u.regbuf, sizeof u.regbuf);
356 	if (len < 12) {
357 		printf("%s \"reg\" %s = %d (need 12)\n", cp, pl, len);
358 		return (0);
359 	}
360 	if (len > 12)
361 		printf("warning: %s \"reg\" %s %d > 12, excess ignored\n",
362 		    cp, pl, len);
363 	rp->ra_node = node;
364 	rp->ra_name = cp;
365 	rp->ra_iospace = u.ireg[0];
366 	rp->ra_paddr = (caddr_t)u.ireg[1];
367 	rp->ra_len = u.ireg[2];
368 	rp->ra_vaddr = (caddr_t)getpropint(node, "address", 0);
369 	len = getprop(node, "intr", (void *)&rp->ra_intr, sizeof rp->ra_intr);
370 	if (len == -1)
371 		len = 0;
372 	if (len & 7) {
373 		printf("%s \"intr\" %s = %d (need multiple of 8)\n",
374 		    cp, pl, len);
375 		len = 0;
376 	}
377 	rp->ra_nintr = len >>= 3;
378 	/* SPARCstation interrupts are not hardware-vectored */
379 	while (--len >= 0) {
380 		if (rp->ra_intr[len].int_vec) {
381 			printf("WARNING: %s interrupt %d has nonzero vector\n",
382 			    cp, len);
383 			break;
384 		}
385 	}
386 	return (1);
387 }
388 
389 /*
390  * Attach the mainbus.
391  *
392  * Our main job is to attach the CPU (the root node we got in configure())
393  * and iterate down the list of `mainbus devices' (children of that node).
394  * We also record the `node id' of the default frame buffer, if any.
395  */
396 static void
397 mainbus_attach(parent, dev, aux)
398 	struct device *parent, *dev;
399 	void *aux;
400 {
401 	register int node0, node;
402 	register const char *cp, *const *ssp, *sp;
403 #define L1A_HACK		/* XXX hack to allow L1-A during autoconf */
404 #ifdef L1A_HACK
405 	int nzs = 0, audio = 0;
406 #endif
407 	struct romaux ra;
408 	static const char *const special[] = {
409 		/* find these first (end with empty string) */
410 		"memory-error", "eeprom", "counter-timer", "",
411 
412 		/* ignore these (end with NULL) */
413 		"options", "packages", "openprom", "memory", "virtual-memory",
414 		"interrupt-enable", NULL
415 	};
416 
417 	printf("\n");
418 
419 	/* configure the cpu */
420 	node = ((struct romaux *)aux)->ra_node;
421 	ra.ra_node = node;
422 	ra.ra_name = cp = "cpu";
423 	ra.ra_paddr = 0;
424 	config_found(dev, (void *)&ra, mbprint);
425 
426 	/* remember which frame buffer, if any, is to be /dev/fb */
427 	fbnode = getpropint(node, "fb", 0);
428 
429 	/* Find the "options" node */
430 	node0 = firstchild(node);
431 	optionsnode = findnode(node0, "options");
432 	if (optionsnode == 0)
433 		panic("no options in OPENPROM");
434 
435 	/*
436 	 * Locate and configure the ``early'' devices.  These must be
437 	 * configured before we can do the rest.  For instance, the
438 	 * EEPROM contains the Ethernet address for the LANCE chip.
439 	 * If the device cannot be located or configured, panic.
440 	 */
441 	for (ssp = special; *(sp = *ssp) != 0; ssp++) {
442 		if ((node = findnode(node0, sp)) == 0) {
443 			printf("could not find %s in OPENPROM\n", sp);
444 			panic(sp);
445 		}
446 		if (!romprop(&ra, sp, node) ||
447 		    !config_found(dev, (void *)&ra, mbprint))
448 			panic(sp);
449 	}
450 
451 	/*
452 	 * Configure the rest of the devices, in PROM order.  Skip
453 	 * PROM entries that are not for devices, or which must be
454 	 * done before we get here.
455 	 */
456 	for (node = node0; node; node = nextsibling(node)) {
457 		cp = getpropstring(node, "name");
458 		for (ssp = special; (sp = *ssp) != NULL; ssp++)
459 			if (strcmp(cp, sp) == 0)
460 				break;
461 		if (sp == NULL && romprop(&ra, cp, node)) {
462 #ifdef L1A_HACK
463 			if (strcmp(cp, "audio") == 0)
464 				audio = 1;
465 			if (strcmp(cp, "zs") == 0)
466 				nzs++;
467 			if (audio && nzs >= 2)
468 				(void) splx(11 << 8);	/* XXX */
469 #endif
470 			(void) config_found(dev, (void *)&ra, mbprint);
471 		}
472 	}
473 }
474 
475 struct cfdriver mainbuscd =
476     { NULL, "mainbus", matchbyname, mainbus_attach,
477       DV_DULL, sizeof(struct device) };
478 
479 /*
480  * findzs() is called from the zs driver (which is, at least in theory,
481  * generic to any machine with a Zilog ZSCC chip).  It should return the
482  * address of the corresponding zs channel.  It may not fail, and it
483  * may be called before the VM code can be used.  Here we count on the
484  * FORTH PROM to map in the required zs chips.
485  */
486 void *
487 findzs(zs)
488 	int zs;
489 {
490 	register int node, addr;
491 
492 	node = firstchild(findroot());
493 	while ((node = findnode(node, "zs")) != 0) {
494 		if (getpropint(node, "slave", -1) == zs) {
495 			if ((addr = getpropint(node, "address", 0)) == 0)
496 				panic("findzs: zs%d not mapped by PROM", zs);
497 			return ((void *)addr);
498 		}
499 		node = nextsibling(node);
500 	}
501 	panic("findzs: cannot find zs%d", zs);
502 	/* NOTREACHED */
503 }
504 
505 int
506 makememarr(ap, max, which)
507 	register struct memarr *ap;
508 	int max, which;
509 {
510 	struct v2rmi {
511 		int	zero;
512 		int	addr;
513 		int	len;
514 	} v2rmi[200];		/* version 2 rom meminfo layout */
515 #define	MAXMEMINFO (sizeof(v2rmi) / sizeof(*v2rmi))
516 	register struct v0mlist *mp;
517 	register int i, node, len;
518 	char *prop;
519 
520 	switch (i = promvec->pv_romvec_vers) {
521 
522 	case 0:
523 		/*
524 		 * Version 0 PROMs use a linked list to describe these
525 		 * guys.
526 		 */
527 		switch (which) {
528 
529 		case MEMARR_AVAILPHYS:
530 			mp = *promvec->pv_v0mem.v0_physavail;
531 			break;
532 
533 		case MEMARR_TOTALPHYS:
534 			mp = *promvec->pv_v0mem.v0_phystot;
535 			break;
536 
537 		default:
538 			panic("makememarr");
539 		}
540 		for (i = 0; mp != NULL; mp = mp->next, i++) {
541 			if (i >= max)
542 				goto overflow;
543 			ap->addr = (u_int)mp->addr;
544 			ap->len = mp->nbytes;
545 			ap++;
546 		}
547 		break;
548 
549 	default:
550 		printf("makememarr: hope version %d PROM is like version 2\n",
551 		    i);
552 		/* FALLTHROUGH */
553 
554 	case 2:
555 		/*
556 		 * Version 2 PROMs use a property array to describe them.
557 		 */
558 		if (max > MAXMEMINFO) {
559 			printf("makememarr: limited to %d\n", MAXMEMINFO);
560 			max = MAXMEMINFO;
561 		}
562 		if ((node = findnode(firstchild(findroot()), "memory")) == 0)
563 			panic("makememarr: cannot find \"memory\" node");
564 		switch (which) {
565 
566 		case MEMARR_AVAILPHYS:
567 			prop = "available";
568 			break;
569 
570 		case MEMARR_TOTALPHYS:
571 			prop = "reg";
572 			break;
573 
574 		default:
575 			panic("makememarr");
576 		}
577 		len = getprop(node, prop, (void *)v2rmi, sizeof v2rmi) /
578 		    sizeof(struct v2rmi);
579 		for (i = 0; i < len; i++) {
580 			if (i >= max)
581 				goto overflow;
582 			ap->addr = v2rmi[i].addr;
583 			ap->len = v2rmi[i].len;
584 			ap++;
585 		}
586 		break;
587 	}
588 
589 	/*
590 	 * Success!  (Hooray)
591 	 */
592 	if (i == 0)
593 		panic("makememarr: no memory found");
594 	return (i);
595 
596 overflow:
597 	/*
598 	 * Oops, there are more things in the PROM than our caller
599 	 * provided space for.  Truncate any extras.
600 	 */
601 	printf("makememarr: WARNING: lost some memory\n");
602 	return (i);
603 }
604 
605 /*
606  * Internal form of getprop().  Returns the actual length.
607  */
608 int
609 getprop(node, name, buf, bufsiz)
610 	int node;
611 	char *name;
612 	void *buf;
613 	register int bufsiz;
614 {
615 	register struct nodeops *no;
616 	register int len;
617 
618 	no = promvec->pv_nodeops;
619 	len = no->no_proplen(node, name);
620 	if (len > bufsiz) {
621 		printf("node %x property %s length %d > %d\n",
622 		    node, name, len, bufsiz);
623 #ifdef DEBUG
624 		panic("getprop");
625 #else
626 		return (0);
627 #endif
628 	}
629 	no->no_getprop(node, name, buf);
630 	return (len);
631 }
632 
633 /*
634  * Return a string property.  There is a (small) limit on the length;
635  * the string is fetched into a static buffer which is overwritten on
636  * subsequent calls.
637  */
638 char *
639 getpropstring(node, name)
640 	int node;
641 	char *name;
642 {
643 	register int len;
644 	static char stringbuf[32];
645 
646 	len = getprop(node, name, (void *)stringbuf, sizeof stringbuf - 1);
647 	stringbuf[len] = '\0';	/* usually unnecessary */
648 	return (stringbuf);
649 }
650 
651 /*
652  * Fetch an integer (or pointer) property.
653  * The return value is the property, or the default if there was none.
654  */
655 int
656 getpropint(node, name, deflt)
657 	int node;
658 	char *name;
659 	int deflt;
660 {
661 	register int len;
662 	char intbuf[16];
663 
664 	len = getprop(node, name, (void *)intbuf, sizeof intbuf);
665 	if (len != 4)
666 		return (deflt);
667 	return (*(int *)intbuf);
668 }
669 
670 /*
671  * OPENPROM functions.  These are here mainly to hide the OPENPROM interface
672  * from the rest of the kernel.
673  */
674 int
675 firstchild(node)
676 	int node;
677 {
678 
679 	return (promvec->pv_nodeops->no_child(node));
680 }
681 
682 int
683 nextsibling(node)
684 	int node;
685 {
686 
687 	return (promvec->pv_nodeops->no_nextnode(node));
688 }
689 
690 /* Pass a string to the FORTH PROM to be interpreted */
691 void
692 rominterpret(s)
693 	register char *s;
694 {
695 
696 	if (promvec->pv_romvec_vers < 2)
697 		promvec->pv_fortheval.v0_eval(strlen(s), s);
698 	else
699 		promvec->pv_fortheval.v2_eval(s);
700 }
701 
702 volatile void
703 romhalt()
704 {
705 
706 	promvec->pv_halt();
707 	panic("PROM exit failed");
708 }
709 
710 volatile void
711 romboot(str)
712 	char *str;
713 {
714 
715 	promvec->pv_reboot(str);
716 	panic("PROM boot failed");
717 }
718 
719 callrom()
720 {
721 
722 #ifdef notdef		/* sun4c FORTH PROMs do this for us */
723 	fb_unblank();
724 #endif
725 	promvec->pv_abort();
726 }
727 
728 /*
729  * Configure swap space and related parameters.
730  */
731 swapconf()
732 {
733 	register struct swdevt *swp;
734 	register int nblks;
735 
736 	for (swp = swdevt; swp->sw_dev; swp++)
737 		if (bdevsw[major(swp->sw_dev)].d_psize) {
738 			nblks =
739 			  (*bdevsw[major(swp->sw_dev)].d_psize)(swp->sw_dev);
740 			if (nblks != -1 &&
741 			    (swp->sw_nblks == 0 || swp->sw_nblks > nblks))
742 				swp->sw_nblks = nblks;
743 		}
744 	dumpconf();
745 }
746 
747 #define	DOSWAP			/* Change swdevt, argdev, and dumpdev too */
748 u_long	bootdev;		/* should be dev_t, but not until 32 bits */
749 
750 static	char devname[][2] = {
751 	0,0,		/* 0 = xx */
752 };
753 
754 #define	PARTITIONMASK	0x7
755 #define	PARTITIONSHIFT	3
756 
757 /*
758  * Attempt to find the device from which we were booted.
759  * If we can do so, and not instructed not to do so,
760  * change rootdev to correspond to the load device.
761  */
762 setroot()
763 {
764 #ifdef notyet
765 	struct swdevt *swp;
766 
767 	if (boothowto & RB_DFLTROOT ||
768 	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
769 		return;
770 	majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
771 	if (majdev > sizeof(devname) / sizeof(devname[0]))
772 		return;
773 	adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
774 	part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
775 	unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
776 	/*
777 	 * First, find the controller type which support this device.
778 	 */
779 	for (hd = hp_dinit; hd->hp_driver; hd++)
780 		if (hd->hp_driver->d_name[0] == devname[majdev][0] &&
781 		    hd->hp_driver->d_name[1] == devname[majdev][1])
782 			break;
783 	if (hd->hp_driver == 0)
784 		return;
785 	/*
786 	 * Next, find the controller of that type corresponding to
787 	 * the adaptor number.
788 	 */
789 	for (hc = hp_cinit; hc->hp_driver; hc++)
790 		if (hc->hp_alive && hc->hp_unit == adaptor &&
791 		    hc->hp_driver == hd->hp_cdriver)
792 			break;
793 	if (hc->hp_driver == 0)
794 		return;
795 	/*
796 	 * Finally, find the device in question attached to that controller.
797 	 */
798 	for (hd = hp_dinit; hd->hp_driver; hd++)
799 		if (hd->hp_alive && hd->hp_slave == unit &&
800 		    hd->hp_cdriver == hc->hp_driver &&
801 		    hd->hp_ctlr == hc->hp_unit)
802 			break;
803 	if (hd->hp_driver == 0)
804 		return;
805 	mindev = hd->hp_unit;
806 	/*
807 	 * Form a new rootdev
808 	 */
809 	mindev = (mindev << PARTITIONSHIFT) + part;
810 	orootdev = rootdev;
811 	rootdev = makedev(majdev, mindev);
812 	/*
813 	 * If the original rootdev is the same as the one
814 	 * just calculated, don't need to adjust the swap configuration.
815 	 */
816 	if (rootdev == orootdev)
817 		return;
818 
819 	printf("Changing root device to %c%c%d%c\n",
820 		devname[majdev][0], devname[majdev][1],
821 		mindev >> PARTITIONSHIFT, part + 'a');
822 
823 #ifdef DOSWAP
824 	mindev &= ~PARTITIONMASK;
825 	for (swp = swdevt; swp->sw_dev; swp++) {
826 		if (majdev == major(swp->sw_dev) &&
827 		    mindev == (minor(swp->sw_dev) & ~PARTITIONMASK)) {
828 			temp = swdevt[0].sw_dev;
829 			swdevt[0].sw_dev = swp->sw_dev;
830 			swp->sw_dev = temp;
831 			break;
832 		}
833 	}
834 	if (swp->sw_dev == 0)
835 		return;
836 
837 	/*
838 	 * If argdev and dumpdev were the same as the old primary swap
839 	 * device, move them to the new primary swap device.
840 	 */
841 	if (temp == dumpdev)
842 		dumpdev = swdevt[0].sw_dev;
843 	if (temp == argdev)
844 		argdev = swdevt[0].sw_dev;
845 #endif
846 #endif
847 }
848 
849 /*
850  * Return pointer to device we booted from. Return NULL if we can't
851  * figure this out.
852  * XXX currently only works for network devices.
853  */
854 
855 static struct bootinfo *
856 findbootdev()
857 {
858 	register struct bootinfo *bi;
859 	register char *bp;
860 	register int unit, controller;
861 	register struct ifnet *ifp;
862 
863 	bi = &bootinfo;
864 	bp = bi->name;
865 printf("findbootdev: (v%d rom) trying \"%s(%x,%x,%x)\"... ",
866     promvec->pv_romvec_vers, bp, bi->val[0], bi->val[1], bi->val[2]);
867 
868 	/* Try network devices first */
869 	unit = bi->val[0];
870 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
871 		if (unit == ifp->if_unit && strcmp(bp, ifp->if_name) == 0) {
872 printf("found \"%s%d\"\n", ifp->if_name, ifp->if_unit);
873 			bi->type = FS_NFS;
874 			bi->data = (caddr_t)ifp;
875 			return (bi);
876 		}
877 printf("not found\n");
878 	return (NULL);
879 }
880 
881 gets(cp)
882 	register char *cp;
883 {
884 	register char *lp;
885 	register int c;
886 
887 	lp = cp;
888 	for (;;) {
889 		c = cngetc();
890 		switch (c) {
891 		case '\n':
892 		case '\r':
893 			printf("\n");
894 			*lp++ = '\0';
895 			return;
896 		case '\b':
897 		case '\177':
898 		case '#':
899 			if (lp > cp) {
900 				lp--;
901 				printf(" \b ");
902 			}
903 			continue;
904 		case '@':
905 		case 'u'&037:
906 			lp = cp;
907 			cnputc('\n');
908 			continue;
909 		default:
910 			if (c < ' ')
911 				continue;
912 			cnputc(c);
913 			*lp++ = c;
914 		}
915 	}
916 }
917