Annotation of src/sys/arch/i386/i386/autoconf.c, Revision 1.44
1.44 ! drochner 1: /* $NetBSD: autoconf.c,v 1.43 1999/10/25 17:26:07 drochner Exp $ */
1.11 cgd 2:
1.1 cgd 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. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the University of
21: * California, Berkeley and its contributors.
22: * 4. Neither the name of the University nor the names of its contributors
23: * may be used to endorse or promote products derived from this software
24: * without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36: * SUCH DAMAGE.
37: *
1.11 cgd 38: * @(#)autoconf.c 7.1 (Berkeley) 5/9/91
1.1 cgd 39: */
40:
41: /*
42: * Setup the system to run on the current machine.
43: *
44: * Configure() is called at boot time and initializes the vba
45: * device tables and the memory controller monitoring. Available
46: * devices are determined (from possibilities mentioned in ioconf.c),
47: * and the drivers are initialized.
48: */
1.43 drochner 49:
50: #include "opt_compat_oldboot.h"
51:
1.9 mycroft 52: #include <sys/param.h>
53: #include <sys/systm.h>
54: #include <sys/buf.h>
55: #include <sys/dkstat.h>
56: #include <sys/disklabel.h>
57: #include <sys/conf.h>
1.43 drochner 58: #ifdef COMPAT_OLDBOOT
1.9 mycroft 59: #include <sys/reboot.h>
1.43 drochner 60: #endif
1.13 mycroft 61: #include <sys/device.h>
1.34 fvdl 62: #include <sys/malloc.h>
1.25 drochner 63: #include <sys/vnode.h>
64: #include <sys/fcntl.h>
65: #include <sys/dkio.h>
1.1 cgd 66:
1.9 mycroft 67: #include <machine/pte.h>
1.20 christos 68: #include <machine/cpu.h>
1.25 drochner 69: #include <machine/bootinfo.h>
1.1 cgd 70:
1.28 drochner 71: static int match_harddisk __P((struct device *, struct btinfo_bootdisk *));
1.32 fvdl 72: static void matchbiosdisks __P((void));
1.23 thorpej 73: void findroot __P((struct device **, int *));
1.19 mycroft 74:
1.35 fvdl 75: extern struct disklist *i386_alldisks;
76: extern int i386_ndisks;
1.34 fvdl 77:
1.1 cgd 78: /*
79: * Determine i/o configuration for a machine.
80: */
1.19 mycroft 81: void
1.40 thorpej 82: cpu_configure()
1.1 cgd 83: {
84:
1.12 mycroft 85: startrtclock();
86:
1.18 cgd 87: if (config_rootfound("mainbus", NULL) == NULL)
88: panic("configure: mainbus not configured");
1.12 mycroft 89:
1.22 christos 90: printf("biomask %x netmask %x ttymask %x\n",
1.12 mycroft 91: (u_short)imask[IPL_BIO], (u_short)imask[IPL_NET],
92: (u_short)imask[IPL_TTY]);
93:
94: spl0();
1.37 thorpej 95:
96: /* Set up proc0's TSS and LDT (after the FPU is configured). */
97: i386_proc0_tss_ldt_init();
1.30 thorpej 98:
99: /* XXX Finish deferred buffer cache allocation. */
100: i386_bufinit();
1.24 gwr 101: }
1.28 drochner 102:
1.24 gwr 103: void
104: cpu_rootconf()
105: {
106: struct device *booted_device;
107: int booted_partition;
1.1 cgd 108:
1.23 thorpej 109: findroot(&booted_device, &booted_partition);
1.32 fvdl 110: matchbiosdisks();
1.23 thorpej 111:
112: printf("boot device: %s\n",
113: booted_device ? booted_device->dv_xname : "<unknown>");
114:
1.38 thorpej 115: setroot(booted_device, booted_partition);
1.1 cgd 116: }
117:
1.34 fvdl 118: /*
119: * XXX ugly bit of code. But, this is the only safe time that the
120: * match between BIOS disks and native disks can be done.
121: */
1.32 fvdl 122: static void
123: matchbiosdisks()
124: {
125: struct btinfo_biosgeom *big;
126: struct bi_biosgeom_entry *be;
127: struct device *dv;
128: struct devnametobdevmaj *d;
1.34 fvdl 129: int i, ck, error, m, n;
1.32 fvdl 130: struct vnode *tv;
1.34 fvdl 131: char mbr[DEV_BSIZE];
1.32 fvdl 132:
133: big = lookup_bootinfo(BTINFO_BIOSGEOM);
134:
1.36 fvdl 135: if (big == NULL)
1.32 fvdl 136: return;
137:
1.34 fvdl 138: /*
139: * First, count all native disks
140: */
141: for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next)
142: if (dv->dv_class == DV_DISK &&
143: (!strcmp(dv->dv_cfdata->cf_driver->cd_name, "sd") ||
144: !strcmp(dv->dv_cfdata->cf_driver->cd_name, "wd")))
1.35 fvdl 145: i386_ndisks++;
146:
147: if (i386_ndisks == 0)
148: return;
1.34 fvdl 149:
150: /* XXX M_TEMP is wrong */
1.35 fvdl 151: i386_alldisks = malloc(sizeof (struct disklist) + (i386_ndisks - 1) *
152: sizeof (struct nativedisk_info),
153: M_TEMP, M_NOWAIT);
154: if (i386_alldisks == NULL)
1.34 fvdl 155: return;
156:
1.35 fvdl 157: i386_alldisks->dl_nnativedisks = i386_ndisks;
158: i386_alldisks->dl_nbiosdisks = big->num;
159: for (i = 0; i < big->num; i++) {
160: i386_alldisks->dl_biosdisks[i].bi_dev = big->disk[i].dev;
161: i386_alldisks->dl_biosdisks[i].bi_sec = big->disk[i].sec;
162: i386_alldisks->dl_biosdisks[i].bi_head = big->disk[i].head;
163: i386_alldisks->dl_biosdisks[i].bi_cyl = big->disk[i].cyl;
164: i386_alldisks->dl_biosdisks[i].bi_lbasecs = big->disk[i].totsec;
165: i386_alldisks->dl_biosdisks[i].bi_flags = big->disk[i].flags;
166: }
167:
1.34 fvdl 168: /*
169: * XXX code duplication from findroot()
170: */
171: n = -1;
1.32 fvdl 172: for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next) {
173: if (dv->dv_class != DV_DISK)
174: continue;
175: #ifdef GEOM_DEBUG
176: printf("matchbiosdisks: trying to match (%s) %s\n",
177: dv->dv_xname, dv->dv_cfdata->cf_driver->cd_name);
178: #endif
179: if (!strcmp(dv->dv_cfdata->cf_driver->cd_name, "sd") ||
180: !strcmp(dv->dv_cfdata->cf_driver->cd_name, "wd")) {
1.34 fvdl 181: n++;
1.35 fvdl 182: sprintf(i386_alldisks->dl_nativedisks[n].ni_devname,
183: "%s%d", dv->dv_cfdata->cf_driver->cd_name,
1.34 fvdl 184: dv->dv_unit);
185:
1.38 thorpej 186: for (d = dev_name2blk; d->d_name &&
1.32 fvdl 187: strcmp(d->d_name, dv->dv_cfdata->cf_driver->cd_name);
188: d++);
189: if (d->d_name == NULL)
190: return;
1.34 fvdl 191:
1.32 fvdl 192: if (bdevvp(MAKEDISKDEV(d->d_maj, dv->dv_unit, RAW_PART),
193: &tv))
194: panic("matchbiosdisks: can't alloc vnode");
1.34 fvdl 195:
1.33 fvdl 196: error = VOP_OPEN(tv, FREAD, NOCRED, 0);
197: if (error) {
1.42 fvdl 198: vput(tv);
1.33 fvdl 199: continue;
200: }
1.34 fvdl 201: error = vn_rdwr(UIO_READ, tv, mbr, DEV_BSIZE, 0,
202: UIO_SYSSPACE, 0, NOCRED, NULL, 0);
203: VOP_CLOSE(tv, FREAD, NOCRED, 0);
204: if (error) {
1.32 fvdl 205: #ifdef GEOM_DEBUG
206: printf("matchbiosdisks: %s: MBR read failure\n",
207: dv->dv_xname);
208: #endif
209: continue;
210: }
1.34 fvdl 211:
1.32 fvdl 212: for (ck = i = 0; i < DEV_BSIZE; i++)
213: ck += mbr[i];
1.34 fvdl 214: for (m = i = 0; i < big->num; i++) {
1.32 fvdl 215: be = &big->disk[i];
216: #ifdef GEOM_DEBUG
217: printf("match %s with %d\n", dv->dv_xname, i);
218: printf("dev ck %x bios ck %x\n", ck, be->cksum);
219: #endif
220: if (be->flags & BI_GEOM_INVALID)
221: continue;
222: if (be->cksum == ck &&
223: !memcmp(&mbr[MBR_PARTOFF], be->dosparts,
224: NMBRPART *
225: sizeof (struct mbr_partition))) {
226: #ifdef GEOM_DEBUG
227: printf("matched bios disk %x with %s\n",
228: be->dev, be->devname);
229: #endif
1.35 fvdl 230: i386_alldisks->dl_nativedisks[n].
231: ni_biosmatches[m++] = i;
1.32 fvdl 232: }
233: }
1.35 fvdl 234: i386_alldisks->dl_nativedisks[n].ni_nmatches = m;
1.42 fvdl 235: vput(tv);
1.32 fvdl 236: }
237: }
238: }
239:
1.43 drochner 240: #ifdef COMPAT_OLDBOOT
1.1 cgd 241: u_long bootdev = 0; /* should be dev_t, but not until 32 bits */
1.43 drochner 242: #endif
1.25 drochner 243: struct device *booted_device;
1.1 cgd 244:
245: /*
1.28 drochner 246: * helper function for "findroot()":
247: * return nonzero if disk device matches bootinfo
248: */
1.32 fvdl 249: static int
250: match_harddisk(dv, bid)
1.28 drochner 251: struct device *dv;
252: struct btinfo_bootdisk *bid;
253: {
254: struct devnametobdevmaj *i;
255: struct vnode *tmpvn;
256: int error;
257: struct disklabel label;
258: int found = 0;
259:
260: /*
261: * A disklabel is required here. The
262: * bootblocks don't refuse to boot from
263: * a disk without a label, but this is
264: * normally not wanted.
265: */
266: if (bid->labelsector == -1)
267: return(0);
268:
269: /*
270: * lookup major number for disk block device
271: */
1.38 thorpej 272: i = dev_name2blk;
1.28 drochner 273: while (i->d_name &&
274: strcmp(i->d_name, dv->dv_cfdata->cf_driver->cd_name))
275: i++;
276: if (i->d_name == NULL)
277: return(0); /* XXX panic() ??? */
278:
279: /*
280: * Fake a temporary vnode for the disk, open
281: * it, and read the disklabel for comparison.
282: */
283: if (bdevvp(MAKEDISKDEV(i->d_maj, dv->dv_unit, bid->partition), &tmpvn))
284: panic("findroot can't alloc vnode");
285: error = VOP_OPEN(tmpvn, FREAD, NOCRED, 0);
286: if (error) {
287: #ifndef DEBUG
1.31 bouyer 288: /*
289: * Ignore errors caused by missing
290: * device, partition or medium.
291: */
292: if (error != ENXIO && error != ENODEV)
1.28 drochner 293: #endif
294: printf("findroot: can't open dev %s%c (%d)\n",
295: dv->dv_xname, 'a' + bid->partition, error);
1.42 fvdl 296: vput(tmpvn);
1.28 drochner 297: return(0);
298: }
299: error = VOP_IOCTL(tmpvn, DIOCGDINFO, (caddr_t)&label, FREAD, NOCRED, 0);
300: if (error) {
301: /*
302: * XXX can't happen - open() would
303: * have errored out (or faked up one)
304: */
305: printf("can't get label for dev %s%c (%d)\n",
306: dv->dv_xname, 'a' + bid->partition, error);
307: goto closeout;
308: }
309:
310: /* compare with our data */
311: if (label.d_type == bid->label.type &&
312: label.d_checksum == bid->label.checksum &&
313: !strncmp(label.d_packname, bid->label.packname, 16))
314: found = 1;
315:
316: closeout:
317: VOP_CLOSE(tmpvn, FREAD, NOCRED, 0);
1.42 fvdl 318: vput(tmpvn);
1.28 drochner 319: return(found);
320: }
321:
322: /*
1.1 cgd 323: * Attempt to find the device from which we were booted.
324: * If we can do so, and not instructed not to do so,
325: * change rootdev to correspond to the load device.
326: */
1.19 mycroft 327: void
1.23 thorpej 328: findroot(devpp, partp)
329: struct device **devpp;
330: int *partp;
1.1 cgd 331: {
1.25 drochner 332: struct btinfo_bootdisk *bid;
333: struct device *dv;
1.43 drochner 334: #ifdef COMPAT_OLDBOOT
1.23 thorpej 335: int i, majdev, unit, part;
336: char buf[32];
1.43 drochner 337: #endif
1.23 thorpej 338:
339: /*
340: * Default to "not found."
341: */
342: *devpp = NULL;
343: *partp = 0;
1.1 cgd 344:
1.26 thorpej 345: if (booted_device) {
1.25 drochner 346: *devpp = booted_device;
347: return;
348: }
1.26 thorpej 349: if (lookup_bootinfo(BTINFO_NETIF)) {
1.25 drochner 350: /*
351: * We got netboot interface information, but
352: * "device_register()" couldn't match it to a configured
353: * device. Bootdisk information cannot be present at the
354: * same time, so give up.
355: */
356: printf("findroot: netboot interface not found\n");
357: return;
358: }
359:
360: bid = lookup_bootinfo(BTINFO_BOOTDISK);
1.26 thorpej 361: if (bid) {
1.25 drochner 362: /*
363: * Scan all disk devices for ones that match the passed data.
364: * Don't break if one is found, to get possible multiple
365: * matches - for problem tracking. Use the first match anyway
366: * because lower device numbers are more likely to be the
367: * boot device.
368: */
369: for (dv = alldevs.tqh_first; dv != NULL;
370: dv = dv->dv_list.tqe_next) {
1.28 drochner 371: if (dv->dv_class != DV_DISK)
1.25 drochner 372: continue;
373:
1.26 thorpej 374: if (!strcmp(dv->dv_cfdata->cf_driver->cd_name, "fd")) {
375: /*
376: * Assume the configured unit number matches
377: * the BIOS device number. (This is the old
378: * behaviour.) Needs some ideas how to handle
379: * BIOS's "swap floppy drive" options.
380: */
381: if ((bid->biosdev & 0x80) ||
382: dv->dv_unit != bid->biosdev)
1.25 drochner 383: continue;
384:
385: goto found;
386: }
387:
1.28 drochner 388: if (!strcmp(dv->dv_cfdata->cf_driver->cd_name, "sd") ||
389: !strcmp(dv->dv_cfdata->cf_driver->cd_name, "wd")) {
1.26 thorpej 390: /*
1.28 drochner 391: * Don't trust BIOS device numbers, try
392: * to match the information passed by the
393: * bootloader instead.
1.26 thorpej 394: */
1.28 drochner 395: if ((bid->biosdev & 0x80) == 0 ||
396: !match_harddisk(dv, bid))
1.25 drochner 397: continue;
398:
1.28 drochner 399: goto found;
1.25 drochner 400: }
401:
402: /* no "fd", "wd" or "sd" */
403: continue;
404:
405: found:
1.26 thorpej 406: if (*devpp) {
407: printf("warning: double match for boot "
408: "device (%s, %s)\n", (*devpp)->dv_xname,
409: dv->dv_xname);
1.25 drochner 410: continue;
411: }
412: *devpp = dv;
413: *partp = bid->partition;
414: }
415:
1.26 thorpej 416: if (*devpp)
1.25 drochner 417: return;
418: }
419:
1.43 drochner 420: #ifdef COMPAT_OLDBOOT
1.20 christos 421: #if 0
1.22 christos 422: printf("howto %x bootdev %x ", boothowto, bootdev);
1.20 christos 423: #endif
1.23 thorpej 424:
425: if ((bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
1.1 cgd 426: return;
1.23 thorpej 427:
1.1 cgd 428: majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
1.38 thorpej 429: for (i = 0; dev_name2blk[i].d_name != NULL; i++)
430: if (majdev == dev_name2blk[i].d_maj)
1.23 thorpej 431: break;
1.38 thorpej 432: if (dev_name2blk[i].d_name == NULL)
1.1 cgd 433: return;
1.23 thorpej 434:
1.1 cgd 435: part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
436: unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
1.23 thorpej 437:
1.38 thorpej 438: sprintf(buf, "%s%d", dev_name2blk[i].d_name, unit);
1.23 thorpej 439: for (dv = alldevs.tqh_first; dv != NULL;
440: dv = dv->dv_list.tqe_next) {
441: if (strcmp(buf, dv->dv_xname) == 0) {
442: *devpp = dv;
443: *partp = part;
444: return;
1.1 cgd 445: }
446: }
1.43 drochner 447: #endif
1.25 drochner 448: }
449:
1.26 thorpej 450: #include "pci.h"
451:
1.25 drochner 452: #include <dev/isa/isavar.h>
1.26 thorpej 453: #if NPCI > 0
1.25 drochner 454: #include <dev/pci/pcivar.h>
1.26 thorpej 455: #endif
1.25 drochner 456:
457: void
458: device_register(dev, aux)
459: struct device *dev;
460: void *aux;
461: {
462: /*
463: * Handle network interfaces here, the attachment information is
464: * not available driver independantly later.
465: * For disks, there is nothing useful available at attach time.
466: */
1.26 thorpej 467: if (dev->dv_class == DV_IFNET) {
1.25 drochner 468: struct btinfo_netif *bin = lookup_bootinfo(BTINFO_NETIF);
1.26 thorpej 469: if (bin == NULL)
1.25 drochner 470: return;
471:
1.44 ! drochner 472: /*
! 473: * We don't check the driver name against the device name
! 474: * passed by the boot ROM. The ROM should stay usable
! 475: * if the driver gets obsoleted.
! 476: * The physical attachment information (checked below)
! 477: * must be sufficient to identify the device.
! 478: */
1.25 drochner 479:
1.26 thorpej 480: if (bin->bus == BI_BUS_ISA &&
481: !strcmp(dev->dv_parent->dv_cfdata->cf_driver->cd_name,
482: "isa")) {
1.25 drochner 483: struct isa_attach_args *iaa = aux;
484:
485: /* compare IO base address */
1.26 thorpej 486: if (bin->addr.iobase == iaa->ia_iobase)
1.27 drochner 487: goto found;
1.25 drochner 488: }
1.26 thorpej 489: #if NPCI > 0
490: if (bin->bus == BI_BUS_PCI &&
491: !strcmp(dev->dv_parent->dv_cfdata->cf_driver->cd_name,
492: "pci")) {
1.25 drochner 493: struct pci_attach_args *paa = aux;
494: int b, d, f;
495:
1.26 thorpej 496: /*
497: * Calculate BIOS representation of:
498: *
499: * <bus,device,function>
500: *
501: * and compare.
502: */
1.25 drochner 503: pci_decompose_tag(paa->pa_pc, paa->pa_tag, &b, &d, &f);
1.26 thorpej 504: if (bin->addr.tag == ((b << 8) | (d << 3) | f))
1.25 drochner 505: goto found;
506: }
1.26 thorpej 507: #endif
1.25 drochner 508: }
509: return;
510:
511: found:
1.26 thorpej 512: if (booted_device) {
1.25 drochner 513: /* XXX should be a "panic()" */
514: printf("warning: double match for boot device (%s, %s)\n",
1.26 thorpej 515: booted_device->dv_xname, dev->dv_xname);
1.25 drochner 516: return;
517: }
518: booted_device = dev;
1.1 cgd 519: }
CVSweb <webmaster@jp.NetBSD.org>