xref: /netbsd/sys/arch/sparc64/sparc64/autoconf.c (revision bf9ec67e)
1 /*	$NetBSD: autoconf.c,v 1.57 2002/05/16 01:01:41 thorpej Exp $ */
2 
3 /*
4  * Copyright (c) 1996
5  *    The President and Fellows of Harvard College. All rights reserved.
6  * Copyright (c) 1992, 1993
7  *	The Regents of the University of California.  All rights reserved.
8  *
9  * This software was developed by the Computer Systems Engineering group
10  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
11  * contributed to Berkeley.
12  *
13  * All advertising materials mentioning features or use of this software
14  * must display the following acknowledgement:
15  *	This product includes software developed by Harvard University.
16  *	This product includes software developed by the University of
17  *	California, Lawrence Berkeley Laboratory.
18  *
19  * Redistribution and use in source and binary forms, with or without
20  * modification, are permitted provided that the following conditions
21  * are met:
22  * 1. Redistributions of source code must retain the above copyright
23  *    notice, this list of conditions and the following disclaimer.
24  * 2. Redistributions in binary form must reproduce the above copyright
25  *    notice, this list of conditions and the following disclaimer in the
26  *    documentation and/or other materials provided with the distribution.
27  * 3. All advertising materials mentioning features or use of this software
28  *    must display the following acknowledgement:
29  *	This product includes software developed by the University of
30  *	California, Berkeley and its contributors.
31  * 4. Neither the name of the University nor the names of its contributors
32  *    may be used to endorse or promote products derived from this software
33  *    without specific prior written permission.
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
36  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
39  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45  * SUCH DAMAGE.
46  *
47  *	@(#)autoconf.c	8.4 (Berkeley) 10/1/93
48  */
49 
50 #include "opt_ddb.h"
51 #include "opt_kgdb.h"
52 
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/map.h>
56 #include <sys/buf.h>
57 #include <sys/disklabel.h>
58 #include <sys/device.h>
59 #include <sys/disk.h>
60 #include <sys/dkstat.h>
61 #include <sys/conf.h>
62 #include <sys/reboot.h>
63 #include <sys/socket.h>
64 #include <sys/malloc.h>
65 #include <sys/queue.h>
66 #include <sys/msgbuf.h>
67 #include <sys/boot_flag.h>
68 
69 #include <net/if.h>
70 
71 #include <dev/cons.h>
72 
73 #include <uvm/uvm_extern.h>
74 
75 #include <machine/bus.h>
76 #include <machine/autoconf.h>
77 #include <machine/openfirm.h>
78 #include <machine/sparc64.h>
79 #include <machine/cpu.h>
80 #include <machine/pmap.h>
81 #include <sparc64/sparc64/timerreg.h>
82 
83 #include <dev/ata/atavar.h>
84 #include <dev/ata/wdvar.h>
85 #include <dev/pci/pcivar.h>
86 #include <dev/sbus/sbusvar.h>
87 
88 #ifdef DDB
89 #include <machine/db_machdep.h>
90 #include <ddb/db_sym.h>
91 #include <ddb/db_extern.h>
92 #endif
93 
94 
95 int printspl = 0;
96 
97 /*
98  * The following several variables are related to
99  * the configuration process, and are used in initializing
100  * the machine.
101  */
102 int	stdinnode;	/* node ID of ROM's console input device */
103 int	fbnode;		/* node ID of ROM's console output device */
104 int	optionsnode;	/* node ID of ROM's options */
105 
106 #ifdef KGDB
107 extern	int kgdb_debug_panic;
108 #endif
109 
110 static	int rootnode;
111 char platform_type[32];
112 
113 static	char *str2hex __P((char *, int *));
114 static	int mbprint __P((void *, const char *));
115 static	void crazymap __P((char *, int *));
116 int	st_crazymap __P((int));
117 void	sync_crash __P((void));
118 int	mainbus_match __P((struct device *, struct cfdata *, void *));
119 static	void mainbus_attach __P((struct device *, struct device *, void *));
120 
121 struct	bootpath bootpath[8];
122 int	nbootpath;
123 static	void bootpath_build __P((void));
124 static	void bootpath_print __P((struct bootpath *));
125 
126 /* Global interrupt mappings for all device types.  Match against the OBP
127  * 'device_type' property.
128  */
129 struct intrmap intrmap[] = {
130 	{ "block",	PIL_FD },	/* Floppy disk */
131 	{ "serial",	PIL_SER },	/* zs */
132 	{ "scsi",	PIL_SCSI },
133 	{ "network",	PIL_NET },
134 	{ "display",	PIL_VIDEO },
135 	{ "audio",	PIL_AUD },
136 	{ "ide",	PIL_SCSI },
137 /* The following devices don't have device types: */
138 	{ "SUNW,CS4231",	PIL_AUD },
139 	{ NULL,		0 }
140 };
141 
142 #ifdef DEBUG
143 #define ACDB_BOOTDEV	0x1
144 #define	ACDB_PROBE	0x2
145 int autoconf_debug = 0x0;
146 #define DPRINTF(l, s)   do { if (autoconf_debug & l) printf s; } while (0)
147 #else
148 #define DPRINTF(l, s)
149 #endif
150 
151 /*
152  * Most configuration on the SPARC is done by matching OPENPROM Forth
153  * device names with our internal names.
154  */
155 int
156 matchbyname(parent, cf, aux)
157 	struct device *parent;
158 	struct cfdata *cf;
159 	void *aux;
160 {
161 	printf("%s: WARNING: matchbyname\n", cf->cf_driver->cd_name);
162 	return (0);
163 }
164 
165 /*
166  * Convert hex ASCII string to a value.  Returns updated pointer.
167  * Depends on ASCII order (this *is* machine-dependent code, you know).
168  */
169 static char *
170 str2hex(str, vp)
171 	register char *str;
172 	register int *vp;
173 {
174 	register int v, c;
175 
176 	for (v = 0;; v = v * 16 + c, str++) {
177 		c = *(u_char *)str;
178 		if (c <= '9') {
179 			if ((c -= '0') < 0)
180 				break;
181 		} else if (c <= 'F') {
182 			if ((c -= 'A' - 10) < 10)
183 				break;
184 		} else if (c <= 'f') {
185 			if ((c -= 'a' - 10) < 10)
186 				break;
187 		} else
188 			break;
189 	}
190 	*vp = v;
191 	return (str);
192 }
193 
194 /*
195  * locore.s code calls bootstrap() just before calling main().
196  *
197  * What we try to do is as follows:
198  *
199  * 1) We will try to re-allocate the old message buffer.
200  *
201  * 2) We will then get the list of the total and available
202  *	physical memory and available virtual memory from the
203  *	prom.
204  *
205  * 3) We will pass the list to pmap_bootstrap to manage them.
206  *
207  * We will try to run out of the prom until we get to cpu_init().
208  */
209 void
210 bootstrap(nctx)
211 	int nctx;
212 {
213 	extern int end;	/* End of kernel */
214 #if defined(DDB) && defined(DB_ELF_SYMBOLS)
215 	extern void *ssym, *esym;
216 #endif
217 #ifndef	__arch64__
218 	/* Assembly glue for the PROM */
219 	extern void OF_sym2val32 __P((void *));
220 	extern void OF_val2sym32 __P((void *));
221 #endif
222 
223 	/*
224 	 * Initialize ddb first and register OBP callbacks.
225 	 * We can do this because ddb_init() does not allocate anything,
226 	 * just initialze some pointers to important things
227 	 * like the symtab.
228 	 *
229 	 * By doing this first and installing the OBP callbacks
230 	 * we get to do symbolic debugging of pmap_bootstrap().
231 	 */
232 #ifdef KGDB
233 /* Moved zs_kgdb_init() to dev/zs.c:consinit(). */
234 	zs_kgdb_init();		/* XXX */
235 #endif
236 	/* Initialize the PROM console so printf will not panic */
237 	(*cn_tab->cn_init)(cn_tab);
238 #ifdef DDB
239 #ifdef DB_ELF_SYMBOLS
240 	ddb_init((int)((caddr_t)esym - (caddr_t)ssym), ssym, esym);
241 #else
242 	ddb_init();
243 #endif
244 #ifdef __arch64__
245 	/* This can only be installed on an 64-bit system cause otherwise our stack is screwed */
246 	OF_set_symbol_lookup(OF_sym2val, OF_val2sym);
247 #else
248 #if 1
249 	OF_set_symbol_lookup(OF_sym2val32, OF_val2sym32);
250 #endif
251 #endif
252 #endif
253 
254 	pmap_bootstrap(KERNBASE, (u_long)&end, nctx);
255 }
256 
257 /*
258  * bootpath_build: build a bootpath. Used when booting a generic
259  * kernel to find our root device.  Newer proms give us a bootpath,
260  * for older proms we have to create one.  An element in a bootpath
261  * has 4 fields: name (device name), val[0], val[1], and val[2]. Note that:
262  * Interpretation of val[] is device-dependent. Some examples:
263  *
264  * if (val[0] == -1) {
265  *	val[1] is a unit number    (happens most often with old proms)
266  * } else {
267  *	[sbus device] val[0] is a sbus slot, and val[1] is an sbus offset
268  *	[scsi disk] val[0] is target, val[1] is lun, val[2] is partition
269  *	[scsi tape] val[0] is target, val[1] is lun, val[2] is file #
270  *	[pci device] val[0] is device, val[1] is function, val[2] might be partition
271  * }
272  *
273  */
274 
275 static void
276 bootpath_build()
277 {
278 	register char *cp, *pp;
279 	register struct bootpath *bp;
280 	register long chosen;
281 	char buf[128];
282 
283 	bzero((void*)bootpath, sizeof(bootpath));
284 	bp = bootpath;
285 
286 	/*
287 	 * Grab boot path from PROM
288 	 */
289 	chosen = OF_finddevice("/chosen");
290 	OF_getprop(chosen, "bootpath", buf, sizeof(buf));
291 	cp = buf;
292 	while (cp != NULL && *cp == '/') {
293 		/* Step over '/' */
294 		++cp;
295 		/* Extract name */
296 		pp = bp->name;
297 		while (*cp != '@' && *cp != '/' && *cp != '\0')
298 			*pp++ = *cp++;
299 		*pp = '\0';
300 		if (*cp == '@') {
301 			cp = str2hex(++cp, &bp->val[0]);
302 			if (*cp == ',')
303 				cp = str2hex(++cp, &bp->val[1]);
304 			if (*cp == ':')
305 				/* XXX - we handle just one char */
306 				bp->val[2] = *++cp - 'a', ++cp;
307 		} else {
308 			bp->val[0] = -1; /* no #'s: assume unit 0, no
309 					    sbus offset/adddress */
310 		}
311 		++bp;
312 		++nbootpath;
313 	}
314 	bp->name[0] = 0;
315 
316 	bootpath_print(bootpath);
317 
318 	/* Setup pointer to boot flags */
319 	OF_getprop(chosen, "bootargs", buf, sizeof(buf));
320 	cp = buf;
321 
322 	/* Find start of boot flags */
323 	while (*cp) {
324 		while(*cp == ' ' || *cp == '\t') cp++;
325 		if (*cp == '-' || *cp == '\0')
326 			break;
327 		while(*cp != ' ' && *cp != '\t' && *cp != '\0') cp++;
328 
329 	}
330 	if (*cp != '-')
331 		return;
332 
333 	for (;*++cp;) {
334 		int fl;
335 
336 		fl = 0;
337 		BOOT_FLAG(*cp, fl);
338 		if (!fl) {
339 			printf("unknown option `%c'\n", *cp);
340 			continue;
341 		}
342 		boothowto |= fl;
343 
344 		/* specialties */
345 		if (*cp == 'd') {
346 #if defined(KGDB)
347 			kgdb_debug_panic = 1;
348 			kgdb_connect(1);
349 #elif defined(DDB)
350 			Debugger();
351 #else
352 			printf("kernel has no debugger\n");
353 #endif
354 		} else if (*cp == 't') {
355 			/* turn on traptrace w/o breaking into kdb */
356 			extern int trap_trace_dis;
357 
358 			trap_trace_dis = 0;
359 		}
360 	}
361 }
362 
363 /*
364  * print out the bootpath
365  * the %x isn't 0x%x because the Sun EPROMs do it this way, and
366  * consistency with the EPROMs is probably better here.
367  */
368 
369 static void
370 bootpath_print(bp)
371 	struct bootpath *bp;
372 {
373 	printf("bootpath: ");
374 	while (bp->name[0]) {
375 		if (bp->val[0] == -1)
376 			printf("/%s%x", bp->name, bp->val[1]);
377 		else
378 			printf("/%s@%x,%x", bp->name, bp->val[0], bp->val[1]);
379 		if (bp->val[2] != 0)
380 			printf(":%c", bp->val[2] + 'a');
381 		bp++;
382 	}
383 	printf("\n");
384 }
385 
386 
387 /*
388  * save or read a bootpath pointer from the boothpath store.
389  *
390  * XXX. required because of SCSI... we don't have control over the "sd"
391  * device, so we can't set boot device there.   we patch in with
392  * dk_establish(), and use this to recover the bootpath.
393  */
394 struct bootpath *
395 bootpath_store(storep, bp)
396 	int storep;
397 	struct bootpath *bp;
398 {
399 	static struct bootpath *save;
400 	struct bootpath *retval;
401 
402 	retval = save;
403 	if (storep)
404 		save = bp;
405 
406 	return (retval);
407 }
408 
409 /*
410  * Set up the sd target mappings for non SUN4 PROMs.
411  * Find out about the real SCSI target, given the PROM's idea of the
412  * target of the (boot) device (i.e., the value in bp->v0val[0]).
413  */
414 static void
415 crazymap(prop, map)
416 	char *prop;
417 	int *map;
418 {
419 	int i;
420 
421 	/*
422 	 * Set up the identity mapping for old sun4 monitors
423 	 * and v[2-] OpenPROMs. Note: dkestablish() does the
424 	 * SCSI-target juggling for sun4 monitors.
425 	 */
426 	for (i = 0; i < 8; ++i)
427 		map[i] = i;
428 }
429 
430 int
431 sd_crazymap(n)
432 	int	n;
433 {
434 	static int prom_sd_crazymap[8]; /* static: compute only once! */
435 	static int init = 0;
436 
437 	if (init == 0) {
438 		crazymap("sd-targets", prom_sd_crazymap);
439 		init = 1;
440 	}
441 	return prom_sd_crazymap[n];
442 }
443 
444 int
445 st_crazymap(n)
446 	int	n;
447 {
448 	static int prom_st_crazymap[8]; /* static: compute only once! */
449 	static int init = 0;
450 
451 	if (init == 0) {
452 		crazymap("st-targets", prom_st_crazymap);
453 		init = 1;
454 	}
455 	return prom_st_crazymap[n];
456 }
457 
458 
459 /*
460  * Determine mass storage and memory configuration for a machine.
461  * We get the PROM's root device and make sure we understand it, then
462  * attach it as `mainbus0'.  We also set up to handle the PROM `sync'
463  * command.
464  */
465 void
466 cpu_configure()
467 {
468 #if 0
469 	extern struct user *proc0paddr;	/* XXX see below */
470 #endif
471 
472 	/* build the bootpath */
473 	bootpath_build();
474 
475 #if notyet
476         /* FIXME FIXME FIXME  This is probably *WRONG!!!**/
477         OF_set_callback(sync_crash);
478 #endif
479 
480 	/* block clock interrupts and anything below */
481 	splclock();
482 	/* Enable device interrupts */
483         setpstate(getpstate()|PSTATE_IE);
484 
485 	if (config_rootfound("mainbus", NULL) == NULL)
486 		panic("mainbus not configured");
487 
488 	/* Enable device interrupts */
489         setpstate(getpstate()|PSTATE_IE);
490 
491 #if 0
492 	/*
493 	 * XXX Re-zero proc0's user area, to nullify the effect of the
494 	 * XXX stack running into it during auto-configuration.
495 	 * XXX - should fix stack usage.
496 	 */
497 	bzero(proc0paddr, sizeof(struct user));
498 #endif
499 
500 	(void)spl0();
501 }
502 
503 
504 void
505 cpu_rootconf()
506 {
507 	struct bootpath *bp;
508 	struct device *bootdv;
509 	int bootpartition;
510 
511 	bp = nbootpath == 0 ? NULL : &bootpath[nbootpath-1];
512 	bootdv = bp == NULL ? NULL : bp->dev;
513 	bootpartition = bootdv == NULL ? 0 : bp->val[2];
514 
515 	setroot(bootdv, bootpartition);
516 }
517 
518 /*
519  * Console `sync' command.  SunOS just does a `panic: zero' so I guess
520  * no one really wants anything fancy...
521  */
522 void
523 sync_crash()
524 {
525 
526 	panic("PROM sync command");
527 }
528 
529 char *
530 clockfreq(freq)
531 	long freq;
532 {
533 	char *p;
534 	static char buf[10];
535 
536 	freq /= 1000;
537 	sprintf(buf, "%ld", freq / 1000);
538 	freq %= 1000;
539 	if (freq) {
540 		freq += 1000;	/* now in 1000..1999 */
541 		p = buf + strlen(buf);
542 		sprintf(p, "%ld", freq);
543 		*p = '.';	/* now buf = %d.%3d */
544 	}
545 	return (buf);
546 }
547 
548 /* ARGSUSED */
549 static int
550 mbprint(aux, name)
551 	void *aux;
552 	const char *name;
553 {
554 	struct mainbus_attach_args *ma = aux;
555 
556 	if (name)
557 		printf("%s at %s", ma->ma_name, name);
558 	if (ma->ma_address)
559 		printf(" addr 0x%08lx", (u_long)ma->ma_address[0]);
560 	if (ma->ma_pri)
561 		printf(" ipl %d", ma->ma_pri);
562 	return (UNCONF);
563 }
564 
565 int
566 findroot()
567 {
568 	register int node;
569 
570 	if ((node = rootnode) == 0 && (node = OF_peer(0)) == 0)
571 		panic("no PROM root device");
572 	rootnode = node;
573 	return (node);
574 }
575 
576 /*
577  * Given a `first child' node number, locate the node with the given name.
578  * Return the node number, or 0 if not found.
579  */
580 int
581 findnode(first, name)
582 	int first;
583 	register const char *name;
584 {
585 	int node;
586 	char buf[32];
587 
588 	for (node = first; node; node = OF_peer(node)) {
589 		if ((OF_getprop(node, "name", buf, sizeof(buf)) > 0) &&
590 			(strcmp(buf, name) == 0))
591 			return (node);
592 	}
593 	return (0);
594 }
595 
596 int
597 mainbus_match(parent, cf, aux)
598 	struct device *parent;
599 	struct cfdata *cf;
600 	void *aux;
601 {
602 
603 	return (1);
604 }
605 
606 int autoconf_nzs = 0;	/* must be global so obio.c can see it */
607 
608 /*
609  * Attach the mainbus.
610  *
611  * Our main job is to attach the CPU (the root node we got in configure())
612  * and iterate down the list of `mainbus devices' (children of that node).
613  * We also record the `node id' of the default frame buffer, if any.
614  */
615 static void
616 mainbus_attach(parent, dev, aux)
617 	struct device *parent, *dev;
618 	void *aux;
619 {
620 extern struct sparc_bus_dma_tag mainbus_dma_tag;
621 extern struct sparc_bus_space_tag mainbus_space_tag;
622 
623 	struct mainbus_attach_args ma;
624 	char buf[32];
625 	const char *const *ssp, *sp = NULL;
626 	int node0, node, rv;
627 
628 	static const char *const openboot_special[] = {
629 		/* ignore these (end with NULL) */
630 		/*
631 		 * These are _root_ devices to ignore. Others must be handled
632 		 * elsewhere.
633 		 */
634 		"virtual-memory",
635 		"aliases",
636 		"memory",
637 		"openprom",
638 		"options",
639 		"packages",
640 		"chosen",
641 		NULL
642 	};
643 
644 	OF_getprop(findroot(), "name", platform_type, sizeof(platform_type));
645 	printf(": %s\n", platform_type);
646 
647 
648 	/*
649 	 * Locate and configure the ``early'' devices.  These must be
650 	 * configured before we can do the rest.  For instance, the
651 	 * EEPROM contains the Ethernet address for the LANCE chip.
652 	 * If the device cannot be located or configured, panic.
653 	 */
654 
655 /*
656  * The rest of this routine is for OBP machines exclusively.
657  */
658 
659 	node = findroot();
660 
661 	/* Establish the first component of the boot path */
662 	bootpath_store(1, bootpath);
663 
664 	/* the first early device to be configured is the cpu */
665 	{
666 		/* XXX - what to do on multiprocessor machines? */
667 
668 		for (node = OF_child(node); node; node = OF_peer(node)) {
669 			if (OF_getprop(node, "device_type",
670 				buf, sizeof(buf)) <= 0)
671 				continue;
672 			if (strcmp(buf, "cpu") == 0) {
673 				bzero(&ma, sizeof(ma));
674 				ma.ma_bustag = &mainbus_space_tag;
675 				ma.ma_dmatag = &mainbus_dma_tag;
676 				ma.ma_node = node;
677 				ma.ma_name = "cpu";
678 				config_found(dev, (void *)&ma, mbprint);
679 				break;
680 			}
681 		}
682 		if (node == 0)
683 			panic("None of the CPUs found\n");
684 	}
685 
686 
687 	node = findroot();	/* re-init root node */
688 
689 	/* Find the "options" node */
690 	node0 = OF_child(node);
691 	optionsnode = findnode(node0, "options");
692 	if (optionsnode == 0)
693 		panic("no options in OPENPROM");
694 
695 	/*
696 	 * Configure the devices, in PROM order.  Skip
697 	 * PROM entries that are not for devices, or which must be
698 	 * done before we get here.
699 	 */
700 	for (node = node0; node; node = OF_peer(node)) {
701 		int portid;
702 
703 		DPRINTF(ACDB_PROBE, ("Node: %x", node));
704 		if ((OF_getprop(node, "device_type", buf, sizeof(buf)) > 0) &&
705 			strcmp(buf, "cpu") == 0)
706 			continue;
707 		OF_getprop(node, "name", buf, sizeof(buf));
708 		DPRINTF(ACDB_PROBE, (" name %s\n", buf));
709 		for (ssp = openboot_special; (sp = *ssp) != NULL; ssp++)
710 			if (strcmp(buf, sp) == 0)
711 				break;
712 		if (sp != NULL)
713 			continue; /* an "early" device already configured */
714 
715 		bzero(&ma, sizeof ma);
716 		ma.ma_bustag = &mainbus_space_tag;
717 		ma.ma_dmatag = &mainbus_dma_tag;
718 		ma.ma_name = buf;
719 		ma.ma_node = node;
720 		if (OF_getprop(node, "upa-portid", &portid, sizeof(portid)) !=
721 			sizeof(portid))
722 			portid = -1;
723 		ma.ma_upaid = portid;
724 
725 		if (PROM_getprop(node, "reg", sizeof(*ma.ma_reg),
726 			     &ma.ma_nreg, (void**)&ma.ma_reg) != 0)
727 			continue;
728 #ifdef DEBUG
729 		if (autoconf_debug & ACDB_PROBE) {
730 			if (ma.ma_nreg)
731 				printf(" reg %08lx.%08lx\n",
732 					(long)ma.ma_reg->ur_paddr,
733 					(long)ma.ma_reg->ur_len);
734 			else
735 				printf(" no reg\n");
736 		}
737 #endif
738 		rv = PROM_getprop(node, "interrupts", sizeof(*ma.ma_interrupts),
739 			&ma.ma_ninterrupts, (void**)&ma.ma_interrupts);
740 		if (rv != 0 && rv != ENOENT) {
741 			free(ma.ma_reg, M_DEVBUF);
742 			continue;
743 		}
744 #ifdef DEBUG
745 		if (autoconf_debug & ACDB_PROBE) {
746 			if (ma.ma_interrupts)
747 				printf(" interrupts %08x\n",
748 					*ma.ma_interrupts);
749 			else
750 				printf(" no interrupts\n");
751 		}
752 #endif
753 		rv = PROM_getprop(node, "address", sizeof(*ma.ma_address),
754 			&ma.ma_naddress, (void**)&ma.ma_address);
755 		if (rv != 0 && rv != ENOENT) {
756 			free(ma.ma_reg, M_DEVBUF);
757 			if (ma.ma_ninterrupts)
758 				free(ma.ma_interrupts, M_DEVBUF);
759 			continue;
760 		}
761 #ifdef DEBUG
762 		if (autoconf_debug & ACDB_PROBE) {
763 			if (ma.ma_naddress)
764 				printf(" address %08x\n",
765 					*ma.ma_address);
766 			else
767 				printf(" no address\n");
768 		}
769 #endif
770 		(void) config_found(dev, (void *)&ma, mbprint);
771 		free(ma.ma_reg, M_DEVBUF);
772 		if (ma.ma_ninterrupts)
773 			free(ma.ma_interrupts, M_DEVBUF);
774 		if (ma.ma_naddress)
775 			free(ma.ma_address, M_DEVBUF);
776 	}
777 	/* Try to attach PROM console */
778 	bzero(&ma, sizeof ma);
779 	ma.ma_name = "pcons";
780 	(void) config_found(dev, (void *)&ma, mbprint);
781 }
782 
783 struct cfattach mainbus_ca = {
784 	sizeof(struct device), mainbus_match, mainbus_attach
785 };
786 
787 int
788 PROM_getprop(node, name, size, nitem, bufp)
789 	int	node;
790 	char	*name;
791 	size_t	size;
792 	int	*nitem;
793 	void	**bufp;
794 {
795 	void	*buf;
796 	long	len;
797 
798 	*nitem = 0;
799 	len = PROM_getproplen(node, name);
800 	if (len <= 0)
801 		return (ENOENT);
802 
803 	if ((len % size) != 0)
804 		return (EINVAL);
805 
806 	buf = *bufp;
807 	if (buf == NULL) {
808 		/* No storage provided, so we allocate some */
809 		buf = malloc(len, M_DEVBUF, M_NOWAIT);
810 		if (buf == NULL)
811 			return (ENOMEM);
812 	}
813 
814 	OF_getprop(node, name, buf, len);
815 	*bufp = buf;
816 	*nitem = len / size;
817 	return (0);
818 }
819 
820 
821 /*
822  * Internal form of proplen().  Returns the property length.
823  */
824 long
825 PROM_getproplen(node, name)
826 	int node;
827 	char *name;
828 {
829 	return (OF_getproplen(node, name));
830 }
831 
832 /*
833  * Return a string property.  There is a (small) limit on the length;
834  * the string is fetched into a static buffer which is overwritten on
835  * subsequent calls.
836  */
837 char *
838 PROM_getpropstring(node, name)
839 	int node;
840 	char *name;
841 {
842 	static char stringbuf[32];
843 
844 	return (PROM_getpropstringA(node, name, stringbuf));
845 }
846 
847 /* Alternative PROM_getpropstring(), where caller provides the buffer */
848 char *
849 PROM_getpropstringA(node, name, buffer)
850 	int node;
851 	char *name;
852 	char *buffer;
853 {
854 	int blen;
855 
856 	if (PROM_getprop(node, name, 1, &blen, (void **)&buffer) != 0)
857 		blen = 0;
858 
859 	buffer[blen] = '\0';	/* usually unnecessary */
860 	return (buffer);
861 }
862 
863 /*
864  * Fetch an integer (or pointer) property.
865  * The return value is the property, or the default if there was none.
866  */
867 int
868 PROM_getpropint(node, name, deflt)
869 	int node;
870 	char *name;
871 	int deflt;
872 {
873 	int intbuf;
874 
875 
876 
877 	if (OF_getprop(node, name, &intbuf, sizeof(intbuf)) != sizeof(intbuf))
878 		return (deflt);
879 
880 	return (intbuf);
881 }
882 
883 /*
884  * OPENPROM functions.  These are here mainly to hide the OPENPROM interface
885  * from the rest of the kernel.
886  */
887 int
888 firstchild(node)
889 	int node;
890 {
891 
892 	return OF_child(node);
893 }
894 
895 int
896 nextsibling(node)
897 	int node;
898 {
899 
900 	return OF_peer(node);
901 }
902 
903 /* The following are used primarily in consinit() */
904 
905 int
906 node_has_property(node, prop)	/* returns 1 if node has given property */
907 	register int node;
908 	register const char *prop;
909 {
910 	return (OF_getproplen(node, (caddr_t)prop) != -1);
911 }
912 
913 #ifdef RASTERCONSOLE
914 /*
915  * Try to figure out where the PROM stores the cursor row & column
916  * variables.  Returns nonzero on error.
917  */
918 int
919 romgetcursoraddr(rowp, colp)
920 	register int **rowp, **colp;
921 {
922 	cell_t row = NULL, col = NULL;
923 
924 	OF_interpret("stdout @ is my-self addr line# addr column# ", 0, 2,
925 		&col, &row);
926 	/*
927 	 * We are running on a 64-bit machine, so these things point to
928 	 * 64-bit values.  To convert them to pointers to integers, add
929 	 * 4 to the address.
930 	 */
931 	*rowp = (int *)(row+4);
932 	*colp = (int *)(col+4);
933 	return (row == NULL || col == NULL);
934 }
935 #endif /* RASTERCONSOLE */
936 
937 void
938 callrom()
939 {
940 
941 	__asm __volatile("wrpr	%%g0, 0, %%tl" : );
942 	OF_enter();
943 }
944 
945 /*
946  * find a device matching "name" and unit number
947  */
948 struct device *
949 getdevunit(name, unit)
950 	char *name;
951 	int unit;
952 {
953 	struct device *dev = alldevs.tqh_first;
954 	char num[10], fullname[16];
955 	int lunit;
956 
957 	/* compute length of name and decimal expansion of unit number */
958 	sprintf(num, "%d", unit);
959 	lunit = strlen(num);
960 	if (strlen(name) + lunit >= sizeof(fullname) - 1)
961 		panic("config_attach: device name too long");
962 
963 	strcpy(fullname, name);
964 	strcat(fullname, num);
965 
966 	while (strcmp(dev->dv_xname, fullname) != 0) {
967 		if ((dev = dev->dv_list.tqe_next) == NULL)
968 			return NULL;
969 	}
970 	return dev;
971 }
972 
973 
974 /*
975  * Device registration used to determine the boot device.
976  *
977  * Copied from the sparc port.
978  */
979 #include <dev/scsipi/scsi_all.h>
980 #include <dev/scsipi/scsipi_all.h>
981 #include <dev/scsipi/scsiconf.h>
982 
983 #define BUSCLASS_NONE		0
984 #define BUSCLASS_MAINBUS	1
985 #define BUSCLASS_IOMMU		2
986 #define BUSCLASS_OBIO		3
987 #define BUSCLASS_SBUS		4
988 #define BUSCLASS_VME		5
989 #define BUSCLASS_PCI		6
990 #define BUSCLASS_XDC		7
991 #define BUSCLASS_XYC		8
992 #define BUSCLASS_FDC		9
993 
994 static int bus_class __P((struct device *));
995 static char *bus_compatible __P((char *, struct device *));
996 static int instance_match __P((struct device *, void *, struct bootpath *));
997 static void nail_bootdev __P((struct device *, struct bootpath *));
998 
999 static struct {
1000 	char	*name;
1001 	int	class;
1002 } bus_class_tab[] = {
1003 	{ "mainbus",	BUSCLASS_MAINBUS },
1004 	{ "upa",	BUSCLASS_MAINBUS },
1005 	{ "psycho",	BUSCLASS_MAINBUS },
1006 	{ "obio",	BUSCLASS_OBIO },
1007 	{ "iommu",	BUSCLASS_IOMMU },
1008 	{ "sbus",	BUSCLASS_SBUS },
1009 	{ "xbox",	BUSCLASS_SBUS },
1010 	{ "esp",	BUSCLASS_SBUS },
1011 	{ "dma",	BUSCLASS_SBUS },
1012 	{ "espdma",	BUSCLASS_SBUS },
1013 	{ "ledma",	BUSCLASS_SBUS },
1014 	{ "simba",	BUSCLASS_PCI },
1015 	{ "ppb",	BUSCLASS_PCI },
1016 	{ "pciide",	BUSCLASS_PCI },
1017 	{ "siop",	BUSCLASS_PCI },
1018 	{ "pci",	BUSCLASS_PCI },
1019 	{ "fdc",	BUSCLASS_FDC },
1020 };
1021 
1022 /*
1023  * A list of PROM device names that differ from our NetBSD
1024  * device names.
1025  */
1026 static struct {
1027 	char	*bpname;
1028 	int	class;
1029 	char	*cfname;
1030 } dev_compat_tab[] = {
1031 	{ "espdma",	BUSCLASS_NONE,		"dma" },
1032 	{ "QLGC,isp",	BUSCLASS_NONE,		"isp" },
1033 	{ "PTI,isp",	BUSCLASS_NONE,		"isp" },
1034 	{ "ptisp",	BUSCLASS_NONE,		"isp" },
1035 	{ "SUNW,fdtwo",	BUSCLASS_NONE,		"fdc" },
1036 	{ "pci",	BUSCLASS_MAINBUS,	"psycho" },
1037 	{ "pci",	BUSCLASS_PCI,		"ppb" },
1038 	{ "ide",	BUSCLASS_PCI,		"pciide" },
1039 	{ "disk",	BUSCLASS_NONE,		"wd" },  /* XXX */
1040 	{ "network",	BUSCLASS_NONE,		"hme" }, /* XXX */
1041 	{ "SUNW,fas",	BUSCLASS_NONE,		"esp" },
1042 	{ "SUNW,hme",	BUSCLASS_NONE,		"hme" },
1043 	{ "glm",	BUSCLASS_PCI,		"siop" },
1044 	{ "SUNW,glm",	BUSCLASS_PCI,		"siop" },
1045 };
1046 
1047 static char *
1048 bus_compatible(bpname, dev)
1049 	char *bpname;
1050 	struct device *dev;
1051 {
1052 	int i, class = bus_class(dev);
1053 
1054 	for (i = sizeof(dev_compat_tab)/sizeof(dev_compat_tab[0]); i-- > 0;) {
1055 		if (strcmp(bpname, dev_compat_tab[i].bpname) == 0 &&
1056 		    (dev_compat_tab[i].class == BUSCLASS_NONE ||
1057 		     dev_compat_tab[i].class == class))
1058 			return (dev_compat_tab[i].cfname);
1059 	}
1060 
1061 	return (bpname);
1062 }
1063 
1064 static int
1065 bus_class(dev)
1066 	struct device *dev;
1067 {
1068 	char *name;
1069 	int i, class;
1070 
1071 	class = BUSCLASS_NONE;
1072 	if (dev == NULL)
1073 		return (class);
1074 
1075 	name = dev->dv_cfdata->cf_driver->cd_name;
1076 	for (i = sizeof(bus_class_tab)/sizeof(bus_class_tab[0]); i-- > 0;) {
1077 		if (strcmp(name, bus_class_tab[i].name) == 0) {
1078 			class = bus_class_tab[i].class;
1079 			break;
1080 		}
1081 	}
1082 
1083 	return (class);
1084 }
1085 
1086 int
1087 instance_match(dev, aux, bp)
1088 	struct device *dev;
1089 	void *aux;
1090 	struct bootpath *bp;
1091 {
1092 	struct mainbus_attach_args *ma;
1093 	struct sbus_attach_args *sa;
1094 	struct pci_attach_args *pa;
1095 
1096 	/*
1097 	 * Several devices are represented on bootpaths in one of
1098 	 * two formats, e.g.:
1099 	 *	(1) ../sbus@.../esp@<offset>,<slot>/sd@..  (PROM v3 style)
1100 	 *	(2) /sbus0/esp0/sd@..                      (PROM v2 style)
1101 	 *
1102 	 * hence we fall back on a `unit number' check if the bus-specific
1103 	 * instance parameter check does not produce a match.
1104 	 *
1105 	 * For PCI devices, we get:
1106 	 *	../pci@../xxx@<dev>,<fn>/...
1107 	 */
1108 
1109 	/*
1110 	 * Rank parent bus so we know which locators to check.
1111 	 */
1112 	switch (bus_class(dev->dv_parent)) {
1113 	case BUSCLASS_MAINBUS:
1114 		ma = aux;
1115 		DPRINTF(ACDB_BOOTDEV,
1116 		    ("instance_match: mainbus device, want %#x have %#x\n",
1117 		    ma->ma_upaid, bp->val[0]));
1118 		if (bp->val[0] == ma->ma_upaid)
1119 			return (1);
1120 		break;
1121 	case BUSCLASS_SBUS:
1122 		sa = aux;
1123 		DPRINTF(ACDB_BOOTDEV, ("instance_match: sbus device, "
1124 		    "want slot %#x offset %#x have slot %#x offset %#x\n",
1125 		     bp->val[0], bp->val[1], sa->sa_slot, sa->sa_offset));
1126 		if (bp->val[0] == sa->sa_slot && bp->val[1] == sa->sa_offset)
1127 			return (1);
1128 		break;
1129 	case BUSCLASS_PCI:
1130 		pa = aux;
1131 		DPRINTF(ACDB_BOOTDEV, ("instance_match: pci device, "
1132 		    "want dev %#x fn %#x have dev %#x fn %#x\n",
1133 		     bp->val[0], bp->val[1], pa->pa_device, pa->pa_function));
1134 		if (bp->val[0] == pa->pa_device &&
1135 		    bp->val[1] == pa->pa_function)
1136 			return (1);
1137 		break;
1138 	default:
1139 		break;
1140 	}
1141 
1142 	if (bp->val[0] == -1 && bp->val[1] == dev->dv_unit)
1143 		return (1);
1144 
1145 	return (0);
1146 }
1147 
1148 struct device *booted_device;
1149 
1150 void
1151 nail_bootdev(dev, bp)
1152 	struct device *dev;
1153 	struct bootpath *bp;
1154 {
1155 
1156 	if (bp->dev != NULL)
1157 		panic("device_register: already got a boot device: %s",
1158 			bp->dev->dv_xname);
1159 
1160 	/*
1161 	 * Mark this bootpath component by linking it to the matched
1162 	 * device. We pick up the device pointer in cpu_rootconf().
1163 	 */
1164 	booted_device = bp->dev = dev;
1165 
1166 	/*
1167 	 * Then clear the current bootpath component, so we don't spuriously
1168 	 * match similar instances on other busses, e.g. a disk on
1169 	 * another SCSI bus with the same target.
1170 	 */
1171 	bootpath_store(1, NULL);
1172 }
1173 
1174 void
1175 device_register(dev, aux)
1176 	struct device *dev;
1177 	void *aux;
1178 {
1179 	struct bootpath *bp = bootpath_store(0, NULL);
1180 	char *dvname, *bpname;
1181 
1182 	/*
1183 	 * If device name does not match current bootpath component
1184 	 * then there's nothing interesting to consider.
1185 	 */
1186 	if (bp == NULL)
1187 		return;
1188 
1189 	/*
1190 	 * Translate PROM name in case our drivers are named differently
1191 	 */
1192 	bpname = bus_compatible(bp->name, dev);
1193 	dvname = dev->dv_cfdata->cf_driver->cd_name;
1194 
1195 	DPRINTF(ACDB_BOOTDEV,
1196 	    ("\n%s: device_register: dvname %s(%s) bpname %s(%s)\n",
1197 	    dev->dv_xname, dvname, dev->dv_xname, bpname, bp->name));
1198 
1199 	/* First, match by name */
1200 	if (strcmp(dvname, bpname) != 0)
1201 		return;
1202 
1203 	if (bus_class(dev) != BUSCLASS_NONE) {
1204 		/*
1205 		 * A bus or controller device of sorts. Check instance
1206 		 * parameters and advance boot path on match.
1207 		 */
1208 		if (instance_match(dev, aux, bp) != 0) {
1209 			bp->dev = dev;
1210 			bootpath_store(1, bp + 1);
1211 			DPRINTF(ACDB_BOOTDEV, ("\t-- found bus controller %s\n",
1212 			    dev->dv_xname));
1213 			return;
1214 		}
1215 	} else if (strcmp(dvname, "le") == 0 ||
1216 		   strcmp(dvname, "hme") == 0) {
1217 		/*
1218 		 * ethernet devices.
1219 		 */
1220 		if (instance_match(dev, aux, bp) != 0) {
1221 			nail_bootdev(dev, bp);
1222 			DPRINTF(ACDB_BOOTDEV, ("\t-- found ethernet controller %s\n",
1223 			    dev->dv_xname));
1224 			return;
1225 		}
1226 	} else if (strcmp(dvname, "sd") == 0 || strcmp(dvname, "cd") == 0) {
1227 		/*
1228 		 * A SCSI disk or cd; retrieve target/lun information
1229 		 * from parent and match with current bootpath component.
1230 		 * Note that we also have look back past the `scsibus'
1231 		 * device to determine whether this target is on the
1232 		 * correct controller in our boot path.
1233 		 */
1234 		struct scsipibus_attach_args *sa = aux;
1235 		struct scsipi_periph *periph = sa->sa_periph;
1236 		struct scsibus_softc *sbsc =
1237 			(struct scsibus_softc *)dev->dv_parent;
1238 		u_int target = bp->val[0];
1239 		u_int lun = bp->val[1];
1240 
1241 		/* Check the controller that this scsibus is on */
1242 		if ((bp-1)->dev != sbsc->sc_dev.dv_parent)
1243 			return;
1244 
1245 		/*
1246 		 * Bounds check: we know the target and lun widths.
1247 		 */
1248 		if (target >= periph->periph_channel->chan_ntargets ||
1249 		    lun >= periph->periph_channel->chan_nluns) {
1250 			printf("SCSI disk bootpath component not accepted: "
1251 			       "target %u; lun %u\n", target, lun);
1252 			return;
1253 		}
1254 
1255 		if (periph->periph_target == target &&
1256 		    periph->periph_lun == lun) {
1257 			nail_bootdev(dev, bp);
1258 			DPRINTF(ACDB_BOOTDEV, ("\t-- found [cs]d disk %s\n",
1259 			    dev->dv_xname));
1260 			return;
1261 		}
1262 	} else if (strcmp("wd", dvname) == 0) {
1263 		/* IDE disks. */
1264 		struct ata_device *adev = aux;
1265 
1266 		if (adev->adev_channel == bp->val[0]) {
1267 			nail_bootdev(dev, bp);
1268 			DPRINTF(ACDB_BOOTDEV, ("\t-- found wd disk %s\n",
1269 			    dev->dv_xname));
1270 			return;
1271 		}
1272 	} else {
1273 		/*
1274 		 * Generic match procedure.
1275 		 */
1276 		if (instance_match(dev, aux, bp) != 0) {
1277 			nail_bootdev(dev, bp);
1278 			DPRINTF(ACDB_BOOTDEV, ("\t-- found generic device %s\n",
1279 			    dev->dv_xname));
1280 			return;
1281 		}
1282 	}
1283 }
1284