autoconf.c revision 27288
1132718Skan/*- 272562Sobrien * Copyright (c) 1990 The Regents of the University of California. 3169689Skan * All rights reserved. 4169689Skan * 550397Sobrien * This code is derived from software contributed to Berkeley by 6132718Skan * William Jolitz. 750397Sobrien * 850397Sobrien * Redistribution and use in source and binary forms, with or without 9132718Skan * modification, are permitted provided that the following conditions 1050397Sobrien * are met: 11132718Skan * 1. Redistributions of source code must retain the above copyright 1250397Sobrien * notice, this list of conditions and the following disclaimer. 1350397Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1450397Sobrien * notice, this list of conditions and the following disclaimer in the 1550397Sobrien * documentation and/or other materials provided with the distribution. 16132718Skan * 3. All advertising materials mentioning features or use of this software 1750397Sobrien * must display the following acknowledgement: 1850397Sobrien * This product includes software developed by the University of 1950397Sobrien * California, Berkeley and its contributors. 2050397Sobrien * 4. Neither the name of the University nor the names of its contributors 2150397Sobrien * may be used to endorse or promote products derived from this software 22132718Skan * without specific prior written permission. 23169689Skan * 24169689Skan * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2550397Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2650397Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2750397Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28132718Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29132718Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3050397Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3150397Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3250397Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3350397Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3450397Sobrien * SUCH DAMAGE. 3550397Sobrien * 36169689Skan * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 3750397Sobrien * $Id: autoconf.c,v 1.2 1997/07/08 23:40:04 smp Exp smp $ 3850397Sobrien */ 3950397Sobrien 4050397Sobrien/* 4190075Sobrien * Setup the system to run on the current machine. 4250397Sobrien * 4390075Sobrien * Configure() is called at boot time and initializes the vba 4450397Sobrien * device tables and the memory controller monitoring. Available 4550397Sobrien * devices are determined (from possibilities mentioned in ioconf.c), 4690075Sobrien * and the drivers are initialized. 4790075Sobrien */ 4890075Sobrien#include "opt_cd9660.h" 4990075Sobrien 5090075Sobrien#include <sys/param.h> 51132718Skan#include <sys/systm.h> 52169689Skan#include <sys/buf.h> 53169689Skan#include <sys/conf.h> 5450397Sobrien#include <sys/dmap.h> 55169689Skan#include <sys/reboot.h> 56169689Skan#include <sys/kernel.h> 57169689Skan#include <sys/mount.h> 58169689Skan#include <sys/vnode.h> 59169689Skan#include <sys/sysctl.h> 60169689Skan 61169689Skan#include <machine/bootinfo.h> 62169689Skan#include <machine/cons.h> 63169689Skan#include <machine/md_var.h> 64169689Skan#ifdef APIC_IO 65169689Skan#include <machine/smp.h> 66169689Skan#endif /* APIC_IO */ 67169689Skan 68169689Skan#include <i386/isa/icu.h> /* For interrupts */ 69169689Skan 70169689Skan#include "isa.h" 71169689Skan#if NISA > 0 72169689Skan#include <i386/isa/isa_device.h> 73169689Skan#endif 74169689Skan 75169689Skan#include "eisa.h" 76169689Skan#if NEISA > 0 77169689Skan#include <i386/eisa/eisaconf.h> 78169689Skan#endif 7950397Sobrien 80169689Skan#include "pci.h" 81169689Skan#if NPCI > 0 82169689Skan#include <pci/pcivar.h> 83169689Skan#endif 84169689Skan 85169689Skan#include "crd.h" 86169689Skan#if NCRD > 0 87169689Skan#include <pccard/driver.h> 88169689Skan#endif 89169689Skan 90169689Skan#include "scbus.h" 91169689Skan#if NSCBUS > 0 92169689Skan#include <scsi/scsiconf.h> 93169689Skan#endif 94169689Skan 95169689Skanstatic void configure __P((void *)); 96169689SkanSYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL) 97169689Skan 98169689Skanstatic void configure_finish __P((void)); 99169689Skanstatic void configure_start __P((void)); 100169689Skanstatic int setdumpdev __P((dev_t dev)); 101169689Skanstatic void setroot __P((void)); 102169689Skan 10350397Sobrien#ifdef CD9660 104169689Skan 105169689Skan#include <sys/fcntl.h> 106169689Skan#include <sys/proc.h> 107169689Skan#include <sys/stat.h> 108169689Skan#include <machine/clock.h> 109169689Skan#include <isofs/cd9660/iso.h> 110169689Skan 111169689Skan/* 112169689Skan * XXX All this CD-ROM root stuff is fairly messy. Ick. 113169689Skan * 114169689Skan * We need to try out all our potential CDROM drives, so we need a table. 115169689Skan */ 116169689Skanstatic struct { 117169689Skan char *name; 118169689Skan int major; 119169689Skan} try_cdrom[] = { 120169689Skan { "cd", 6 }, 121169689Skan { "mcd", 7 }, 122169689Skan { "scd", 16 }, 123169689Skan { "matcd", 17 }, 124169689Skan { "wcd", 19 }, 125169689Skan { 0, 0} 126169689Skan}; 127169689Skan 128169689Skanstatic int find_cdrom_root __P((void)); 129169689Skan 130169689Skanstatic int 131169689Skanfind_cdrom_root() 132169689Skan{ 133169689Skan int i, j, error; 134169689Skan struct bdevsw *bd; 135169689Skan dev_t orootdev; 136169689Skan 137169689Skan#if CD9660_ROOTDELAY > 0 138169689Skan DELAY(CD9660_ROOTDELAY * 1000000); 139169689Skan#endif 140169689Skan orootdev = rootdev; 141169689Skan for (i = 0 ; i < 2; i++) 142169689Skan for (j = 0 ; try_cdrom[j].name ; j++) { 143169689Skan if (try_cdrom[j].major >= nblkdev) 144169689Skan continue; 145169689Skan rootdev = makedev(try_cdrom[j].major, i * 8); 146169689Skan bd = bdevsw[major(rootdev)]; 147169689Skan if (bd == NULL || bd->d_open == NULL) 148169689Skan continue; 149169689Skan if (bootverbose) 150169689Skan printf("trying %s%d as rootdev (0x%x)\n", 151169689Skan try_cdrom[j].name, i, rootdev); 152169689Skan error = (bd->d_open)(rootdev, FREAD, S_IFBLK, curproc); 153169689Skan if (error == 0) { 154169689Skan if (bd->d_close != NULL) 155169689Skan (bd->d_close)(rootdev, FREAD, S_IFBLK, 156169689Skan curproc); 157169689Skan return 0; 158169689Skan } 159169689Skan } 160169689Skan 161169689Skan rootdev = orootdev; 162169689Skan return EINVAL; 163169689Skan} 164169689Skan#endif /* CD9660 */ 165169689Skan 166169689Skanstatic void 167169689Skanconfigure_start() 168169689Skan{ 169169689Skan#if NSCBUS > 0 170169689Skan scsi_configure_start(); 171169689Skan#endif 172169689Skan} 173169689Skan 174169689Skanstatic void 175169689Skanconfigure_finish() 176169689Skan{ 177169689Skan#if NSCBUS > 0 178169689Skan scsi_configure_finish(); 179169689Skan#endif 180169689Skan} 181169689Skan 182169689Skan/* 183169689Skan * Determine i/o configuration for a machine. 184169689Skan */ 185169689Skanstatic void 186169689Skanconfigure(dummy) 187169689Skan void *dummy; 188169689Skan{ 189169689Skan int i; 190169689Skan 191169689Skan configure_start(); 192169689Skan 193169689Skan /* Allow all routines to decide for themselves if they want intrs */ 194169689Skan#ifdef APIC_IO 195169689Skan bsp_apic_configure(); 196169689Skan enable_intr(); 197169689Skan#else 198169689Skan enable_intr(); 199169689Skan INTREN(IRQ_SLAVE); 200169689Skan#endif /* APIC_IO */ 201169689Skan 202169689Skan#if NEISA > 0 203169689Skan eisa_configure(); 204169689Skan#endif 205169689Skan 206169689Skan#if NPCI > 0 207169689Skan pci_configure(); 208169689Skan#endif 209169689Skan 210169689Skan#if NISA > 0 211169689Skan isa_configure(); 212169689Skan#endif 213169689Skan 214169689Skan#if NCRD > 0 215169689Skan /* After everyone else has a chance at grabbing resources */ 216169689Skan pccard_configure(); 217169689Skan#endif 218169689Skan 219169689Skan if (setdumpdev(dumpdev) != 0) 220169689Skan dumpdev = NODEV; 221169689Skan 222169689Skan configure_finish(); 223169689Skan 224169689Skan cninit_finish(); 225169689Skan 226169689Skan if (bootverbose) { 227169689Skan /* 228169689Skan * Print out the BIOS's idea of the disk geometries. 229169689Skan */ 230169689Skan printf("BIOS Geometries:\n"); 231169689Skan for (i = 0; i < N_BIOS_GEOM; i++) { 232169689Skan unsigned long bios_geom; 233169689Skan int max_cylinder, max_head, max_sector; 234169689Skan 235169689Skan bios_geom = bootinfo.bi_bios_geom[i]; 236169689Skan 23750397Sobrien /* 23850397Sobrien * XXX the bootstrap punts a 1200K floppy geometry 23950397Sobrien * when the get-disk-geometry interrupt fails. Skip 240169689Skan * drives that have this geometry. 241169689Skan */ 242169689Skan if (bios_geom == 0x4f010f) 24350397Sobrien continue; 24450397Sobrien 245132718Skan printf(" %x:%08lx ", i, bios_geom); 246132718Skan max_cylinder = bios_geom >> 16; 24750397Sobrien max_head = (bios_geom >> 8) & 0xff; 24896263Sobrien max_sector = bios_geom & 0xff; 24996263Sobrien printf( 25090075Sobrien "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n", 25190075Sobrien max_cylinder, max_cylinder + 1, 252169689Skan max_head, max_head + 1, 253169689Skan max_sector, max_sector); 254169689Skan } 255169689Skan printf(" %d accounted for\n", bootinfo.bi_n_bios_used); 256169689Skan 257169689Skan printf("Device configuration finished.\n"); 25850397Sobrien } 25950397Sobrien 260169689Skan#ifdef CD9660 26150397Sobrien if ((boothowto & RB_CDROM)) { 26296263Sobrien if (bootverbose) 26396263Sobrien printf("Considering CD-ROM root f/s.\n"); 26496263Sobrien /* NB: find_cdrom_root() sets rootdev if successful. */ 26596263Sobrien if (find_cdrom_root() == 0) 26650397Sobrien mountrootfsname = "cd9660"; 26750397Sobrien else if (bootverbose) 26850397Sobrien printf("No CD-ROM available as root f/s.\n"); 26950397Sobrien } 27050397Sobrien#endif 27150397Sobrien 27250397Sobrien#ifdef MFS_ROOT 27350397Sobrien if (!mountrootfsname) { 27450397Sobrien if (bootverbose) 27550397Sobrien printf("Considering MFS root f/s.\n"); 27650397Sobrien mountrootfsname = "mfs"; 27750397Sobrien /* 27850397Sobrien * Ignore the -a flag if this kernel isn't compiled 27950397Sobrien * with a generic root/swap configuration: if we skip 28050397Sobrien * setroot() and we aren't a generic kernel, chaos 28190075Sobrien * will ensue because setconf() will be a no-op. 28290075Sobrien * (rootdev is always initialized to NODEV in a 28390075Sobrien * generic configuration, so we test for that.) 28490075Sobrien */ 28590075Sobrien if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 28690075Sobrien setroot(); 28790075Sobrien } 28890075Sobrien#endif 28990075Sobrien 29090075Sobrien#ifdef BOOTP_NFSROOT 29190075Sobrien if (!mountrootfsname && !nfs_diskless_valid) { 29290075Sobrien if (bootverbose) 29390075Sobrien printf("Considering BOOTP NFS root f/s.\n"); 29490075Sobrien mountrootfsname = "nfs"; 29590075Sobrien } 29690075Sobrien#endif /* BOOTP_NFSROOT */ 29790075Sobrien#ifdef NFS 29890075Sobrien if (!mountrootfsname && nfs_diskless_valid) { 299132718Skan if (bootverbose) 300132718Skan printf("Considering NFS root f/s.\n"); 301132718Skan mountrootfsname = "nfs"; 302132718Skan } 303169689Skan#endif /* NFS */ 304169689Skan 305169689Skan#ifdef FFS 306169689Skan if (!mountrootfsname) { 307169689Skan mountrootfsname = "ufs"; 308169689Skan if (bootverbose) 309169689Skan printf("Considering FFS root f/s.\n"); 310169689Skan /* 311169689Skan * Ignore the -a flag if this kernel isn't compiled 312132718Skan * with a generic root/swap configuration: if we skip 313132718Skan * setroot() and we aren't a generic kernel, chaos 314169689Skan * will ensue because setconf() will be a no-op. 315169689Skan * (rootdev is always initialized to NODEV in a 31650397Sobrien * generic configuration, so we test for that.) 317169689Skan */ 318169689Skan if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 319169689Skan setroot(); 320169689Skan } 321169689Skan#endif 322132718Skan 32350397Sobrien#ifdef LFS 324169689Skan if (!mountrootfsname) { 325169689Skan if (bootverbose) 326169689Skan printf("Considering LFS root f/s.\n"); 327169689Skan mountrootfsname = "lfs"; 328132718Skan /* 329132718Skan * Ignore the -a flag if this kernel isn't compiled 330132718Skan * with a generic root/swap configuration: if we skip 331132718Skan * setroot() and we aren't a generic kernel, chaos 33250397Sobrien * will ensue because setconf() will be a no-op. 333132718Skan * (rootdev is always initialized to NODEV in a 334132718Skan * generic configuration, so we test for that.) 33552284Sobrien */ 336132718Skan if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 337132718Skan setroot(); 338132718Skan } 339169689Skan#endif 340132718Skan 341132718Skan if (!mountrootfsname) { 342132718Skan panic("Nobody wants to mount my root for me"); 343169689Skan } 344169689Skan 345169689Skan setconf(); 346169689Skan cold = 0; 347169689Skan if (bootverbose) 348169689Skan printf("configure() finished.\n"); 34990075Sobrien} 350169689Skan 35190075Sobrienstatic int 35252284Sobriensetdumpdev(dev) 353132718Skan dev_t dev; 354132718Skan{ 355132718Skan int maj, psize; 356132718Skan long newdumplo; 35796263Sobrien 358132718Skan if (dev == NODEV) { 359132718Skan dumpdev = dev; 360132718Skan return (0); 361132718Skan } 362132718Skan maj = major(dev); 363117395Skan if (maj >= nblkdev) 364132718Skan return (ENXIO); 365132718Skan if (bdevsw[maj] == NULL) 366169689Skan return (ENXIO); /* XXX is this right? */ 367169689Skan if (bdevsw[maj]->d_psize == NULL) 368169689Skan return (ENXIO); /* XXX should be ENODEV ? */ 369169689Skan psize = bdevsw[maj]->d_psize(dev); 370169689Skan if (psize == -1) 371169689Skan return (ENXIO); /* XXX should be ENODEV ? */ 372132718Skan newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE; 373132718Skan if (newdumplo < 0) 374146895Skan return (ENOSPC); 375146895Skan dumpdev = dev; 376132718Skan dumplo = newdumplo; 377132718Skan return (0); 378132718Skan} 379132718Skan 380132718Skanu_long bootdev = 0; /* not a dev_t - encoding is different */ 381132718Skan 382132718Skanstatic char devname[][2] = { 383169689Skan {'w','d'}, /* 0 = wd */ 384169689Skan {'s','w'}, /* 1 = sw */ 385169689Skan#define FDMAJOR 2 386169689Skan {'f','d'}, /* 2 = fd */ 387169689Skan {'w','t'}, /* 3 = wt */ 388169689Skan {'s','d'}, /* 4 = sd -- new SCSI system */ 389169689Skan}; 390169689Skan 391169689Skan#define PARTITIONMASK 0x7 392169689Skan#define PARTITIONSHIFT 3 393169689Skan#define FDUNITSHIFT 6 394169689Skan#define RAW_PART 2 395169689Skan 396169689Skan/* 397169689Skan * Attempt to find the device from which we were booted. 398169689Skan * If we can do so, and not instructed not to do so, 399169689Skan * change rootdev to correspond to the load device. 400169689Skan */ 401169689Skanstatic void 40250397Sobriensetroot() 40350397Sobrien{ 40450397Sobrien int majdev, mindev, unit, part, adaptor; 40550397Sobrien dev_t orootdev; 40650397Sobrien 40750397Sobrien/*printf("howto %x bootdev %x ", boothowto, bootdev);*/ 40890075Sobrien if (boothowto & RB_DFLTROOT || 40950397Sobrien (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 41050397Sobrien return; 41150397Sobrien majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; 41250397Sobrien if (majdev > sizeof(devname) / sizeof(devname[0])) 41350397Sobrien return; 41450397Sobrien adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; 41550397Sobrien unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; 41650397Sobrien if (majdev == FDMAJOR) { 41750397Sobrien part = RAW_PART; 41850397Sobrien mindev = unit << FDUNITSHIFT; 41950397Sobrien } 42050397Sobrien else { 421169689Skan part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; 422169689Skan mindev = (unit << PARTITIONSHIFT) + part; 423169689Skan } 424169689Skan orootdev = rootdev; 42590075Sobrien rootdev = makedev(majdev, mindev); 42650397Sobrien /* 42790075Sobrien * If the original rootdev is the same as the one 42890075Sobrien * just calculated, don't need to adjust the swap configuration. 42990075Sobrien */ 43090075Sobrien if (rootdev == orootdev) 43190075Sobrien return; 43290075Sobrien printf("changing root device to %c%c%d%c\n", 43390075Sobrien devname[majdev][0], devname[majdev][1], 43490075Sobrien mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT), 43590075Sobrien part + 'a'); 43690075Sobrien} 43790075Sobrien 43890075Sobrienstatic int 43990075Sobriensysctl_kern_dumpdev SYSCTL_HANDLER_ARGS 44090075Sobrien{ 44190075Sobrien int error; 44290075Sobrien dev_t ndumpdev; 44390075Sobrien 44490075Sobrien ndumpdev = dumpdev; 44590075Sobrien error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); 44690075Sobrien if (error == 0 && req->newptr != NULL) 44790075Sobrien error = setdumpdev(ndumpdev); 448169689Skan return (error); 44990075Sobrien} 450169689Skan 45190075SobrienSYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, 45290075Sobrien 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", ""); 45390075Sobrien