autoconf.c revision 25723
14Srgrimes/*- 24Srgrimes * Copyright (c) 1990 The Regents of the University of California. 34Srgrimes * All rights reserved. 44Srgrimes * 54Srgrimes * This code is derived from software contributed to Berkeley by 64Srgrimes * William Jolitz. 74Srgrimes * 84Srgrimes * Redistribution and use in source and binary forms, with or without 94Srgrimes * modification, are permitted provided that the following conditions 104Srgrimes * are met: 114Srgrimes * 1. Redistributions of source code must retain the above copyright 124Srgrimes * notice, this list of conditions and the following disclaimer. 134Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 144Srgrimes * notice, this list of conditions and the following disclaimer in the 154Srgrimes * documentation and/or other materials provided with the distribution. 164Srgrimes * 3. All advertising materials mentioning features or use of this software 174Srgrimes * must display the following acknowledgement: 184Srgrimes * This product includes software developed by the University of 194Srgrimes * California, Berkeley and its contributors. 204Srgrimes * 4. Neither the name of the University nor the names of its contributors 214Srgrimes * may be used to endorse or promote products derived from this software 224Srgrimes * without specific prior written permission. 234Srgrimes * 244Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 254Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 264Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 274Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 284Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 294Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 304Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 314Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 324Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 334Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 344Srgrimes * SUCH DAMAGE. 354Srgrimes * 36620Srgrimes * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 3725723Stegge * $Id: autoconf.c,v 1.67 1997/05/04 15:24:19 joerg Exp $ 384Srgrimes */ 394Srgrimes 404Srgrimes/* 414Srgrimes * Setup the system to run on the current machine. 424Srgrimes * 438876Srgrimes * Configure() is called at boot time and initializes the vba 444Srgrimes * device tables and the memory controller monitoring. Available 454Srgrimes * devices are determined (from possibilities mentioned in ioconf.c), 464Srgrimes * and the drivers are initialized. 474Srgrimes */ 4825164Speter#include "opt_smp.h" 4925460Sjoerg#include "opt_cd9660.h" 5025164Speter 512056Swollman#include <sys/param.h> 522056Swollman#include <sys/systm.h> 532056Swollman#include <sys/buf.h> 542056Swollman#include <sys/conf.h> 552056Swollman#include <sys/dmap.h> 562056Swollman#include <sys/reboot.h> 572056Swollman#include <sys/kernel.h> 5812604Sbde#include <sys/mount.h> 5922521Sdyson#include <sys/vnode.h> 6012649Speter#include <sys/sysctl.h> 614Srgrimes 6220641Sbde#include <machine/bootinfo.h> 6310665Sbde#include <machine/cons.h> 647090Sbde#include <machine/md_var.h> 6525164Speter#if defined(APIC_IO) 6625164Speter#include <machine/smp.h> 6725164Speter#endif /* APIC_IO */ 6825172Speter#include <i386/isa/icu.h> /* For interrupts */ 6925164Speter 7012604Sbde#include "isa.h" 7112604Sbde#if NISA > 0 7212604Sbde#include <i386/isa/isa_device.h> 7312604Sbde#endif 7410665Sbde 7512604Sbde#include "eisa.h" 7612604Sbde#if NEISA > 0 7712604Sbde#include <i386/eisa/eisaconf.h> 7812604Sbde#endif 7910665Sbde 8012604Sbde#include "pci.h" 8112604Sbde#if NPCI > 0 8212604Sbde#include <pci/pcivar.h> 8312604Sbde#endif 84798Swollman 8512604Sbde#include "crd.h" 8612604Sbde#if NCRD > 0 8712604Sbde#include <pccard/driver.h> 8812604Sbde#endif 894Srgrimes 9012604Sbde#include "scbus.h" 9112604Sbde#if NSCBUS > 0 9212604Sbde#include <scsi/scsiconf.h> 9312604Sbde#endif 9412604Sbde 9512604Sbdestatic void configure __P((void *)); 9612604SbdeSYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL) 9712604Sbde 9812848Sbdestatic void configure_finish __P((void)); 9912848Sbdestatic void configure_start __P((void)); 10012848Sbdestatic int setdumpdev __P((dev_t dev)); 10112848Sbdestatic void setroot __P((void)); 10212848Sbde 1038007Sphk#ifdef CD9660 10422521Sdyson 10525460Sjoerg#include <sys/fcntl.h> 10625460Sjoerg#include <sys/proc.h> 10725460Sjoerg#include <sys/stat.h> 10825460Sjoerg#include <machine/clock.h> 10922521Sdyson#include <isofs/cd9660/iso.h> 11022521Sdyson 11125460Sjoerg/* 11225460Sjoerg * XXX All this CD-ROM root stuff is fairly messy. Ick. 11325460Sjoerg * 11425460Sjoerg * We need to try out all our potential CDROM drives, so we need a table. 11525460Sjoerg */ 1167731Sphkstatic struct { 1177731Sphk char *name; 1187731Sphk int major; 1197731Sphk} try_cdrom[] = { 1207731Sphk { "cd", 6 }, 1217731Sphk { "mcd", 7 }, 1227731Sphk { "scd", 16 }, 1237731Sphk { "matcd", 17 }, 12425460Sjoerg { "wcd", 19 }, 1257731Sphk { 0, 0} 1267731Sphk}; 1277731Sphk 12825460Sjoergstatic int find_cdrom_root __P((void)); 12912604Sbde 13012604Sbdestatic int 13125460Sjoergfind_cdrom_root() 1327731Sphk{ 13325460Sjoerg int i, j, error; 13425460Sjoerg struct bdevsw *bd; 13525460Sjoerg dev_t orootdev; 1367731Sphk 13725460Sjoerg#if CD9660_ROOTDELAY > 0 13825460Sjoerg DELAY(CD9660_ROOTDELAY * 1000000); 13925460Sjoerg#endif 14025460Sjoerg orootdev = rootdev; 14125460Sjoerg for (i = 0 ; i < 2; i++) 14225460Sjoerg for (j = 0 ; try_cdrom[j].name ; j++) { 14325460Sjoerg if (try_cdrom[j].major >= nblkdev) 14425460Sjoerg continue; 14525460Sjoerg rootdev = makedev(try_cdrom[j].major, i * 8); 14625460Sjoerg bd = bdevsw[major(rootdev)]; 14725460Sjoerg if (bd == NULL || bd->d_open == NULL) 14825460Sjoerg continue; 14925460Sjoerg if (bootverbose) 15025460Sjoerg printf("trying %s%d as rootdev (0x%x)\n", 15125460Sjoerg try_cdrom[j].name, i, rootdev); 15225460Sjoerg error = (bd->d_open)(rootdev, FREAD, S_IFBLK, curproc); 15325460Sjoerg if (error == 0) { 15425460Sjoerg if (bd->d_close != NULL) 15525460Sjoerg (bd->d_close)(rootdev, FREAD, S_IFBLK, 15625460Sjoerg curproc); 15725460Sjoerg return 0; 15825460Sjoerg } 1597731Sphk } 16025460Sjoerg 16125460Sjoerg rootdev = orootdev; 1627731Sphk return EINVAL; 1637731Sphk} 1648007Sphk#endif /* CD9660 */ 1657731Sphk 16612604Sbdestatic void 1677818Sdufaultconfigure_start() 1687818Sdufault{ 1697818Sdufault#if NSCBUS > 0 1707818Sdufault scsi_configure_start(); 1717818Sdufault#endif 1727818Sdufault} 1737818Sdufault 17412604Sbdestatic void 1757818Sdufaultconfigure_finish() 1767818Sdufault{ 1777818Sdufault#if NSCBUS > 0 1787818Sdufault scsi_configure_finish(); 1797818Sdufault#endif 1807818Sdufault} 1817818Sdufault 1824Srgrimes/* 1834Srgrimes * Determine i/o configuration for a machine. 1844Srgrimes */ 18510665Sbdestatic void 18610665Sbdeconfigure(dummy) 18710653Sdg void *dummy; 1884Srgrimes{ 18920641Sbde int i; 1904Srgrimes 1918015Sjulian configure_start(); 1928015Sjulian 19312791Sgibbs /* Allow all routines to decide for themselves if they want intrs */ 19425164Speter#if defined(APIC_IO) 19525164Speter configure_local_apic(); 19625164Speter#endif /* APIC_IO */ 19725172Speter enable_intr(); 19825172Speter#if !defined(APIC_IO) 19925172Speter INTREN(IRQ_SLAVE); 20025172Speter#endif /* !APIC_IO */ 20112791Sgibbs 20212091Sgibbs#if NEISA > 0 20312091Sgibbs eisa_configure(); 20412091Sgibbs#endif 20512091Sgibbs 2062430Sse#if NPCI > 0 2072430Sse pci_configure(); 2082430Sse#endif 2092430Sse 21012791Sgibbs#if NISA > 0 21112791Sgibbs isa_configure(); 21212791Sgibbs#endif 21312791Sgibbs 21422564Sbde#if NCRD > 0 21522564Sbde /* After everyone else has a chance at grabbing resources */ 21622564Sbde pccard_configure(); 21722564Sbde#endif 21822564Sbde 21917355Sbde if (setdumpdev(dumpdev) != 0) 22017355Sbde dumpdev = NODEV; 22117355Sbde 2227818Sdufault configure_finish(); 2237818Sdufault 22410665Sbde cninit_finish(); 22510665Sbde 22620641Sbde if (bootverbose) { 22720641Sbde /* 22820641Sbde * Print out the BIOS's idea of the disk geometries. 22920641Sbde */ 23020641Sbde printf("BIOS Geometries:\n"); 23120641Sbde for (i = 0; i < N_BIOS_GEOM; i++) { 23220641Sbde unsigned long bios_geom; 23320641Sbde int max_cylinder, max_head, max_sector; 23420641Sbde 23520641Sbde bios_geom = bootinfo.bi_bios_geom[i]; 23620641Sbde 23720641Sbde /* 23820641Sbde * XXX the bootstrap punts a 1200K floppy geometry 23920641Sbde * when the get-disk-geometry interrupt fails. Skip 24020641Sbde * drives that have this geometry. 24120641Sbde */ 24220641Sbde if (bios_geom == 0x4f010f) 24320641Sbde continue; 24420641Sbde 24520641Sbde printf(" %x:%08lx ", i, bios_geom); 24620641Sbde max_cylinder = bios_geom >> 16; 24720641Sbde max_head = (bios_geom >> 8) & 0xff; 24820641Sbde max_sector = bios_geom & 0xff; 24920641Sbde printf( 25020641Sbde "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n", 25120641Sbde max_cylinder, max_cylinder + 1, 25220641Sbde max_head, max_head + 1, 25320641Sbde max_sector, max_sector); 25420641Sbde } 25520641Sbde printf(" %d accounted for\n", bootinfo.bi_n_bios_used); 25620641Sbde 25716075Sjoerg printf("Device configuration finished.\n"); 25820641Sbde } 25916075Sjoerg 2607731Sphk#ifdef CD9660 26122521Sdyson if ((boothowto & RB_CDROM)) { 26216075Sjoerg if (bootverbose) 26316075Sjoerg printf("Considering CD-ROM root f/s.\n"); 26425460Sjoerg /* NB: find_cdrom_root() sets rootdev if successful. */ 26525460Sjoerg if (find_cdrom_root() == 0) 26625460Sjoerg mountrootfsname = "cd9660"; 26725460Sjoerg else if (bootverbose) 26825460Sjoerg printf("No CD-ROM available as root f/s.\n"); 26916075Sjoerg } 2707731Sphk#endif 2718007Sphk 27212499Speter#ifdef MFS_ROOT 27322521Sdyson if (!mountrootfsname) { 27416075Sjoerg if (bootverbose) 27516075Sjoerg printf("Considering MFS root f/s.\n"); 27622521Sdyson mountrootfsname = "mfs"; 27712499Speter /* 27812499Speter * Ignore the -a flag if this kernel isn't compiled 27912499Speter * with a generic root/swap configuration: if we skip 28012499Speter * setroot() and we aren't a generic kernel, chaos 28112499Speter * will ensue because setconf() will be a no-op. 28212499Speter * (rootdev is always initialized to NODEV in a 28312499Speter * generic configuration, so we test for that.) 28412499Speter */ 28512499Speter if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 28612499Speter setroot(); 28712499Speter } 28812499Speter#endif 28922564Sbde 29025723Stegge#ifdef BOOTP_NFSROOT 29125723Stegge if (!mountrootfsname && !nfs_diskless_valid) { 29225723Stegge if (bootverbose) 29325723Stegge printf("Considering BOOTP NFS root f/s.\n"); 29425723Stegge mountrootfsname = "nfs"; 29525723Stegge } 29625723Stegge#endif /* BOOTP_NFSROOT */ 29722564Sbde#ifdef NFS 29822564Sbde if (!mountrootfsname && nfs_diskless_valid) { 29922564Sbde if (bootverbose) 30022564Sbde printf("Considering NFS root f/s.\n"); 30122564Sbde mountrootfsname = "nfs"; 30222564Sbde } 30322564Sbde#endif /* NFS */ 30422564Sbde 3054370Sphk#ifdef FFS 30622521Sdyson if (!mountrootfsname) { 30722521Sdyson mountrootfsname = "ufs"; 30816075Sjoerg if (bootverbose) 30916075Sjoerg printf("Considering FFS root f/s.\n"); 3106547Swpaul /* 3116547Swpaul * Ignore the -a flag if this kernel isn't compiled 3126547Swpaul * with a generic root/swap configuration: if we skip 3136547Swpaul * setroot() and we aren't a generic kernel, chaos 3146547Swpaul * will ensue because setconf() will be a no-op. 3156547Swpaul * (rootdev is always initialized to NODEV in a 3166547Swpaul * generic configuration, so we test for that.) 3176547Swpaul */ 3186547Swpaul if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 3195321Sjkh setroot(); 3203795Sphk } 3214Srgrimes#endif 32222564Sbde 32310358Sjulian#ifdef LFS 32422521Sdyson if (!mountrootfsname) { 32516075Sjoerg if (bootverbose) 32616075Sjoerg printf("Considering LFS root f/s.\n"); 32722521Sdyson mountrootfsname = "lfs"; 32810358Sjulian /* 32910358Sjulian * Ignore the -a flag if this kernel isn't compiled 33010358Sjulian * with a generic root/swap configuration: if we skip 33110358Sjulian * setroot() and we aren't a generic kernel, chaos 33210358Sjulian * will ensue because setconf() will be a no-op. 33310358Sjulian * (rootdev is always initialized to NODEV in a 33410358Sjulian * generic configuration, so we test for that.) 33510358Sjulian */ 33610358Sjulian if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 33710358Sjulian setroot(); 33810358Sjulian } 33910358Sjulian#endif 34022564Sbde 34122521Sdyson if (!mountrootfsname) { 3424370Sphk panic("Nobody wants to mount my root for me"); 3434370Sphk } 34417355Sbde 3458433Swpaul setconf(); 3464Srgrimes cold = 0; 34716075Sjoerg if (bootverbose) 34816075Sjoerg printf("configure() finished.\n"); 3494Srgrimes} 3504Srgrimes 35112722Sphkstatic int 3528833Sdgsetdumpdev(dev) 3538833Sdg dev_t dev; 3548481Swollman{ 3558833Sdg int maj, psize; 3568833Sdg long newdumplo; 3578833Sdg 3588833Sdg if (dev == NODEV) { 3598481Swollman dumpdev = dev; 3608833Sdg return (0); 3618481Swollman } 3628833Sdg maj = major(dev); 3638833Sdg if (maj >= nblkdev) 3648833Sdg return (ENXIO); 36512889Speter if (bdevsw[maj] == NULL) 36612889Speter return (ENXIO); /* XXX is this right? */ 36712813Sjulian if (bdevsw[maj]->d_psize == NULL) 36812889Speter return (ENXIO); /* XXX should be ENODEV ? */ 36912813Sjulian psize = bdevsw[maj]->d_psize(dev); 3708833Sdg if (psize == -1) 37112889Speter return (ENXIO); /* XXX should be ENODEV ? */ 37215538Sphk newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE; 3738833Sdg if (newdumplo < 0) 3748833Sdg return (ENOSPC); 3758833Sdg dumpdev = dev; 3768833Sdg dumplo = newdumplo; 3778833Sdg return (0); 3788876Srgrimes} 3798481Swollman 3808833Sdgu_long bootdev = 0; /* not a dev_t - encoding is different */ 3814Srgrimes 3824Srgrimesstatic char devname[][2] = { 3836105Sse {'w','d'}, /* 0 = wd */ 3846105Sse {'s','w'}, /* 1 = sw */ 3851289Sache#define FDMAJOR 2 3866105Sse {'f','d'}, /* 2 = fd */ 3876105Sse {'w','t'}, /* 3 = wt */ 3886105Sse {'s','d'}, /* 4 = sd -- new SCSI system */ 3894Srgrimes}; 3904Srgrimes 3914Srgrimes#define PARTITIONMASK 0x7 3924Srgrimes#define PARTITIONSHIFT 3 3931290Sache#define FDUNITSHIFT 6 3942400Sache#define RAW_PART 2 3954Srgrimes 3964Srgrimes/* 3974Srgrimes * Attempt to find the device from which we were booted. 3984Srgrimes * If we can do so, and not instructed not to do so, 3994Srgrimes * change rootdev to correspond to the load device. 4004Srgrimes */ 401798Swollmanstatic void 4024Srgrimessetroot() 4034Srgrimes{ 4044Srgrimes int majdev, mindev, unit, part, adaptor; 40512417Sphk dev_t orootdev; 4064Srgrimes 4074Srgrimes/*printf("howto %x bootdev %x ", boothowto, bootdev);*/ 4084Srgrimes if (boothowto & RB_DFLTROOT || 4094Srgrimes (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 4104Srgrimes return; 4114Srgrimes majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; 4124Srgrimes if (majdev > sizeof(devname) / sizeof(devname[0])) 4134Srgrimes return; 4144Srgrimes adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; 4154Srgrimes unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; 4161290Sache if (majdev == FDMAJOR) { 4172400Sache part = RAW_PART; 4181290Sache mindev = unit << FDUNITSHIFT; 4191290Sache } 4201290Sache else { 4211290Sache part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; 4221289Sache mindev = (unit << PARTITIONSHIFT) + part; 4231290Sache } 4244Srgrimes orootdev = rootdev; 4254Srgrimes rootdev = makedev(majdev, mindev); 4264Srgrimes /* 4274Srgrimes * If the original rootdev is the same as the one 4284Srgrimes * just calculated, don't need to adjust the swap configuration. 4294Srgrimes */ 4304Srgrimes if (rootdev == orootdev) 4314Srgrimes return; 4324Srgrimes printf("changing root device to %c%c%d%c\n", 4334Srgrimes devname[majdev][0], devname[majdev][1], 4341290Sache mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT), 4351290Sache part + 'a'); 4364Srgrimes} 43712649Speter 43812649Speterstatic int 43912649Spetersysctl_kern_dumpdev SYSCTL_HANDLER_ARGS 44012649Speter{ 44112649Speter int error; 44212649Speter dev_t ndumpdev; 44312649Speter 44412649Speter ndumpdev = dumpdev; 44512649Speter error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); 44617355Sbde if (error == 0 && req->newptr != NULL) 44712649Speter error = setdumpdev(ndumpdev); 44812649Speter return (error); 44912649Speter} 45012649Speter 45112649SpeterSYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, 45222564Sbde 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", ""); 453