xref: /netbsd-src/sys/arch/sparc64/sparc64/autoconf.c (revision 1d5e5cd8e2b1b6e32523e94aad614ee014e84ca6)
1 /*	$NetBSD: autoconf.c,v 1.243 2024/11/19 20:38:24 palle 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 <sys/cdefs.h>
51 __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.243 2024/11/19 20:38:24 palle Exp $");
52 
53 #include "opt_ddb.h"
54 #include "opt_kgdb.h"
55 #include "opt_modular.h"
56 #include "opt_multiprocessor.h"
57 
58 #include <sys/param.h>
59 #include <sys/kernel.h>
60 #include <sys/systm.h>
61 #include <sys/buf.h>
62 #include <sys/disklabel.h>
63 #include <sys/device.h>
64 #include <sys/disk.h>
65 #include <sys/conf.h>
66 #include <sys/reboot.h>
67 #include <sys/socket.h>
68 #include <sys/vnode.h>
69 #include <sys/fcntl.h>
70 #include <sys/queue.h>
71 #include <sys/msgbuf.h>
72 #include <sys/boot_flag.h>
73 #include <sys/ksyms.h>
74 #include <sys/kauth.h>
75 #include <sys/userconf.h>
76 #include <prop/proplib.h>
77 
78 #include <net/if.h>
79 #include <net/if_ether.h>
80 
81 #include <dev/cons.h>
82 #include <sparc64/dev/cons.h>
83 
84 #include <uvm/uvm_extern.h>
85 
86 #include <sys/bus.h>
87 #include <machine/autoconf.h>
88 #include <machine/openfirm.h>
89 #include <machine/sparc64.h>
90 #include <machine/cpu.h>
91 #include <machine/pmap.h>
92 #include <machine/bootinfo.h>
93 #include <sparc64/sparc64/cache.h>
94 #include <sparc64/sparc64/ofw_patch.h>
95 #include <sparc64/sparc64/timerreg.h>
96 #include <sparc64/dev/cbusvar.h>
97 
98 #include <dev/ata/atavar.h>
99 #include <dev/pci/pcivar.h>
100 #include <dev/ebus/ebusvar.h>
101 #include <dev/sbus/sbusvar.h>
102 #include <dev/i2c/i2cvar.h>
103 
104 #ifdef DDB
105 #include <machine/db_machdep.h>
106 #include <ddb/db_sym.h>
107 #include <ddb/db_extern.h>
108 #endif
109 
110 #ifdef RASTERCONSOLE
111 #error options RASTERCONSOLE is obsolete for sparc64 - remove it from your config file
112 #endif
113 
114 #include <dev/wsfb/genfbvar.h>
115 
116 #include "ksyms.h"
117 
118 int autoconf_debug = 0x0;
119 
120 struct evcnt intr_evcnts[] = {
121 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "spur"),
122 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev1"),
123 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev2"),
124 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev3"),
125 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev4"),
126 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev5"),
127 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev6"),
128 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev7"),
129 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev8"),
130 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev9"),
131 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "clock"),
132 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev11"),
133 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev12"),
134 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev13"),
135 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "prof"),
136 	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr",  "lev15")
137 };
138 
139 void *bootinfo = 0;
140 
141 #ifdef KGDB
142 int kgdb_break_at_attach;
143 #endif
144 
145 #define	OFPATHLEN	128
146 
147 char	machine_banner[100];
148 char	machine_model[100];
149 char	ofbootpath[OFPATHLEN], *ofboottarget, *ofbootpartition;
150 char	ofbootargs[OFPATHLEN], *ofbootfile, *ofbootflags;
151 int	ofbootpackage;
152 
153 static	int mbprint(void *, const char *);
154 int	mainbus_match(device_t, cfdata_t, void *);
155 static	void mainbus_attach(device_t, device_t, void *);
156 static  void get_ncpus(void);
157 static	void get_bootpath_from_prom(void);
158 
159 /*
160  * Kernel 4MB mappings.
161  */
162 struct tlb_entry *kernel_tlbs;
163 int kernel_dtlb_slots;
164 int kernel_itlb_slots;
165 
166 /* Global interrupt mappings for all device types.  Match against the OBP
167  * 'device_type' property.  Note, that the resulting PIL must be higher than
168  * the highest soft interrupt level (IPL_SOFTSERIAL).
169  */
170 struct intrmap intrmap[] = {
171 	{ "block",	PIL_FD },	/* Floppy disk */
172 	{ "serial",	PIL_SER },	/* zs */
173 	{ "scsi",	PIL_BIO },
174 	{ "scsi-2",	PIL_BIO },
175 	{ "network",	PIL_NET },
176 	{ "display",	PIL_VIDEO },
177 	{ "audio",	PIL_AUD },
178 	{ "ide",	PIL_BIO },
179 	{ "socal",	PIL_BIO },
180 /* The following devices don't have device types: */
181 	{ "SUNW,CS4231",	PIL_AUD },
182 	{ "SUNW,bpp",	PIL_BIO },
183 	{ NULL,		0 }
184 };
185 
186 #ifdef SUN4V
187 void	sun4v_soft_state_init(void);
188 void	sun4v_set_soft_state(int, const char *);
189 
190 #define __align32 __attribute__((__aligned__(32)))
191 char sun4v_soft_state_booting[] __align32 = "NetBSD booting";
192 char sun4v_soft_state_running[] __align32 = "NetBSD running";
193 
194 void	sun4v_interrupt_init(void);
195 #if 0
196 XXX notyet
197 void	sun4v_sdio_init(void);
198 #endif
199 #endif
200 
201 int console_node, console_instance;
202 struct genfb_colormap_callback gfb_cb;
203 static void of_set_palette(void *, int, int, int, int);
204 static void copyprops(device_t, int, prop_dictionary_t, int);
205 
206 static void
207 get_ncpus(void)
208 {
209 #ifdef MULTIPROCESSOR
210 	int node, l;
211 	char sbuf[32];
212 
213 	node = findroot();
214 
215 	sparc_ncpus = 0;
216 	for (node = OF_child(node); node; node = OF_peer(node)) {
217 		if (OF_getprop(node, "device_type", sbuf, sizeof(sbuf)) <= 0)
218 			continue;
219 		if (strcmp(sbuf, "cpu") != 0)
220 			continue;
221 		sparc_ncpus++;
222 		l = prom_getpropint(node, "dcache-line-size", 0);
223 		if (l > dcache_line_size)
224 			dcache_line_size = l;
225 		l = prom_getpropint(node, "icache-line-size", 0);
226 		if (l > icache_line_size)
227 			icache_line_size = l;
228 	}
229 #else
230 	/* #define sparc_ncpus 1 */
231 	icache_line_size = dcache_line_size = 8; /* will be fixed later */
232 #endif
233 }
234 
235 /*
236  * lookup_bootinfo:
237  * Look up information in bootinfo of boot loader.
238  */
239 void *
240 lookup_bootinfo(int type)
241 {
242 	struct btinfo_common *bt;
243 	char *help = bootinfo;
244 
245 	/* Check for a bootinfo record first. */
246 	if (help == NULL)
247 		return (NULL);
248 
249 	do {
250 		bt = (struct btinfo_common *)help;
251 		if (bt->type == type)
252 			return ((void *)help);
253 		help += bt->next;
254 	} while (bt->next != 0 &&
255 		(size_t)help < (size_t)bootinfo + BOOTINFO_SIZE);
256 
257 	return (NULL);
258 }
259 
260 /*
261  * locore.s code calls bootstrap() just before calling main().
262  *
263  * What we try to do is as follows:
264  * - Initialize PROM and the console
265  * - Read in part of information provided by a bootloader and find out
266  *   kernel load and end addresses
267  * - Initialize ksyms
268  * - Find out number of active CPUs
269  * - Finalize the bootstrap by calling pmap_bootstrap()
270  *
271  * We will try to run out of the prom until we get out of pmap_bootstrap().
272  */
273 void
274 bootstrap(void *o0, void *bootargs, void *bootsize, void *o3, void *ofw)
275 {
276 	void *bi;
277 	long bmagic;
278 	char buf[32];
279 
280 #if NKSYMS || defined(DDB) || defined(MODULAR)
281 	struct btinfo_symtab *bi_sym;
282 #endif
283 	struct btinfo_count *bi_count;
284 	struct btinfo_kernend *bi_kend;
285 	struct btinfo_tlb *bi_tlb;
286 	struct btinfo_boothowto *bi_howto;
287 
288 	extern void *romtba;
289 	extern void* get_romtba(void);
290 	extern void  OF_val2sym32(void *);
291 	extern void OF_sym2val32(void *);
292 	extern struct consdev consdev_prom;
293 
294 	/* Save OpenFirmware entry point */
295 	romp   = ofw;
296 	romtba = get_romtba();
297 
298 	prom_init();
299 	console_instance = promops.po_stdout;
300 	console_node = OF_instance_to_package(promops.po_stdout);
301 
302 	/* Initialize the PROM console so printf will not panic */
303 	cn_tab = &consdev_prom;
304 	(*cn_tab->cn_init)(cn_tab);
305 
306 	DPRINTF(ACDB_BOOTARGS,
307 		("sparc64_init(%p, %p, %p, %p, %p)\n", o0, bootargs, bootsize,
308 			o3, ofw));
309 
310 	/* Extract bootinfo pointer */
311 	if ((long)bootsize >= (4 * sizeof(uint64_t))) {
312 		/* Loaded by 64-bit bootloader */
313 		bi = (void*)(u_long)(((uint64_t*)bootargs)[3]);
314 		bmagic = (long)(((uint64_t*)bootargs)[0]);
315 	} else if ((long)bootsize >= (4 * sizeof(uint32_t))) {
316 		/* Loaded by 32-bit bootloader */
317 		bi = (void*)(u_long)(((uint32_t*)bootargs)[3]);
318 		bmagic = (long)(((uint32_t*)bootargs)[0]);
319 	} else {
320 		printf("Bad bootinfo size.\n");
321 die_old_boot_loader:
322 		printf("This kernel requires NetBSD boot loader version 1.9 "
323 		       "or newer\n");
324 		panic("sparc64_init.");
325 	}
326 
327 	DPRINTF(ACDB_BOOTARGS,
328 		("sparc64_init: bmagic=%lx, bi=%p\n", bmagic, bi));
329 
330 	/* Read in the information provided by NetBSD boot loader */
331 	if (SPARC_MACHINE_OPENFIRMWARE != bmagic) {
332 		printf("No bootinfo information.\n");
333 		goto die_old_boot_loader;
334 	}
335 
336 	bootinfo = (void*)(u_long)((uint64_t*)bi)[1];
337 	LOOKUP_BOOTINFO(bi_kend, BTINFO_KERNEND);
338 
339 	if (bi_kend->addr == (vaddr_t)0) {
340 		panic("Kernel end address is not found in bootinfo.\n");
341 	}
342 
343 #if NKSYMS || defined(DDB) || defined(MODULAR)
344 	LOOKUP_BOOTINFO(bi_sym, BTINFO_SYMTAB);
345 	ksyms_addsyms_elf(bi_sym->nsym, (int *)(u_long)bi_sym->ssym,
346 			(int *)(u_long)bi_sym->esym);
347 #ifdef DDB
348 #ifdef __arch64__
349 	/* This can only be installed on an 64-bit system cause otherwise our stack is screwed */
350 	OF_set_symbol_lookup(OF_sym2val, OF_val2sym);
351 #else
352 	OF_set_symbol_lookup(OF_sym2val32, OF_val2sym32);
353 #endif
354 #endif
355 #endif
356 	if (OF_getprop(findroot(), "compatible", buf, sizeof(buf)) > 0) {
357 		if (strcmp(buf, "sun4us") == 0)
358 			setcputyp(CPU_SUN4US);
359 		else if (strcmp(buf, "sun4v") == 0)
360 			setcputyp(CPU_SUN4V);
361 	}
362 
363 	bi_howto = lookup_bootinfo(BTINFO_BOOTHOWTO);
364 	if (bi_howto)
365 		boothowto = bi_howto->boothowto;
366 
367 	LOOKUP_BOOTINFO(bi_count, BTINFO_DTLB_SLOTS);
368 	kernel_dtlb_slots = bi_count->count;
369 	kernel_itlb_slots = kernel_dtlb_slots-1;
370 	bi_count = lookup_bootinfo(BTINFO_ITLB_SLOTS);
371 	if (bi_count)
372 		kernel_itlb_slots = bi_count->count;
373 	LOOKUP_BOOTINFO(bi_tlb, BTINFO_DTLB);
374 	kernel_tlbs = &bi_tlb->tlb[0];
375 
376 	get_ncpus();
377 	pmap_bootstrap(KERNBASE, bi_kend->addr);
378 
379 #ifdef SUN4V
380 	if (CPU_ISSUN4V) {
381 		sun4v_soft_state_init();
382 		sun4v_set_soft_state(SIS_TRANSITION, sun4v_soft_state_booting);
383 		sun4v_interrupt_init();
384 #if 0
385 XXX notyet
386 		sun4v_sdio_init();
387 #endif
388 	}
389 #endif
390 }
391 
392 /*
393  * get_bootpath_from_prom()
394  * fetch the OF settings to identify our boot device during autoconfiguration
395  */
396 
397 static void
398 get_bootpath_from_prom(void)
399 {
400 	struct btinfo_bootdev *bdev = NULL;
401 	char sbuf[OFPATHLEN], *cp;
402 	int chosen;
403 
404 	/*
405 	 * Grab boot path from PROM
406 	 */
407 	if ((chosen = OF_finddevice("/chosen")) == -1)
408 		return;
409 
410 	bdev = lookup_bootinfo(BTINFO_BOOTDEV);
411 	if (bdev != NULL) {
412 		strcpy(ofbootpath, bdev->name);
413 	} else {
414 		if (OF_getprop(chosen, "bootpath", sbuf, sizeof(sbuf)) < 0)
415 			return;
416 		strcpy(ofbootpath, sbuf);
417 	}
418 	DPRINTF(ACDB_BOOTDEV, ("bootpath: %s\n", ofbootpath));
419 	ofbootpackage = prom_finddevice(ofbootpath);
420 
421 	/*
422 	 * Strip partition or boot protocol
423 	 */
424 	cp = strrchr(ofbootpath, ':');
425 	if (cp) {
426 		*cp = '\0';
427 		ofbootpartition = cp+1;
428 	}
429 	cp = strrchr(ofbootpath, '@');
430 	if (cp) {
431 		for (; cp != ofbootpath; cp--) {
432 			if (*cp == '/') {
433 				ofboottarget = cp+1;
434 				break;
435 			}
436 		}
437 	}
438 
439 	DPRINTF(ACDB_BOOTDEV, ("bootpath phandle: 0x%x\n", ofbootpackage));
440 	DPRINTF(ACDB_BOOTDEV, ("boot target: %s\n",
441 	    ofboottarget ? ofboottarget : "<none>"));
442 	DPRINTF(ACDB_BOOTDEV, ("boot partition: %s\n",
443 	    ofbootpartition ? ofbootpartition : "<none>"));
444 
445 	/* Setup pointer to boot flags */
446 	if (OF_getprop(chosen, "bootargs", sbuf, sizeof(sbuf)) == -1)
447 		return;
448 	strcpy(ofbootargs, sbuf);
449 
450 	cp = ofbootargs;
451 
452 	/* Find start of boot flags */
453 	while (*cp) {
454 		while(*cp == ' ' || *cp == '\t') cp++;
455 		if (*cp == '-' || *cp == '\0')
456 			break;
457 		while(*cp != ' ' && *cp != '\t' && *cp != '\0') cp++;
458 		if (*cp != '\0')
459 			*cp++ = '\0';
460 	}
461 	if (cp != ofbootargs)
462 		ofbootfile = ofbootargs;
463 	ofbootflags = cp;
464 	if (*cp != '-')
465 		return;
466 
467 	for (;*++cp;) {
468 		int fl;
469 
470 		fl = 0;
471 		BOOT_FLAG(*cp, fl);
472 		if (!fl) {
473 			printf("unknown option `%c'\n", *cp);
474 			continue;
475 		}
476 		boothowto |= fl;
477 
478 		/* specialties */
479 		if (*cp == 'd') {
480 #if defined(KGDB)
481 			kgdb_break_at_attach = 1;
482 #elif defined(DDB)
483 			Debugger();
484 #else
485 			printf("kernel has no debugger\n");
486 #endif
487 		} else if (*cp == 't') {
488 			/* turn on traptrace w/o breaking into kdb */
489 			extern int trap_trace_dis;
490 
491 			trap_trace_dis = 0;
492 		}
493 	}
494 }
495 
496 /*
497  * Determine mass storage and memory configuration for a machine.
498  * We get the PROM's root device and make sure we understand it, then
499  * attach it as `mainbus0'.  We also set up to handle the PROM `sync'
500  * command.
501  */
502 void
503 cpu_configure(void)
504 {
505 
506 	bool userconf = (boothowto & RB_USERCONF) != 0;
507 
508 	/* fetch boot device settings */
509 	get_bootpath_from_prom();
510 	if (((boothowto & RB_USERCONF) != 0) && !userconf)
511 		/*
512 		 * Old bootloaders do not pass boothowto, and MI code
513 		 * has already handled userconfig before we get here
514 		 * and finally fetch the right options. So if we missed
515 		 * it, just do it here.
516  		 */
517 		userconf_prompt();
518 
519 	/* block clock interrupts and anything below */
520 	splclock();
521 	/* Enable device interrupts */
522         setpstate(getpstate()|PSTATE_IE);
523 
524 	if (config_rootfound("mainbus", NULL) == NULL)
525 		panic("mainbus not configured");
526 
527 	/* Enable device interrupts */
528         setpstate(getpstate()|PSTATE_IE);
529 
530 	(void)spl0();
531 
532 #ifdef SUN4V
533 	if (CPU_ISSUN4V)
534 		sun4v_set_soft_state(SIS_NORMAL, sun4v_soft_state_running);
535 #endif
536 }
537 
538 #ifdef SUN4V
539 
540 #define HSVC_GROUP_INTERRUPT	0x002
541 #define HSVC_GROUP_SOFT_STATE	0x003
542 #define HSVC_GROUP_SDIO		0x108
543 
544 int sun4v_soft_state_initialized = 0;
545 
546 void
547 sun4v_soft_state_init(void)
548 {
549 	uint64_t minor;
550 
551 	if (prom_set_sun4v_api_version(HSVC_GROUP_SOFT_STATE, 1, 0, &minor))
552 		return;
553 
554 	prom_sun4v_soft_state_supported();
555 	sun4v_soft_state_initialized = 1;
556 }
557 
558 void
559 sun4v_set_soft_state(int state, const char *desc)
560 {
561 	paddr_t pa;
562 	int err;
563 
564 	if (!sun4v_soft_state_initialized)
565 		return;
566 
567 	if (!pmap_extract(pmap_kernel(), (vaddr_t)desc, &pa))
568 		panic("sun4v_set_soft_state: pmap_extract failed");
569 
570 	err = hv_soft_state_set(state, pa);
571 	if (err != H_EOK)
572 		printf("soft_state_set: %d\n", err);
573 }
574 
575 void
576 sun4v_interrupt_init(void)
577 {
578 	uint64_t minor;
579 
580 	if (prom_set_sun4v_api_version(HSVC_GROUP_INTERRUPT, 3, 0, &minor))
581 		return;
582 
583 	sun4v_group_interrupt_major = 3;
584 }
585 
586 #if 0
587 XXX notyet
588 void
589 sun4v_sdio_init(void)
590 {
591 	uint64_t minor;
592 
593 	if (prom_set_sun4v_api_version(HSVC_GROUP_SDIO, 1, 0, &minor))
594 		return;
595 
596 	sun4v_group_sdio_major = 1;
597 }
598 #endif
599 
600 #endif
601 
602 void
603 cpu_rootconf(void)
604 {
605 	if (booted_device == NULL) {
606 		printf("FATAL: boot device not found, check your firmware "
607 		    "settings!\n");
608 	}
609 
610 	rootconf();
611 }
612 
613 char *
614 clockfreq(uint64_t freq)
615 {
616 	static char buf[10];
617 	size_t len;
618 
619 	freq /= 1000;
620 	len = snprintf(buf, sizeof(buf), "%" PRIu64, freq / 1000);
621 	freq %= 1000;
622 	if (freq)
623 		snprintf(buf + len, sizeof(buf) - len, ".%03" PRIu64, freq);
624 	return buf;
625 }
626 
627 /* ARGSUSED */
628 static int
629 mbprint(void *aux, const char *name)
630 {
631 	struct mainbus_attach_args *ma = aux;
632 
633 	if (name)
634 		aprint_normal("%s at %s", ma->ma_name, name);
635 	if (ma->ma_address)
636 		aprint_normal(" addr 0x%08lx", (u_long)ma->ma_address[0]);
637 	if (ma->ma_pri)
638 		aprint_normal(" ipl %d", ma->ma_pri);
639 	return (UNCONF);
640 }
641 
642 int
643 mainbus_match(device_t parent, cfdata_t cf, void *aux)
644 {
645 
646 	return (1);
647 }
648 
649 /*
650  * Attach the mainbus.
651  *
652  * Our main job is to attach the CPU (the root node we got in configure())
653  * and iterate down the list of `mainbus devices' (children of that node).
654  * We also record the `node id' of the default frame buffer, if any.
655  */
656 static void
657 mainbus_attach(device_t parent, device_t dev, void *aux)
658 {
659 extern struct sparc_bus_dma_tag mainbus_dma_tag;
660 extern struct sparc_bus_space_tag mainbus_space_tag;
661 
662 	struct mainbus_attach_args ma;
663 	char sbuf[32];
664 	const char *const *ssp, *sp = NULL;
665 	char *c;
666 	int node0, node, rv, i;
667 
668 	static const char *const openboot_special[] = {
669 		/* ignore these (end with NULL) */
670 		/*
671 		 * These are _root_ devices to ignore. Others must be handled
672 		 * elsewhere.
673 		 */
674 		"virtual-memory",
675 		"aliases",
676 		"memory",
677 		"openprom",
678 		"options",
679 		"packages",
680 		"chosen",
681 		NULL
682 	};
683 
684 	if (OF_getprop(findroot(), "banner-name", machine_banner,
685 	    sizeof machine_banner) < 0)
686 		i = 0;
687 	else {
688 		i = 1;
689 		if (((c = strchr(machine_banner, '(')) != NULL) &&
690 		    c != &machine_banner[0]) {
691 				while (*c == '(' || *c == ' ') {
692 					*c = '\0';
693 					c--;
694 				}
695 			}
696 	}
697 	OF_getprop(findroot(), "name", machine_model, sizeof machine_model);
698 	prom_getidprom();
699 	if (i)
700 		aprint_normal(": %s (%s): hostid %lx\n", machine_model,
701 		    machine_banner, hostid);
702 	else
703 		aprint_normal(": %s: hostid %lx\n", machine_model, hostid);
704 	aprint_naive("\n");
705 
706 	devhandle_t selfh = device_handle(dev);
707 
708 	/*
709 	 * Locate and configure the ``early'' devices.  These must be
710 	 * configured before we can do the rest.  For instance, the
711 	 * EEPROM contains the Ethernet address for the LANCE chip.
712 	 * If the device cannot be located or configured, panic.
713 	 */
714 	if (sparc_ncpus == 0)
715 		panic("None of the CPUs found");
716 
717 	/*
718 	 * Init static interrupt eventcounters
719 	 */
720 	for (i = 0; i < __arraycount(intr_evcnts); i++)
721 		evcnt_attach_static(&intr_evcnts[i]);
722 
723 	node = findroot();
724 
725 	/* first early device to be configured is the CPU */
726 	for (node = OF_child(node); node; node = OF_peer(node)) {
727 		if (OF_getprop(node, "device_type", sbuf, sizeof(sbuf)) <= 0)
728 			continue;
729 		if (strcmp(sbuf, "cpu") != 0)
730 			continue;
731 		memset(&ma, 0, sizeof(ma));
732 		ma.ma_bustag = &mainbus_space_tag;
733 		ma.ma_dmatag = &mainbus_dma_tag;
734 		ma.ma_node = node;
735 		ma.ma_name = "cpu";
736 		config_found(dev, &ma, mbprint,
737 		    CFARGS(.devhandle = devhandle_from_of(selfh, ma.ma_node)));
738 	}
739 
740 	node = findroot();	/* re-init root node */
741 
742 	/* Find the "options" node */
743 	node0 = OF_child(node);
744 
745 	/*
746 	 * Configure the devices, in PROM order.  Skip
747 	 * PROM entries that are not for devices, or which must be
748 	 * done before we get here.
749 	 */
750 	for (node = node0; node; node = OF_peer(node)) {
751 		int portid;
752 
753 		DPRINTF(ACDB_PROBE, ("Node: %x", node));
754 		if ((OF_getprop(node, "device_type", sbuf, sizeof(sbuf)) > 0) &&
755 		    strcmp(sbuf, "cpu") == 0)
756 			continue;
757 		OF_getprop(node, "name", sbuf, sizeof(sbuf));
758 		DPRINTF(ACDB_PROBE, (" name %s\n", sbuf));
759 		for (ssp = openboot_special; (sp = *ssp) != NULL; ssp++)
760 			if (strcmp(sbuf, sp) == 0)
761 				break;
762 		if (sp != NULL)
763 			continue; /* an "early" device already configured */
764 
765 		memset(&ma, 0, sizeof ma);
766 		ma.ma_bustag = &mainbus_space_tag;
767 		ma.ma_dmatag = &mainbus_dma_tag;
768 		ma.ma_name = sbuf;
769 		ma.ma_node = node;
770 		if (OF_getprop(node, "upa-portid", &portid, sizeof(portid)) !=
771 		    sizeof(portid) &&
772 		    OF_getprop(node, "portid", &portid, sizeof(portid)) !=
773 		    sizeof(portid))
774 			portid = -1;
775 		ma.ma_upaid = portid;
776 
777 		if (prom_getprop(node, "reg", sizeof(*ma.ma_reg),
778 				 &ma.ma_nreg, &ma.ma_reg) != 0)
779 			continue;
780 #ifdef DEBUG
781 		if (autoconf_debug & ACDB_PROBE) {
782 			if (ma.ma_nreg)
783 				printf(" reg %08lx.%08lx\n",
784 					(long)ma.ma_reg->ur_paddr,
785 					(long)ma.ma_reg->ur_len);
786 			else
787 				printf(" no reg\n");
788 		}
789 #endif
790 		rv = prom_getprop(node, "interrupts", sizeof(*ma.ma_interrupts),
791 			&ma.ma_ninterrupts, &ma.ma_interrupts);
792 		if (rv != 0 && rv != ENOENT) {
793 			free(ma.ma_reg, M_DEVBUF);
794 			continue;
795 		}
796 #ifdef DEBUG
797 		if (autoconf_debug & ACDB_PROBE) {
798 			if (ma.ma_interrupts)
799 				printf(" interrupts %08x\n", *ma.ma_interrupts);
800 			else
801 				printf(" no interrupts\n");
802 		}
803 #endif
804 		rv = prom_getprop(node, "address", sizeof(*ma.ma_address),
805 			&ma.ma_naddress, &ma.ma_address);
806 		if (rv != 0 && rv != ENOENT) {
807 			free(ma.ma_reg, M_DEVBUF);
808 			if (ma.ma_ninterrupts)
809 				free(ma.ma_interrupts, M_DEVBUF);
810 			continue;
811 		}
812 #ifdef DEBUG
813 		if (autoconf_debug & ACDB_PROBE) {
814 			if (ma.ma_naddress)
815 				printf(" address %08x\n", *ma.ma_address);
816 			else
817 				printf(" no address\n");
818 		}
819 #endif
820 		(void) config_found(dev, (void *)&ma, mbprint,
821 		    CFARGS(.devhandle = prom_node_to_devhandle(selfh,
822 							       ma.ma_node)));
823 		free(ma.ma_reg, M_DEVBUF);
824 		if (ma.ma_ninterrupts)
825 			free(ma.ma_interrupts, M_DEVBUF);
826 		if (ma.ma_naddress)
827 			free(ma.ma_address, M_DEVBUF);
828 	}
829 	/* Try to attach PROM console */
830 	memset(&ma, 0, sizeof ma);
831 	ma.ma_name = "pcons";
832 	(void) config_found(dev, (void *)&ma, mbprint, CFARGS_NONE);
833 }
834 
835 CFATTACH_DECL_NEW(mainbus, 0,
836     mainbus_match, mainbus_attach, NULL, NULL);
837 
838 
839 /*
840  * Try to figure out where the PROM stores the cursor row & column
841  * variables.  Returns nonzero on error.
842  */
843 int
844 romgetcursoraddr(int **rowp, int **colp)
845 {
846 	cell_t row = 0UL, col = 0UL;
847 
848 	OF_interpret("stdout @ is my-self addr line# addr column# ", 0, 2,
849 		&col, &row);
850 	/*
851 	 * We are running on a 64-bit machine, so these things point to
852 	 * 64-bit values.  To convert them to pointers to integers, add
853 	 * 4 to the address.
854 	 */
855 	*rowp = (int *)(intptr_t)(row+4);
856 	*colp = (int *)(intptr_t)(col+4);
857 	return (row == 0UL || col == 0UL);
858 }
859 
860 /*
861  * Match a device_t against the bootpath, by
862  * comparing its firmware package handle. If they match
863  * exactly, we found the boot device.
864  */
865 static void
866 dev_path_exact_match(device_t dev, int ofnode)
867 {
868 
869 	if (ofnode != ofbootpackage)
870 		return;
871 
872 	booted_device = dev;
873 	DPRINTF(ACDB_BOOTDEV, ("found bootdevice: %s\n", device_xname(dev)));
874 }
875 
876 /*
877  * Match a device_t against the bootpath, by
878  * comparing its firmware package handle and calculating
879  * the target/lun suffix and comparing that against
880  * the bootpath remainder.
881  */
882 static void
883 dev_path_drive_match(device_t dev, int ctrlnode, int target,
884     uint64_t wwn, int lun)
885 {
886 	int child = 0, ide_node = 0;
887 	char buf[OFPATHLEN];
888 
889 	DPRINTF(ACDB_BOOTDEV, ("dev_path_drive_match: %s, controller %x, "
890 	    "target %d wwn %016" PRIx64 " lun %d\n", device_xname(dev),
891 	    ctrlnode, target, wwn, lun));
892 
893 	/*
894 	 * The ofbootpackage points to a disk on this controller, so
895 	 * iterate over all child nodes and compare.
896 	 */
897 	for (child = prom_firstchild(ctrlnode); child != 0;
898 	    child = prom_nextsibling(child))
899 		if (child == ofbootpackage)
900 			break;
901 
902 	if (child != ofbootpackage) {
903 		/*
904 		 * Try Mac firmware style (also used by QEMU/OpenBIOS):
905 		 * below the controller there is an intermediate node
906 		 * for each IDE channel, and individual targets always
907 		 * are "@0"
908 		 */
909 		for (ide_node = prom_firstchild(ctrlnode); ide_node != 0;
910 		    ide_node = prom_nextsibling(ide_node)) {
911 			const char * name = prom_getpropstring(ide_node,
912 			    "device_type");
913 			if (strcmp(name, "ide") != 0) continue;
914 			for (child = prom_firstchild(ide_node); child != 0;
915 			    child = prom_nextsibling(child))
916 				if (child == ofbootpackage)
917 					break;
918 			if (child == ofbootpackage)
919 				break;
920 		}
921 	}
922 
923 	if (child == ofbootpackage) {
924 		const char * name = prom_getpropstring(child, "name");
925 
926 		/* boot device is on this controller */
927 		DPRINTF(ACDB_BOOTDEV, ("found controller of bootdevice\n"));
928 
929 		/*
930 		 * Note: "child" here is == ofbootpackage (s.a.), which
931 		 * may be completely wrong for the device we are checking,
932 		 * what we really do here is to match "target" and "lun".
933 		 */
934 		if (wwn)
935 			snprintf(buf, sizeof(buf), "%s@w%016" PRIx64 ",%d",
936 			    name, wwn, lun);
937 		else if (ide_node)
938 			snprintf(buf, sizeof(buf), "%s@0",
939 			    device_is_a(dev, "cd") ? "cdrom" : "disk");
940 		else
941 			snprintf(buf, sizeof(buf), "%s@%d,%d",
942 			    name, target, lun);
943 		if (ofboottarget && strcmp(buf, ofboottarget) == 0) {
944 			booted_device = dev;
945 			if (ofbootpartition)
946 				booted_partition = *ofbootpartition - 'a';
947 			DPRINTF(ACDB_BOOTDEV, ("found boot device: %s"
948 			    ", partition %d\n", device_xname(dev),
949 			    booted_partition));
950 		}
951 	}
952 }
953 
954  /*
955  * Recursively check for a child node.
956  */
957 static bool
958 has_child_node(int parent, int search)
959 {
960 	int child;
961 
962 	for (child = prom_firstchild(parent); child != 0;
963 	    child = prom_nextsibling(child)) {
964 		if (child == search)
965 			return true;
966 		if (has_child_node(child, search))
967 			return true;
968 	}
969 
970 	return false;
971 }
972 
973 /*
974  * The interposed pseudo-parent node in OpenBIOS has a
975  * device_type = "ide" and no "compatible" property.
976  * It is the secondary bus if the name is "ide1" or "ide"
977  * with newer OpenBIOS versions. In the latter case, read
978  * the first reg value to discriminate the two channels.
979  */
980 static bool
981 openbios_secondary_ata_heuristic(int parent)
982 {
983 	char tmp[OFPATHLEN];
984 	int regs[4];
985 
986 	if (OF_getprop(parent, "device_type", tmp, sizeof(tmp)) <= 0)
987 		return false;
988 	if (strcmp(tmp, "ide") != 0)
989 		return false;
990 	DPRINTF(ACDB_BOOTDEV, ("parent device_type is ide\n"));
991 
992 	if (OF_getprop(parent, "compatible", tmp, sizeof(tmp)) > 0)
993 		return false;
994 	DPRINTF(ACDB_BOOTDEV, ("parent has no compatible property\n"));
995 
996 	if (OF_getprop(parent, "name", tmp, sizeof(tmp)) <= 0)
997 		return false;
998 	if (strcmp(tmp, "ide1") == 0) {
999 		DPRINTF(ACDB_BOOTDEV, ("parent seems to be an (old) OpenBIOS"
1000 		   " secondary ATA bus, applying workaround target+2\n"));
1001 		return true;
1002 	} else if (strcmp(tmp, "ide") == 0) {
1003 		if (OF_getprop(parent, "reg", &regs, sizeof(regs))
1004 		    >= sizeof(regs[0])) {
1005 			DPRINTF(ACDB_BOOTDEV, ("parent seems to be an OpenBIOS"
1006 			   " ATA bus #%u\n", regs[0]));
1007 
1008 			return regs[0] == 1;
1009 		}
1010 
1011 	}
1012 
1013 	return false;
1014 }
1015 
1016 /*
1017  * Match a device_t against the controller/target/lun/wwn
1018  * info passed in from the bootloader (if available),
1019  * otherwise fall back to old style string matching
1020  * heuristics.
1021  */
1022 static void
1023 dev_bi_unit_drive_match(device_t dev, int ctrlnode, int target,
1024     uint64_t wwn, int lun)
1025 {
1026 	static struct btinfo_bootdev_unit *bi_unit = NULL;
1027 	uint32_t off = 0;
1028 	static bool passed = false;
1029 #ifdef DEBUG
1030 	char ctrl_path[OFPATHLEN], parent_path[OFPATHLEN], dev_path[OFPATHLEN];
1031 #endif
1032 
1033 	if (!passed) {
1034 		bi_unit = lookup_bootinfo(BTINFO_BOOTDEV_UNIT);
1035 		passed = true;
1036 	}
1037 
1038 	if (bi_unit == NULL) {
1039 		dev_path_drive_match(dev, ctrlnode, target, wwn, lun);
1040 		return;
1041 	}
1042 
1043 #ifdef DEBUG
1044 	DPRINTF(ACDB_BOOTDEV, ("dev_bi_unit_drive_match: %s, controller %x, "
1045 	    "target %d wwn %016" PRIx64 " lun %d\n", device_xname(dev),
1046 	    ctrlnode, target, wwn, lun));
1047 
1048 	OF_package_to_path(ctrlnode, ctrl_path, sizeof(ctrl_path));
1049 	OF_package_to_path(bi_unit->phandle, dev_path, sizeof(dev_path));
1050 	OF_package_to_path(bi_unit->parent, parent_path, sizeof(parent_path));
1051 	DPRINTF(ACDB_BOOTDEV, ("controller %x : %s\n", ctrlnode, ctrl_path));
1052 	DPRINTF(ACDB_BOOTDEV, ("phandle %x : %s\n", bi_unit->phandle, dev_path));
1053 	DPRINTF(ACDB_BOOTDEV, ("parent %x : %s\n", bi_unit->parent, parent_path));
1054 #endif
1055 	if (ctrlnode != bi_unit->parent
1056 	    && !has_child_node(ctrlnode, bi_unit->phandle)) {
1057 		DPRINTF(ACDB_BOOTDEV, ("controller %x : %s does not match "
1058 		    "bootinfo: %x : %s\n",
1059 		    ctrlnode, ctrl_path, bi_unit->parent, parent_path));
1060 		return;
1061 	}
1062 	if (ctrlnode == bi_unit->parent) {
1063 		DPRINTF(ACDB_BOOTDEV, ("controller %x : %s is bootinfo"
1064 		    " parent\n", ctrlnode, ctrl_path));
1065 	} else {
1066 		DPRINTF(ACDB_BOOTDEV, ("controller %x : %s is parent of"
1067 		    " %x : %s\n", ctrlnode, ctrl_path, bi_unit->parent,
1068 		    parent_path));
1069 
1070 		/*
1071 		 * Our kernel and "real" OpenFirmware use a 0 .. 3 numbering
1072 		 * scheme for IDE devices, but OpenBIOS splits it into
1073 		 * two "buses" and numbers each 0..1.
1074 		 * Check if we are on the secondary "bus" and adjust
1075 		 * if needed...
1076 		 */
1077 		if (openbios_secondary_ata_heuristic(bi_unit->parent))
1078 			off = 2;
1079 	}
1080 
1081 	if (bi_unit->wwn != wwn || (bi_unit->target+off) != target
1082 	    || bi_unit->lun != lun) {
1083 		DPRINTF(ACDB_BOOTDEV, ("mismatch: wwn %016" PRIx64 " - %016" PRIx64
1084 		    ", target %d - %d, lun %d - %d\n",
1085 		    bi_unit->wwn, wwn, bi_unit->target, target, bi_unit->lun, lun));
1086 		return;
1087 	}
1088 
1089 	booted_device = dev;
1090 	if (ofbootpartition)
1091 		booted_partition = *ofbootpartition - 'a';
1092 	DPRINTF(ACDB_BOOTDEV, ("found boot device: %s"
1093 	    ", partition %d\n", device_xname(dev),
1094 	    booted_partition));
1095 }
1096 
1097 /*
1098  * Called back during autoconfiguration for each device found
1099  */
1100 void
1101 device_register(device_t dev, void *aux)
1102 {
1103 	device_t busdev = device_parent(dev);
1104 	devhandle_t devhandle;
1105 	int ofnode = 0;
1106 
1107 	/*
1108 	 * If the device has a valid OpenFirmware node association,
1109 	 * grab it now.
1110 	 */
1111 	devhandle = device_handle(dev);
1112 	if (devhandle_type(devhandle) == DEVHANDLE_TYPE_OF) {
1113 		ofnode = devhandle_to_of(devhandle);
1114 	}
1115 
1116 	/*
1117 	 * We don't know the type of 'aux' - it depends on the
1118 	 * bus this device attaches to. We are only interested in
1119 	 * certain bus types, this only is used to find the boot
1120 	 * device.
1121 	 */
1122 	if (busdev == NULL) {
1123 		/*
1124 		 * Ignore mainbus0 itself, it certainly is not a boot
1125 		 * device.
1126 		 */
1127 	} else if (device_is_a(busdev, "iic")) {
1128 		struct i2c_attach_args *ia = aux;
1129 
1130 		if (ia->ia_name == NULL)	/* indirect config */
1131 			return;
1132 
1133 		ofnode = (int)ia->ia_cookie;
1134 		if (device_is_a(dev, "pcagpio")) {
1135 			if (!strcmp(machine_model, "SUNW,Sun-Fire-V240") ||
1136 			    !strcmp(machine_model, "SUNW,Sun-Fire-V210")) {
1137 				add_gpio_props_v210(dev, aux);
1138 			}
1139 		}
1140 		if (device_is_a(dev, "pcf8574io")) {
1141 			if (!strcmp(machine_model, "SUNW,Ultra-250")) {
1142 				add_gpio_props_e250(dev, aux);
1143 			}
1144 		}
1145 		return;
1146 	} else if (device_is_a(dev, "sd") || device_is_a(dev, "cd")) {
1147 		struct scsipibus_attach_args *sa = aux;
1148 		struct scsipi_periph *periph = sa->sa_periph;
1149 		int off = 0;
1150 
1151 		/*
1152 		 * There are two "cd" attachments:
1153 		 *   atapibus -> atabus -> controller
1154 		 *   scsibus -> controller
1155 		 * We want the node of the controller.
1156 		 */
1157 		if (device_is_a(busdev, "atapibus")) {
1158 			busdev = device_parent(busdev);
1159 			/*
1160 			 * if the atapibus is connected to the secondary
1161 			 * channel of the atabus, we need an offset of 2
1162 			 * to match OF's idea of the target number.
1163 			 * (i.e. on U5/U10 "cdrom" and "disk2" have the
1164 			 * same target encoding, though different names)
1165 			 */
1166 			if (periph->periph_channel->chan_channel == 1)
1167 				off = 2;
1168 		}
1169 
1170 		/*
1171 		 * busdev now points to the direct descendent of the
1172 		 * controller ("atabus" or "scsibus").  Get the
1173 		 * controller's devhandle.  Hoist it up one more so
1174 		 * that busdev points at the controller.
1175 		 */
1176 		busdev = device_parent(busdev);
1177 		devhandle = device_handle(busdev);
1178 		KASSERT(devhandle_type(devhandle) == DEVHANDLE_TYPE_OF);
1179 		ofnode = devhandle_to_of(devhandle);
1180 
1181 		/*
1182 		 * Special sun4v handling in case the kernel is running in a
1183 		 * secondary logical domain
1184 		 *
1185 		 * The bootpath looks something like this:
1186 		 *   /virtual-devices@100/channel-devices@200/disk@1:a (disk)
1187 		 *   /virtual-devices@100/channel-devices@200/disk@4:f (cdrom)
1188 		 *
1189 		 * The device hierarchy constructed during autoconfiguration
1190 		 * is:
1191 		 *   /mainbus/vbus/cbus/vdsk/scsibus/sd or
1192 		 *   /mainbus/vbus/cbus/vdsk/scsibus/cd
1193 		 */
1194 		if (CPU_ISSUN4V && device_is_a(busdev, "vdsk")) {
1195 			dev_path_exact_match(dev, ofnode);
1196 		} else {
1197 			dev_bi_unit_drive_match(dev, ofnode,
1198 			    periph->periph_target + off, 0, periph->periph_lun);
1199 		}
1200 
1201 		if (device_is_a(busdev, "scsibus")) {
1202 			/* see if we're in a known SCA drivebay */
1203 			add_drivebay_props(dev, ofnode, aux);
1204 		}
1205 		return;
1206 	} else if (device_is_a(dev, "wd")) {
1207 		struct ata_device *adev = aux;
1208 
1209 		/*
1210 		 * busdev points to the direct descendent of the controller,
1211 		 * e.g. "atabus".  Get the controller's devhandle.
1212 		 */
1213 		devhandle = device_handle(device_parent(busdev));
1214 		KASSERT(devhandle_type(devhandle) == DEVHANDLE_TYPE_OF);
1215 		ofnode = devhandle_to_of(devhandle);
1216 
1217 		dev_bi_unit_drive_match(dev, ofnode, adev->adev_channel*2+
1218 		    adev->adev_drv_data->drive, 0, 0);
1219 		return;
1220 	} else if (device_is_a(dev, "ld")) {
1221 		/*
1222 		 * Get the devhandle of the RAID (or whatever) controller.
1223 		 */
1224 		devhandle = device_handle(busdev);
1225 		ofnode = devhandle_to_of(devhandle);
1226 	}
1227 
1228 	if (busdev == NULL)
1229 		return;
1230 
1231 	if (ofnode != 0) {
1232 		uint8_t eaddr[ETHER_ADDR_LEN];
1233 		char tmpstr[32];
1234 		char tmpstr2[32];
1235 		int node;
1236 		uint32_t id = 0;
1237 		uint64_t nwwn = 0, pwwn = 0;
1238 		prop_dictionary_t dict;
1239 		prop_data_t blob;
1240 		prop_number_t pwwnd = NULL, nwwnd = NULL;
1241 		prop_number_t idd = NULL;
1242 
1243 		dev_path_exact_match(dev, ofnode);
1244 
1245 		if (OF_getprop(ofnode, "name", tmpstr, sizeof(tmpstr)) <= 0)
1246 			tmpstr[0] = 0;
1247 		if (OF_getprop(ofnode, "device_type", tmpstr2, sizeof(tmpstr2)) <= 0)
1248 			tmpstr2[0] = 0;
1249 
1250 		/*
1251 		 * If this is a network interface, note the
1252 		 * mac address.
1253 		 */
1254 		if (strcmp(tmpstr, "network") == 0
1255 		   || strcmp(tmpstr, "ethernet") == 0
1256 		   || strcmp(tmpstr2, "network") == 0
1257 		   || strcmp(tmpstr2, "ethernet") == 0
1258 		   || OF_getprop(ofnode, "mac-address", &eaddr, sizeof(eaddr))
1259 		      >= ETHER_ADDR_LEN
1260 		   || OF_getprop(ofnode, "local-mac-address", &eaddr, sizeof(eaddr))
1261 		      >= ETHER_ADDR_LEN) {
1262 
1263 			dict = device_properties(dev);
1264 
1265 			/*
1266 			 * Is it a network interface with FCode?
1267 			 */
1268 			if (strcmp(tmpstr, "network") == 0 ||
1269 			    strcmp(tmpstr2, "network") == 0) {
1270 				prop_dictionary_set_bool(dict,
1271 				    "without-seeprom", true);
1272 				prom_getether(ofnode, eaddr);
1273 			} else {
1274 				if (!prom_get_node_ether(ofnode, eaddr))
1275 					goto noether;
1276 			}
1277 			blob = prop_data_create_copy(eaddr, ETHER_ADDR_LEN);
1278 			prop_dictionary_set(dict, "mac-address", blob);
1279 			prop_object_release(blob);
1280 			of_to_dataprop(dict, ofnode, "shared-pins",
1281 			    "shared-pins");
1282 		}
1283 noether:
1284 
1285 		/* is this a FC node? */
1286 		if (strcmp(tmpstr, "scsi-fcp") == 0) {
1287 
1288 			dict = device_properties(dev);
1289 
1290 			if (OF_getprop(ofnode, "port-wwn", &pwwn, sizeof(pwwn))
1291 			    == sizeof(pwwn)) {
1292 				pwwnd =
1293 				    prop_number_create_unsigned(pwwn);
1294 				prop_dictionary_set(dict, "port-wwn", pwwnd);
1295 				prop_object_release(pwwnd);
1296 			}
1297 
1298 			if (OF_getprop(ofnode, "node-wwn", &nwwn, sizeof(nwwn))
1299 			    == sizeof(nwwn)) {
1300 				nwwnd =
1301 				    prop_number_create_unsigned(nwwn);
1302 				prop_dictionary_set(dict, "node-wwn", nwwnd);
1303 				prop_object_release(nwwnd);
1304 			}
1305 		}
1306 
1307 		/* is this an spi device?  look for scsi-initiator-id */
1308 		if (strcmp(tmpstr2, "scsi") == 0 ||
1309 		    strcmp(tmpstr2, "scsi-2") == 0) {
1310 
1311 			dict = device_properties(dev);
1312 
1313 			for (node = ofnode; node != 0; node = OF_parent(node)) {
1314 				if (OF_getprop(node, "scsi-initiator-id", &id,
1315 				    sizeof(id)) <= 0)
1316 					continue;
1317 
1318 				idd = prop_number_create_unsigned(id);
1319 				prop_dictionary_set(dict,
1320 						    "scsi-initiator-id", idd);
1321 				prop_object_release(idd);
1322 				break;
1323 			}
1324 		}
1325 	}
1326 
1327 	/*
1328 	 * Check for I2C busses and add data for their direct configuration.
1329 	 */
1330 	if (device_is_a(dev, "iic")) {
1331 		devhandle_t bushandle = device_handle(busdev);
1332 		int busnode =
1333 		    devhandle_type(bushandle) == DEVHANDLE_TYPE_OF ?
1334 		    devhandle_to_of(bushandle) : 0;
1335 
1336 		if (busnode) {
1337 			prop_dictionary_t props = device_properties(busdev);
1338 			prop_object_t cfg = prop_dictionary_get(props,
1339 				"i2c-child-devices");
1340 			if (!cfg) {
1341 				int node;
1342 				const char *name;
1343 
1344 				/*
1345 				 * pmu's i2c devices are under the "i2c" node,
1346 				 * so find it out.
1347 				 */
1348 				name = prom_getpropstring(busnode, "name");
1349 				if (strcmp(name, "pmu") == 0) {
1350 					for (node = OF_child(busnode);
1351 					     node != 0; node = OF_peer(node)) {
1352 						name = prom_getpropstring(node,
1353 						    "name");
1354 						if (strcmp(name, "i2c") == 0) {
1355 							busnode = node;
1356 							break;
1357 						}
1358 					}
1359 				}
1360 
1361 				of_enter_i2c_devs(props, busnode,
1362 				    sizeof(cell_t), 1);
1363 			}
1364 		}
1365 
1366 		if (!strcmp(machine_model, "TAD,SPARCLE"))
1367 			add_spdmem_props_sparcle(busdev);
1368 
1369 		if (device_is_a(busdev, "pcfiic") &&
1370 		    (!strcmp(machine_model, "SUNW,Sun-Fire-V240") ||
1371 		    !strcmp(machine_model, "SUNW,Sun-Fire-V210")))
1372 			add_env_sensors_v210(busdev);
1373 
1374 		/* E450 SUNW,envctrl */
1375 		if (device_is_a(busdev, "pcfiic") &&
1376 		    (!strcmp(machine_model, "SUNW,Ultra-4")))
1377 			add_i2c_props_e450(busdev, busnode);
1378 
1379 		/* E250 SUNW,envctrltwo */
1380 		if (device_is_a(busdev, "pcfiic") &&
1381 		    (!strcmp(machine_model, "SUNW,Ultra-250")))
1382 			add_i2c_props_e250(busdev, busnode);
1383 	}
1384 
1385 	/* set properties for PCI framebuffers */
1386 	if (device_is_a(busdev, "pci")) {
1387 		/* see if this is going to be console */
1388 		struct pci_attach_args *pa = aux;
1389 		prop_dictionary_t dict;
1390 		int sub;
1391 		int console = 0;
1392 
1393 		dict = device_properties(dev);
1394 
1395 		/* we only care about display devices from here on */
1396 		if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY)
1397 			return;
1398 
1399 		console = (ofnode == console_node);
1400 
1401 		if (!console) {
1402 			/*
1403 			 * see if any child matches since OF attaches
1404 			 * nodes for each head and /chosen/stdout
1405 			 * points to the head rather than the device
1406 			 * itself in this case
1407 			 */
1408 			sub = OF_child(ofnode);
1409 			while ((sub != 0) && (sub != console_node)) {
1410 				sub = OF_peer(sub);
1411 			}
1412 			if (sub == console_node) {
1413 				console = true;
1414 			}
1415 		}
1416 
1417 		copyprops(busdev, ofnode, dict, console);
1418 
1419 		if (console) {
1420 			uint64_t cmap_cb;
1421 			prop_dictionary_set_uint32(dict,
1422 			    "instance_handle", console_instance);
1423 
1424 			gfb_cb.gcc_cookie =
1425 			    (void *)(intptr_t)console_instance;
1426 			gfb_cb.gcc_set_mapreg = of_set_palette;
1427 			cmap_cb = (uint64_t)(uintptr_t)&gfb_cb;
1428 			prop_dictionary_set_uint64(dict,
1429 			    "cmap_callback", cmap_cb);
1430 		}
1431 #ifdef notyet
1432 		else {
1433 			int width;
1434 
1435 			/*
1436 			 * the idea is to 'open' display devices with no useful
1437 			 * properties, in the hope that the firmware will
1438 			 * properly initialize them and we can run things like
1439 			 * genfb on them
1440 			 */
1441 			if (OF_getprop(node, "width", &width, sizeof(width))
1442 			    != 4) {
1443 				instance = OF_open(name);
1444 			}
1445 		}
1446 #endif
1447 		set_static_edid(dict);
1448 	}
1449 
1450 	set_hw_props(dev);
1451 }
1452 
1453 /*
1454  * Called back after autoconfiguration of a device is done
1455  */
1456 void
1457 device_register_post_config(device_t dev, void *aux)
1458 {
1459 	if (booted_device == NULL && device_is_a(dev, "sd")) {
1460 		struct scsipibus_attach_args *sa = aux;
1461 		struct scsipi_periph *periph = sa->sa_periph;
1462 		uint64_t wwn = 0;
1463 
1464 		/*
1465 		 * If this is a FC-AL drive it will have
1466 		 * acquired its WWN device property by now,
1467 		 * so we can properly match it.
1468 		 */
1469 		if (prop_dictionary_get_uint64(device_properties(dev),
1470 		    "port-wwn", &wwn)) {
1471 			/*
1472 			 * Different to what we do in device_register,
1473 			 * we do not pass the "controller" ofnode,
1474 			 * because FC-AL devices attach below a "fp" node,
1475 			 * E.g.: /pci/SUNW,qlc@4/fp@0,0/disk
1476 			 * and we need the parent of "disk" here.
1477 			 */
1478 			devhandle_t ctlr_devhandle = device_handle(
1479 			    device_parent(device_parent(dev)));
1480 			KASSERT(devhandle_type(ctlr_devhandle) ==
1481 			    DEVHANDLE_TYPE_OF);
1482 			int ofnode = devhandle_to_of(ctlr_devhandle);
1483 
1484 			for (ofnode = OF_child(ofnode);
1485 			     ofnode != 0 && booted_device == NULL;
1486 			     ofnode = OF_peer(ofnode)) {
1487 				dev_bi_unit_drive_match(dev, ofnode,
1488 				    periph->periph_target,
1489 				    wwn, periph->periph_lun);
1490 			}
1491 		}
1492 	}
1493 }
1494 
1495 static void
1496 copyprops(device_t busdev, int node, prop_dictionary_t dict, int is_console)
1497 {
1498 	device_t cntrlr;
1499 	prop_dictionary_t psycho;
1500 	paddr_t fbpa, mem_base = 0;
1501 	uint32_t temp, fboffset;
1502 	uint32_t fbaddr = 0;
1503 	int options;
1504 	char output_device[OFPATHLEN];
1505 	char *pos;
1506 
1507 	cntrlr = device_parent(busdev);
1508 	if (cntrlr != NULL) {
1509 		psycho = device_properties(cntrlr);
1510 		prop_dictionary_get_uint64(psycho, "mem_base", &mem_base);
1511 	}
1512 
1513 	if (is_console)
1514 		prop_dictionary_set_bool(dict, "is_console", 1);
1515 
1516 	of_to_uint32_prop(dict, node, "width", "width");
1517 	of_to_uint32_prop(dict, node, "height", "height");
1518 	of_to_uint32_prop(dict, node, "linebytes", "linebytes");
1519 	if (!of_to_uint32_prop(dict, node, "depth", "depth") &&
1520 	    /* Some cards have an extra space in the property name */
1521 	    !of_to_uint32_prop(dict, node, "depth ", "depth")) {
1522 		/*
1523 		 * XXX we should check linebytes vs. width but those
1524 		 * FBs that don't have a depth property ( /chaos/control... )
1525 		 * won't have linebytes either
1526 		 */
1527 		prop_dictionary_set_uint32(dict, "depth", 8);
1528 	}
1529 
1530 	OF_getprop(node, "address", &fbaddr, sizeof(fbaddr));
1531 	if (fbaddr != 0) {
1532 
1533 		pmap_extract(pmap_kernel(), fbaddr, &fbpa);
1534 #ifdef DEBUG
1535 		printf("membase: %lx fbpa: %lx\n", (unsigned long)mem_base,
1536 		    (unsigned long)fbpa);
1537 #endif
1538 		if (mem_base == 0) {
1539 			/* XXX this is guesswork */
1540 			fboffset = (uint32_t)(fbpa & 0xffffffff);
1541 		}
1542 			fboffset = (uint32_t)(fbpa - mem_base);
1543 		prop_dictionary_set_uint32(dict, "address", fboffset);
1544 	}
1545 
1546 	if (!of_to_dataprop(dict, node, "EDID", "EDID"))
1547 		of_to_dataprop(dict, node, "edid", "EDID");
1548 
1549 	temp = 0;
1550 	if (OF_getprop(node, "ATY,RefCLK", &temp, sizeof(temp)) != 4) {
1551 
1552 		OF_getprop(OF_parent(node), "ATY,RefCLK", &temp,
1553 		    sizeof(temp));
1554 	}
1555 	if (temp != 0)
1556 		prop_dictionary_set_uint32(dict, "refclk", temp / 10);
1557 
1558 	/*
1559 	 * finally, let's see if there's a video mode specified in
1560 	 * output-device and pass it on so drivers like radeonfb
1561 	 * can do their thing
1562 	 */
1563 
1564 	if (!is_console)
1565 		return;
1566 
1567 	options = OF_finddevice("/options");
1568 	if ((options == 0) || (options == -1))
1569 		return;
1570 	if (OF_getprop(options, "output-device", output_device, OFPATHLEN) == 0)
1571 		return;
1572 	/* find the mode string if there is one */
1573 	pos = strstr(output_device, ":r");
1574 	if (pos == NULL)
1575 		return;
1576 	prop_dictionary_set_string(dict, "videomode", pos + 2);
1577 }
1578 
1579 static void
1580 of_set_palette(void *cookie, int index, int r, int g, int b)
1581 {
1582 	int ih = (int)((intptr_t)cookie);
1583 
1584 	OF_call_method_1("color!", ih, 4, r, g, b, index);
1585 }
1586