1/*	$OpenBSD: autoconf.c,v 1.151 2024/05/17 20:05:08 miod Exp $	*/
2/*	$NetBSD: autoconf.c,v 1.51 2001/07/24 19:32:11 eeh Exp $ */
3
4/*
5 * Copyright (c) 1996
6 *    The President and Fellows of Harvard College. All rights reserved.
7 * Copyright (c) 1992, 1993
8 *	The Regents of the University of California.  All rights reserved.
9 *
10 * This software was developed by the Computer Systems Engineering group
11 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
12 * contributed to Berkeley.
13 *
14 * All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 *	This product includes software developed by Harvard University.
17 *	This product includes software developed by the University of
18 *	California, Lawrence Berkeley Laboratory.
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 * 1. Redistributions of source code must retain the above copyright
24 *    notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 *    notice, this list of conditions and the following disclaimer in the
27 *    documentation and/or other materials provided with the distribution.
28 * 3. Neither the name of the University nor the names of its contributors
29 *    may be used to endorse or promote products derived from this software
30 *    without specific prior written permission.
31 *
32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
42 * SUCH DAMAGE.
43 *
44 *	@(#)autoconf.c	8.4 (Berkeley) 10/1/93
45 */
46
47#include "mpath.h"
48
49#include <sys/param.h>
50#include <sys/systm.h>
51#include <sys/buf.h>
52#include <sys/disklabel.h>
53#include <sys/device.h>
54#include <sys/disk.h>
55#include <sys/conf.h>
56#include <sys/reboot.h>
57#include <sys/socket.h>
58#include <sys/malloc.h>
59#include <sys/queue.h>
60#include <sys/msgbuf.h>
61
62#include <net/if.h>
63
64#include <dev/cons.h>
65#include <dev/clock_subr.h>
66
67#include <uvm/uvm_extern.h>
68
69#include <machine/bus.h>
70#include <machine/boot_flag.h>
71#include <machine/autoconf.h>
72#include <machine/hypervisor.h>
73#include <machine/mdesc.h>
74#include <machine/openfirm.h>
75#include <machine/sparc64.h>
76#include <machine/cpu.h>
77#include <machine/pmap.h>
78#include <machine/trap.h>
79#include <sparc64/sparc64/cache.h>
80#include <sparc64/dev/vbusvar.h>
81#include <sparc64/dev/cbusvar.h>
82
83#include <stand/boot/bootarg.h>
84
85#include <dev/ata/atavar.h>
86#include <dev/pci/pcivar.h>
87#include <dev/sbus/sbusvar.h>
88
89#include <scsi/scsi_all.h>
90#include <scsi/scsiconf.h>
91#if NMPATH > 0
92#include <scsi/mpathvar.h>
93#endif
94
95#ifdef DDB
96#include <machine/db_machdep.h>
97#include <ddb/db_sym.h>
98#include <ddb/db_extern.h>
99#endif
100
101#include "softraid.h"
102#if NSOFTRAID > 0
103#include <sys/sensors.h>
104#include <dev/softraidvar.h>
105
106/* XXX */
107#undef DPRINTF
108#undef DNPRINTF
109#endif
110
111int printspl = 0;
112
113/*
114 * The following several variables are related to
115 * the configuration process, and are used in initializing
116 * the machine.
117 */
118int	stdinnode;	/* node ID of ROM's console input device */
119int	fbnode;		/* node ID of ROM's console output device */
120int	optionsnode;	/* node ID of ROM's options */
121
122static	int rootnode;
123
124static	char *str2hex(char *, long *);
125static	int mbprint(void *, const char *);
126int	mainbus_match(struct device *, void *, void *);
127static	void mainbus_attach(struct device *, struct device *, void *);
128int	get_ncpus(void);
129
130struct device *booted_device;
131struct	bootpath bootpath[16];
132int	nbootpath;
133int	bootnode;
134static	void bootpath_build(void);
135static	void bootpath_print(struct bootpath *);
136void bootpath_nodes(struct bootpath *, int);
137
138struct openbsd_bootdata obd __attribute__((section(".openbsd.bootdata")));
139
140void nail_bootdev(struct device *, struct bootpath *);
141
142/* Global interrupt mappings for all device types.  Match against the OBP
143 * 'device_type' property.
144 */
145struct intrmap intrmap[] = {
146	{ "block",	PIL_FD },	/* Floppy disk */
147	{ "serial",	PIL_SER },	/* zs */
148	{ "scsi",	PIL_SCSI },
149	{ "scsi-2",	PIL_SCSI },
150	{ "network",	PIL_NET },
151	{ "display",	PIL_VIDEO },
152	{ "audio",	PIL_AUD },
153	{ "ide",	PIL_SCSI },
154/* The following devices don't have device types: */
155	{ "SUNW,CS4231",	PIL_AUD },
156	{ NULL,		0 }
157};
158
159#ifdef SUN4V
160void	sun4v_soft_state_init(void);
161void	sun4v_set_soft_state(int, const char *);
162
163#define __align32 __attribute__((__aligned__(32)))
164char sun4v_soft_state_booting[] __align32 = "OpenBSD booting";
165char sun4v_soft_state_running[] __align32 = "OpenBSD running";
166
167void	sun4v_interrupt_init(void);
168void	sun4v_sdio_init(void);
169#endif
170
171extern void us_tlb_flush_pte(vaddr_t, uint64_t);
172extern void us3_tlb_flush_pte(vaddr_t, uint64_t);
173extern void sun4v_tlb_flush_pte(vaddr_t, uint64_t);
174extern void us_tlb_flush_ctx(uint64_t);
175extern void us3_tlb_flush_ctx(uint64_t);
176extern void sun4v_tlb_flush_ctx(uint64_t);
177
178void (*sp_tlb_flush_pte)(vaddr_t, uint64_t) = us_tlb_flush_pte;
179void (*sp_tlb_flush_ctx)(uint64_t) = us_tlb_flush_ctx;
180
181#ifdef DEBUG
182#define ACDB_BOOTDEV	0x1
183#define	ACDB_PROBE	0x2
184int autoconf_debug = 0x0;
185#define DPRINTF(l, s)   do { if (autoconf_debug & l) printf s; } while (0)
186#else
187#define DPRINTF(l, s)
188#endif
189
190/*
191 * Convert hex ASCII string to a value.  Returns updated pointer.
192 * Depends on ASCII order (this *is* machine-dependent code, you know).
193 */
194static char *
195str2hex(char *str, long *vp)
196{
197	long v;
198	int c;
199
200	if (*str == 'w') {
201		for (v = 1;; v++) {
202			if (str[v] >= '0' && str[v] <= '9')
203				continue;
204			if (str[v] >= 'a' && str[v] <= 'f')
205				continue;
206			if (str[v] >= 'A' && str[v] <= 'F')
207				continue;
208			if (str[v] == '\0' || str[v] == ',')
209				break;
210			*vp = 0;
211			return (str + v);
212		}
213		str++;
214	}
215
216	for (v = 0;; v = v * 16 + c, str++) {
217		c = *(u_char *)str;
218		if (c <= '9') {
219			if ((c -= '0') < 0)
220				break;
221		} else if (c <= 'F') {
222			if ((c -= 'A' - 10) < 10)
223				break;
224		} else if (c <= 'f') {
225			if ((c -= 'a' - 10) < 10)
226				break;
227		} else
228			break;
229	}
230	*vp = v;
231	return (str);
232}
233
234/*
235 * Hunt through the device tree for CPUs.  There should be no need to
236 * go more than four levels deep; an UltraSPARC-IV on Seregeti shows
237 * up as /ssm@0,0/cmp@0,0/cpu@0 and a SPARC64-VI will show up as
238 * /cmp@0,0/core@0/cpu@0.
239 */
240int
241get_ncpus(void)
242{
243	int node, child, stack[4], depth, ncpus;
244	char buf[32];
245
246	stack[0] = findroot();
247	depth = 0;
248
249	ncpus = 0;
250	for (;;) {
251		node = stack[depth];
252
253		if (node == 0 || node == -1) {
254			if (--depth < 0)
255				goto done;
256
257			stack[depth] = OF_peer(stack[depth]);
258			continue;
259		}
260
261		if (OF_getprop(node, "device_type", buf, sizeof(buf)) > 0 &&
262		    strcmp(buf, "cpu") == 0)
263			ncpus++;
264
265		child = OF_child(node);
266		if (child != 0 && child != -1 && depth < 3)
267			stack[++depth] = child;
268		else
269			stack[depth] = OF_peer(stack[depth]);
270	}
271
272done:
273	ncpusfound = ncpus;
274#ifdef MULTIPROCESSOR
275	return (ncpus);
276#else
277	return (1);
278#endif
279}
280
281/*
282 * locore.s code calls bootstrap() just before calling main().
283 *
284 * What we try to do is as follows:
285 *
286 * 1) We will try to re-allocate the old message buffer.
287 *
288 * 2) We will then get the list of the total and available
289 *	physical memory and available virtual memory from the
290 *	prom.
291 *
292 * 3) We will pass the list to pmap_bootstrap to manage them.
293 *
294 * We will try to run out of the prom until we get to cpu_init().
295 */
296void
297bootstrap(int nctx)
298{
299	extern int end;	/* End of kernel */
300	struct trapvec *romtba;
301#if defined(SUN4US) || defined(SUN4V)
302	char buf[32];
303#endif
304	int impl = 0;
305	int ncpus;
306
307	/* Initialize the PROM console so printf will not panic. */
308	(*cn_tab->cn_init)(cn_tab);
309
310	/*
311	 * Initialize ddb first and register OBP callbacks.
312	 * We can do this because ddb_init() does not allocate anything,
313	 * just initializes some pointers to important things
314	 * like the symtab.
315	 *
316	 * By doing this first and installing the OBP callbacks
317	 * we get to do symbolic debugging of pmap_bootstrap().
318	 */
319#ifdef DDB
320	db_machine_init();
321	ddb_init();
322	/* This can only be installed on an 64-bit system cause otherwise our stack is screwed */
323	OF_set_symbol_lookup(OF_sym2val, OF_val2sym);
324#endif
325
326#if defined (SUN4US) || defined(SUN4V)
327	if (OF_getprop(findroot(), "compatible", buf, sizeof(buf)) > 0) {
328		if (strcmp(buf, "sun4us") == 0)
329			cputyp = CPU_SUN4US;
330		if (strcmp(buf, "sun4v") == 0)
331			cputyp = CPU_SUN4V;
332	}
333#endif
334
335	/* We cannot read %ver on sun4v systems. */
336	if (CPU_ISSUN4U || CPU_ISSUN4US)
337		impl = (getver() & VER_IMPL) >> VER_IMPL_SHIFT;
338
339	if (impl >= IMPL_CHEETAH) {
340		extern vaddr_t dlflush_start;
341		vaddr_t *pva;
342		u_int32_t insn;
343
344		for (pva = &dlflush_start; *pva; pva++) {
345			insn = *(u_int32_t *)(*pva);
346			insn &= ~(ASI_DCACHE_TAG << 5);
347			insn |= (ASI_DCACHE_INVALIDATE << 5);
348			*(u_int32_t *)(*pva) = insn;
349			flush((void *)(*pva));
350		}
351
352		cacheinfo.c_dcache_flush_page = us3_dcache_flush_page;
353		sp_tlb_flush_pte = us3_tlb_flush_pte;
354		sp_tlb_flush_ctx = us3_tlb_flush_ctx;
355	}
356
357	if ((impl >= IMPL_ZEUS && impl <= IMPL_JUPITER) || CPU_ISSUN4V) {
358		extern vaddr_t dlflush_start;
359		vaddr_t *pva;
360
361		for (pva = &dlflush_start; *pva; pva++) {
362			*(u_int32_t *)(*pva) = 0x01000000; /* nop */
363			flush((void *)(*pva));
364		}
365
366		cacheinfo.c_dcache_flush_page = no_dcache_flush_page;
367	}
368
369#ifdef MULTIPROCESSOR
370	if (impl >= IMPL_OLYMPUS_C && impl <= IMPL_JUPITER) {
371		struct sun4u_patch {
372			u_int32_t addr;
373			u_int32_t insn;
374		} *p;
375
376		extern struct sun4u_patch sun4u_mtp_patch;
377		extern struct sun4u_patch sun4u_mtp_patch_end;
378
379		for (p = &sun4u_mtp_patch; p < &sun4u_mtp_patch_end; p++) {
380			*(u_int32_t *)(vaddr_t)p->addr = p->insn;
381			flush((void *)(vaddr_t)p->addr);
382		}
383	}
384#endif
385
386#ifdef SUN4V
387	if (CPU_ISSUN4V) {
388		struct sun4v_patch {
389			u_int32_t addr;
390			u_int32_t insn;
391		} *p;
392
393		extern struct sun4v_patch sun4v_patch;
394		extern struct sun4v_patch sun4v_patch_end;
395
396		for (p = &sun4v_patch; p < &sun4v_patch_end; p++) {
397			*(u_int32_t *)(vaddr_t)p->addr = p->insn;
398			flush((void *)(vaddr_t)p->addr);
399		}
400
401#ifdef MULTIPROCESSOR
402		extern struct sun4v_patch sun4v_mp_patch;
403		extern struct sun4v_patch sun4v_mp_patch_end;
404
405		for (p = &sun4v_mp_patch; p < &sun4v_mp_patch_end; p++) {
406			*(u_int32_t *)(vaddr_t)p->addr = p->insn;
407			flush((void *)(vaddr_t)p->addr);
408		}
409#endif
410
411		sp_tlb_flush_pte = sun4v_tlb_flush_pte;
412		sp_tlb_flush_ctx = sun4v_tlb_flush_ctx;
413	}
414#endif
415
416	/*
417	 * Copy over the OBP breakpoint trap vector; OpenFirmware 5.x
418	 * needs it to be able to return to the ok prompt.
419	 */
420	romtba = (struct trapvec *)sparc_rdpr(tba);
421	bcopy(&romtba[T_MON_BREAKPOINT], &trapbase[T_MON_BREAKPOINT],
422	    sizeof(struct trapvec));
423	flush((void *)trapbase);
424
425	ncpus = get_ncpus();
426	pmap_bootstrap(KERNBASE, (u_long)&end, nctx, ncpus);
427
428	if (obd.version == BOOTDATA_VERSION &&
429	    obd.len >= BOOTDATA_LEN_BOOTHOWTO)
430		boothowto = obd.boothowto;
431
432#ifdef SUN4V
433	if (CPU_ISSUN4V) {
434		sun4v_soft_state_init();
435		sun4v_set_soft_state(SIS_TRANSITION, sun4v_soft_state_booting);
436		sun4v_interrupt_init();
437		sun4v_sdio_init();
438	}
439#endif
440}
441
442void
443bootpath_nodes(struct bootpath *bp, int nbp)
444{
445	int chosen;
446	int i;
447	char buf[128], *cp, c;
448
449	chosen = OF_finddevice("/chosen");
450	OF_getprop(chosen, "bootpath", buf, sizeof(buf));
451	cp = buf;
452
453	for (i = 0; i < nbp; i++, bp++) {
454		if (*cp == '\0')
455			return;
456		while (*cp != '\0' && *cp == '/')
457			cp++;
458		while (*cp && *cp != '/')
459			cp++;
460		c = *cp;
461		*cp = '\0';
462		bootnode = bp->node = OF_finddevice(buf);
463		*cp = c;
464	}
465}
466
467/*
468 * bootpath_build: build a bootpath. Used when booting a generic
469 * kernel to find our root device.  Newer proms give us a bootpath,
470 * for older proms we have to create one.  An element in a bootpath
471 * has 4 fields: name (device name), val[0], val[1], and val[2]. Note that:
472 * Interpretation of val[] is device-dependent. Some examples:
473 *
474 * if (val[0] == -1) {
475 *	val[1] is a unit number    (happens most often with old proms)
476 * } else {
477 *	[sbus device] val[0] is a sbus slot, and val[1] is an sbus offset
478 *	[scsi disk] val[0] is target, val[1] is lun, val[2] is partition
479 *	[scsi tape] val[0] is target, val[1] is lun, val[2] is file #
480 *	[pci device] val[0] is device, val[1] is function, val[2] might be partition
481 * }
482 *
483 */
484
485static void
486bootpath_build(void)
487{
488	register char *cp, *pp;
489	register struct bootpath *bp;
490	register long chosen;
491	char buf[128];
492
493	bzero((void *)bootpath, sizeof(bootpath));
494	bp = bootpath;
495
496	/*
497	 * Grab boot path from PROM
498	 */
499	chosen = OF_finddevice("/chosen");
500	OF_getprop(chosen, "bootpath", buf, sizeof(buf));
501	cp = buf;
502	while (cp != NULL && *cp == '/') {
503		/* Step over '/' */
504		++cp;
505		/* Extract name */
506		pp = bp->name;
507		while (*cp != '@' && *cp != '/' && *cp != '\0')
508			*pp++ = *cp++;
509		*pp = '\0';
510		if (*cp == '@') {
511			cp = str2hex(++cp, &bp->val[0]);
512			if (*cp == ',')
513				cp = str2hex(++cp, &bp->val[1]);
514			if (*cp == ':') {
515				/*
516				 * We only store one character here, as we will
517				 * only use this field to compute a partition
518				 * index for block devices.  However, it might
519				 * be an ethernet media specification, so be
520				 * sure to skip all letters.
521				 */
522				bp->val[2] = *++cp - 'a';
523				while (*cp != '\0' && *cp != '/')
524					cp++;
525			}
526		} else {
527			bp->val[0] = -1; /* no #'s: assume unit 0, no
528					    sbus offset/address */
529		}
530		++bp;
531		++nbootpath;
532	}
533	bp->name[0] = 0;
534
535	bootpath_nodes(bootpath, nbootpath);
536
537	/* Setup pointer to boot flags */
538	OF_getprop(chosen, "bootargs", buf, sizeof(buf));
539	cp = buf;
540
541	/* Find start of boot flags */
542	while (*cp) {
543		while(*cp == ' ' || *cp == '\t') cp++;
544		if (*cp == '-' || *cp == '\0')
545			break;
546		while(*cp != ' ' && *cp != '\t' && *cp != '\0') cp++;
547
548	}
549	if (*cp != '-')
550		return;
551
552	for (;*++cp;) {
553		int fl;
554
555		fl = 0;
556		switch(*cp) {
557		case 'a':
558			fl |= RB_ASKNAME;
559			break;
560		case 'b':
561			fl |= RB_HALT;
562			break;
563		case 'c':
564			fl |= RB_CONFIG;
565			break;
566		case 'd':
567			fl |= RB_KDB;
568			break;
569		case 's':
570			fl |= RB_SINGLE;
571			break;
572		default:
573			break;
574		}
575		if (!fl) {
576			printf("unknown option `%c'\n", *cp);
577			continue;
578		}
579		boothowto |= fl;
580
581		/* specialties */
582		if (*cp == 'd') {
583#if defined(DDB)
584			db_enter();
585#else
586			printf("kernel has no debugger\n");
587#endif
588		}
589	}
590}
591
592/*
593 * print out the bootpath
594 * the %x isn't 0x%x because the Sun EPROMs do it this way, and
595 * consistency with the EPROMs is probably better here.
596 */
597
598static void
599bootpath_print(struct bootpath *bp)
600{
601	printf("bootpath: ");
602	while (bp->name[0]) {
603		if (bp->val[0] == -1)
604			printf("/%s%lx", bp->name, bp->val[1]);
605		else
606			printf("/%s@%lx,%lx", bp->name, bp->val[0], bp->val[1]);
607		if (bp->val[2] != 0)
608			printf(":%c", (int)bp->val[2] + 'a');
609		bp++;
610	}
611	printf("\n");
612}
613
614
615/*
616 * save or read a bootpath pointer from the boothpath store.
617 *
618 * XXX. required because of SCSI... we don't have control over the "sd"
619 * device, so we can't set boot device there.   we patch in with
620 * device_register(), and use this to recover the bootpath.
621 */
622struct bootpath *
623bootpath_store(int storep, struct bootpath *bp)
624{
625	static struct bootpath *save;
626	struct bootpath *retval;
627
628	retval = save;
629	if (storep)
630		save = bp;
631
632	return (retval);
633}
634
635/*
636 * Determine mass storage and memory configuration for a machine.
637 * We get the PROM's root device and make sure we understand it, then
638 * attach it as `mainbus0'.
639 */
640void
641cpu_configure(void)
642{
643#ifdef SUN4V
644	int pause = 0;
645
646	if (CPU_ISSUN4V) {
647		const char *prop;
648		size_t len;
649		int idx;
650
651		mdesc_init();
652		idx = mdesc_find_node("cpu");
653		prop = mdesc_get_prop_data(idx, "hwcap-list", &len);
654		if (prop) {
655			while (len > 0) {
656				if (strcmp(prop, "pause") == 0)
657					pause = 1;
658				len -= strlen(prop) + 1;
659				prop += strlen(prop) + 1;
660			}
661		}
662	}
663
664	if (pause) {
665		struct sun4v_patch {
666			u_int32_t addr;
667			u_int32_t insn;
668		} *p;
669		paddr_t pa;
670
671		extern struct sun4v_patch sun4v_pause_patch;
672		extern struct sun4v_patch sun4v_pause_patch_end;
673
674		/*
675		 * Use physical addresses to patch since kernel .text
676		 * is already mapped read-only at this point.
677		 */
678		for (p = &sun4v_pause_patch; p < &sun4v_pause_patch_end; p++) {
679			pmap_extract(pmap_kernel(), (vaddr_t)p->addr, &pa);
680			stwa(pa, ASI_PHYS_NON_CACHED, p->insn);
681			flush((void *)(vaddr_t)p->addr);
682		}
683	}
684#endif
685
686	if (obd.version == BOOTDATA_VERSION &&
687	    obd.len >= BOOTDATA_LEN_BOOTHOWTO) {
688#if NSOFTRAID > 0
689		memcpy(sr_bootuuid.sui_id, obd.sr_uuid,
690		    sizeof(sr_bootuuid.sui_id));
691		memcpy(sr_bootkey, obd.sr_maskkey, sizeof(sr_bootkey));
692#endif
693		explicit_bzero(obd.sr_maskkey, sizeof(obd.sr_maskkey));
694	}
695
696	/* build the bootpath */
697	bootpath_build();
698
699	if (boothowto & RB_CONFIG) {
700#ifdef BOOT_CONFIG
701		user_config();
702#else
703		printf("kernel does not support -c; continuing..\n");
704#endif
705	}
706
707	/* block clock interrupts and anything below */
708	splclock();
709	/* Enable device interrupts */
710        setpstate(getpstate()|PSTATE_IE);
711
712	if (config_rootfound("mainbus", NULL) == NULL)
713		panic("mainbus not configured");
714
715	/* Enable device interrupts */
716        setpstate(getpstate()|PSTATE_IE);
717
718	(void)spl0();
719	cold = 0;
720
721#ifdef SUN4V
722	if (CPU_ISSUN4V)
723		sun4v_set_soft_state(SIS_NORMAL, sun4v_soft_state_running);
724#endif
725}
726
727#ifdef SUN4V
728
729#define HSVC_GROUP_INTERRUPT	0x002
730#define HSVC_GROUP_SOFT_STATE	0x003
731#define HSVC_GROUP_SDIO		0x108
732
733int sun4v_soft_state_initialized = 0;
734
735void
736sun4v_soft_state_init(void)
737{
738	uint64_t minor;
739
740	if (prom_set_sun4v_api_version(HSVC_GROUP_SOFT_STATE, 1, 0, &minor))
741		return;
742
743	prom_sun4v_soft_state_supported();
744	sun4v_soft_state_initialized = 1;
745}
746
747void
748sun4v_set_soft_state(int state, const char *desc)
749{
750	paddr_t pa;
751	int err;
752
753	if (!sun4v_soft_state_initialized)
754		return;
755
756	if (!pmap_extract(pmap_kernel(), (vaddr_t)desc, &pa))
757		panic("sun4v_set_soft_state: pmap_extract failed");
758
759	err = hv_soft_state_set(state, pa);
760	if (err != H_EOK)
761		printf("soft_state_set: %d\n", err);
762}
763
764void
765sun4v_interrupt_init(void)
766{
767	uint64_t minor;
768
769	if (prom_set_sun4v_api_version(HSVC_GROUP_INTERRUPT, 3, 0, &minor))
770		return;
771
772	sun4v_group_interrupt_major = 3;
773}
774
775void
776sun4v_sdio_init(void)
777{
778	uint64_t minor;
779
780	if (prom_set_sun4v_api_version(HSVC_GROUP_SDIO, 1, 0, &minor))
781		return;
782
783	sun4v_group_sdio_major = 1;
784}
785
786#endif
787
788void
789diskconf(void)
790{
791	struct bootpath *bp;
792	struct device *bootdv;
793
794	bootpath_print(bootpath);
795
796	bp = nbootpath == 0 ? NULL : &bootpath[nbootpath-1];
797	bootdv = (bp == NULL) ? NULL : bp->dev;
798
799#if NMPATH > 0
800	if (bootdv != NULL)
801		bootdv = mpath_bootdv(bootdv);
802#endif
803
804	setroot(bootdv, bp->val[2], RB_USERREQ | RB_HALT);
805	dumpconf();
806}
807
808char *
809clockfreq(long freq)
810{
811	char *p;
812	static char buf[10];
813
814	freq /= 1000;
815	snprintf(buf, sizeof buf, "%ld", freq / 1000);
816	freq %= 1000;
817	if (freq) {
818		freq += 1000;	/* now in 1000..1999 */
819		p = buf + strlen(buf);
820		snprintf(p, buf + sizeof buf - p, "%ld", freq);
821		*p = '.';	/* now buf = %d.%3d */
822	}
823	return (buf);
824}
825
826static int
827mbprint(void *aux, const char *name)
828{
829	struct mainbus_attach_args *ma = aux;
830
831	if (name)
832		printf("\"%s\" at %s", ma->ma_name, name);
833	if (ma->ma_address)
834		printf(" addr 0x%08lx", (u_long)ma->ma_address[0]);
835	if (ma->ma_pri)
836		printf(" ipl %d", ma->ma_pri);
837	return (UNCONF);
838}
839
840int
841findroot(void)
842{
843	int node;
844
845	if ((node = rootnode) == 0 && (node = OF_peer(0)) == 0)
846		panic("no PROM root device");
847	rootnode = node;
848	return (node);
849}
850
851/*
852 * Given a `first child' node number, locate the node with the given name.
853 * Return the node number, or 0 if not found.
854 */
855int
856findnode(int first, const char *name)
857{
858	int node;
859	char buf[32];
860
861	for (node = first; node; node = OF_peer(node)) {
862		if ((OF_getprop(node, "name", buf, sizeof(buf)) > 0) &&
863			(strcmp(buf, name) == 0))
864			return (node);
865	}
866	return (0);
867}
868
869int
870mainbus_match(struct device *parent, void *cf, void *aux)
871{
872	return (1);
873}
874
875/*
876 * Attach the mainbus.
877 *
878 * Our main job is to attach the CPU (the root node we got in cpu_configure())
879 * and iterate down the list of `mainbus devices' (children of that node).
880 * We also record the `node id' of the default frame buffer, if any.
881 */
882static void
883mainbus_attach(struct device *parent, struct device *dev, void *aux)
884{
885extern struct sparc_bus_dma_tag mainbus_dma_tag;
886extern bus_space_tag_t mainbus_space_tag;
887
888	struct mainbus_attach_args ma;
889	char buf[64];
890	const char *const *ssp, *sp = NULL;
891	int node0, node, rv, len;
892
893	static const char *const openboot_special[] = {
894		/* ignore these (end with NULL) */
895		/*
896		 * These are _root_ devices to ignore. Others must be handled
897		 * elsewhere.
898		 */
899		"virtual-memory",
900		"aliases",
901		"memory",
902		"openprom",
903		"options",
904		"packages",
905		"chosen",
906		"counter-timer",
907		NULL
908	};
909
910	/*
911	 * Print the "banner-name" property in dmesg.  It provides a
912	 * description of the machine that is generally more
913	 * informative than the "name" property.  However, if the
914	 * "banner-name" property is missing, fall back on the "name"
915	 * property.
916	 */
917	if (OF_getprop(findroot(), "banner-name", buf, sizeof(buf)) > 0 ||
918	    OF_getprop(findroot(), "name", buf, sizeof(buf)) > 0)
919		printf(": %s\n", buf);
920	else
921		printf("\n");
922
923	/*
924	 * Base the hw.product and hw.vendor strings on the "name"
925	 * property.  They describe the hardware in a much more
926	 * consistent way than the "banner-property".
927	 */
928	if ((len = OF_getprop(findroot(), "name", buf, sizeof(buf))) > 0) {
929		hw_prod = malloc(len, M_DEVBUF, M_NOWAIT);
930		if (hw_prod)
931			strlcpy(hw_prod, buf, len);
932
933		if (strncmp(buf, "SUNW,", 5) == 0)
934			hw_vendor = "Sun";
935		if (strncmp(buf, "FJSV,", 5) == 0)
936			hw_vendor = "Fujitsu";
937		if (strncmp(buf, "TAD,", 4) == 0)
938			hw_vendor = "Tadpole";
939		if (strncmp(buf, "NATE,", 5) == 0)
940			hw_vendor = "Naturetech";
941		if (strncmp(buf, "ORCL,", 5) == 0)
942			hw_vendor = "Oracle";
943
944		/*
945		 * The Momentum Leopard-V advertises itself as
946		 * SUNW,UltraSPARC-IIi-Engine, but can be
947		 * distinguished by looking at the "model" property.
948		 */
949		if (OF_getprop(findroot(), "model", buf, sizeof(buf)) > 0 &&
950		    strncmp(buf, "MOMENTUM,", 9) == 0)
951			hw_vendor = "Momentum";
952	}
953
954	/* Establish the first component of the boot path */
955	bootpath_store(1, bootpath);
956
957	/* We configure the CPUs first. */
958
959	node = findroot();
960	for (node0 = OF_child(node); node0; node0 = OF_peer(node0)) {
961		if (OF_getprop(node0, "name", buf, sizeof(buf)) <= 0)
962			continue;
963	}
964
965	for (node = OF_child(node); node; node = OF_peer(node)) {
966		if (!checkstatus(node))
967			continue;
968
969		/*
970		 * UltraSPARC-IV cpus appear as two "cpu" nodes below
971		 * a "cmp" node.
972		 */
973		if (OF_getprop(node, "name", buf, sizeof(buf)) <= 0)
974			continue;
975		if (strcmp(buf, "cmp") == 0) {
976			bzero(&ma, sizeof(ma));
977			ma.ma_node = node;
978			ma.ma_name = buf;
979			getprop(node, "reg", sizeof(*ma.ma_reg),
980			    &ma.ma_nreg, (void **)&ma.ma_reg);
981			config_found(dev, &ma, mbprint);
982			continue;
983		}
984
985		if (OF_getprop(node, "device_type", buf, sizeof(buf)) <= 0)
986			continue;
987		if (strcmp(buf, "cpu") == 0) {
988			bzero(&ma, sizeof(ma));
989			ma.ma_node = node;
990			OF_getprop(node, "name", buf, sizeof(buf));
991			if (strcmp(buf, "cpu") == 0)
992				OF_getprop(node, "compatible", buf, sizeof(buf));
993			ma.ma_name = buf;
994			getprop(node, "reg", sizeof(*ma.ma_reg),
995			    &ma.ma_nreg, (void **)&ma.ma_reg);
996			config_found(dev, &ma, mbprint);
997			continue;
998		}
999	}
1000
1001	node = findroot();	/* re-init root node */
1002
1003	/* Find the "options" node */
1004	node0 = OF_child(node);
1005	optionsnode = findnode(node0, "options");
1006	if (optionsnode == 0)
1007		panic("no options in OPENPROM");
1008
1009	for (node0 = OF_child(node); node0; node0 = OF_peer(node0)) {
1010		if (OF_getprop(node0, "name", buf, sizeof(buf)) <= 0)
1011			continue;
1012	}
1013
1014	/*
1015	 * Configure the devices, in PROM order.  Skip
1016	 * PROM entries that are not for devices, or which must be
1017	 * done before we get here.
1018	 */
1019	for (node = OF_child(node); node; node = OF_peer(node)) {
1020		int portid;
1021
1022		DPRINTF(ACDB_PROBE, ("Node: %x", node));
1023		if (OF_getprop(node, "device_type", buf, sizeof(buf)) > 0 &&
1024		    strcmp(buf, "cpu") == 0)
1025			continue;
1026		if (OF_getprop(node, "name", buf, sizeof(buf)) > 0 &&
1027		    strcmp(buf, "cmp") == 0)
1028			continue;
1029		DPRINTF(ACDB_PROBE, (" name %s\n", buf));
1030		for (ssp = openboot_special; (sp = *ssp) != NULL; ssp++)
1031			if (strcmp(buf, sp) == 0)
1032				break;
1033		if (sp != NULL)
1034			continue; /* an "early" device already configured */
1035
1036		if (!checkstatus(node))
1037			continue;
1038
1039		bzero(&ma, sizeof ma);
1040		ma.ma_bustag = mainbus_space_tag;
1041		ma.ma_dmatag = &mainbus_dma_tag;
1042		ma.ma_name = buf;
1043		ma.ma_node = node;
1044		if (OF_getprop(node, "upa-portid", &portid, sizeof(portid)) !=
1045		    sizeof(portid)) {
1046			if (OF_getprop(node, "portid", &portid,
1047			    sizeof(portid)) != sizeof(portid))
1048				portid = -1;
1049		}
1050		ma.ma_upaid = portid;
1051
1052		if (getprop(node, "reg", sizeof(*ma.ma_reg),
1053			     &ma.ma_nreg, (void **)&ma.ma_reg) != 0)
1054			continue;
1055#ifdef DEBUG
1056		if (autoconf_debug & ACDB_PROBE) {
1057			if (ma.ma_nreg)
1058				printf(" reg %08lx.%08lx\n",
1059					(long)ma.ma_reg->ur_paddr,
1060					(long)ma.ma_reg->ur_len);
1061			else
1062				printf(" no reg\n");
1063		}
1064#endif
1065		rv = getprop(node, "interrupts", sizeof(*ma.ma_interrupts),
1066			&ma.ma_ninterrupts, (void **)&ma.ma_interrupts);
1067		if (rv != 0 && rv != ENOENT) {
1068			free(ma.ma_reg, M_DEVBUF, 0);
1069			continue;
1070		}
1071#ifdef DEBUG
1072		if (autoconf_debug & ACDB_PROBE) {
1073			if (ma.ma_interrupts)
1074				printf(" interrupts %08x\n",
1075					*ma.ma_interrupts);
1076			else
1077				printf(" no interrupts\n");
1078		}
1079#endif
1080		rv = getprop(node, "address", sizeof(*ma.ma_address),
1081			&ma.ma_naddress, (void **)&ma.ma_address);
1082		if (rv != 0 && rv != ENOENT) {
1083			free(ma.ma_reg, M_DEVBUF, 0);
1084			free(ma.ma_interrupts, M_DEVBUF, 0);
1085			continue;
1086		}
1087#ifdef DEBUG
1088		if (autoconf_debug & ACDB_PROBE) {
1089			if (ma.ma_naddress)
1090				printf(" address %08x\n",
1091					*ma.ma_address);
1092			else
1093				printf(" no address\n");
1094		}
1095#endif
1096		config_found(dev, &ma, mbprint);
1097		free(ma.ma_reg, M_DEVBUF, 0);
1098		free(ma.ma_interrupts, M_DEVBUF, 0);
1099		free(ma.ma_address, M_DEVBUF, 0);
1100	}
1101
1102	extern int prom_cngetc(dev_t);
1103
1104	/* Attach PROM console if no other console attached. */
1105	if (cn_tab->cn_getc == prom_cngetc) {
1106		bzero(&ma, sizeof ma);
1107		ma.ma_name = "pcons";
1108		config_found(dev, &ma, mbprint);
1109	}
1110
1111	extern todr_chip_handle_t todr_handle;
1112
1113	if (todr_handle == NULL) {
1114		bzero(&ma, sizeof ma);
1115		ma.ma_name = "prtc";
1116		config_found(dev, &ma, mbprint);
1117	}
1118}
1119
1120const struct cfattach mainbus_ca = {
1121	sizeof(struct device), mainbus_match, mainbus_attach
1122};
1123
1124int
1125getprop(int node, char *name, size_t size, int *nitem, void **bufp)
1126{
1127	void	*buf;
1128	long	len;
1129
1130	*nitem = 0;
1131	len = getproplen(node, name);
1132	if (len <= 0)
1133		return (ENOENT);
1134
1135	if ((len % size) != 0)
1136		return (EINVAL);
1137
1138	buf = *bufp;
1139	if (buf == NULL) {
1140		/* No storage provided, so we allocate some */
1141		buf = malloc(len + 1, M_DEVBUF, M_NOWAIT);
1142		if (buf == NULL)
1143			return (ENOMEM);
1144	}
1145
1146	OF_getprop(node, name, buf, len);
1147	*bufp = buf;
1148	*nitem = len / size;
1149	return (0);
1150}
1151
1152
1153/*
1154 * Internal form of proplen().  Returns the property length.
1155 */
1156long
1157getproplen(int node, char *name)
1158{
1159	return (OF_getproplen(node, name));
1160}
1161
1162/*
1163 * Return a string property.  There is a (small) limit on the length;
1164 * the string is fetched into a static buffer which is overwritten on
1165 * subsequent calls.
1166 */
1167char *
1168getpropstring(int node, char *name)
1169{
1170	static char stringbuf[32];
1171
1172	return (getpropstringA(node, name, stringbuf));
1173}
1174
1175/* Alternative getpropstring(), where caller provides the buffer */
1176char *
1177getpropstringA(int node, char *name, char *buffer)
1178{
1179	int blen;
1180
1181	if (getprop(node, name, 1, &blen, (void **)&buffer) != 0)
1182		blen = 0;
1183
1184	buffer[blen] = '\0';	/* usually unnecessary */
1185	return (buffer);
1186}
1187
1188/*
1189 * Fetch an integer (or pointer) property.
1190 * The return value is the property, or the default if there was none.
1191 */
1192int
1193getpropint(int node, char *name, int deflt)
1194{
1195	int intbuf;
1196
1197	if (OF_getprop(node, name, &intbuf, sizeof(intbuf)) != sizeof(intbuf))
1198		return (deflt);
1199
1200	return (intbuf);
1201}
1202
1203int
1204getpropspeed(int node, char *name)
1205{
1206	char buf[128];
1207	int i, speed = 0;
1208
1209	if (OF_getprop(node, name, buf, sizeof(buf)) != -1) {
1210		for (i = 0; i < sizeof(buf); i++) {
1211			if (buf[i] < '0' || buf[i] > '9')
1212				break;
1213			speed *= 10;
1214			speed += buf[i] - '0';
1215		}
1216	}
1217
1218	if (speed == 0)
1219		speed = 9600;
1220
1221	return (speed);
1222}
1223
1224/*
1225 * OPENPROM functions.  These are here mainly to hide the OPENPROM interface
1226 * from the rest of the kernel.
1227 */
1228int
1229firstchild(int node)
1230{
1231
1232	return OF_child(node);
1233}
1234
1235int
1236nextsibling(int node)
1237{
1238
1239	return OF_peer(node);
1240}
1241
1242int
1243checkstatus(int node)
1244{
1245	char buf[32];
1246
1247	/* If there is no "status" property, assume everything is fine. */
1248	if (OF_getprop(node, "status", buf, sizeof(buf)) <= 0)
1249		return 1;
1250
1251	/*
1252	 * If OpenBoot Diagnostics discovers a problem with a device
1253	 * it will mark it with "fail" or "fail-xxx", where "xxx" is
1254	 * additional human-readable information about the particular
1255	 * fault-condition.
1256	 */
1257	if (strcmp(buf, "disabled") == 0 || strncmp(buf, "fail", 4) == 0)
1258		return 0;
1259
1260	return 1;
1261}
1262
1263/* returns 1 if node has given property */
1264int
1265node_has_property(int node, const char *prop)
1266{
1267	return (OF_getproplen(node, (caddr_t)prop) != -1);
1268}
1269
1270/*
1271 * Try to figure out where the PROM stores the cursor row & column
1272 * variables.  Returns nonzero on error.
1273 */
1274int
1275romgetcursoraddr(int **rowp, int **colp)
1276{
1277	cell_t row = 0, col = 0;
1278
1279	OF_interpret("stdout @ is my-self addr line# addr column# ",
1280	    2, &col, &row);
1281
1282	/*
1283	 * We are running on a 64-bit big-endian machine, so these things
1284	 * point to 64-bit big-endian values.  To convert them to pointers
1285	 * to int, add 4 to the address.
1286	 */
1287	if (row == 0 || col == 0)
1288		return (-1);
1289	*rowp = (int *)(row + 4);
1290	*colp = (int *)(col + 4);
1291	return (0);
1292}
1293
1294void
1295callrom(void)
1296{
1297
1298	__asm volatile("wrpr	%%g0, 0, %%tl" : );
1299	OF_enter();
1300}
1301
1302/*
1303 * find a device matching "name" and unit number
1304 */
1305struct device *
1306getdevunit(const char *name, int unit)
1307{
1308	struct device *dev = TAILQ_FIRST(&alldevs);
1309	char num[10], fullname[16];
1310	int lunit;
1311
1312	/* compute length of name and decimal expansion of unit number */
1313	snprintf(num, sizeof num, "%d", unit);
1314	lunit = strlen(num);
1315	if (strlen(name) + lunit >= sizeof(fullname) - 1)
1316		panic("config_attach: device name too long");
1317
1318	strlcpy(fullname, name, sizeof fullname);
1319	strlcat(fullname, num, sizeof fullname);
1320
1321	while (strcmp(dev->dv_xname, fullname) != 0) {
1322		if ((dev = TAILQ_NEXT(dev, dv_list)) == NULL)
1323			return NULL;
1324	}
1325	return dev;
1326}
1327
1328void
1329device_register(struct device *dev, void *aux)
1330{
1331	struct mainbus_attach_args *ma = aux;
1332	struct pci_attach_args *pa = aux;
1333	struct sbus_attach_args *sa = aux;
1334	struct vbus_attach_args *va = aux;
1335	struct cbus_attach_args *ca = aux;
1336	struct bootpath *bp = bootpath_store(0, NULL);
1337	struct device *busdev = dev->dv_parent;
1338	const char *devname = dev->dv_cfdata->cf_driver->cd_name;
1339	const char *busname;
1340	int node = -1;
1341
1342	/*
1343	 * There is no point in continuing if we've exhausted all
1344	 * bootpath components.
1345	 */
1346	if (bp == NULL)
1347		return;
1348
1349	DPRINTF(ACDB_BOOTDEV,
1350	    ("\n%s: device_register: devname %s(%s) component %s\n",
1351	    dev->dv_xname, devname, dev->dv_xname, bp->name));
1352
1353	/*
1354	 * Ignore mainbus0 itself, it certainly is not a boot device.
1355	 */
1356	if (busdev == NULL)
1357		return;
1358
1359	/*
1360	 * We don't know the type of 'aux'; it depends on the bus this
1361	 * device attaches to.  We are only interested in certain bus
1362	 * types; this is only used to find the boot device.
1363	 */
1364	busname = busdev->dv_cfdata->cf_driver->cd_name;
1365	if (strcmp(busname, "mainbus") == 0 ||
1366	    strcmp(busname, "ssm") == 0 || strcmp(busname, "upa") == 0)
1367		node = ma->ma_node;
1368	else if (strcmp(busname, "sbus") == 0 ||
1369	    strcmp(busname, "dma") == 0 || strcmp(busname, "ledma") == 0)
1370		node = sa->sa_node;
1371	else if (strcmp(busname, "vbus") == 0)
1372		node = va->va_node;
1373	else if (strcmp(busname, "cbus") == 0)
1374		node = ca->ca_node;
1375	else if (strcmp(busname, "pci") == 0)
1376		node = PCITAG_NODE(pa->pa_tag);
1377
1378	if (node == bootnode) {
1379		if (strcmp(devname, "vdsk") == 0) {
1380			/*
1381			 * For virtual disks, don't nail the boot
1382			 * device just yet.  Instead, we add fake a
1383			 * SCSI target/lun, such that we match it the
1384			 * next time around.
1385			 */
1386			bp->dev = dev;
1387			(bp + 1)->val[0] = 0;
1388			(bp + 1)->val[1] = 0;
1389			nbootpath++;
1390			bootpath_store(1, bp + 1);
1391			return;
1392		}
1393
1394		nail_bootdev(dev, bp);
1395		return;
1396	}
1397
1398	if (node == bp->node) {
1399		bp->dev = dev;
1400		DPRINTF(ACDB_BOOTDEV, ("\t-- matched component %s to %s\n",
1401		    bp->name, dev->dv_xname));
1402		bootpath_store(1, bp + 1);
1403		return;
1404	}
1405
1406	if (strcmp(devname, "scsibus") == 0) {
1407		/*
1408		 * Booting from anything but the first (physical) port
1409		 * isn't supported by OBP.
1410		 */
1411		if (strcmp(bp->name, "fp") == 0 && bp->val[0] == 0) {
1412			DPRINTF(ACDB_BOOTDEV, ("\t-- matched component %s to %s\n",
1413			    bp->name, dev->dv_xname));
1414			bootpath_store(1, bp + 1);
1415			return;
1416		}
1417	}
1418
1419	if (strcmp(busname, "scsibus") == 0) {
1420		/*
1421		 * A SCSI disk or cd; retrieve target/lun information
1422		 * from parent and match with current bootpath component.
1423		 * Note that we also have look back past the `scsibus'
1424		 * device to determine whether this target is on the
1425		 * correct controller in our boot path.
1426		 */
1427		struct scsi_attach_args *sa = aux;
1428		struct scsi_link *sl = sa->sa_sc_link;
1429		u_int target = bp->val[0];
1430		u_int lun = bp->val[1];
1431
1432		if (bp->val[0] & 0xffffffff00000000 && bp->val[0] != -1) {
1433			/* Hardware RAID or Fibre channel? */
1434			if (bp->val[0] == sl->port_wwn && lun == sl->lun) {
1435				nail_bootdev(dev, bp);
1436			}
1437
1438			/*
1439			 * sata devices on some controllers don't get
1440			 * port_wwn filled in, so look at devid too.
1441			 */
1442			if (sl->id && sl->id->d_len == 8 &&
1443			    sl->id->d_type == DEVID_NAA &&
1444			    memcmp(sl->id + 1, &bp->val[0], 8) == 0)
1445				nail_bootdev(dev, bp);
1446			return;
1447		}
1448
1449		/* Check the controller that this scsibus is on. */
1450		if ((bp-1)->dev != sl->bus->sc_dev.dv_parent)
1451			return;
1452
1453		/*
1454		 * Bounds check: we know the target and lun widths.
1455		 */
1456		if (target >= sl->bus->sb_adapter_buswidth ||
1457		    lun >= sl->bus->sb_luns) {
1458			printf("SCSI disk bootpath component not accepted: "
1459			       "target %u; lun %u\n", target, lun);
1460			return;
1461		}
1462
1463		if (target == sl->target && lun == sl->lun) {
1464			nail_bootdev(dev, bp);
1465			return;
1466		}
1467	}
1468
1469	if (strcmp("wd", devname) == 0) {
1470		/* IDE disks. */
1471		struct ata_atapi_attach *aa = aux;
1472		u_int channel, drive;
1473
1474		if (strcmp(bp->name, "ata") == 0 &&
1475		    bp->val[0] == aa->aa_channel) {
1476			channel = bp->val[0]; bp++;
1477			drive = bp->val[0];
1478		} else {
1479			channel = bp->val[0] / 2;
1480			drive = bp->val[0] % 2;
1481		}
1482
1483		if (channel == aa->aa_channel &&
1484		    drive == aa->aa_drv_data->drive) {
1485			nail_bootdev(dev, bp);
1486			return;
1487		}
1488	}
1489}
1490
1491void
1492nail_bootdev(struct device *dev, struct bootpath *bp)
1493{
1494
1495	if (bp->dev != NULL)
1496		panic("device_register: already got a boot device: %s",
1497			bp->dev->dv_xname);
1498
1499	/*
1500	 * Mark this bootpath component by linking it to the matched
1501	 * device. We pick up the device pointer in cpu_rootconf().
1502	 */
1503	booted_device = bp->dev = dev;
1504	DPRINTF(ACDB_BOOTDEV, ("\t-- found bootdevice: %s\n",dev->dv_xname));
1505
1506	/*
1507	 * Then clear the current bootpath component, so we don't spuriously
1508	 * match similar instances on other busses, e.g. a disk on
1509	 * another SCSI bus with the same target.
1510	 */
1511	bootpath_store(1, NULL);
1512}
1513
1514const struct nam2blk nam2blk[] = {
1515	{ "rd",		 5 },
1516	{ "sd",		 7 },
1517	{ "vnd",	 8 },
1518	{ "wd",		12 },
1519	{ "fd",		16 },
1520	{ "cd",		18 },
1521	{ NULL,		-1 }
1522};
1523