Annotation of src/sys/arch/i386/i386/autoconf.c, Revision 1.45.2.8
1.45.2.6 sommerfe 1: /* $NetBSD$ */
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.45.2.7 sommerfe 69: #include <machine/gdt.h>
1.25 drochner 70: #include <machine/bootinfo.h>
1.1 cgd 71:
1.45.2.1 sommerfe 72: #include "ioapic.h"
73:
74: #if NIOAPIC > 0
75: #include <machine/i82093var.h>
76: #endif
77:
1.28 drochner 78: static int match_harddisk __P((struct device *, struct btinfo_bootdisk *));
1.32 fvdl 79: static void matchbiosdisks __P((void));
1.45.2.3 sommerfe 80: static void findroot __P((void));
1.19 mycroft 81:
1.35 fvdl 82: extern struct disklist *i386_alldisks;
83: extern int i386_ndisks;
1.34 fvdl 84:
1.45 thorpej 85: #include "bios32.h"
86: #if NBIOS32 > 0
87: #include <machine/bios32.h>
88: #endif
89:
90: #include "opt_pcibios.h"
91: #ifdef PCIBIOS
92: #include <dev/pci/pcireg.h>
93: #include <dev/pci/pcivar.h>
94: #include <i386/pci/pcibios.h>
95: #endif
96:
1.45.2.3 sommerfe 97: struct device *booted_device;
98: int booted_partition;
99:
1.1 cgd 100: /*
101: * Determine i/o configuration for a machine.
102: */
1.19 mycroft 103: void
1.40 thorpej 104: cpu_configure()
1.1 cgd 105: {
106:
1.12 mycroft 107: startrtclock();
1.45 thorpej 108:
109: #if NBIOS32 > 0
110: bios32_init();
111: #endif
112: #ifdef PCIBIOS
113: pcibios_init();
114: #endif
1.12 mycroft 115:
1.18 cgd 116: if (config_rootfound("mainbus", NULL) == NULL)
117: panic("configure: mainbus not configured");
1.12 mycroft 118:
1.22 christos 119: printf("biomask %x netmask %x ttymask %x\n",
1.45.2.1 sommerfe 120: (u_short)IMASK(IPL_BIO), (u_short)IMASK(IPL_NET),
121: (u_short)IMASK(IPL_TTY));
122:
123: #if NIOAPIC > 0
124: ioapic_enable();
125: #endif
1.12 mycroft 126:
127: spl0();
1.37 thorpej 128:
1.45.2.7 sommerfe 129: gdt_init();
1.30 thorpej 130:
1.45.2.5 sommerfe 131: #ifdef MULTIPROCESSOR
1.45.2.4 sommerfe 132: cpu_init_idle_pcbs();
1.45.2.5 sommerfe 133: #endif
1.45.2.7 sommerfe 134:
135: /* Set up proc0's TSS and LDT (after the FPU is configured). */
136: i386_proc0_tss_ldt_init();
1.45.2.5 sommerfe 137:
1.30 thorpej 138: /* XXX Finish deferred buffer cache allocation. */
139: i386_bufinit();
1.24 gwr 140: }
1.28 drochner 141:
1.24 gwr 142: void
143: cpu_rootconf()
144: {
1.45.2.3 sommerfe 145: findroot();
1.32 fvdl 146: matchbiosdisks();
1.23 thorpej 147:
148: printf("boot device: %s\n",
149: booted_device ? booted_device->dv_xname : "<unknown>");
150:
1.38 thorpej 151: setroot(booted_device, booted_partition);
1.1 cgd 152: }
153:
1.34 fvdl 154: /*
155: * XXX ugly bit of code. But, this is the only safe time that the
156: * match between BIOS disks and native disks can be done.
157: */
1.32 fvdl 158: static void
159: matchbiosdisks()
160: {
161: struct btinfo_biosgeom *big;
162: struct bi_biosgeom_entry *be;
163: struct device *dv;
164: struct devnametobdevmaj *d;
1.34 fvdl 165: int i, ck, error, m, n;
1.32 fvdl 166: struct vnode *tv;
1.34 fvdl 167: char mbr[DEV_BSIZE];
1.32 fvdl 168:
169: big = lookup_bootinfo(BTINFO_BIOSGEOM);
170:
1.36 fvdl 171: if (big == NULL)
1.32 fvdl 172: return;
173:
1.34 fvdl 174: /*
175: * First, count all native disks
176: */
177: for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next)
178: if (dv->dv_class == DV_DISK &&
179: (!strcmp(dv->dv_cfdata->cf_driver->cd_name, "sd") ||
1.45.2.2 sommerfe 180: !strcmp(dv->dv_cfdata->cf_driver->cd_name, "wd") ||
1.45.2.8! sommerfe 181: !strcmp(dv->dv_cfdata->cf_driver->cd_name, "ld") ||
! 182: !strcmp(dv->dv_cfdata->cf_driver->cd_name, "ed")))
1.35 fvdl 183: i386_ndisks++;
184:
185: if (i386_ndisks == 0)
186: return;
1.34 fvdl 187:
188: /* XXX M_TEMP is wrong */
1.35 fvdl 189: i386_alldisks = malloc(sizeof (struct disklist) + (i386_ndisks - 1) *
190: sizeof (struct nativedisk_info),
191: M_TEMP, M_NOWAIT);
192: if (i386_alldisks == NULL)
1.34 fvdl 193: return;
194:
1.35 fvdl 195: i386_alldisks->dl_nnativedisks = i386_ndisks;
196: i386_alldisks->dl_nbiosdisks = big->num;
197: for (i = 0; i < big->num; i++) {
198: i386_alldisks->dl_biosdisks[i].bi_dev = big->disk[i].dev;
199: i386_alldisks->dl_biosdisks[i].bi_sec = big->disk[i].sec;
200: i386_alldisks->dl_biosdisks[i].bi_head = big->disk[i].head;
201: i386_alldisks->dl_biosdisks[i].bi_cyl = big->disk[i].cyl;
202: i386_alldisks->dl_biosdisks[i].bi_lbasecs = big->disk[i].totsec;
203: i386_alldisks->dl_biosdisks[i].bi_flags = big->disk[i].flags;
204: }
205:
1.34 fvdl 206: /*
207: * XXX code duplication from findroot()
208: */
209: n = -1;
1.32 fvdl 210: for (dv = alldevs.tqh_first; dv != NULL; dv = dv->dv_list.tqe_next) {
211: if (dv->dv_class != DV_DISK)
212: continue;
213: #ifdef GEOM_DEBUG
214: printf("matchbiosdisks: trying to match (%s) %s\n",
215: dv->dv_xname, dv->dv_cfdata->cf_driver->cd_name);
216: #endif
217: if (!strcmp(dv->dv_cfdata->cf_driver->cd_name, "sd") ||
1.45.2.2 sommerfe 218: !strcmp(dv->dv_cfdata->cf_driver->cd_name, "wd") ||
1.45.2.8! sommerfe 219: !strcmp(dv->dv_cfdata->cf_driver->cd_name, "ld") ||
! 220: !strcmp(dv->dv_cfdata->cf_driver->cd_name, "ed")) {
1.34 fvdl 221: n++;
1.35 fvdl 222: sprintf(i386_alldisks->dl_nativedisks[n].ni_devname,
223: "%s%d", dv->dv_cfdata->cf_driver->cd_name,
1.34 fvdl 224: dv->dv_unit);
225:
1.38 thorpej 226: for (d = dev_name2blk; d->d_name &&
1.32 fvdl 227: strcmp(d->d_name, dv->dv_cfdata->cf_driver->cd_name);
228: d++);
229: if (d->d_name == NULL)
230: return;
1.34 fvdl 231:
1.32 fvdl 232: if (bdevvp(MAKEDISKDEV(d->d_maj, dv->dv_unit, RAW_PART),
233: &tv))
234: panic("matchbiosdisks: can't alloc vnode");
1.34 fvdl 235:
1.33 fvdl 236: error = VOP_OPEN(tv, FREAD, NOCRED, 0);
237: if (error) {
1.42 fvdl 238: vput(tv);
1.33 fvdl 239: continue;
240: }
1.34 fvdl 241: error = vn_rdwr(UIO_READ, tv, mbr, DEV_BSIZE, 0,
242: UIO_SYSSPACE, 0, NOCRED, NULL, 0);
243: VOP_CLOSE(tv, FREAD, NOCRED, 0);
244: if (error) {
1.32 fvdl 245: #ifdef GEOM_DEBUG
246: printf("matchbiosdisks: %s: MBR read failure\n",
247: dv->dv_xname);
248: #endif
249: continue;
250: }
1.34 fvdl 251:
1.32 fvdl 252: for (ck = i = 0; i < DEV_BSIZE; i++)
253: ck += mbr[i];
1.34 fvdl 254: for (m = i = 0; i < big->num; i++) {
1.32 fvdl 255: be = &big->disk[i];
256: #ifdef GEOM_DEBUG
257: printf("match %s with %d\n", dv->dv_xname, i);
258: printf("dev ck %x bios ck %x\n", ck, be->cksum);
259: #endif
260: if (be->flags & BI_GEOM_INVALID)
261: continue;
262: if (be->cksum == ck &&
263: !memcmp(&mbr[MBR_PARTOFF], be->dosparts,
264: NMBRPART *
265: sizeof (struct mbr_partition))) {
266: #ifdef GEOM_DEBUG
267: printf("matched bios disk %x with %s\n",
268: be->dev, be->devname);
269: #endif
1.35 fvdl 270: i386_alldisks->dl_nativedisks[n].
271: ni_biosmatches[m++] = i;
1.32 fvdl 272: }
273: }
1.35 fvdl 274: i386_alldisks->dl_nativedisks[n].ni_nmatches = m;
1.42 fvdl 275: vput(tv);
1.32 fvdl 276: }
277: }
278: }
279:
1.43 drochner 280: #ifdef COMPAT_OLDBOOT
1.1 cgd 281: u_long bootdev = 0; /* should be dev_t, but not until 32 bits */
1.43 drochner 282: #endif
1.1 cgd 283:
284: /*
1.28 drochner 285: * helper function for "findroot()":
286: * return nonzero if disk device matches bootinfo
287: */
1.32 fvdl 288: static int
289: match_harddisk(dv, bid)
1.28 drochner 290: struct device *dv;
291: struct btinfo_bootdisk *bid;
292: {
293: struct devnametobdevmaj *i;
294: struct vnode *tmpvn;
295: int error;
296: struct disklabel label;
297: int found = 0;
298:
299: /*
300: * A disklabel is required here. The
301: * bootblocks don't refuse to boot from
302: * a disk without a label, but this is
303: * normally not wanted.
304: */
305: if (bid->labelsector == -1)
306: return(0);
307:
308: /*
309: * lookup major number for disk block device
310: */
1.38 thorpej 311: i = dev_name2blk;
1.28 drochner 312: while (i->d_name &&
313: strcmp(i->d_name, dv->dv_cfdata->cf_driver->cd_name))
314: i++;
315: if (i->d_name == NULL)
316: return(0); /* XXX panic() ??? */
317:
318: /*
319: * Fake a temporary vnode for the disk, open
320: * it, and read the disklabel for comparison.
321: */
322: if (bdevvp(MAKEDISKDEV(i->d_maj, dv->dv_unit, bid->partition), &tmpvn))
323: panic("findroot can't alloc vnode");
324: error = VOP_OPEN(tmpvn, FREAD, NOCRED, 0);
325: if (error) {
326: #ifndef DEBUG
1.31 bouyer 327: /*
328: * Ignore errors caused by missing
329: * device, partition or medium.
330: */
331: if (error != ENXIO && error != ENODEV)
1.28 drochner 332: #endif
333: printf("findroot: can't open dev %s%c (%d)\n",
334: dv->dv_xname, 'a' + bid->partition, error);
1.42 fvdl 335: vput(tmpvn);
1.28 drochner 336: return(0);
337: }
338: error = VOP_IOCTL(tmpvn, DIOCGDINFO, (caddr_t)&label, FREAD, NOCRED, 0);
339: if (error) {
340: /*
341: * XXX can't happen - open() would
342: * have errored out (or faked up one)
343: */
344: printf("can't get label for dev %s%c (%d)\n",
345: dv->dv_xname, 'a' + bid->partition, error);
346: goto closeout;
347: }
348:
349: /* compare with our data */
350: if (label.d_type == bid->label.type &&
351: label.d_checksum == bid->label.checksum &&
352: !strncmp(label.d_packname, bid->label.packname, 16))
353: found = 1;
354:
355: closeout:
356: VOP_CLOSE(tmpvn, FREAD, NOCRED, 0);
1.42 fvdl 357: vput(tmpvn);
1.28 drochner 358: return(found);
359: }
360:
361: /*
1.1 cgd 362: * Attempt to find the device from which we were booted.
363: * If we can do so, and not instructed not to do so,
364: * change rootdev to correspond to the load device.
365: */
1.19 mycroft 366: void
1.45.2.3 sommerfe 367: findroot(void)
1.1 cgd 368: {
1.25 drochner 369: struct btinfo_bootdisk *bid;
370: struct device *dv;
1.43 drochner 371: #ifdef COMPAT_OLDBOOT
1.23 thorpej 372: int i, majdev, unit, part;
373: char buf[32];
1.43 drochner 374: #endif
1.23 thorpej 375:
1.45.2.3 sommerfe 376: if (booted_device)
1.25 drochner 377: return;
1.45.2.3 sommerfe 378:
1.26 thorpej 379: if (lookup_bootinfo(BTINFO_NETIF)) {
1.25 drochner 380: /*
381: * We got netboot interface information, but
382: * "device_register()" couldn't match it to a configured
383: * device. Bootdisk information cannot be present at the
384: * same time, so give up.
385: */
386: printf("findroot: netboot interface not found\n");
387: return;
388: }
389:
390: bid = lookup_bootinfo(BTINFO_BOOTDISK);
1.26 thorpej 391: if (bid) {
1.25 drochner 392: /*
393: * Scan all disk devices for ones that match the passed data.
394: * Don't break if one is found, to get possible multiple
395: * matches - for problem tracking. Use the first match anyway
396: * because lower device numbers are more likely to be the
397: * boot device.
398: */
399: for (dv = alldevs.tqh_first; dv != NULL;
400: dv = dv->dv_list.tqe_next) {
1.28 drochner 401: if (dv->dv_class != DV_DISK)
1.25 drochner 402: continue;
403:
1.26 thorpej 404: if (!strcmp(dv->dv_cfdata->cf_driver->cd_name, "fd")) {
405: /*
406: * Assume the configured unit number matches
407: * the BIOS device number. (This is the old
408: * behaviour.) Needs some ideas how to handle
409: * BIOS's "swap floppy drive" options.
410: */
411: if ((bid->biosdev & 0x80) ||
412: dv->dv_unit != bid->biosdev)
1.25 drochner 413: continue;
414:
415: goto found;
416: }
417:
1.28 drochner 418: if (!strcmp(dv->dv_cfdata->cf_driver->cd_name, "sd") ||
1.45.2.2 sommerfe 419: !strcmp(dv->dv_cfdata->cf_driver->cd_name, "wd") ||
1.45.2.8! sommerfe 420: !strcmp(dv->dv_cfdata->cf_driver->cd_name, "ld") ||
! 421: !strcmp(dv->dv_cfdata->cf_driver->cd_name, "ed")) {
1.26 thorpej 422: /*
1.28 drochner 423: * Don't trust BIOS device numbers, try
424: * to match the information passed by the
425: * bootloader instead.
1.26 thorpej 426: */
1.28 drochner 427: if ((bid->biosdev & 0x80) == 0 ||
428: !match_harddisk(dv, bid))
1.25 drochner 429: continue;
430:
1.28 drochner 431: goto found;
1.25 drochner 432: }
433:
1.45.2.8! sommerfe 434: /* no "fd", "wd", "sd", "ld", "ed" */
1.25 drochner 435: continue;
436:
437: found:
1.45.2.3 sommerfe 438: if (booted_device) {
1.26 thorpej 439: printf("warning: double match for boot "
1.45.2.3 sommerfe 440: "device (%s, %s)\n", booted_device->dv_xname,
1.26 thorpej 441: dv->dv_xname);
1.25 drochner 442: continue;
443: }
1.45.2.3 sommerfe 444: booted_device = dv;
445: booted_partition = bid->partition;
1.25 drochner 446: }
447:
1.45.2.3 sommerfe 448: if (booted_device)
1.25 drochner 449: return;
450: }
451:
1.43 drochner 452: #ifdef COMPAT_OLDBOOT
1.20 christos 453: #if 0
1.22 christos 454: printf("howto %x bootdev %x ", boothowto, bootdev);
1.20 christos 455: #endif
1.23 thorpej 456:
457: if ((bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
1.1 cgd 458: return;
1.23 thorpej 459:
1.1 cgd 460: majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
1.38 thorpej 461: for (i = 0; dev_name2blk[i].d_name != NULL; i++)
462: if (majdev == dev_name2blk[i].d_maj)
1.23 thorpej 463: break;
1.38 thorpej 464: if (dev_name2blk[i].d_name == NULL)
1.1 cgd 465: return;
1.23 thorpej 466:
1.1 cgd 467: part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
468: unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
1.23 thorpej 469:
1.38 thorpej 470: sprintf(buf, "%s%d", dev_name2blk[i].d_name, unit);
1.23 thorpej 471: for (dv = alldevs.tqh_first; dv != NULL;
472: dv = dv->dv_list.tqe_next) {
473: if (strcmp(buf, dv->dv_xname) == 0) {
1.45.2.3 sommerfe 474: booted_device = dv;
475: booted_partition = part;
1.23 thorpej 476: return;
1.1 cgd 477: }
478: }
1.43 drochner 479: #endif
1.25 drochner 480: }
481:
1.26 thorpej 482: #include "pci.h"
483:
1.25 drochner 484: #include <dev/isa/isavar.h>
1.26 thorpej 485: #if NPCI > 0
1.25 drochner 486: #include <dev/pci/pcivar.h>
1.26 thorpej 487: #endif
1.25 drochner 488:
489: void
490: device_register(dev, aux)
491: struct device *dev;
492: void *aux;
493: {
494: /*
495: * Handle network interfaces here, the attachment information is
496: * not available driver independantly later.
497: * For disks, there is nothing useful available at attach time.
498: */
1.26 thorpej 499: if (dev->dv_class == DV_IFNET) {
1.25 drochner 500: struct btinfo_netif *bin = lookup_bootinfo(BTINFO_NETIF);
1.26 thorpej 501: if (bin == NULL)
1.25 drochner 502: return;
503:
1.44 drochner 504: /*
505: * We don't check the driver name against the device name
506: * passed by the boot ROM. The ROM should stay usable
507: * if the driver gets obsoleted.
508: * The physical attachment information (checked below)
509: * must be sufficient to identify the device.
510: */
1.25 drochner 511:
1.26 thorpej 512: if (bin->bus == BI_BUS_ISA &&
513: !strcmp(dev->dv_parent->dv_cfdata->cf_driver->cd_name,
514: "isa")) {
1.25 drochner 515: struct isa_attach_args *iaa = aux;
516:
517: /* compare IO base address */
1.26 thorpej 518: if (bin->addr.iobase == iaa->ia_iobase)
1.27 drochner 519: goto found;
1.25 drochner 520: }
1.26 thorpej 521: #if NPCI > 0
522: if (bin->bus == BI_BUS_PCI &&
523: !strcmp(dev->dv_parent->dv_cfdata->cf_driver->cd_name,
524: "pci")) {
1.25 drochner 525: struct pci_attach_args *paa = aux;
526: int b, d, f;
527:
1.26 thorpej 528: /*
529: * Calculate BIOS representation of:
530: *
531: * <bus,device,function>
532: *
533: * and compare.
534: */
1.25 drochner 535: pci_decompose_tag(paa->pa_pc, paa->pa_tag, &b, &d, &f);
1.26 thorpej 536: if (bin->addr.tag == ((b << 8) | (d << 3) | f))
1.25 drochner 537: goto found;
538: }
1.26 thorpej 539: #endif
1.25 drochner 540: }
541: return;
542:
543: found:
1.26 thorpej 544: if (booted_device) {
1.25 drochner 545: /* XXX should be a "panic()" */
546: printf("warning: double match for boot device (%s, %s)\n",
1.26 thorpej 547: booted_device->dv_xname, dev->dv_xname);
1.25 drochner 548: return;
549: }
550: booted_device = dev;
1.1 cgd 551: }
CVSweb <webmaster@jp.NetBSD.org>