1/*	$NetBSD$ */
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$");
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/malloc.h>
69#include <sys/vnode.h>
70#include <sys/fcntl.h>
71#include <sys/queue.h>
72#include <sys/msgbuf.h>
73#include <sys/boot_flag.h>
74#include <sys/ksyms.h>
75#include <sys/kauth.h>
76#include <sys/userconf.h>
77#include <prop/proplib.h>
78
79#include <net/if.h>
80#include <net/if_ether.h>
81
82#include <dev/cons.h>
83#include <sparc64/dev/cons.h>
84
85#include <uvm/uvm_extern.h>
86
87#include <sys/bus.h>
88#include <machine/autoconf.h>
89#include <machine/openfirm.h>
90#include <machine/sparc64.h>
91#include <machine/cpu.h>
92#include <machine/pmap.h>
93#include <machine/bootinfo.h>
94#include <sparc64/sparc64/cache.h>
95#include <sparc64/sparc64/timerreg.h>
96
97#include <dev/ata/atavar.h>
98#include <dev/pci/pcivar.h>
99#include <dev/ebus/ebusvar.h>
100#include <dev/sbus/sbusvar.h>
101#include <dev/i2c/i2cvar.h>
102
103#ifdef DDB
104#include <machine/db_machdep.h>
105#include <ddb/db_sym.h>
106#include <ddb/db_extern.h>
107#endif
108
109#ifdef RASTERCONSOLE
110#error options RASTERCONSOLE is obsolete for sparc64 - remove it from your config file
111#endif
112
113#include <dev/wsfb/genfbvar.h>
114
115#include "ksyms.h"
116
117struct evcnt intr_evcnts[] = {
118	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "spur"),
119	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev1"),
120	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev2"),
121	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev3"),
122	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev4"),
123	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev5"),
124	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev6"),
125	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev7"),
126	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev8"),
127	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev9"),
128	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "clock"),
129	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev11"),
130	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev12"),
131	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "lev13"),
132	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr", "prof"),
133	EVCNT_INITIALIZER(EVCNT_TYPE_INTR, NULL, "intr",  "lev15")
134};
135
136void *bootinfo = 0;
137
138#ifdef KGDB
139int kgdb_break_at_attach;
140#endif
141
142/* Default to sun4u */
143int cputyp = CPU_SUN4U;
144
145#define	OFPATHLEN	128
146#define	OFNODEKEY	"OFpnode"
147
148char	machine_banner[100];
149char	machine_model[100];
150char	ofbootpath[OFPATHLEN], *ofboottarget, *ofbootpartition;
151int	ofbootpackage;
152
153static	int mbprint(void *, const char *);
154int	mainbus_match(device_t, cfdata_t, void *);
155static	void mainbus_attach(device_t, device_t, void *);
156static  void get_ncpus(void);
157static	void get_bootpath_from_prom(void);
158
159/*
160 * Kernel 4MB mappings.
161 */
162struct tlb_entry *kernel_tlbs;
163int kernel_tlb_slots;
164
165/* Global interrupt mappings for all device types.  Match against the OBP
166 * 'device_type' property.
167 */
168struct intrmap intrmap[] = {
169	{ "block",	PIL_FD },	/* Floppy disk */
170	{ "serial",	PIL_SER },	/* zs */
171	{ "scsi",	PIL_SCSI },
172	{ "scsi-2",	PIL_SCSI },
173	{ "network",	PIL_NET },
174	{ "display",	PIL_VIDEO },
175	{ "audio",	PIL_AUD },
176	{ "ide",	PIL_SCSI },
177/* The following devices don't have device types: */
178	{ "SUNW,CS4231",	PIL_AUD },
179	{ NULL,		0 }
180};
181
182#ifdef DEBUG
183#define ACDB_BOOTDEV	0x1
184#define	ACDB_PROBE	0x2
185#define ACDB_BOOTARGS	0x4
186int autoconf_debug = 0x0;
187#define DPRINTF(l, s)   do { if (autoconf_debug & l) printf s; } while (0)
188#else
189#define DPRINTF(l, s)
190#endif
191
192int console_node, console_instance;
193struct genfb_colormap_callback gfb_cb;
194static void of_set_palette(void *, int, int, int, int);
195static void copyprops(device_t, int, prop_dictionary_t, int);
196
197static void
198get_ncpus(void)
199{
200#ifdef MULTIPROCESSOR
201	int node, l;
202	char sbuf[32];
203
204	node = findroot();
205
206	sparc_ncpus = 0;
207	for (node = OF_child(node); node; node = OF_peer(node)) {
208		if (OF_getprop(node, "device_type", sbuf, sizeof(sbuf)) <= 0)
209			continue;
210		if (strcmp(sbuf, "cpu") != 0)
211			continue;
212		sparc_ncpus++;
213		l = prom_getpropint(node, "dcache-line-size", 0);
214		if (l > dcache_line_size)
215			dcache_line_size = l;
216		l = prom_getpropint(node, "icache-line-size", 0);
217		if (l > icache_line_size)
218			icache_line_size = l;
219	}
220#else
221	/* #define sparc_ncpus 1 */
222	icache_line_size = dcache_line_size = 8; /* will be fixed later */
223#endif
224}
225
226/*
227 * lookup_bootinfo:
228 * Look up information in bootinfo of boot loader.
229 */
230void *
231lookup_bootinfo(int type)
232{
233	struct btinfo_common *bt;
234	char *help = bootinfo;
235
236	/* Check for a bootinfo record first. */
237	if (help == NULL)
238		return (NULL);
239
240	do {
241		bt = (struct btinfo_common *)help;
242		if (bt->type == type)
243			return ((void *)help);
244		help += bt->next;
245	} while (bt->next != 0 &&
246		(size_t)help < (size_t)bootinfo + BOOTINFO_SIZE);
247
248	return (NULL);
249}
250
251/*
252 * locore.s code calls bootstrap() just before calling main().
253 *
254 * What we try to do is as follows:
255 * - Initialize PROM and the console
256 * - Read in part of information provided by a bootloader and find out
257 *   kernel load and end addresses
258 * - Initialize ksyms
259 * - Find out number of active CPUs
260 * - Finalize the bootstrap by calling pmap_bootstrap()
261 *
262 * We will try to run out of the prom until we get out of pmap_bootstrap().
263 */
264void
265bootstrap(void *o0, void *bootargs, void *bootsize, void *o3, void *ofw)
266{
267	void *bi;
268	long bmagic;
269	char buf[32];
270
271#if NKSYMS || defined(DDB) || defined(MODULAR)
272	struct btinfo_symtab *bi_sym;
273#endif
274	struct btinfo_count *bi_count;
275	struct btinfo_kernend *bi_kend;
276	struct btinfo_tlb *bi_tlb;
277	struct btinfo_boothowto *bi_howto;
278
279	extern void *romtba;
280	extern void* get_romtba(void);
281	extern void  OF_val2sym32(void *);
282	extern void OF_sym2val32(void *);
283
284	/* Save OpenFrimware entry point */
285	romp   = ofw;
286	romtba = get_romtba();
287
288	prom_init();
289	console_instance = promops.po_stdout;
290	console_node = OF_instance_to_package(promops.po_stdout);
291
292	/* Initialize the PROM console so printf will not panic */
293	(*cn_tab->cn_init)(cn_tab);
294
295	DPRINTF(ACDB_BOOTARGS,
296		("sparc64_init(%p, %p, %p, %p, %p)\n", o0, bootargs, bootsize,
297			o3, ofw));
298
299	/* Extract bootinfo pointer */
300	if ((long)bootsize >= (4 * sizeof(uint64_t))) {
301		/* Loaded by 64-bit bootloader */
302		bi = (void*)(u_long)(((uint64_t*)bootargs)[3]);
303		bmagic = (long)(((uint64_t*)bootargs)[0]);
304	} else if ((long)bootsize >= (4 * sizeof(uint32_t))) {
305		/* Loaded by 32-bit bootloader */
306		bi = (void*)(u_long)(((uint32_t*)bootargs)[3]);
307		bmagic = (long)(((uint32_t*)bootargs)[0]);
308	} else {
309		printf("Bad bootinfo size.\n");
310die_old_boot_loader:
311		printf("This kernel requires NetBSD boot loader version 1.9 "
312		       "or newer\n");
313		panic("sparc64_init.");
314	}
315
316	DPRINTF(ACDB_BOOTARGS,
317		("sparc64_init: bmagic=%lx, bi=%p\n", bmagic, bi));
318
319	/* Read in the information provided by NetBSD boot loader */
320	if (SPARC_MACHINE_OPENFIRMWARE != bmagic) {
321		printf("No bootinfo information.\n");
322		goto die_old_boot_loader;
323	}
324
325	bootinfo = (void*)(u_long)((uint64_t*)bi)[1];
326	LOOKUP_BOOTINFO(bi_kend, BTINFO_KERNEND);
327
328	if (bi_kend->addr == (vaddr_t)0) {
329		panic("Kernel end address is not found in bootinfo.\n");
330	}
331
332#if NKSYMS || defined(DDB) || defined(MODULAR)
333	LOOKUP_BOOTINFO(bi_sym, BTINFO_SYMTAB);
334	ksyms_addsyms_elf(bi_sym->nsym, (int *)(u_long)bi_sym->ssym,
335			(int *)(u_long)bi_sym->esym);
336#ifdef DDB
337#ifdef __arch64__
338	/* This can only be installed on an 64-bit system cause otherwise our stack is screwed */
339	OF_set_symbol_lookup(OF_sym2val, OF_val2sym);
340#else
341	OF_set_symbol_lookup(OF_sym2val32, OF_val2sym32);
342#endif
343#endif
344#endif
345
346	if (OF_getprop(findroot(), "compatible", buf, sizeof(buf)) > 0) {
347		if (strcmp(buf, "sun4us") == 0)
348			cputyp = CPU_SUN4US;
349		else if (strcmp(buf, "sun4v") == 0)
350			cputyp = CPU_SUN4V;
351	}
352
353	bi_howto = lookup_bootinfo(BTINFO_BOOTHOWTO);
354	if (bi_howto)
355		boothowto = bi_howto->boothowto;
356
357	LOOKUP_BOOTINFO(bi_count, BTINFO_DTLB_SLOTS);
358	kernel_tlb_slots = bi_count->count;
359	LOOKUP_BOOTINFO(bi_tlb, BTINFO_DTLB);
360	kernel_tlbs = &bi_tlb->tlb[0];
361
362	get_ncpus();
363	pmap_bootstrap(KERNBASE, bi_kend->addr);
364}
365
366/*
367 * get_bootpath_from_prom()
368 * fetch the OF settings to identify our boot device during autoconfiguration
369 */
370
371static void
372get_bootpath_from_prom(void)
373{
374	struct btinfo_bootdev *bdev = NULL;
375	char sbuf[OFPATHLEN], *cp;
376	int chosen;
377
378	/*
379	 * Grab boot path from PROM
380	 */
381	if ((chosen = OF_finddevice("/chosen")) == -1)
382		return;
383
384	bdev = lookup_bootinfo(BTINFO_BOOTDEV);
385	if (bdev != NULL) {
386		strcpy(ofbootpath, bdev->name);
387	} else {
388		if (OF_getprop(chosen, "bootpath", sbuf, sizeof(sbuf)) < 0)
389			return;
390		strcpy(ofbootpath, sbuf);
391	}
392	DPRINTF(ACDB_BOOTDEV, ("bootpath: %s\n", ofbootpath));
393	ofbootpackage = prom_finddevice(ofbootpath);
394
395	/*
396	 * Strip partition or boot protocol
397	 */
398	cp = strrchr(ofbootpath, ':');
399	if (cp) {
400		*cp = '\0';
401		ofbootpartition = cp+1;
402	}
403	cp = strrchr(ofbootpath, '@');
404	if (cp) {
405		for (; cp != ofbootpath; cp--) {
406			if (*cp == '/') {
407				ofboottarget = cp+1;
408				break;
409			}
410		}
411	}
412
413	DPRINTF(ACDB_BOOTDEV, ("bootpath phandle: 0x%x\n", ofbootpackage));
414	DPRINTF(ACDB_BOOTDEV, ("boot target: %s\n",
415	    ofboottarget ? ofboottarget : "<none>"));
416	DPRINTF(ACDB_BOOTDEV, ("boot partition: %s\n",
417	    ofbootpartition ? ofbootpartition : "<none>"));
418
419	/* Setup pointer to boot flags */
420	if (OF_getprop(chosen, "bootargs", sbuf, sizeof(sbuf)) == -1)
421		return;
422
423	cp = sbuf;
424
425	/* Find start of boot flags */
426	while (*cp) {
427		while(*cp == ' ' || *cp == '\t') cp++;
428		if (*cp == '-' || *cp == '\0')
429			break;
430		while(*cp != ' ' && *cp != '\t' && *cp != '\0') cp++;
431
432	}
433	if (*cp != '-')
434		return;
435
436	for (;*++cp;) {
437		int fl;
438
439		fl = 0;
440		BOOT_FLAG(*cp, fl);
441		if (!fl) {
442			printf("unknown option `%c'\n", *cp);
443			continue;
444		}
445		boothowto |= fl;
446
447		/* specialties */
448		if (*cp == 'd') {
449#if defined(KGDB)
450			kgdb_break_at_attach = 1;
451#elif defined(DDB)
452			Debugger();
453#else
454			printf("kernel has no debugger\n");
455#endif
456		} else if (*cp == 't') {
457			/* turn on traptrace w/o breaking into kdb */
458			extern int trap_trace_dis;
459
460			trap_trace_dis = 0;
461		}
462	}
463}
464
465/*
466 * Determine mass storage and memory configuration for a machine.
467 * We get the PROM's root device and make sure we understand it, then
468 * attach it as `mainbus0'.  We also set up to handle the PROM `sync'
469 * command.
470 */
471void
472cpu_configure(void)
473{
474	bool userconf = (boothowto & RB_USERCONF) != 0;
475
476	/* fetch boot device settings */
477	get_bootpath_from_prom();
478	if (((boothowto & RB_USERCONF) != 0) && !userconf)
479		/*
480		 * Old bootloaders do not pass boothowto, and MI code
481		 * has already handled userconfig before we get here
482		 * and finally fetch the right options. So if we missed
483		 * it, just do it here.
484 		 */
485		userconf_prompt();
486
487	/* block clock interrupts and anything below */
488	splclock();
489	/* Enable device interrupts */
490        setpstate(getpstate()|PSTATE_IE);
491
492	if (config_rootfound("mainbus", NULL) == NULL)
493		panic("mainbus not configured");
494
495	/* Enable device interrupts */
496        setpstate(getpstate()|PSTATE_IE);
497
498	(void)spl0();
499}
500
501void
502cpu_rootconf(void)
503{
504	if (booted_device == NULL) {
505		printf("FATAL: boot device not found, check your firmware "
506		    "settings!\n");
507	}
508
509	rootconf();
510}
511
512char *
513clockfreq(long freq)
514{
515	char *p;
516	static char sbuf[10];
517
518	freq /= 1000;
519	sprintf(sbuf, "%ld", freq / 1000);
520	freq %= 1000;
521	if (freq) {
522		freq += 1000;	/* now in 1000..1999 */
523		p = sbuf + strlen(sbuf);
524		sprintf(p, "%ld", freq);
525		*p = '.';	/* now sbuf = %d.%3d */
526	}
527	return (sbuf);
528}
529
530/* ARGSUSED */
531static int
532mbprint(void *aux, const char *name)
533{
534	struct mainbus_attach_args *ma = aux;
535
536	if (name)
537		aprint_normal("%s at %s", ma->ma_name, name);
538	if (ma->ma_address)
539		aprint_normal(" addr 0x%08lx", (u_long)ma->ma_address[0]);
540	if (ma->ma_pri)
541		aprint_normal(" ipl %d", ma->ma_pri);
542	return (UNCONF);
543}
544
545int
546mainbus_match(device_t parent, cfdata_t cf, void *aux)
547{
548
549	return (1);
550}
551
552/*
553 * Attach the mainbus.
554 *
555 * Our main job is to attach the CPU (the root node we got in configure())
556 * and iterate down the list of `mainbus devices' (children of that node).
557 * We also record the `node id' of the default frame buffer, if any.
558 */
559static void
560mainbus_attach(device_t parent, device_t dev, void *aux)
561{
562extern struct sparc_bus_dma_tag mainbus_dma_tag;
563extern struct sparc_bus_space_tag mainbus_space_tag;
564
565	struct mainbus_attach_args ma;
566	char sbuf[32];
567	const char *const *ssp, *sp = NULL;
568	char *c;
569	int node0, node, rv, i;
570
571	static const char *const openboot_special[] = {
572		/* ignore these (end with NULL) */
573		/*
574		 * These are _root_ devices to ignore. Others must be handled
575		 * elsewhere.
576		 */
577		"virtual-memory",
578		"aliases",
579		"memory",
580		"openprom",
581		"options",
582		"packages",
583		"chosen",
584		NULL
585	};
586
587	if (OF_getprop(findroot(), "banner-name", machine_banner,
588	    sizeof machine_banner) < 0)
589		i = 0;
590	else {
591		i = 1;
592		if (((c = strchr(machine_banner, '(')) != NULL) &&
593		    c != &machine_banner[0]) {
594				while (*c == '(' || *c == ' ') {
595					*c = '\0';
596					c--;
597				}
598			}
599	}
600	OF_getprop(findroot(), "name", machine_model, sizeof machine_model);
601	prom_getidprom();
602	if (i)
603		aprint_normal(": %s (%s): hostid %lx\n", machine_model,
604		    machine_banner, hostid);
605	else
606		aprint_normal(": %s: hostid %lx\n", machine_model, hostid);
607	aprint_naive("\n");
608
609	/*
610	 * Locate and configure the ``early'' devices.  These must be
611	 * configured before we can do the rest.  For instance, the
612	 * EEPROM contains the Ethernet address for the LANCE chip.
613	 * If the device cannot be located or configured, panic.
614	 */
615	if (sparc_ncpus == 0)
616		panic("None of the CPUs found");
617
618	/*
619	 * Init static interrupt eventcounters
620	 */
621	for (i = 0; i < __arraycount(intr_evcnts); i++)
622		evcnt_attach_static(&intr_evcnts[i]);
623
624	node = findroot();
625
626	/* first early device to be configured is the CPU */
627	for (node = OF_child(node); node; node = OF_peer(node)) {
628		if (OF_getprop(node, "device_type", sbuf, sizeof(sbuf)) <= 0)
629			continue;
630		if (strcmp(sbuf, "cpu") != 0)
631			continue;
632		memset(&ma, 0, sizeof(ma));
633		ma.ma_bustag = &mainbus_space_tag;
634		ma.ma_dmatag = &mainbus_dma_tag;
635		ma.ma_node = node;
636		ma.ma_name = "cpu";
637		config_found(dev, &ma, mbprint);
638	}
639
640	node = findroot();	/* re-init root node */
641
642	/* Find the "options" node */
643	node0 = OF_child(node);
644
645	/*
646	 * Configure the devices, in PROM order.  Skip
647	 * PROM entries that are not for devices, or which must be
648	 * done before we get here.
649	 */
650	for (node = node0; node; node = OF_peer(node)) {
651		int portid;
652
653		DPRINTF(ACDB_PROBE, ("Node: %x", node));
654		if ((OF_getprop(node, "device_type", sbuf, sizeof(sbuf)) > 0) &&
655		    strcmp(sbuf, "cpu") == 0)
656			continue;
657		OF_getprop(node, "name", sbuf, sizeof(sbuf));
658		DPRINTF(ACDB_PROBE, (" name %s\n", sbuf));
659		for (ssp = openboot_special; (sp = *ssp) != NULL; ssp++)
660			if (strcmp(sbuf, sp) == 0)
661				break;
662		if (sp != NULL)
663			continue; /* an "early" device already configured */
664
665		memset(&ma, 0, sizeof ma);
666		ma.ma_bustag = &mainbus_space_tag;
667		ma.ma_dmatag = &mainbus_dma_tag;
668		ma.ma_name = sbuf;
669		ma.ma_node = node;
670		if (OF_getprop(node, "upa-portid", &portid, sizeof(portid)) !=
671		    sizeof(portid) &&
672		    OF_getprop(node, "portid", &portid, sizeof(portid)) !=
673		    sizeof(portid))
674			portid = -1;
675		ma.ma_upaid = portid;
676
677		if (prom_getprop(node, "reg", sizeof(*ma.ma_reg),
678				 &ma.ma_nreg, &ma.ma_reg) != 0)
679			continue;
680#ifdef DEBUG
681		if (autoconf_debug & ACDB_PROBE) {
682			if (ma.ma_nreg)
683				printf(" reg %08lx.%08lx\n",
684					(long)ma.ma_reg->ur_paddr,
685					(long)ma.ma_reg->ur_len);
686			else
687				printf(" no reg\n");
688		}
689#endif
690		rv = prom_getprop(node, "interrupts", sizeof(*ma.ma_interrupts),
691			&ma.ma_ninterrupts, &ma.ma_interrupts);
692		if (rv != 0 && rv != ENOENT) {
693			free(ma.ma_reg, M_DEVBUF);
694			continue;
695		}
696#ifdef DEBUG
697		if (autoconf_debug & ACDB_PROBE) {
698			if (ma.ma_interrupts)
699				printf(" interrupts %08x\n", *ma.ma_interrupts);
700			else
701				printf(" no interrupts\n");
702		}
703#endif
704		rv = prom_getprop(node, "address", sizeof(*ma.ma_address),
705			&ma.ma_naddress, &ma.ma_address);
706		if (rv != 0 && rv != ENOENT) {
707			free(ma.ma_reg, M_DEVBUF);
708			if (ma.ma_ninterrupts)
709				free(ma.ma_interrupts, M_DEVBUF);
710			continue;
711		}
712#ifdef DEBUG
713		if (autoconf_debug & ACDB_PROBE) {
714			if (ma.ma_naddress)
715				printf(" address %08x\n", *ma.ma_address);
716			else
717				printf(" no address\n");
718		}
719#endif
720		(void) config_found(dev, (void *)&ma, mbprint);
721		free(ma.ma_reg, M_DEVBUF);
722		if (ma.ma_ninterrupts)
723			free(ma.ma_interrupts, M_DEVBUF);
724		if (ma.ma_naddress)
725			free(ma.ma_address, M_DEVBUF);
726	}
727	/* Try to attach PROM console */
728	memset(&ma, 0, sizeof ma);
729	ma.ma_name = "pcons";
730	(void) config_found(dev, (void *)&ma, mbprint);
731}
732
733CFATTACH_DECL_NEW(mainbus, 0,
734    mainbus_match, mainbus_attach, NULL, NULL);
735
736
737/*
738 * Try to figure out where the PROM stores the cursor row & column
739 * variables.  Returns nonzero on error.
740 */
741int
742romgetcursoraddr(int **rowp, int **colp)
743{
744	cell_t row = 0UL, col = 0UL;
745
746	OF_interpret("stdout @ is my-self addr line# addr column# ", 0, 2,
747		&col, &row);
748	/*
749	 * We are running on a 64-bit machine, so these things point to
750	 * 64-bit values.  To convert them to pointers to integers, add
751	 * 4 to the address.
752	 */
753	*rowp = (int *)(intptr_t)(row+4);
754	*colp = (int *)(intptr_t)(col+4);
755	return (row == 0UL || col == 0UL);
756}
757
758/*
759 * Match a struct device against the bootpath, by
760 * comparing it's firmware package handle. If they match
761 * exactly, we found the boot device.
762 */
763static void
764dev_path_exact_match(device_t dev, int ofnode)
765{
766
767	if (ofnode != ofbootpackage)
768		return;
769
770	booted_device = dev;
771	DPRINTF(ACDB_BOOTDEV, ("found bootdevice: %s\n", device_xname(dev)));
772}
773
774/*
775 * Match a struct device against the bootpath, by
776 * comparing it's firmware package handle and calculating
777 * the target/lun suffix and comparing that against
778 * the bootpath remainder.
779 */
780static void
781dev_path_drive_match(device_t dev, int ctrlnode, int target,
782    uint64_t wwn, int lun)
783{
784	int child = 0;
785	char buf[OFPATHLEN];
786
787	DPRINTF(ACDB_BOOTDEV, ("dev_path_drive_match: %s, controller %x, "
788	    "target %d wwn %016" PRIx64 " lun %d\n", device_xname(dev),
789	    ctrlnode, target, wwn, lun));
790
791	/*
792	 * The ofbootpackage points to a disk on this controller, so
793	 * iterate over all child nodes and compare.
794	 */
795	for (child = prom_firstchild(ctrlnode); child != 0;
796	    child = prom_nextsibling(child))
797		if (child == ofbootpackage)
798			break;
799
800	if (child == ofbootpackage) {
801		const char * name = prom_getpropstring(child, "name");
802
803		/* boot device is on this controller */
804		DPRINTF(ACDB_BOOTDEV, ("found controller of bootdevice\n"));
805
806		/*
807		 * Note: "child" here is == ofbootpackage (s.a.), which
808		 * may be completely wrong for the device we are checking,
809		 * what we realy do here is to match "target" and "lun".
810		 */
811		if (wwn)
812			sprintf(buf, "%s@w%016" PRIx64 ",%d", name, wwn,
813			    lun);
814		else
815			sprintf(buf, "%s@%d,%d", name, target, lun);
816		if (ofboottarget && strcmp(buf, ofboottarget) == 0) {
817			booted_device = dev;
818			if (ofbootpartition)
819				booted_partition = *ofbootpartition - 'a';
820			DPRINTF(ACDB_BOOTDEV, ("found boot device: %s"
821			    ", partition %d\n", device_xname(dev),
822			    booted_partition));
823		}
824	}
825}
826
827/*
828 * Get the firmware package handle from a struct device.
829 * Assuming we have previously stored it in the device properties
830 * dictionary.
831 */
832static int
833device_ofnode(device_t dev)
834{
835	prop_dictionary_t props;
836	prop_object_t obj;
837
838	if (dev == NULL)
839		return 0;
840	props = device_properties(dev);
841	if (props == NULL)
842		return 0;
843	obj = prop_dictionary_get(props, OFNODEKEY);
844	if (obj == NULL)
845		return 0;
846
847	return prop_number_integer_value(obj);
848}
849
850/*
851 * Save the firmware package handle inside the properties dictionary
852 * of a struct device.
853 */
854static void
855device_setofnode(device_t dev, int node)
856{
857	prop_dictionary_t props;
858	prop_object_t obj;
859
860	if (dev == NULL)
861		return;
862	props = device_properties(dev);
863	if (props == NULL)
864		return;
865	obj = prop_number_create_integer(node);
866	if (obj == NULL)
867		return;
868	prop_dictionary_set(props, OFNODEKEY, obj);
869	prop_object_release(obj);
870	DPRINTF(ACDB_BOOTDEV, (" [device %s has node %x] ",
871	    device_xname(dev), node));
872}
873
874/*
875 * Called back during autoconfiguration for each device found
876 */
877void
878device_register(device_t dev, void *aux)
879{
880	device_t busdev = device_parent(dev);
881	int ofnode = 0;
882
883	/*
884	 * We don't know the type of 'aux' - it depends on the
885	 * bus this device attaches to. We are only interested in
886	 * certain bus types, this only is used to find the boot
887	 * device.
888	 */
889	if (busdev == NULL) {
890		/*
891		 * Ignore mainbus0 itself, it certainly is not a boot
892		 * device.
893		 */
894	} else if (device_is_a(busdev, "mainbus")) {
895		struct mainbus_attach_args *ma = aux;
896
897		ofnode = ma->ma_node;
898	} else if (device_is_a(busdev, "pci")) {
899		struct pci_attach_args *pa = aux;
900
901		ofnode = PCITAG_NODE(pa->pa_tag);
902	} else if (device_is_a(busdev, "sbus") || device_is_a(busdev, "dma")
903	    || device_is_a(busdev, "ledma")) {
904		struct sbus_attach_args *sa = aux;
905
906		ofnode = sa->sa_node;
907	} else if (device_is_a(busdev, "ebus")) {
908		struct ebus_attach_args *ea = aux;
909
910		ofnode = ea->ea_node;
911	} else if (device_is_a(busdev, "iic")) {
912		struct i2c_attach_args *ia = aux;
913
914		ofnode = (int)ia->ia_cookie;
915	} else if (device_is_a(dev, "sd") || device_is_a(dev, "cd")) {
916		struct scsipibus_attach_args *sa = aux;
917		struct scsipi_periph *periph = sa->sa_periph;
918		int off = 0;
919
920		/*
921		 * There are two "cd" attachments:
922		 *   atapibus -> atabus -> controller
923		 *   scsibus -> controller
924		 * We want the node of the controller.
925		 */
926		if (device_is_a(busdev, "atapibus")) {
927			busdev = device_parent(busdev);
928			/*
929			 * if the atapibus is connected to the secondary
930			 * channel of the atabus, we need an offset of 2
931			 * to match OF's idea of the target number.
932			 * (i.e. on U5/U10 "cdrom" and "disk2" have the
933			 * same target encoding, though different names)
934			 */
935			if (periph->periph_channel->chan_channel == 1)
936				off = 2;
937		}
938		ofnode = device_ofnode(device_parent(busdev));
939		dev_path_drive_match(dev, ofnode, periph->periph_target + off,
940		    0, periph->periph_lun);
941		return;
942	} else if (device_is_a(dev, "wd")) {
943		struct ata_device *adev = aux;
944
945		ofnode = device_ofnode(device_parent(busdev));
946		dev_path_drive_match(dev, ofnode, adev->adev_channel*2+
947		    adev->adev_drv_data->drive, 0, 0);
948		return;
949	}
950
951	if (busdev == NULL)
952		return;
953
954	if (ofnode != 0) {
955		uint8_t eaddr[ETHER_ADDR_LEN];
956		char tmpstr[32];
957		char tmpstr2[32];
958		int node;
959		uint32_t id = 0;
960		uint64_t nwwn = 0, pwwn = 0;
961		prop_dictionary_t dict;
962		prop_data_t blob;
963		prop_number_t pwwnd = NULL, nwwnd = NULL;
964		prop_number_t idd = NULL;
965
966		device_setofnode(dev, ofnode);
967		dev_path_exact_match(dev, ofnode);
968
969		if (OF_getprop(ofnode, "name", tmpstr, sizeof(tmpstr)) <= 0)
970			tmpstr[0] = 0;
971		if (OF_getprop(ofnode, "device_type", tmpstr2, sizeof(tmpstr2)) <= 0)
972			tmpstr2[0] = 0;
973
974		/*
975		 * If this is a network interface, note the
976		 * mac address.
977		 */
978		if (strcmp(tmpstr, "network") == 0
979		   || strcmp(tmpstr, "ethernet") == 0
980		   || strcmp(tmpstr2, "network") == 0
981		   || strcmp(tmpstr2, "ethernet") == 0
982		   || OF_getprop(ofnode, "mac-address", &eaddr, sizeof(eaddr))
983		      >= ETHER_ADDR_LEN
984		   || OF_getprop(ofnode, "local-mac-address", &eaddr, sizeof(eaddr))
985		      >= ETHER_ADDR_LEN) {
986
987			dict = device_properties(dev);
988
989			/*
990			 * Is it a network interface with FCode?
991			 */
992			if (strcmp(tmpstr, "network") == 0 ||
993			    strcmp(tmpstr2, "network") == 0) {
994				prop_dictionary_set_bool(dict,
995				    "without-seeprom", true);
996				prom_getether(ofnode, eaddr);
997			} else {
998				if (!prom_get_node_ether(ofnode, eaddr))
999					goto noether;
1000			}
1001			blob = prop_data_create_data(eaddr, ETHER_ADDR_LEN);
1002			prop_dictionary_set(dict, "mac-address", blob);
1003			prop_object_release(blob);
1004			of_to_dataprop(dict, ofnode, "shared-pins",
1005			    "shared-pins");
1006		}
1007noether:
1008
1009		/* is this a FC node? */
1010		if (strcmp(tmpstr, "scsi-fcp") == 0) {
1011
1012			dict = device_properties(dev);
1013
1014			if (OF_getprop(ofnode, "port-wwn", &pwwn, sizeof(pwwn))
1015			    == sizeof(pwwn)) {
1016				pwwnd =
1017				    prop_number_create_unsigned_integer(pwwn);
1018				prop_dictionary_set(dict, "port-wwn", pwwnd);
1019				prop_object_release(pwwnd);
1020			}
1021
1022			if (OF_getprop(ofnode, "node-wwn", &nwwn, sizeof(nwwn))
1023			    == sizeof(nwwn)) {
1024				nwwnd =
1025				    prop_number_create_unsigned_integer(nwwn);
1026				prop_dictionary_set(dict, "node-wwn", nwwnd);
1027				prop_object_release(nwwnd);
1028			}
1029		}
1030
1031		/* is this an spi device?  look for scsi-initiator-id */
1032		if (strcmp(tmpstr2, "scsi") == 0 ||
1033		    strcmp(tmpstr2, "scsi-2") == 0) {
1034
1035			dict = device_properties(dev);
1036
1037			for (node = ofnode; node != 0; node = OF_parent(node)) {
1038				if (OF_getprop(node, "scsi-initiator-id", &id,
1039				    sizeof(id)) <= 0)
1040					continue;
1041
1042				idd = prop_number_create_unsigned_integer(id);
1043				prop_dictionary_set(dict,
1044						    "scsi-initiator-id", idd);
1045				prop_object_release(idd);
1046				break;
1047			}
1048		}
1049	}
1050
1051	/*
1052	 * Check for I2C busses and add data for their direct configuration.
1053	 */
1054	if (device_is_a(dev, "iic")) {
1055		int busnode = device_ofnode(busdev);
1056
1057		if (busnode) {
1058			prop_dictionary_t props = device_properties(busdev);
1059			prop_object_t cfg = prop_dictionary_get(props,
1060				"i2c-child-devices");
1061			if (!cfg) {
1062				int node;
1063				const char *name;
1064
1065				/*
1066				 * pmu's i2c devices are under the "i2c" node,
1067				 * so find it out.
1068				 */
1069				name = prom_getpropstring(busnode, "name");
1070				if (strcmp(name, "pmu") == 0) {
1071					for (node = OF_child(busnode);
1072					     node != 0; node = OF_peer(node)) {
1073						name = prom_getpropstring(node,
1074						    "name");
1075						if (strcmp(name, "i2c") == 0) {
1076							busnode = node;
1077							break;
1078						}
1079					}
1080				}
1081
1082				of_enter_i2c_devs(props, busnode,
1083				    sizeof(cell_t));
1084			}
1085		}
1086	}
1087
1088	/* set properties for PCI framebuffers */
1089	if (device_is_a(busdev, "pci")) {
1090		/* see if this is going to be console */
1091		struct pci_attach_args *pa = aux;
1092		prop_dictionary_t dict;
1093		int sub;
1094		int console = 0;
1095
1096		dict = device_properties(dev);
1097
1098		/* we only care about display devices from here on */
1099		if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY)
1100			return;
1101
1102		console = (ofnode == console_node);
1103
1104		if (!console) {
1105			/*
1106			 * see if any child matches since OF attaches
1107			 * nodes for each head and /chosen/stdout
1108			 * points to the head rather than the device
1109			 * itself in this case
1110			 */
1111			sub = OF_child(ofnode);
1112			while ((sub != 0) && (sub != console_node)) {
1113				sub = OF_peer(sub);
1114			}
1115			if (sub == console_node) {
1116				console = true;
1117			}
1118		}
1119
1120		copyprops(busdev, ofnode, dict, console);
1121
1122		if (console) {
1123			uint64_t cmap_cb;
1124			prop_dictionary_set_uint32(dict,
1125			    "instance_handle", console_instance);
1126
1127			gfb_cb.gcc_cookie =
1128			    (void *)(intptr_t)console_instance;
1129			gfb_cb.gcc_set_mapreg = of_set_palette;
1130			cmap_cb = (uint64_t)(uintptr_t)&gfb_cb;
1131			prop_dictionary_set_uint64(dict,
1132			    "cmap_callback", cmap_cb);
1133		}
1134#ifdef notyet
1135		else {
1136			int width;
1137
1138			/*
1139			 * the idea is to 'open' display devices with no useful
1140			 * properties, in the hope that the firmware will
1141			 * properly initialize them and we can run things like
1142			 * genfb on them
1143			 */
1144			if (OF_getprop(node, "width", &width, sizeof(width))
1145			    != 4) {
1146				instance = OF_open(name);
1147#endif
1148	}
1149}
1150
1151/*
1152 * Called back after autoconfiguration of a device is done
1153 */
1154void
1155device_register_post_config(device_t dev, void *aux)
1156{
1157	if (booted_device == NULL && device_is_a(dev, "sd")) {
1158		struct scsipibus_attach_args *sa = aux;
1159		struct scsipi_periph *periph = sa->sa_periph;
1160		uint64_t wwn = 0;
1161		int ofnode;
1162
1163		/*
1164		 * If this is a FC-AL drive it will have
1165		 * aquired it's WWN device property by now,
1166		 * so we can properly match it.
1167		 */
1168		if (prop_dictionary_get_uint64(device_properties(dev),
1169		    "port-wwn", &wwn)) {
1170			/*
1171			 * Different to what we do in device_register,
1172			 * we do not pass the "controller" ofnode,
1173			 * because FC-AL devices attach below a "fp" node,
1174			 * E.g.: /pci/SUNW,qlc@4/fp@0,0/disk
1175			 * and we need the parent of "disk" here.
1176			 */
1177			ofnode = device_ofnode(
1178			    device_parent(device_parent(dev)));
1179			for (ofnode = OF_child(ofnode);
1180			    ofnode != 0 && booted_device == NULL;
1181			    ofnode = OF_peer(ofnode)) {
1182				dev_path_drive_match(dev, ofnode,
1183				    periph->periph_target,
1184				    wwn, periph->periph_lun);
1185			}
1186		}
1187	}
1188}
1189
1190static void
1191copyprops(device_t busdev, int node, prop_dictionary_t dict, int is_console)
1192{
1193	device_t cntrlr;
1194	prop_dictionary_t psycho;
1195	paddr_t fbpa, mem_base = 0;
1196	uint32_t temp, fboffset;
1197	uint32_t fbaddr = 0;
1198	int options;
1199	char output_device[256];
1200	char *pos;
1201
1202	cntrlr = device_parent(busdev);
1203	if (cntrlr != NULL) {
1204		psycho = device_properties(cntrlr);
1205		prop_dictionary_get_uint64(psycho, "mem_base", &mem_base);
1206	}
1207
1208	if (is_console)
1209		prop_dictionary_set_bool(dict, "is_console", 1);
1210
1211	of_to_uint32_prop(dict, node, "width", "width");
1212	of_to_uint32_prop(dict, node, "height", "height");
1213	of_to_uint32_prop(dict, node, "linebytes", "linebytes");
1214	if (!of_to_uint32_prop(dict, node, "depth", "depth") &&
1215	    /* Some cards have an extra space in the property name */
1216	    !of_to_uint32_prop(dict, node, "depth ", "depth")) {
1217		/*
1218		 * XXX we should check linebytes vs. width but those
1219		 * FBs that don't have a depth property ( /chaos/control... )
1220		 * won't have linebytes either
1221		 */
1222		prop_dictionary_set_uint32(dict, "depth", 8);
1223	}
1224
1225	OF_getprop(node, "address", &fbaddr, sizeof(fbaddr));
1226	if (fbaddr != 0) {
1227
1228		pmap_extract(pmap_kernel(), fbaddr, &fbpa);
1229#ifdef DEBUG
1230		printf("membase: %lx fbpa: %lx\n", (unsigned long)mem_base,
1231		    (unsigned long)fbpa);
1232#endif
1233		if (mem_base == 0) {
1234			/* XXX this is guesswork */
1235			fboffset = (uint32_t)(fbpa & 0xffffffff);
1236		}
1237			fboffset = (uint32_t)(fbpa - mem_base);
1238		prop_dictionary_set_uint32(dict, "address", fboffset);
1239	}
1240
1241	if (!of_to_dataprop(dict, node, "EDID", "EDID"))
1242		of_to_dataprop(dict, node, "edid", "EDID");
1243
1244	temp = 0;
1245	if (OF_getprop(node, "ATY,RefCLK", &temp, sizeof(temp)) != 4) {
1246
1247		OF_getprop(OF_parent(node), "ATY,RefCLK", &temp,
1248		    sizeof(temp));
1249	}
1250	if (temp != 0)
1251		prop_dictionary_set_uint32(dict, "refclk", temp / 10);
1252
1253	/*
1254	 * finally, let's see if there's a video mode specified in
1255	 * output-device and pass it on so drivers like radeonfb
1256	 * can do their thing
1257	 */
1258
1259	if (!is_console)
1260		return;
1261
1262	options = OF_finddevice("/options");
1263	if ((options == 0) || (options == -1))
1264		return;
1265	if (OF_getprop(options, "output-device", output_device, 256) == 0)
1266		return;
1267	/* find the mode string if there is one */
1268	pos = strstr(output_device, ":r");
1269	if (pos == NULL)
1270		return;
1271	prop_dictionary_set_cstring(dict, "videomode", pos + 2);
1272}
1273
1274static void
1275of_set_palette(void *cookie, int index, int r, int g, int b)
1276{
1277	int ih = (int)((intptr_t)cookie);
1278
1279	OF_call_method_1("color!", ih, 4, r, g, b, index);
1280}
1281