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
111 int 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 */
118 int stdinnode; /* node ID of ROM's console input device */
119 int fbnode; /* node ID of ROM's console output device */
120 int optionsnode; /* node ID of ROM's options */
121
122 static int rootnode;
123
124 static char *str2hex(char *, long *);
125 static int mbprint(void *, const char *);
126 int mainbus_match(struct device *, void *, void *);
127 static void mainbus_attach(struct device *, struct device *, void *);
128 int get_ncpus(void);
129
130 struct device *booted_device;
131 struct bootpath bootpath[16];
132 int nbootpath;
133 int bootnode;
134 static void bootpath_build(void);
135 static void bootpath_print(struct bootpath *);
136 void bootpath_nodes(struct bootpath *, int);
137
138 struct openbsd_bootdata obd __attribute__((section(".openbsd.bootdata")));
139
140 void nail_bootdev(struct device *, struct bootpath *);
141
142 /* Global interrupt mappings for all device types. Match against the OBP
143 * 'device_type' property.
144 */
145 struct 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
160 void sun4v_soft_state_init(void);
161 void sun4v_set_soft_state(int, const char *);
162
163 #define __align32 __attribute__((__aligned__(32)))
164 char sun4v_soft_state_booting[] __align32 = "OpenBSD booting";
165 char sun4v_soft_state_running[] __align32 = "OpenBSD running";
166
167 void sun4v_interrupt_init(void);
168 void sun4v_sdio_init(void);
169 #endif
170
171 extern void us_tlb_flush_pte(vaddr_t, uint64_t);
172 extern void us3_tlb_flush_pte(vaddr_t, uint64_t);
173 extern void sun4v_tlb_flush_pte(vaddr_t, uint64_t);
174 extern void us_tlb_flush_ctx(uint64_t);
175 extern void us3_tlb_flush_ctx(uint64_t);
176 extern void sun4v_tlb_flush_ctx(uint64_t);
177
178 void (*sp_tlb_flush_pte)(vaddr_t, uint64_t) = us_tlb_flush_pte;
179 void (*sp_tlb_flush_ctx)(uint64_t) = us_tlb_flush_ctx;
180
181 #ifdef DEBUG
182 #define ACDB_BOOTDEV 0x1
183 #define ACDB_PROBE 0x2
184 int 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 */
194 static char *
str2hex(char * str,long * vp)195 str2hex(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 */
240 int
get_ncpus(void)241 get_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
272 done:
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 */
296 void
bootstrap(int nctx)297 bootstrap(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
442 void
bootpath_nodes(struct bootpath * bp,int nbp)443 bootpath_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
485 static void
bootpath_build(void)486 bootpath_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
598 static void
bootpath_print(struct bootpath * bp)599 bootpath_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 */
622 struct bootpath *
bootpath_store(int storep,struct bootpath * bp)623 bootpath_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 */
640 void
cpu_configure(void)641 cpu_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
733 int sun4v_soft_state_initialized = 0;
734
735 void
sun4v_soft_state_init(void)736 sun4v_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
747 void
sun4v_set_soft_state(int state,const char * desc)748 sun4v_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
764 void
sun4v_interrupt_init(void)765 sun4v_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
775 void
sun4v_sdio_init(void)776 sun4v_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
788 void
diskconf(void)789 diskconf(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
808 char *
clockfreq(long freq)809 clockfreq(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
826 static int
mbprint(void * aux,const char * name)827 mbprint(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
840 int
findroot(void)841 findroot(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 */
855 int
findnode(int first,const char * name)856 findnode(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
869 int
mainbus_match(struct device * parent,void * cf,void * aux)870 mainbus_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 */
882 static void
mainbus_attach(struct device * parent,struct device * dev,void * aux)883 mainbus_attach(struct device *parent, struct device *dev, void *aux)
884 {
885 extern struct sparc_bus_dma_tag mainbus_dma_tag;
886 extern 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
1120 const struct cfattach mainbus_ca = {
1121 sizeof(struct device), mainbus_match, mainbus_attach
1122 };
1123
1124 int
getprop(int node,char * name,size_t size,int * nitem,void ** bufp)1125 getprop(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 */
1156 long
getproplen(int node,char * name)1157 getproplen(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 */
1167 char *
getpropstring(int node,char * name)1168 getpropstring(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 */
1176 char *
getpropstringA(int node,char * name,char * buffer)1177 getpropstringA(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 */
1192 int
getpropint(int node,char * name,int deflt)1193 getpropint(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
1203 int
getpropspeed(int node,char * name)1204 getpropspeed(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 */
1228 int
firstchild(int node)1229 firstchild(int node)
1230 {
1231
1232 return OF_child(node);
1233 }
1234
1235 int
nextsibling(int node)1236 nextsibling(int node)
1237 {
1238
1239 return OF_peer(node);
1240 }
1241
1242 int
checkstatus(int node)1243 checkstatus(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 */
1264 int
node_has_property(int node,const char * prop)1265 node_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 */
1274 int
romgetcursoraddr(int ** rowp,int ** colp)1275 romgetcursoraddr(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
1294 void
callrom(void)1295 callrom(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 */
1305 struct device *
getdevunit(const char * name,int unit)1306 getdevunit(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
1328 void
device_register(struct device * dev,void * aux)1329 device_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
1491 void
nail_bootdev(struct device * dev,struct bootpath * bp)1492 nail_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
1514 const 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