Annotation of src/sys/arch/x86/x86/x86_autoconf.c, Revision 1.55
1.55 ! jmcneill 1: /* $NetBSD: x86_autoconf.c,v 1.54 2011/02/08 10:52:56 jmcneill Exp $ */
1.1 thorpej 2:
3: /*-
4: * Copyright (c) 1990 The Regents of the University of California.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to Berkeley by
8: * William Jolitz.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. Neither the name of the University nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: *
34: * @(#)autoconf.c 7.1 (Berkeley) 5/9/91
35: */
36:
37: #include <sys/cdefs.h>
1.55 ! jmcneill 38: __KERNEL_RCSID(0, "$NetBSD: x86_autoconf.c,v 1.54 2011/02/08 10:52:56 jmcneill Exp $");
1.1 thorpej 39:
40: #include <sys/param.h>
41: #include <sys/systm.h>
42: #include <sys/device.h>
43: #include <sys/disklabel.h>
44: #include <sys/conf.h>
45: #include <sys/malloc.h>
46: #include <sys/vnode.h>
47: #include <sys/fcntl.h>
1.2 thorpej 48: #include <sys/disk.h>
1.1 thorpej 49: #include <sys/proc.h>
1.2 thorpej 50: #include <sys/md5.h>
1.16 elad 51: #include <sys/kauth.h>
1.1 thorpej 52:
53: #include <machine/bootinfo.h>
1.36 jmcneill 54: #include <machine/pio.h>
1.1 thorpej 55:
1.43 jmcneill 56: #include "acpica.h"
1.1 thorpej 57: #include "pci.h"
1.51 jmcneill 58: #include "isa.h"
1.38 jmcneill 59: #include "genfb.h"
60: #include "wsdisplay.h"
1.43 jmcneill 61: #include "opt_vga.h"
1.55 ! jmcneill 62: #include "opt_ddb.h"
! 63:
! 64: #ifdef DDB
! 65: #include <machine/db_machdep.h>
! 66: #include <ddb/db_sym.h>
! 67: #include <ddb/db_extern.h>
! 68: #endif
1.1 thorpej 69:
1.51 jmcneill 70: #if NACPICA > 0
71: #include <dev/acpi/acpivar.h>
72: #endif
73:
1.43 jmcneill 74: #ifdef VGA_POST
75: #include <x86/vga_post.h>
76: #endif
1.1 thorpej 77: #include <dev/isa/isavar.h>
78: #if NPCI > 0
79: #include <dev/pci/pcivar.h>
80: #endif
1.36 jmcneill 81: #include <dev/wsfb/genfbvar.h>
1.54 jmcneill 82: #include <arch/x86/include/genfb_machdep.h>
1.47 tron 83: #if NPCI > 0
1.43 jmcneill 84: #include <dev/pci/genfb_pcivar.h>
1.47 tron 85: #endif
1.36 jmcneill 86: #include <dev/ic/vgareg.h>
87:
1.47 tron 88: #if NPCI > 0
1.42 jmcneill 89: static struct genfb_colormap_callback gfb_cb;
90: static struct genfb_pmf_callback pmf_cb;
1.54 jmcneill 91: static struct genfb_mode_callback mode_cb;
1.47 tron 92: #endif
1.43 jmcneill 93: #ifdef VGA_POST
94: static struct vga_post *vga_posth = NULL;
95: #endif
1.1 thorpej 96:
97: struct disklist *x86_alldisks;
98: int x86_ndisks;
99:
1.41 dsl 100: #if NPCI > 0
1.18 christos 101: static void
1.36 jmcneill 102: x86_genfb_set_mapreg(void *opaque, int index, int r, int g, int b)
103: {
104: outb(0x3c0 + VGA_DAC_ADDRW, index);
105: outb(0x3c0 + VGA_DAC_PALETTE, (uint8_t)r >> 2);
106: outb(0x3c0 + VGA_DAC_PALETTE, (uint8_t)g >> 2);
107: outb(0x3c0 + VGA_DAC_PALETTE, (uint8_t)b >> 2);
108: }
1.42 jmcneill 109:
110: static bool
1.54 jmcneill 111: x86_genfb_setmode(struct genfb_softc *sc, int newmode)
112: {
113: if (newmode == WSDISPLAYIO_MODE_EMUL)
114: x86_genfb_mtrr_init(sc->sc_fboffset,
115: sc->sc_height * sc->sc_stride);
116: return true;
117: }
118:
119: static bool
1.50 dyoung 120: x86_genfb_suspend(device_t dev, const pmf_qual_t *qual)
1.42 jmcneill 121: {
122: return true;
123: }
124:
125: static bool
1.50 dyoung 126: x86_genfb_resume(device_t dev, const pmf_qual_t *qual)
1.42 jmcneill 127: {
1.44 jmcneill 128: #if NGENFB > 0
1.43 jmcneill 129: struct pci_genfb_softc *psc = device_private(dev);
130: #if NACPICA > 0 && defined(VGA_POST)
131: extern int acpi_md_vbios_reset;
132: extern int acpi_md_vesa_modenum;
133: #endif
1.42 jmcneill 134:
1.43 jmcneill 135: #if NACPICA > 0 && defined(VGA_POST)
136: if (vga_posth != NULL && acpi_md_vbios_reset == 2) {
137: vga_post_call(vga_posth);
138: if (acpi_md_vesa_modenum != 0)
139: vga_post_set_vbe(vga_posth, acpi_md_vesa_modenum);
140: }
141: #endif
142: genfb_restore_palette(&psc->sc_gen);
1.44 jmcneill 143: #endif
1.42 jmcneill 144:
145: return true;
146: }
1.41 dsl 147: #endif
1.36 jmcneill 148:
149: static void
1.39 cegger 150: handle_wedges(device_t dv, int par)
1.18 christos 151: {
1.26 dyoung 152: if (config_handle_wedges(dv, par) == 0)
153: return;
1.18 christos 154: booted_device = dv;
155: booted_partition = par;
156: }
157:
1.1 thorpej 158: static int
1.39 cegger 159: is_valid_disk(device_t dv)
1.1 thorpej 160: {
161:
1.9 thorpej 162: if (device_class(dv) != DV_DISK)
1.1 thorpej 163: return (0);
164:
1.17 christos 165: return (device_is_a(dv, "dk") ||
166: device_is_a(dv, "sd") ||
1.13 thorpej 167: device_is_a(dv, "wd") ||
168: device_is_a(dv, "ld") ||
169: device_is_a(dv, "ed"));
1.1 thorpej 170: }
171:
172: /*
173: * XXX Ugly bit of code. But, this is the only safe time that the
174: * match between BIOS disks and native disks can be done.
175: */
1.8 jmmv 176: static void
177: matchbiosdisks(void)
1.1 thorpej 178: {
179: struct btinfo_biosgeom *big;
180: struct bi_biosgeom_entry *be;
1.39 cegger 181: device_t dv;
1.46 dyoung 182: deviter_t di;
1.1 thorpej 183: int i, ck, error, m, n;
184: struct vnode *tv;
185: char mbr[DEV_BSIZE];
186: int dklist_size;
1.18 christos 187: int numbig;
1.1 thorpej 188:
189: big = lookup_bootinfo(BTINFO_BIOSGEOM);
190:
191: numbig = big ? big->num : 0;
192:
193: /* First, count all native disks. */
1.46 dyoung 194: for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL;
195: dv = deviter_next(&di)) {
1.1 thorpej 196: if (is_valid_disk(dv))
197: x86_ndisks++;
198: }
1.46 dyoung 199: deviter_release(&di);
1.1 thorpej 200:
201: dklist_size = sizeof(struct disklist) + (x86_ndisks - 1) *
202: sizeof(struct nativedisk_info);
203:
204: /* XXX M_TEMP is wrong */
205: x86_alldisks = malloc(dklist_size, M_TEMP, M_NOWAIT | M_ZERO);
206: if (x86_alldisks == NULL)
207: return;
208:
209: x86_alldisks->dl_nnativedisks = x86_ndisks;
210: x86_alldisks->dl_nbiosdisks = numbig;
211: for (i = 0; i < numbig; i++) {
212: x86_alldisks->dl_biosdisks[i].bi_dev = big->disk[i].dev;
213: x86_alldisks->dl_biosdisks[i].bi_sec = big->disk[i].sec;
214: x86_alldisks->dl_biosdisks[i].bi_head = big->disk[i].head;
215: x86_alldisks->dl_biosdisks[i].bi_cyl = big->disk[i].cyl;
216: x86_alldisks->dl_biosdisks[i].bi_lbasecs = big->disk[i].totsec;
217: x86_alldisks->dl_biosdisks[i].bi_flags = big->disk[i].flags;
218: #ifdef GEOM_DEBUG
219: #ifdef notyet
220: printf("disk %x: flags %x, interface %x, device %llx\n",
221: big->disk[i].dev, big->disk[i].flags,
222: big->disk[i].interface_path, big->disk[i].device_path);
223: #endif
224: #endif
225: }
226:
227: /* XXX Code duplication from findroot(). */
228: n = -1;
1.46 dyoung 229: for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL;
230: dv = deviter_next(&di)) {
1.9 thorpej 231: if (device_class(dv) != DV_DISK)
1.1 thorpej 232: continue;
233: #ifdef GEOM_DEBUG
234: printf("matchbiosdisks: trying to match (%s) %s\n",
1.34 cegger 235: device_xname(dv), device_cfdata(dv)->cf_name);
1.1 thorpej 236: #endif
237: if (is_valid_disk(dv)) {
238: n++;
239: snprintf(x86_alldisks->dl_nativedisks[n].ni_devname,
240: sizeof(x86_alldisks->dl_nativedisks[n].ni_devname),
1.34 cegger 241: "%s", device_xname(dv));
1.1 thorpej 242:
1.18 christos 243: if ((tv = opendisk(dv)) == NULL)
244: continue;
1.1 thorpej 245:
246: error = vn_rdwr(UIO_READ, tv, mbr, DEV_BSIZE, 0,
247: UIO_SYSSPACE, 0, NOCRED, NULL, NULL);
1.31 pooka 248: VOP_CLOSE(tv, FREAD, NOCRED);
1.1 thorpej 249: if (error) {
250: #ifdef GEOM_DEBUG
251: printf("matchbiosdisks: %s: MBR read failure\n",
1.34 cegger 252: device_xname(dv));
1.1 thorpej 253: #endif
254: continue;
255: }
256:
257: for (ck = i = 0; i < DEV_BSIZE; i++)
258: ck += mbr[i];
259: for (m = i = 0; i < numbig; i++) {
260: be = &big->disk[i];
261: #ifdef GEOM_DEBUG
262: printf("match %s with %d "
1.34 cegger 263: "dev ck %x bios ck %x\n", device_xname(dv), i,
1.1 thorpej 264: ck, be->cksum);
265: #endif
266: if (be->flags & BI_GEOM_INVALID)
267: continue;
268: if (be->cksum == ck &&
269: memcmp(&mbr[MBR_PART_OFFSET], be->dosparts,
270: MBR_PART_COUNT *
271: sizeof(struct mbr_partition)) == 0) {
272: #ifdef GEOM_DEBUG
273: printf("matched BIOS disk %x with %s\n",
1.34 cegger 274: be->dev, device_xname(dv));
1.1 thorpej 275: #endif
276: x86_alldisks->dl_nativedisks[n].
277: ni_biosmatches[m++] = i;
278: }
279: }
280: x86_alldisks->dl_nativedisks[n].ni_nmatches = m;
281: vput(tv);
282: }
283: }
1.46 dyoung 284: deviter_release(&di);
1.1 thorpej 285: }
286:
287: /*
288: * Helper function for findroot():
1.2 thorpej 289: * Return non-zero if wedge device matches bootinfo.
290: */
291: static int
1.39 cegger 292: match_bootwedge(device_t dv, struct btinfo_bootwedge *biw)
1.2 thorpej 293: {
294: MD5_CTX ctx;
295: struct vnode *tmpvn;
296: int error;
1.4 christos 297: uint8_t bf[DEV_BSIZE];
1.2 thorpej 298: uint8_t hash[16];
299: int found = 0;
300: daddr_t blk;
301: uint64_t nblks;
302:
303: /*
304: * If the boot loader didn't specify the sector, abort.
305: */
306: if (biw->matchblk == -1)
307: return (0);
308:
1.19 christos 309: if ((tmpvn = opendisk(dv)) == NULL)
310: return 0;
311:
1.2 thorpej 312: MD5Init(&ctx);
313: for (blk = biw->matchblk, nblks = biw->matchnblks;
314: nblks != 0; nblks--, blk++) {
1.25 christos 315: error = vn_rdwr(UIO_READ, tmpvn, (void *) bf,
1.4 christos 316: sizeof(bf), blk * DEV_BSIZE, UIO_SYSSPACE,
1.2 thorpej 317: 0, NOCRED, NULL, NULL);
318: if (error) {
1.53 jakllsch 319: printf("findroot: unable to read block %" PRId64 " "
320: "of dev %s (%d)\n", blk, device_xname(dv), error);
1.2 thorpej 321: goto closeout;
322: }
1.4 christos 323: MD5Update(&ctx, bf, sizeof(bf));
1.2 thorpej 324: }
325: MD5Final(hash, &ctx);
326:
327: /* Compare with the provided hash. */
328: found = memcmp(biw->matchhash, hash, sizeof(hash)) == 0;
329:
330: closeout:
1.31 pooka 331: VOP_CLOSE(tmpvn, FREAD, NOCRED);
1.2 thorpej 332: vput(tmpvn);
333: return (found);
334: }
335:
336: /*
337: * Helper function for findroot():
1.1 thorpej 338: * Return non-zero if disk device matches bootinfo.
339: */
340: static int
1.39 cegger 341: match_bootdisk(device_t dv, struct btinfo_bootdisk *bid)
1.1 thorpej 342: {
343: struct vnode *tmpvn;
344: int error;
345: struct disklabel label;
346: int found = 0;
1.18 christos 347:
348: if (device_is_a(dv, "dk"))
349: return 0;
1.1 thorpej 350:
351: /*
352: * A disklabel is required here. The boot loader doesn't refuse
353: * to boot from a disk without a label, but this is normally not
354: * wanted.
355: */
356: if (bid->labelsector == -1)
357: return (0);
358:
1.18 christos 359: if ((tmpvn = opendisk(dv)) == NULL)
360: return 0;
1.2 thorpej 361:
1.31 pooka 362: error = VOP_IOCTL(tmpvn, DIOCGDINFO, &label, FREAD, NOCRED);
1.1 thorpej 363: if (error) {
364: /*
365: * XXX Can't happen -- open() would have errored out
366: * or faked one up.
367: */
1.3 xtraeme 368: printf("findroot: can't get label for dev %s (%d)\n",
1.34 cegger 369: device_xname(dv), error);
1.1 thorpej 370: goto closeout;
371: }
372:
373: /* Compare with our data. */
374: if (label.d_type == bid->label.type &&
375: label.d_checksum == bid->label.checksum &&
376: strncmp(label.d_packname, bid->label.packname, 16) == 0)
1.18 christos 377: found = 1;
1.1 thorpej 378:
379: closeout:
1.31 pooka 380: VOP_CLOSE(tmpvn, FREAD, NOCRED);
1.1 thorpej 381: vput(tmpvn);
382: return (found);
383: }
384:
385: /*
386: * Attempt to find the device from which we were booted. If we can do so,
387: * and not instructed not to do so, change rootdev to correspond to the
388: * load device.
389: */
390: static void
391: findroot(void)
392: {
1.6 jmmv 393: struct btinfo_rootdevice *biv;
1.1 thorpej 394: struct btinfo_bootdisk *bid;
1.2 thorpej 395: struct btinfo_bootwedge *biw;
1.35 tsutsui 396: struct btinfo_biosgeom *big;
1.32 joerg 397: device_t dv;
1.46 dyoung 398: deviter_t di;
1.1 thorpej 399:
400: if (booted_device)
401: return;
402:
403: if (lookup_bootinfo(BTINFO_NETIF) != NULL) {
404: /*
405: * We got netboot interface information, but device_register()
406: * failed to match it to a configured device. Boot disk
407: * information cannot be present at the same time, so give
408: * up.
409: */
410: printf("findroot: netboot interface not found.\n");
411: return;
412: }
413:
1.6 jmmv 414: if ((biv = lookup_bootinfo(BTINFO_ROOTDEVICE)) != NULL) {
1.46 dyoung 415: for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST);
416: dv != NULL;
417: dv = deviter_next(&di)) {
1.40 cegger 418: cfdata_t cd;
1.6 jmmv 419: size_t len;
420:
1.9 thorpej 421: if (device_class(dv) != DV_DISK)
1.6 jmmv 422: continue;
423:
1.15 thorpej 424: cd = device_cfdata(dv);
1.6 jmmv 425: len = strlen(cd->cf_name);
426:
427: if (strncmp(cd->cf_name, biv->devname, len) == 0 &&
428: biv->devname[len] - '0' == cd->cf_unit) {
1.18 christos 429: handle_wedges(dv, biv->devname[len + 1] - 'a');
1.46 dyoung 430: break;
1.6 jmmv 431: }
432: }
1.46 dyoung 433: deviter_release(&di);
434: if (dv != NULL)
435: return;
1.6 jmmv 436: }
437:
1.2 thorpej 438: if ((biw = lookup_bootinfo(BTINFO_BOOTWEDGE)) != NULL) {
439: /*
440: * Scan all disk devices for ones that match the passed data.
441: * Don't break if one is found, to get possible multiple
442: * matches - for problem tracking. Use the first match anyway
443: * because lower devices numbers are more likely to be the
444: * boot device.
445: */
1.46 dyoung 446: for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST);
447: dv != NULL;
448: dv = deviter_next(&di)) {
1.9 thorpej 449: if (device_class(dv) != DV_DISK)
1.2 thorpej 450: continue;
451:
452: if (is_valid_disk(dv)) {
453: /*
454: * Don't trust BIOS device numbers, try
455: * to match the information passed by the
456: * boot loader instead.
457: */
458: if ((biw->biosdev & 0x80) == 0 ||
459: match_bootwedge(dv, biw) == 0)
460: continue;
461: goto bootwedge_found;
462: }
463:
464: continue;
465: bootwedge_found:
466: if (booted_device) {
467: printf("WARNING: double match for boot "
468: "device (%s, %s)\n",
1.34 cegger 469: device_xname(booted_device),
470: device_xname(dv));
1.2 thorpej 471: continue;
472: }
473: dkwedge_set_bootwedge(dv, biw->startblk, biw->nblks);
474: }
1.46 dyoung 475: deviter_release(&di);
1.2 thorpej 476:
477: if (booted_wedge)
478: return;
479: }
480:
481: if ((bid = lookup_bootinfo(BTINFO_BOOTDISK)) != NULL) {
1.1 thorpej 482: /*
483: * Scan all disk devices for ones that match the passed data.
484: * Don't break if one is found, to get possible multiple
485: * matches - for problem tracking. Use the first match anyway
486: * because lower device numbers are more likely to be the
487: * boot device.
488: */
1.46 dyoung 489: for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST);
490: dv != NULL;
491: dv = deviter_next(&di)) {
1.9 thorpej 492: if (device_class(dv) != DV_DISK)
1.1 thorpej 493: continue;
494:
1.12 thorpej 495: if (device_is_a(dv, "fd")) {
1.1 thorpej 496: /*
497: * Assume the configured unit number matches
498: * the BIOS device number. (This is the old
499: * behavior.) Needs some ideas how to handle
500: * the BIOS's "swap floppy drive" options.
501: */
1.14 thorpej 502: /* XXX device_unit() abuse */
1.1 thorpej 503: if ((bid->biosdev & 0x80) != 0 ||
1.14 thorpej 504: device_unit(dv) != bid->biosdev)
1.1 thorpej 505: continue;
1.2 thorpej 506: goto bootdisk_found;
1.1 thorpej 507: }
508:
509: if (is_valid_disk(dv)) {
510: /*
511: * Don't trust BIOS device numbers, try
512: * to match the information passed by the
513: * boot loader instead.
514: */
515: if ((bid->biosdev & 0x80) == 0 ||
516: match_bootdisk(dv, bid) == 0)
517: continue;
1.2 thorpej 518: goto bootdisk_found;
1.1 thorpej 519: }
520:
521: continue;
1.2 thorpej 522: bootdisk_found:
1.1 thorpej 523: if (booted_device) {
524: printf("WARNING: double match for boot "
525: "device (%s, %s)\n",
1.34 cegger 526: device_xname(booted_device),
527: device_xname(dv));
1.1 thorpej 528: continue;
529: }
1.18 christos 530: handle_wedges(dv, bid->partition);
1.1 thorpej 531: }
1.46 dyoung 532: deviter_release(&di);
1.1 thorpej 533:
534: if (booted_device)
535: return;
1.35 tsutsui 536:
537: /*
538: * No booted device found; check CD-ROM boot at last.
539: *
540: * Our bootloader assumes CD-ROM boot if biosdev is larger
541: * than the number of hard drives recognized by the BIOS.
542: * The number of drives can be found in BTINFO_BIOSGEOM here.
543: *
544: * See src/sys/arch/i386/stand/boot/devopen.c and
545: * src/sys/arch/i386/stand/lib/bootinfo_biosgeom.c .
546: */
547: if ((big = lookup_bootinfo(BTINFO_BIOSGEOM)) != NULL &&
548: bid->biosdev > 0x80 + big->num) {
549: /*
550: * XXX
551: * There is no proper way to detect which unit is
552: * recognized as a bootable CD-ROM drive by the BIOS.
553: * Assume the first unit is the one.
554: */
1.46 dyoung 555: for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST);
556: dv != NULL;
557: dv = deviter_next(&di)) {
1.35 tsutsui 558: if (device_class(dv) == DV_DISK &&
559: device_is_a(dv, "cd")) {
560: booted_device = dv;
561: booted_partition = 0;
562: break;
563: }
564: }
1.46 dyoung 565: deviter_release(&di);
1.35 tsutsui 566: }
1.1 thorpej 567: }
568: }
569:
570: void
1.8 jmmv 571: cpu_rootconf(void)
1.1 thorpej 572: {
573:
574: findroot();
1.8 jmmv 575: matchbiosdisks();
1.1 thorpej 576:
1.2 thorpej 577: if (booted_wedge) {
578: KASSERT(booted_device != NULL);
1.49 hubertf 579: aprint_normal("boot device: %s (%s)\n",
1.34 cegger 580: device_xname(booted_wedge), device_xname(booted_device));
1.2 thorpej 581: setroot(booted_wedge, 0);
582: } else {
1.49 hubertf 583: aprint_normal("boot device: %s\n",
1.34 cegger 584: booted_device ? device_xname(booted_device) : "<unknown>");
1.2 thorpej 585: setroot(booted_device, booted_partition);
586: }
1.1 thorpej 587: }
588:
589: void
1.39 cegger 590: device_register(device_t dev, void *aux)
1.1 thorpej 591: {
1.41 dsl 592: #if NPCI > 0
1.36 jmcneill 593: static bool found_console = false;
1.41 dsl 594: #endif
1.1 thorpej 595:
596: /*
597: * Handle network interfaces here, the attachment information is
598: * not available driver-independently later.
599: *
600: * For disks, there is nothing useful available at attach time.
601: */
1.9 thorpej 602: if (device_class(dev) == DV_IFNET) {
1.1 thorpej 603: struct btinfo_netif *bin = lookup_bootinfo(BTINFO_NETIF);
604: if (bin == NULL)
605: return;
606:
607: /*
608: * We don't check the driver name against the device name
609: * passed by the boot ROM. The ROM should stay usable if
610: * the driver becomes obsolete. The physical attachment
611: * information (checked below) must be sufficient to
612: * idenfity the device.
613: */
614: if (bin->bus == BI_BUS_ISA &&
1.11 thorpej 615: device_is_a(device_parent(dev), "isa")) {
1.1 thorpej 616: struct isa_attach_args *iaa = aux;
617:
618: /* Compare IO base address */
619: /* XXXJRT What about multiple IO addrs? */
620: if (iaa->ia_nio > 0 &&
621: bin->addr.iobase == iaa->ia_io[0].ir_addr)
622: goto found;
623: }
624: #if NPCI > 0
625: if (bin->bus == BI_BUS_PCI &&
1.11 thorpej 626: device_is_a(device_parent(dev), "pci")) {
1.1 thorpej 627: struct pci_attach_args *paa = aux;
628: int b, d, f;
629:
630: /*
631: * Calculate BIOS representation of:
632: *
633: * <bus,device,function>
634: *
635: * and compare.
636: */
637: pci_decompose_tag(paa->pa_pc, paa->pa_tag, &b, &d, &f);
638: if (bin->addr.tag == ((b << 8) | (d << 3) | f))
639: goto found;
640: }
641: #endif /* NPCI > 0 */
642: }
1.51 jmcneill 643: #if NISA > 0 && NACPICA > 0
1.52 jmcneill 644: #if notyet
1.51 jmcneill 645: if (device_is_a(dev, "isa") && acpi_active) {
646: if (!(AcpiGbl_FADT.BootFlags & ACPI_FADT_LEGACY_DEVICES))
647: prop_dictionary_set_bool(device_properties(dev),
648: "no-legacy-devices", true);
649: }
1.52 jmcneill 650: #endif
1.51 jmcneill 651: #endif /* NISA > 0 && NACPICA > 0 */
1.36 jmcneill 652: #if NPCI > 0
653: if (device_parent(dev) && device_is_a(device_parent(dev), "pci") &&
654: found_console == false) {
655: struct btinfo_framebuffer *fbinfo;
656: struct pci_attach_args *pa = aux;
657: prop_dictionary_t dict;
658:
659: if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY) {
1.38 jmcneill 660: #if NWSDISPLAY > 0 && NGENFB > 0
1.37 jmcneill 661: extern struct vcons_screen x86_genfb_console_screen;
1.38 jmcneill 662: #endif
1.37 jmcneill 663:
1.36 jmcneill 664: fbinfo = lookup_bootinfo(BTINFO_FRAMEBUFFER);
665: dict = device_properties(dev);
1.45 macallan 666: /*
667: * framebuffer drivers other than genfb can work
668: * without the address property
669: */
670: if (fbinfo != NULL) {
671: if (fbinfo->physaddr != 0) {
672: prop_dictionary_set_uint32(dict, "width",
673: fbinfo->width);
674: prop_dictionary_set_uint32(dict, "height",
675: fbinfo->height);
676: prop_dictionary_set_uint8(dict, "depth",
677: fbinfo->depth);
678: prop_dictionary_set_uint16(dict, "linebytes",
679: fbinfo->stride);
680:
681: prop_dictionary_set_uint64(dict,
682: "address", fbinfo->physaddr);
683: }
684: #if notyet
685: prop_dictionary_set_bool(dict, "splash",
686: fbinfo->flags & BI_FB_SPLASH ?
687: true : false);
688: #endif
689: if (fbinfo->depth == 8) {
690: gfb_cb.gcc_cookie = NULL;
691: gfb_cb.gcc_set_mapreg =
692: x86_genfb_set_mapreg;
693: prop_dictionary_set_uint64(dict,
694: "cmap_callback", (uint64_t)&gfb_cb);
695: }
1.54 jmcneill 696: if (fbinfo->physaddr != 0) {
697: mode_cb.gmc_setmode = x86_genfb_setmode;
698: prop_dictionary_set_uint64(dict,
699: "mode_callback",
700: (uint64_t)&mode_cb);
701: }
1.55 ! jmcneill 702:
! 703: #if NWSDISPLAY > 0 && NGENFB > 0
! 704: if (device_is_a(dev, "genfb")) {
! 705: x86_genfb_set_console_dev(dev);
! 706: #ifdef DDB
! 707: db_trap_callback =
! 708: x86_genfb_ddb_trap_callback;
! 709: #endif
! 710: }
! 711: #endif
1.45 macallan 712: }
1.36 jmcneill 713: prop_dictionary_set_bool(dict, "is_console", true);
1.37 jmcneill 714: prop_dictionary_set_bool(dict, "clear-screen", false);
1.38 jmcneill 715: #if NWSDISPLAY > 0 && NGENFB > 0
1.37 jmcneill 716: prop_dictionary_set_uint16(dict, "cursor-row",
717: x86_genfb_console_screen.scr_ri.ri_crow);
1.38 jmcneill 718: #endif
1.36 jmcneill 719: #if notyet
720: prop_dictionary_set_bool(dict, "splash",
721: fbinfo->flags & BI_FB_SPLASH ? true : false);
722: #endif
1.42 jmcneill 723: pmf_cb.gpc_suspend = x86_genfb_suspend;
724: pmf_cb.gpc_resume = x86_genfb_resume;
725: prop_dictionary_set_uint64(dict,
726: "pmf_callback", (uint64_t)&pmf_cb);
1.43 jmcneill 727: #ifdef VGA_POST
728: vga_posth = vga_post_init(pa->pa_bus, pa->pa_device,
729: pa->pa_function);
730: #endif
1.36 jmcneill 731: found_console = true;
732: return;
733: }
734: }
735: #endif
1.1 thorpej 736: return;
737:
738: found:
739: if (booted_device) {
740: /* XXX should be a panic() */
741: printf("WARNING: double match for boot device (%s, %s)\n",
1.34 cegger 742: device_xname(booted_device), device_xname(dev));
1.1 thorpej 743: return;
744: }
745: booted_device = dev;
746: }
CVSweb <webmaster@jp.NetBSD.org>