1 /* $NetBSD: autoconf.c,v 1.207 2015/12/16 08:01:19 jdc Exp $ */
2
3 /*
4 * Copyright (c) 1996
5 * The President and Fellows of Harvard College. All rights reserved.
6 * Copyright (c) 1992, 1993
7 * The Regents of the University of California. All rights reserved.
8 *
9 * This software was developed by the Computer Systems Engineering group
10 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
11 * contributed to Berkeley.
12 *
13 * All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Harvard University.
16 * This product includes software developed by the University of
17 * California, Lawrence Berkeley Laboratory.
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions
21 * are met:
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 * 3. All advertising materials mentioning features or use of this software
28 * must display the following acknowledgement:
29 * This product includes software developed by the University of
30 * California, Berkeley and its contributors.
31 * 4. Neither the name of the University nor the names of its contributors
32 * may be used to endorse or promote products derived from this software
33 * without specific prior written permission.
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
36 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
39 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * SUCH DAMAGE.
46 *
47 * @(#)autoconf.c 8.4 (Berkeley) 10/1/93
48 */
49
50 #include <sys/cdefs.h>
51 __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.207 2015/12/16 08:01:19 jdc Exp $");
52
53 #include "opt_ddb.h"
54 #include "opt_kgdb.h"
55 #include "opt_modular.h"
56 #include "opt_multiprocessor.h"
57
58 #include <sys/param.h>
59 #include <sys/kernel.h>
60 #include <sys/systm.h>
61 #include <sys/buf.h>
62 #include <sys/disklabel.h>
63 #include <sys/device.h>
64 #include <sys/disk.h>
65 #include <sys/conf.h>
66 #include <sys/reboot.h>
67 #include <sys/socket.h>
68 #include <sys/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
117 struct 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
136 void *bootinfo = 0;
137
138 #ifdef KGDB
139 int kgdb_break_at_attach;
140 #endif
141
142 #define OFPATHLEN 128
143 #define OFNODEKEY "OFpnode"
144
145 char machine_banner[100];
146 char machine_model[100];
147 char ofbootpath[OFPATHLEN], *ofboottarget, *ofbootpartition;
148 char ofbootargs[OFPATHLEN], *ofbootfile, *ofbootflags;
149 int ofbootpackage;
150
151 static int mbprint(void *, const char *);
152 int mainbus_match(device_t, cfdata_t, void *);
153 static void mainbus_attach(device_t, device_t, void *);
154 static void get_ncpus(void);
155 static void get_bootpath_from_prom(void);
156
157 /*
158 * Kernel 4MB mappings.
159 */
160 struct tlb_entry *kernel_tlbs;
161 int kernel_dtlb_slots;
162 int kernel_itlb_slots;
163
164 /* Global interrupt mappings for all device types. Match against the OBP
165 * 'device_type' property.
166 */
167 struct intrmap intrmap[] = {
168 { "block", PIL_FD }, /* Floppy disk */
169 { "serial", PIL_SER }, /* zs */
170 { "scsi", PIL_SCSI },
171 { "scsi-2", PIL_SCSI },
172 { "network", PIL_NET },
173 { "display", PIL_VIDEO },
174 { "audio", PIL_AUD },
175 { "ide", PIL_SCSI },
176 /* The following devices don't have device types: */
177 { "SUNW,CS4231", PIL_AUD },
178 { NULL, 0 }
179 };
180
181 #ifdef DEBUG
182 #define ACDB_BOOTDEV 0x1
183 #define ACDB_PROBE 0x2
184 #define ACDB_BOOTARGS 0x4
185 int autoconf_debug = 0x0;
186 #define DPRINTF(l, s) do { if (autoconf_debug & l) printf s; } while (0)
187 #else
188 #define DPRINTF(l, s)
189 #endif
190
191 int console_node, console_instance;
192 struct genfb_colormap_callback gfb_cb;
193 static void of_set_palette(void *, int, int, int, int);
194 static void copyprops(device_t, int, prop_dictionary_t, int);
195
196 static void
get_ncpus(void)197 get_ncpus(void)
198 {
199 #ifdef MULTIPROCESSOR
200 int node, l;
201 char sbuf[32];
202
203 node = findroot();
204
205 sparc_ncpus = 0;
206 for (node = OF_child(node); node; node = OF_peer(node)) {
207 if (OF_getprop(node, "device_type", sbuf, sizeof(sbuf)) <= 0)
208 continue;
209 if (strcmp(sbuf, "cpu") != 0)
210 continue;
211 sparc_ncpus++;
212 l = prom_getpropint(node, "dcache-line-size", 0);
213 if (l > dcache_line_size)
214 dcache_line_size = l;
215 l = prom_getpropint(node, "icache-line-size", 0);
216 if (l > icache_line_size)
217 icache_line_size = l;
218 }
219 #else
220 /* #define sparc_ncpus 1 */
221 icache_line_size = dcache_line_size = 8; /* will be fixed later */
222 #endif
223 }
224
225 /*
226 * lookup_bootinfo:
227 * Look up information in bootinfo of boot loader.
228 */
229 void *
lookup_bootinfo(int type)230 lookup_bootinfo(int type)
231 {
232 struct btinfo_common *bt;
233 char *help = bootinfo;
234
235 /* Check for a bootinfo record first. */
236 if (help == NULL)
237 return (NULL);
238
239 do {
240 bt = (struct btinfo_common *)help;
241 if (bt->type == type)
242 return ((void *)help);
243 help += bt->next;
244 } while (bt->next != 0 &&
245 (size_t)help < (size_t)bootinfo + BOOTINFO_SIZE);
246
247 return (NULL);
248 }
249
250 /*
251 * locore.s code calls bootstrap() just before calling main().
252 *
253 * What we try to do is as follows:
254 * - Initialize PROM and the console
255 * - Read in part of information provided by a bootloader and find out
256 * kernel load and end addresses
257 * - Initialize ksyms
258 * - Find out number of active CPUs
259 * - Finalize the bootstrap by calling pmap_bootstrap()
260 *
261 * We will try to run out of the prom until we get out of pmap_bootstrap().
262 */
263 void
bootstrap(void * o0,void * bootargs,void * bootsize,void * o3,void * ofw)264 bootstrap(void *o0, void *bootargs, void *bootsize, void *o3, void *ofw)
265 {
266 void *bi;
267 long bmagic;
268 char buf[32];
269
270 #if NKSYMS || defined(DDB) || defined(MODULAR)
271 struct btinfo_symtab *bi_sym;
272 #endif
273 struct btinfo_count *bi_count;
274 struct btinfo_kernend *bi_kend;
275 struct btinfo_tlb *bi_tlb;
276 struct btinfo_boothowto *bi_howto;
277
278 extern void *romtba;
279 extern void* get_romtba(void);
280 extern void OF_val2sym32(void *);
281 extern void OF_sym2val32(void *);
282 extern struct consdev consdev_prom;
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 = &consdev_prom;
294 (*cn_tab->cn_init)(cn_tab);
295
296 DPRINTF(ACDB_BOOTARGS,
297 ("sparc64_init(%p, %p, %p, %p, %p)\n", o0, bootargs, bootsize,
298 o3, ofw));
299
300 /* Extract bootinfo pointer */
301 if ((long)bootsize >= (4 * sizeof(uint64_t))) {
302 /* Loaded by 64-bit bootloader */
303 bi = (void*)(u_long)(((uint64_t*)bootargs)[3]);
304 bmagic = (long)(((uint64_t*)bootargs)[0]);
305 } else if ((long)bootsize >= (4 * sizeof(uint32_t))) {
306 /* Loaded by 32-bit bootloader */
307 bi = (void*)(u_long)(((uint32_t*)bootargs)[3]);
308 bmagic = (long)(((uint32_t*)bootargs)[0]);
309 } else {
310 printf("Bad bootinfo size.\n");
311 die_old_boot_loader:
312 printf("This kernel requires NetBSD boot loader version 1.9 "
313 "or newer\n");
314 panic("sparc64_init.");
315 }
316
317 DPRINTF(ACDB_BOOTARGS,
318 ("sparc64_init: bmagic=%lx, bi=%p\n", bmagic, bi));
319
320 /* Read in the information provided by NetBSD boot loader */
321 if (SPARC_MACHINE_OPENFIRMWARE != bmagic) {
322 printf("No bootinfo information.\n");
323 goto die_old_boot_loader;
324 }
325
326 bootinfo = (void*)(u_long)((uint64_t*)bi)[1];
327 LOOKUP_BOOTINFO(bi_kend, BTINFO_KERNEND);
328
329 if (bi_kend->addr == (vaddr_t)0) {
330 panic("Kernel end address is not found in bootinfo.\n");
331 }
332
333 #if NKSYMS || defined(DDB) || defined(MODULAR)
334 LOOKUP_BOOTINFO(bi_sym, BTINFO_SYMTAB);
335 ksyms_addsyms_elf(bi_sym->nsym, (int *)(u_long)bi_sym->ssym,
336 (int *)(u_long)bi_sym->esym);
337 #ifdef DDB
338 #ifdef __arch64__
339 /* This can only be installed on an 64-bit system cause otherwise our stack is screwed */
340 OF_set_symbol_lookup(OF_sym2val, OF_val2sym);
341 #else
342 OF_set_symbol_lookup(OF_sym2val32, OF_val2sym32);
343 #endif
344 #endif
345 #endif
346 if (OF_getprop(findroot(), "compatible", buf, sizeof(buf)) > 0) {
347 if (strcmp(buf, "sun4us") == 0)
348 setcputyp(CPU_SUN4US);
349 else if (strcmp(buf, "sun4v") == 0)
350 setcputyp(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_dtlb_slots = bi_count->count;
359 kernel_itlb_slots = kernel_dtlb_slots-1;
360 bi_count = lookup_bootinfo(BTINFO_ITLB_SLOTS);
361 if (bi_count)
362 kernel_itlb_slots = bi_count->count;
363 LOOKUP_BOOTINFO(bi_tlb, BTINFO_DTLB);
364 kernel_tlbs = &bi_tlb->tlb[0];
365
366 get_ncpus();
367 pmap_bootstrap(KERNBASE, bi_kend->addr);
368 }
369
370 /*
371 * get_bootpath_from_prom()
372 * fetch the OF settings to identify our boot device during autoconfiguration
373 */
374
375 static void
get_bootpath_from_prom(void)376 get_bootpath_from_prom(void)
377 {
378 struct btinfo_bootdev *bdev = NULL;
379 char sbuf[OFPATHLEN], *cp;
380 int chosen;
381
382 /*
383 * Grab boot path from PROM
384 */
385 if ((chosen = OF_finddevice("/chosen")) == -1)
386 return;
387
388 bdev = lookup_bootinfo(BTINFO_BOOTDEV);
389 if (bdev != NULL) {
390 strcpy(ofbootpath, bdev->name);
391 } else {
392 if (OF_getprop(chosen, "bootpath", sbuf, sizeof(sbuf)) < 0)
393 return;
394 strcpy(ofbootpath, sbuf);
395 }
396 DPRINTF(ACDB_BOOTDEV, ("bootpath: %s\n", ofbootpath));
397 ofbootpackage = prom_finddevice(ofbootpath);
398
399 /*
400 * Strip partition or boot protocol
401 */
402 cp = strrchr(ofbootpath, ':');
403 if (cp) {
404 *cp = '\0';
405 ofbootpartition = cp+1;
406 }
407 cp = strrchr(ofbootpath, '@');
408 if (cp) {
409 for (; cp != ofbootpath; cp--) {
410 if (*cp == '/') {
411 ofboottarget = cp+1;
412 break;
413 }
414 }
415 }
416
417 DPRINTF(ACDB_BOOTDEV, ("bootpath phandle: 0x%x\n", ofbootpackage));
418 DPRINTF(ACDB_BOOTDEV, ("boot target: %s\n",
419 ofboottarget ? ofboottarget : "<none>"));
420 DPRINTF(ACDB_BOOTDEV, ("boot partition: %s\n",
421 ofbootpartition ? ofbootpartition : "<none>"));
422
423 /* Setup pointer to boot flags */
424 if (OF_getprop(chosen, "bootargs", sbuf, sizeof(sbuf)) == -1)
425 return;
426 strcpy(ofbootargs, sbuf);
427
428 cp = ofbootargs;
429
430 /* Find start of boot flags */
431 while (*cp) {
432 while(*cp == ' ' || *cp == '\t') cp++;
433 if (*cp == '-' || *cp == '\0')
434 break;
435 while(*cp != ' ' && *cp != '\t' && *cp != '\0') cp++;
436 if (*cp != '\0')
437 *cp++ = '\0';
438 }
439 if (cp != ofbootargs)
440 ofbootfile = ofbootargs;
441 ofbootflags = cp;
442 if (*cp != '-')
443 return;
444
445 for (;*++cp;) {
446 int fl;
447
448 fl = 0;
449 BOOT_FLAG(*cp, fl);
450 if (!fl) {
451 printf("unknown option `%c'\n", *cp);
452 continue;
453 }
454 boothowto |= fl;
455
456 /* specialties */
457 if (*cp == 'd') {
458 #if defined(KGDB)
459 kgdb_break_at_attach = 1;
460 #elif defined(DDB)
461 Debugger();
462 #else
463 printf("kernel has no debugger\n");
464 #endif
465 } else if (*cp == 't') {
466 /* turn on traptrace w/o breaking into kdb */
467 extern int trap_trace_dis;
468
469 trap_trace_dis = 0;
470 }
471 }
472 }
473
474 /*
475 * Determine mass storage and memory configuration for a machine.
476 * We get the PROM's root device and make sure we understand it, then
477 * attach it as `mainbus0'. We also set up to handle the PROM `sync'
478 * command.
479 */
480 void
cpu_configure(void)481 cpu_configure(void)
482 {
483
484 bool userconf = (boothowto & RB_USERCONF) != 0;
485
486 /* fetch boot device settings */
487 get_bootpath_from_prom();
488 if (((boothowto & RB_USERCONF) != 0) && !userconf)
489 /*
490 * Old bootloaders do not pass boothowto, and MI code
491 * has already handled userconfig before we get here
492 * and finally fetch the right options. So if we missed
493 * it, just do it here.
494 */
495 userconf_prompt();
496
497 /* block clock interrupts and anything below */
498 splclock();
499 /* Enable device interrupts */
500 setpstate(getpstate()|PSTATE_IE);
501
502 if (config_rootfound("mainbus", NULL) == NULL)
503 panic("mainbus not configured");
504
505 /* Enable device interrupts */
506 setpstate(getpstate()|PSTATE_IE);
507
508 (void)spl0();
509 }
510
511 void
cpu_rootconf(void)512 cpu_rootconf(void)
513 {
514 if (booted_device == NULL) {
515 printf("FATAL: boot device not found, check your firmware "
516 "settings!\n");
517 }
518
519 rootconf();
520 }
521
522 char *
clockfreq(long freq)523 clockfreq(long freq)
524 {
525 static char buf[10];
526 size_t len;
527
528 freq /= 1000;
529 len = snprintf(buf, sizeof(buf), "%ld", freq / 1000);
530 freq %= 1000;
531 if (freq)
532 snprintf(buf + len, sizeof(buf) - len, ".%03ld", freq);
533 return buf;
534 }
535
536 /* ARGSUSED */
537 static int
mbprint(void * aux,const char * name)538 mbprint(void *aux, const char *name)
539 {
540 struct mainbus_attach_args *ma = aux;
541
542 if (name)
543 aprint_normal("%s at %s", ma->ma_name, name);
544 if (ma->ma_address)
545 aprint_normal(" addr 0x%08lx", (u_long)ma->ma_address[0]);
546 if (ma->ma_pri)
547 aprint_normal(" ipl %d", ma->ma_pri);
548 return (UNCONF);
549 }
550
551 int
mainbus_match(device_t parent,cfdata_t cf,void * aux)552 mainbus_match(device_t parent, cfdata_t cf, void *aux)
553 {
554
555 return (1);
556 }
557
558 /*
559 * Attach the mainbus.
560 *
561 * Our main job is to attach the CPU (the root node we got in configure())
562 * and iterate down the list of `mainbus devices' (children of that node).
563 * We also record the `node id' of the default frame buffer, if any.
564 */
565 static void
mainbus_attach(device_t parent,device_t dev,void * aux)566 mainbus_attach(device_t parent, device_t dev, void *aux)
567 {
568 extern struct sparc_bus_dma_tag mainbus_dma_tag;
569 extern struct sparc_bus_space_tag mainbus_space_tag;
570
571 struct mainbus_attach_args ma;
572 char sbuf[32];
573 const char *const *ssp, *sp = NULL;
574 char *c;
575 int node0, node, rv, i;
576
577 static const char *const openboot_special[] = {
578 /* ignore these (end with NULL) */
579 /*
580 * These are _root_ devices to ignore. Others must be handled
581 * elsewhere.
582 */
583 "virtual-memory",
584 "aliases",
585 "memory",
586 "openprom",
587 "options",
588 "packages",
589 "chosen",
590 NULL
591 };
592
593 if (OF_getprop(findroot(), "banner-name", machine_banner,
594 sizeof machine_banner) < 0)
595 i = 0;
596 else {
597 i = 1;
598 if (((c = strchr(machine_banner, '(')) != NULL) &&
599 c != &machine_banner[0]) {
600 while (*c == '(' || *c == ' ') {
601 *c = '\0';
602 c--;
603 }
604 }
605 }
606 OF_getprop(findroot(), "name", machine_model, sizeof machine_model);
607 prom_getidprom();
608 if (i)
609 aprint_normal(": %s (%s): hostid %lx\n", machine_model,
610 machine_banner, hostid);
611 else
612 aprint_normal(": %s: hostid %lx\n", machine_model, hostid);
613 aprint_naive("\n");
614
615 /*
616 * Locate and configure the ``early'' devices. These must be
617 * configured before we can do the rest. For instance, the
618 * EEPROM contains the Ethernet address for the LANCE chip.
619 * If the device cannot be located or configured, panic.
620 */
621 if (sparc_ncpus == 0)
622 panic("None of the CPUs found");
623
624 /*
625 * Init static interrupt eventcounters
626 */
627 for (i = 0; i < __arraycount(intr_evcnts); i++)
628 evcnt_attach_static(&intr_evcnts[i]);
629
630 node = findroot();
631
632 /* first early device to be configured is the CPU */
633 for (node = OF_child(node); node; node = OF_peer(node)) {
634 if (OF_getprop(node, "device_type", sbuf, sizeof(sbuf)) <= 0)
635 continue;
636 if (strcmp(sbuf, "cpu") != 0)
637 continue;
638 memset(&ma, 0, sizeof(ma));
639 ma.ma_bustag = &mainbus_space_tag;
640 ma.ma_dmatag = &mainbus_dma_tag;
641 ma.ma_node = node;
642 ma.ma_name = "cpu";
643 config_found(dev, &ma, mbprint);
644 }
645
646 node = findroot(); /* re-init root node */
647
648 /* Find the "options" node */
649 node0 = OF_child(node);
650
651 /*
652 * Configure the devices, in PROM order. Skip
653 * PROM entries that are not for devices, or which must be
654 * done before we get here.
655 */
656 for (node = node0; node; node = OF_peer(node)) {
657 int portid;
658
659 DPRINTF(ACDB_PROBE, ("Node: %x", node));
660 if ((OF_getprop(node, "device_type", sbuf, sizeof(sbuf)) > 0) &&
661 strcmp(sbuf, "cpu") == 0)
662 continue;
663 OF_getprop(node, "name", sbuf, sizeof(sbuf));
664 DPRINTF(ACDB_PROBE, (" name %s\n", sbuf));
665 for (ssp = openboot_special; (sp = *ssp) != NULL; ssp++)
666 if (strcmp(sbuf, sp) == 0)
667 break;
668 if (sp != NULL)
669 continue; /* an "early" device already configured */
670
671 memset(&ma, 0, sizeof ma);
672 ma.ma_bustag = &mainbus_space_tag;
673 ma.ma_dmatag = &mainbus_dma_tag;
674 ma.ma_name = sbuf;
675 ma.ma_node = node;
676 if (OF_getprop(node, "upa-portid", &portid, sizeof(portid)) !=
677 sizeof(portid) &&
678 OF_getprop(node, "portid", &portid, sizeof(portid)) !=
679 sizeof(portid))
680 portid = -1;
681 ma.ma_upaid = portid;
682
683 if (prom_getprop(node, "reg", sizeof(*ma.ma_reg),
684 &ma.ma_nreg, &ma.ma_reg) != 0)
685 continue;
686 #ifdef DEBUG
687 if (autoconf_debug & ACDB_PROBE) {
688 if (ma.ma_nreg)
689 printf(" reg %08lx.%08lx\n",
690 (long)ma.ma_reg->ur_paddr,
691 (long)ma.ma_reg->ur_len);
692 else
693 printf(" no reg\n");
694 }
695 #endif
696 rv = prom_getprop(node, "interrupts", sizeof(*ma.ma_interrupts),
697 &ma.ma_ninterrupts, &ma.ma_interrupts);
698 if (rv != 0 && rv != ENOENT) {
699 free(ma.ma_reg, M_DEVBUF);
700 continue;
701 }
702 #ifdef DEBUG
703 if (autoconf_debug & ACDB_PROBE) {
704 if (ma.ma_interrupts)
705 printf(" interrupts %08x\n", *ma.ma_interrupts);
706 else
707 printf(" no interrupts\n");
708 }
709 #endif
710 rv = prom_getprop(node, "address", sizeof(*ma.ma_address),
711 &ma.ma_naddress, &ma.ma_address);
712 if (rv != 0 && rv != ENOENT) {
713 free(ma.ma_reg, M_DEVBUF);
714 if (ma.ma_ninterrupts)
715 free(ma.ma_interrupts, M_DEVBUF);
716 continue;
717 }
718 #ifdef DEBUG
719 if (autoconf_debug & ACDB_PROBE) {
720 if (ma.ma_naddress)
721 printf(" address %08x\n", *ma.ma_address);
722 else
723 printf(" no address\n");
724 }
725 #endif
726 (void) config_found(dev, (void *)&ma, mbprint);
727 free(ma.ma_reg, M_DEVBUF);
728 if (ma.ma_ninterrupts)
729 free(ma.ma_interrupts, M_DEVBUF);
730 if (ma.ma_naddress)
731 free(ma.ma_address, M_DEVBUF);
732 }
733 /* Try to attach PROM console */
734 memset(&ma, 0, sizeof ma);
735 ma.ma_name = "pcons";
736 (void) config_found(dev, (void *)&ma, mbprint);
737 }
738
739 CFATTACH_DECL_NEW(mainbus, 0,
740 mainbus_match, mainbus_attach, NULL, NULL);
741
742
743 /*
744 * Try to figure out where the PROM stores the cursor row & column
745 * variables. Returns nonzero on error.
746 */
747 int
romgetcursoraddr(int ** rowp,int ** colp)748 romgetcursoraddr(int **rowp, int **colp)
749 {
750 cell_t row = 0UL, col = 0UL;
751
752 OF_interpret("stdout @ is my-self addr line# addr column# ", 0, 2,
753 &col, &row);
754 /*
755 * We are running on a 64-bit machine, so these things point to
756 * 64-bit values. To convert them to pointers to integers, add
757 * 4 to the address.
758 */
759 *rowp = (int *)(intptr_t)(row+4);
760 *colp = (int *)(intptr_t)(col+4);
761 return (row == 0UL || col == 0UL);
762 }
763
764 /*
765 * Match a device_t against the bootpath, by
766 * comparing its firmware package handle. If they match
767 * exactly, we found the boot device.
768 */
769 static void
dev_path_exact_match(device_t dev,int ofnode)770 dev_path_exact_match(device_t dev, int ofnode)
771 {
772
773 if (ofnode != ofbootpackage)
774 return;
775
776 booted_device = dev;
777 DPRINTF(ACDB_BOOTDEV, ("found bootdevice: %s\n", device_xname(dev)));
778 }
779
780 /*
781 * Match a device_t against the bootpath, by
782 * comparing its firmware package handle and calculating
783 * the target/lun suffix and comparing that against
784 * the bootpath remainder.
785 */
786 static void
dev_path_drive_match(device_t dev,int ctrlnode,int target,uint64_t wwn,int lun)787 dev_path_drive_match(device_t dev, int ctrlnode, int target,
788 uint64_t wwn, int lun)
789 {
790 int child = 0, ide_node = 0;
791 char buf[OFPATHLEN];
792
793 DPRINTF(ACDB_BOOTDEV, ("dev_path_drive_match: %s, controller %x, "
794 "target %d wwn %016" PRIx64 " lun %d\n", device_xname(dev),
795 ctrlnode, target, wwn, lun));
796
797 /*
798 * The ofbootpackage points to a disk on this controller, so
799 * iterate over all child nodes and compare.
800 */
801 for (child = prom_firstchild(ctrlnode); child != 0;
802 child = prom_nextsibling(child))
803 if (child == ofbootpackage)
804 break;
805
806 if (child != ofbootpackage) {
807 /*
808 * Try Mac firmware style (also used by QEMU/OpenBIOS):
809 * below the controller there is an intermediate node
810 * for each IDE channel, and individual targets always
811 * are "@0"
812 */
813 for (ide_node = prom_firstchild(ctrlnode); ide_node != 0;
814 ide_node = prom_nextsibling(ide_node)) {
815 const char * name = prom_getpropstring(ide_node,
816 "device_type");
817 if (strcmp(name, "ide") != 0) continue;
818 for (child = prom_firstchild(ide_node); child != 0;
819 child = prom_nextsibling(child))
820 if (child == ofbootpackage)
821 break;
822 if (child == ofbootpackage)
823 break;
824 }
825 }
826
827 if (child == ofbootpackage) {
828 const char * name = prom_getpropstring(child, "name");
829
830 /* boot device is on this controller */
831 DPRINTF(ACDB_BOOTDEV, ("found controller of bootdevice\n"));
832
833 /*
834 * Note: "child" here is == ofbootpackage (s.a.), which
835 * may be completely wrong for the device we are checking,
836 * what we realy do here is to match "target" and "lun".
837 */
838 if (wwn)
839 snprintf(buf, sizeof(buf), "%s@w%016" PRIx64 ",%d",
840 name, wwn, lun);
841 else if (ide_node)
842 snprintf(buf, sizeof(buf), "%s@0",
843 device_is_a(dev, "cd") ? "cdrom" : "disk");
844 else
845 snprintf(buf, sizeof(buf), "%s@%d,%d",
846 name, target, lun);
847 if (ofboottarget && strcmp(buf, ofboottarget) == 0) {
848 booted_device = dev;
849 if (ofbootpartition)
850 booted_partition = *ofbootpartition - 'a';
851 DPRINTF(ACDB_BOOTDEV, ("found boot device: %s"
852 ", partition %d\n", device_xname(dev),
853 booted_partition));
854 }
855 }
856 }
857
858 /*
859 * Get the firmware package handle from a device_t.
860 * Assuming we have previously stored it in the device properties
861 * dictionary.
862 */
863 static int
device_ofnode(device_t dev)864 device_ofnode(device_t dev)
865 {
866 prop_dictionary_t props;
867 prop_object_t obj;
868
869 if (dev == NULL)
870 return 0;
871 props = device_properties(dev);
872 if (props == NULL)
873 return 0;
874 obj = prop_dictionary_get(props, OFNODEKEY);
875 if (obj == NULL)
876 return 0;
877
878 return prop_number_integer_value(obj);
879 }
880
881 /*
882 * Save the firmware package handle inside the properties dictionary
883 * of a device_t.
884 */
885 static void
device_setofnode(device_t dev,int node)886 device_setofnode(device_t dev, int node)
887 {
888 prop_dictionary_t props;
889 prop_object_t obj;
890
891 if (dev == NULL)
892 return;
893 props = device_properties(dev);
894 if (props == NULL)
895 return;
896 obj = prop_number_create_integer(node);
897 if (obj == NULL)
898 return;
899 prop_dictionary_set(props, OFNODEKEY, obj);
900 prop_object_release(obj);
901 DPRINTF(ACDB_BOOTDEV, (" [device %s has node %x] ",
902 device_xname(dev), node));
903 }
904
905 /*
906 * Called back during autoconfiguration for each device found
907 */
908 void
device_register(device_t dev,void * aux)909 device_register(device_t dev, void *aux)
910 {
911 device_t busdev = device_parent(dev);
912 int ofnode = 0;
913
914 /*
915 * We don't know the type of 'aux' - it depends on the
916 * bus this device attaches to. We are only interested in
917 * certain bus types, this only is used to find the boot
918 * device.
919 */
920 if (busdev == NULL) {
921 /*
922 * Ignore mainbus0 itself, it certainly is not a boot
923 * device.
924 */
925 } else if (device_is_a(busdev, "mainbus")) {
926 struct mainbus_attach_args *ma = aux;
927
928 ofnode = ma->ma_node;
929 } else if (device_is_a(busdev, "pci")) {
930 struct pci_attach_args *pa = aux;
931
932 ofnode = PCITAG_NODE(pa->pa_tag);
933 } else if (device_is_a(busdev, "sbus") || device_is_a(busdev, "dma")
934 || device_is_a(busdev, "ledma")) {
935 struct sbus_attach_args *sa = aux;
936
937 ofnode = sa->sa_node;
938 } else if (device_is_a(busdev, "ebus")) {
939 struct ebus_attach_args *ea = aux;
940
941 ofnode = ea->ea_node;
942 } else if (device_is_a(busdev, "iic")) {
943 struct i2c_attach_args *ia = aux;
944
945 if (ia->ia_name == NULL) /* indirect config */
946 return;
947
948 ofnode = (int)ia->ia_cookie;
949 } else if (device_is_a(dev, "sd") || device_is_a(dev, "cd")) {
950 struct scsipibus_attach_args *sa = aux;
951 struct scsipi_periph *periph = sa->sa_periph;
952 int off = 0;
953
954 /*
955 * There are two "cd" attachments:
956 * atapibus -> atabus -> controller
957 * scsibus -> controller
958 * We want the node of the controller.
959 */
960 if (device_is_a(busdev, "atapibus")) {
961 busdev = device_parent(busdev);
962 /*
963 * if the atapibus is connected to the secondary
964 * channel of the atabus, we need an offset of 2
965 * to match OF's idea of the target number.
966 * (i.e. on U5/U10 "cdrom" and "disk2" have the
967 * same target encoding, though different names)
968 */
969 if (periph->periph_channel->chan_channel == 1)
970 off = 2;
971 }
972 ofnode = device_ofnode(device_parent(busdev));
973 dev_path_drive_match(dev, ofnode, periph->periph_target + off,
974 0, periph->periph_lun);
975 return;
976 } else if (device_is_a(dev, "wd")) {
977 struct ata_device *adev = aux;
978
979 ofnode = device_ofnode(device_parent(busdev));
980 dev_path_drive_match(dev, ofnode, adev->adev_channel*2+
981 adev->adev_drv_data->drive, 0, 0);
982 return;
983 }
984
985 if (busdev == NULL)
986 return;
987
988 if (ofnode != 0) {
989 uint8_t eaddr[ETHER_ADDR_LEN];
990 char tmpstr[32];
991 char tmpstr2[32];
992 int node;
993 uint32_t id = 0;
994 uint64_t nwwn = 0, pwwn = 0;
995 prop_dictionary_t dict;
996 prop_data_t blob;
997 prop_number_t pwwnd = NULL, nwwnd = NULL;
998 prop_number_t idd = NULL;
999
1000 device_setofnode(dev, ofnode);
1001 dev_path_exact_match(dev, ofnode);
1002
1003 if (OF_getprop(ofnode, "name", tmpstr, sizeof(tmpstr)) <= 0)
1004 tmpstr[0] = 0;
1005 if (OF_getprop(ofnode, "device_type", tmpstr2, sizeof(tmpstr2)) <= 0)
1006 tmpstr2[0] = 0;
1007
1008 /*
1009 * If this is a network interface, note the
1010 * mac address.
1011 */
1012 if (strcmp(tmpstr, "network") == 0
1013 || strcmp(tmpstr, "ethernet") == 0
1014 || strcmp(tmpstr2, "network") == 0
1015 || strcmp(tmpstr2, "ethernet") == 0
1016 || OF_getprop(ofnode, "mac-address", &eaddr, sizeof(eaddr))
1017 >= ETHER_ADDR_LEN
1018 || OF_getprop(ofnode, "local-mac-address", &eaddr, sizeof(eaddr))
1019 >= ETHER_ADDR_LEN) {
1020
1021 dict = device_properties(dev);
1022
1023 /*
1024 * Is it a network interface with FCode?
1025 */
1026 if (strcmp(tmpstr, "network") == 0 ||
1027 strcmp(tmpstr2, "network") == 0) {
1028 prop_dictionary_set_bool(dict,
1029 "without-seeprom", true);
1030 prom_getether(ofnode, eaddr);
1031 } else {
1032 if (!prom_get_node_ether(ofnode, eaddr))
1033 goto noether;
1034 }
1035 blob = prop_data_create_data(eaddr, ETHER_ADDR_LEN);
1036 prop_dictionary_set(dict, "mac-address", blob);
1037 prop_object_release(blob);
1038 of_to_dataprop(dict, ofnode, "shared-pins",
1039 "shared-pins");
1040 }
1041 noether:
1042
1043 /* is this a FC node? */
1044 if (strcmp(tmpstr, "scsi-fcp") == 0) {
1045
1046 dict = device_properties(dev);
1047
1048 if (OF_getprop(ofnode, "port-wwn", &pwwn, sizeof(pwwn))
1049 == sizeof(pwwn)) {
1050 pwwnd =
1051 prop_number_create_unsigned_integer(pwwn);
1052 prop_dictionary_set(dict, "port-wwn", pwwnd);
1053 prop_object_release(pwwnd);
1054 }
1055
1056 if (OF_getprop(ofnode, "node-wwn", &nwwn, sizeof(nwwn))
1057 == sizeof(nwwn)) {
1058 nwwnd =
1059 prop_number_create_unsigned_integer(nwwn);
1060 prop_dictionary_set(dict, "node-wwn", nwwnd);
1061 prop_object_release(nwwnd);
1062 }
1063 }
1064
1065 /* is this an spi device? look for scsi-initiator-id */
1066 if (strcmp(tmpstr2, "scsi") == 0 ||
1067 strcmp(tmpstr2, "scsi-2") == 0) {
1068
1069 dict = device_properties(dev);
1070
1071 for (node = ofnode; node != 0; node = OF_parent(node)) {
1072 if (OF_getprop(node, "scsi-initiator-id", &id,
1073 sizeof(id)) <= 0)
1074 continue;
1075
1076 idd = prop_number_create_unsigned_integer(id);
1077 prop_dictionary_set(dict,
1078 "scsi-initiator-id", idd);
1079 prop_object_release(idd);
1080 break;
1081 }
1082 }
1083 }
1084
1085 /*
1086 * Check for I2C busses and add data for their direct configuration.
1087 */
1088 if (device_is_a(dev, "iic")) {
1089 int busnode = device_ofnode(busdev);
1090
1091 if (busnode) {
1092 prop_dictionary_t props = device_properties(busdev);
1093 prop_object_t cfg = prop_dictionary_get(props,
1094 "i2c-child-devices");
1095 if (!cfg) {
1096 int node;
1097 const char *name;
1098
1099 /*
1100 * pmu's i2c devices are under the "i2c" node,
1101 * so find it out.
1102 */
1103 name = prom_getpropstring(busnode, "name");
1104 if (strcmp(name, "pmu") == 0) {
1105 for (node = OF_child(busnode);
1106 node != 0; node = OF_peer(node)) {
1107 name = prom_getpropstring(node,
1108 "name");
1109 if (strcmp(name, "i2c") == 0) {
1110 busnode = node;
1111 break;
1112 }
1113 }
1114 }
1115
1116 of_enter_i2c_devs(props, busnode,
1117 sizeof(cell_t), 1);
1118 }
1119 }
1120
1121 /*
1122 * Add SPARCle spdmem devices (0x50 and 0x51) that the
1123 * firmware does not know about.
1124 */
1125 if (!strcmp(machine_model, "TAD,SPARCLE")) {
1126 prop_dictionary_t props = device_properties(busdev);
1127 prop_array_t cfg = prop_array_create();
1128 int i;
1129
1130 DPRINTF(ACDB_PROBE, ("\nAdding spdmem for SPARCle "));
1131 for (i = 0x50; i <= 0x51; i++) {
1132 prop_dictionary_t spd =
1133 prop_dictionary_create();
1134 prop_dictionary_set_cstring(spd, "name",
1135 "dimm-spd");
1136 prop_dictionary_set_uint32(spd, "addr", i);
1137 prop_dictionary_set_uint64(spd, "cookie", 0);
1138 prop_array_add(cfg, spd);
1139 prop_object_release(spd);
1140 }
1141 prop_dictionary_set(props, "i2c-child-devices", cfg);
1142 prop_object_release(cfg);
1143
1144 }
1145
1146 /*
1147 * Add V210/V240 environmental sensors that are not in
1148 * the OFW tree.
1149 */
1150 if (device_is_a(busdev, "pcfiic") &&
1151 (!strcmp(machine_model, "SUNW,Sun-Fire-V240") ||
1152 !strcmp(machine_model, "SUNW,Sun-Fire-V210"))) {
1153 prop_dictionary_t props = device_properties(busdev);
1154 prop_array_t cfg = NULL;
1155 prop_dictionary_t sens;
1156 prop_data_t data;
1157 const char name_lm[] = "i2c-lm75";
1158 const char name_adm[] = "i2c-adm1026";
1159
1160 DPRINTF(ACDB_PROBE, ("\nAdding sensors for %s ",
1161 machine_model));
1162 cfg = prop_dictionary_get(props, "i2c-child-devices");
1163 if (!cfg) {
1164 cfg = prop_array_create();
1165 prop_dictionary_set(props, "i2c-child-devices",
1166 cfg);
1167 prop_dictionary_set_bool(props,
1168 "i2c-indirect-config", false);
1169 }
1170
1171 /* ADM1026 at 0x2e */
1172 sens = prop_dictionary_create();
1173 prop_dictionary_set_uint32(sens, "addr", 0x2e);
1174 prop_dictionary_set_uint64(sens, "cookie", 0);
1175 prop_dictionary_set_cstring(sens, "name",
1176 "hardware-monitor");
1177 data = prop_data_create_data(&name_adm[0],
1178 sizeof(name_adm));
1179 prop_dictionary_set(sens, "compatible", data);
1180 prop_object_release(data);
1181 prop_array_add(cfg, sens);
1182 prop_object_release(sens);
1183
1184 /* LM75 at 0x4e */
1185 sens = prop_dictionary_create();
1186 prop_dictionary_set_uint32(sens, "addr", 0x4e);
1187 prop_dictionary_set_uint64(sens, "cookie", 0);
1188 prop_dictionary_set_cstring(sens, "name",
1189 "temperature-sensor");
1190 data = prop_data_create_data(&name_lm[0],
1191 sizeof(name_lm));
1192 prop_dictionary_set(sens, "compatible", data);
1193 prop_object_release(data);
1194 prop_array_add(cfg, sens);
1195 prop_object_release(sens);
1196 }
1197 }
1198
1199 /* set properties for PCI framebuffers */
1200 if (device_is_a(busdev, "pci")) {
1201 /* see if this is going to be console */
1202 struct pci_attach_args *pa = aux;
1203 prop_dictionary_t dict;
1204 int sub;
1205 int console = 0;
1206
1207 dict = device_properties(dev);
1208
1209 /* we only care about display devices from here on */
1210 if (PCI_CLASS(pa->pa_class) != PCI_CLASS_DISPLAY)
1211 return;
1212
1213 console = (ofnode == console_node);
1214
1215 if (!console) {
1216 /*
1217 * see if any child matches since OF attaches
1218 * nodes for each head and /chosen/stdout
1219 * points to the head rather than the device
1220 * itself in this case
1221 */
1222 sub = OF_child(ofnode);
1223 while ((sub != 0) && (sub != console_node)) {
1224 sub = OF_peer(sub);
1225 }
1226 if (sub == console_node) {
1227 console = true;
1228 }
1229 }
1230
1231 copyprops(busdev, ofnode, dict, console);
1232
1233 if (console) {
1234 uint64_t cmap_cb;
1235 prop_dictionary_set_uint32(dict,
1236 "instance_handle", console_instance);
1237
1238 gfb_cb.gcc_cookie =
1239 (void *)(intptr_t)console_instance;
1240 gfb_cb.gcc_set_mapreg = of_set_palette;
1241 cmap_cb = (uint64_t)(uintptr_t)&gfb_cb;
1242 prop_dictionary_set_uint64(dict,
1243 "cmap_callback", cmap_cb);
1244 }
1245 #ifdef notyet
1246 else {
1247 int width;
1248
1249 /*
1250 * the idea is to 'open' display devices with no useful
1251 * properties, in the hope that the firmware will
1252 * properly initialize them and we can run things like
1253 * genfb on them
1254 */
1255 if (OF_getprop(node, "width", &width, sizeof(width))
1256 != 4) {
1257 instance = OF_open(name);
1258 #endif
1259 }
1260
1261 /* Hardware specific device properties */
1262 if ((!strcmp(machine_model, "SUNW,Sun-Fire-V240") ||
1263 !strcmp(machine_model, "SUNW,Sun-Fire-V210"))) {
1264 device_t busparent = device_parent(busdev);
1265 prop_dictionary_t props = device_properties(dev);
1266
1267 if (busparent != NULL && device_is_a(busparent, "pcfiic") &&
1268 device_is_a(dev, "adm1026hm") && props != NULL) {
1269 prop_dictionary_set_uint8(props, "fan_div2", 0x55);
1270 prop_dictionary_set_bool(props, "multi_read", true);
1271 }
1272 }
1273 if (!strcmp(machine_model, "SUNW,Sun-Fire-V440")) {
1274 device_t busparent = device_parent(busdev);
1275 prop_dictionary_t props = device_properties(dev);
1276 if (busparent != NULL && device_is_a(busparent, "pcfiic") &&
1277 device_is_a(dev, "adm1026hm") && props != NULL) {
1278 prop_dictionary_set_bool(props, "multi_read", true);
1279 }
1280 }
1281 }
1282
1283 /*
1284 * Called back after autoconfiguration of a device is done
1285 */
1286 void
1287 device_register_post_config(device_t dev, void *aux)
1288 {
1289 if (booted_device == NULL && device_is_a(dev, "sd")) {
1290 struct scsipibus_attach_args *sa = aux;
1291 struct scsipi_periph *periph = sa->sa_periph;
1292 uint64_t wwn = 0;
1293 int ofnode;
1294
1295 /*
1296 * If this is a FC-AL drive it will have
1297 * aquired its WWN device property by now,
1298 * so we can properly match it.
1299 */
1300 if (prop_dictionary_get_uint64(device_properties(dev),
1301 "port-wwn", &wwn)) {
1302 /*
1303 * Different to what we do in device_register,
1304 * we do not pass the "controller" ofnode,
1305 * because FC-AL devices attach below a "fp" node,
1306 * E.g.: /pci/SUNW,qlc@4/fp@0,0/disk
1307 * and we need the parent of "disk" here.
1308 */
1309 ofnode = device_ofnode(
1310 device_parent(device_parent(dev)));
1311 for (ofnode = OF_child(ofnode);
1312 ofnode != 0 && booted_device == NULL;
1313 ofnode = OF_peer(ofnode)) {
1314 dev_path_drive_match(dev, ofnode,
1315 periph->periph_target,
1316 wwn, periph->periph_lun);
1317 }
1318 }
1319 }
1320 }
1321
1322 static void
1323 copyprops(device_t busdev, int node, prop_dictionary_t dict, int is_console)
1324 {
1325 device_t cntrlr;
1326 prop_dictionary_t psycho;
1327 paddr_t fbpa, mem_base = 0;
1328 uint32_t temp, fboffset;
1329 uint32_t fbaddr = 0;
1330 int options;
1331 char output_device[256];
1332 char *pos;
1333
1334 cntrlr = device_parent(busdev);
1335 if (cntrlr != NULL) {
1336 psycho = device_properties(cntrlr);
1337 prop_dictionary_get_uint64(psycho, "mem_base", &mem_base);
1338 }
1339
1340 if (is_console)
1341 prop_dictionary_set_bool(dict, "is_console", 1);
1342
1343 of_to_uint32_prop(dict, node, "width", "width");
1344 of_to_uint32_prop(dict, node, "height", "height");
1345 of_to_uint32_prop(dict, node, "linebytes", "linebytes");
1346 if (!of_to_uint32_prop(dict, node, "depth", "depth") &&
1347 /* Some cards have an extra space in the property name */
1348 !of_to_uint32_prop(dict, node, "depth ", "depth")) {
1349 /*
1350 * XXX we should check linebytes vs. width but those
1351 * FBs that don't have a depth property ( /chaos/control... )
1352 * won't have linebytes either
1353 */
1354 prop_dictionary_set_uint32(dict, "depth", 8);
1355 }
1356
1357 OF_getprop(node, "address", &fbaddr, sizeof(fbaddr));
1358 if (fbaddr != 0) {
1359
1360 pmap_extract(pmap_kernel(), fbaddr, &fbpa);
1361 #ifdef DEBUG
1362 printf("membase: %lx fbpa: %lx\n", (unsigned long)mem_base,
1363 (unsigned long)fbpa);
1364 #endif
1365 if (mem_base == 0) {
1366 /* XXX this is guesswork */
1367 fboffset = (uint32_t)(fbpa & 0xffffffff);
1368 }
1369 fboffset = (uint32_t)(fbpa - mem_base);
1370 prop_dictionary_set_uint32(dict, "address", fboffset);
1371 }
1372
1373 if (!of_to_dataprop(dict, node, "EDID", "EDID"))
1374 of_to_dataprop(dict, node, "edid", "EDID");
1375
1376 temp = 0;
1377 if (OF_getprop(node, "ATY,RefCLK", &temp, sizeof(temp)) != 4) {
1378
1379 OF_getprop(OF_parent(node), "ATY,RefCLK", &temp,
1380 sizeof(temp));
1381 }
1382 if (temp != 0)
1383 prop_dictionary_set_uint32(dict, "refclk", temp / 10);
1384
1385 /*
1386 * finally, let's see if there's a video mode specified in
1387 * output-device and pass it on so drivers like radeonfb
1388 * can do their thing
1389 */
1390
1391 if (!is_console)
1392 return;
1393
1394 options = OF_finddevice("/options");
1395 if ((options == 0) || (options == -1))
1396 return;
1397 if (OF_getprop(options, "output-device", output_device, 256) == 0)
1398 return;
1399 /* find the mode string if there is one */
1400 pos = strstr(output_device, ":r");
1401 if (pos == NULL)
1402 return;
1403 prop_dictionary_set_cstring(dict, "videomode", pos + 2);
1404 }
1405
1406 static void
1407 of_set_palette(void *cookie, int index, int r, int g, int b)
1408 {
1409 int ih = (int)((intptr_t)cookie);
1410
1411 OF_call_method_1("color!", ih, 4, r, g, b, index);
1412 }
1413