autoconf.c revision 29243
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 3729243Sjmg * $Id: autoconf.c,v 1.74 1997/07/22 20:12:32 fsmp 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 */ 4825460Sjoerg#include "opt_cd9660.h" 4925164Speter 502056Swollman#include <sys/param.h> 512056Swollman#include <sys/systm.h> 522056Swollman#include <sys/conf.h> 532056Swollman#include <sys/reboot.h> 542056Swollman#include <sys/kernel.h> 5512604Sbde#include <sys/mount.h> 5612649Speter#include <sys/sysctl.h> 574Srgrimes 5820641Sbde#include <machine/bootinfo.h> 5910665Sbde#include <machine/cons.h> 607090Sbde#include <machine/md_var.h> 6127288Sfsmp#ifdef APIC_IO 6225164Speter#include <machine/smp.h> 6325164Speter#endif /* APIC_IO */ 6427288Sfsmp 6525172Speter#include <i386/isa/icu.h> /* For interrupts */ 6625164Speter 6712604Sbde#include "isa.h" 6812604Sbde#if NISA > 0 6912604Sbde#include <i386/isa/isa_device.h> 7012604Sbde#endif 7110665Sbde 7229243Sjmg#include "pnp.h" 7329243Sjmg#if NPNP > 0 7429243Sjmg#include <i386/isa/pnp.h> 7529243Sjmg#endif 7629243Sjmg 7712604Sbde#include "eisa.h" 7812604Sbde#if NEISA > 0 7912604Sbde#include <i386/eisa/eisaconf.h> 8012604Sbde#endif 8110665Sbde 8212604Sbde#include "pci.h" 8312604Sbde#if NPCI > 0 8412604Sbde#include <pci/pcivar.h> 8512604Sbde#endif 86798Swollman 8712604Sbde#include "crd.h" 8812604Sbde#if NCRD > 0 8912604Sbde#include <pccard/driver.h> 9012604Sbde#endif 914Srgrimes 9212604Sbde#include "scbus.h" 9312604Sbde#if NSCBUS > 0 9412604Sbde#include <scsi/scsiconf.h> 9512604Sbde#endif 9612604Sbde 9712604Sbdestatic void configure __P((void *)); 9812604SbdeSYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL) 9912604Sbde 10012848Sbdestatic void configure_finish __P((void)); 10112848Sbdestatic void configure_start __P((void)); 10212848Sbdestatic int setdumpdev __P((dev_t dev)); 10312848Sbdestatic void setroot __P((void)); 10412848Sbde 1058007Sphk#ifdef CD9660 10622521Sdyson 10725460Sjoerg#include <sys/fcntl.h> 10825460Sjoerg#include <sys/proc.h> 10925460Sjoerg#include <sys/stat.h> 11025460Sjoerg#include <machine/clock.h> 11122521Sdyson 11225460Sjoerg/* 11325460Sjoerg * XXX All this CD-ROM root stuff is fairly messy. Ick. 11425460Sjoerg * 11525460Sjoerg * We need to try out all our potential CDROM drives, so we need a table. 11625460Sjoerg */ 1177731Sphkstatic struct { 1187731Sphk char *name; 1197731Sphk int major; 1207731Sphk} try_cdrom[] = { 1217731Sphk { "cd", 6 }, 1227731Sphk { "mcd", 7 }, 1237731Sphk { "scd", 16 }, 1247731Sphk { "matcd", 17 }, 12525460Sjoerg { "wcd", 19 }, 1267731Sphk { 0, 0} 1277731Sphk}; 1287731Sphk 12925460Sjoergstatic int find_cdrom_root __P((void)); 13012604Sbde 13112604Sbdestatic int 13225460Sjoergfind_cdrom_root() 1337731Sphk{ 13425460Sjoerg int i, j, error; 13525460Sjoerg struct bdevsw *bd; 13625460Sjoerg dev_t orootdev; 1377731Sphk 13825460Sjoerg#if CD9660_ROOTDELAY > 0 13925460Sjoerg DELAY(CD9660_ROOTDELAY * 1000000); 14025460Sjoerg#endif 14125460Sjoerg orootdev = rootdev; 14225460Sjoerg for (i = 0 ; i < 2; i++) 14325460Sjoerg for (j = 0 ; try_cdrom[j].name ; j++) { 14425460Sjoerg if (try_cdrom[j].major >= nblkdev) 14525460Sjoerg continue; 14625460Sjoerg rootdev = makedev(try_cdrom[j].major, i * 8); 14725460Sjoerg bd = bdevsw[major(rootdev)]; 14825460Sjoerg if (bd == NULL || bd->d_open == NULL) 14925460Sjoerg continue; 15025460Sjoerg if (bootverbose) 15125460Sjoerg printf("trying %s%d as rootdev (0x%x)\n", 15225460Sjoerg try_cdrom[j].name, i, rootdev); 15325460Sjoerg error = (bd->d_open)(rootdev, FREAD, S_IFBLK, curproc); 15425460Sjoerg if (error == 0) { 15525460Sjoerg if (bd->d_close != NULL) 15625460Sjoerg (bd->d_close)(rootdev, FREAD, S_IFBLK, 15725460Sjoerg curproc); 15825460Sjoerg return 0; 15925460Sjoerg } 1607731Sphk } 16125460Sjoerg 16225460Sjoerg rootdev = orootdev; 1637731Sphk return EINVAL; 1647731Sphk} 1658007Sphk#endif /* CD9660 */ 1667731Sphk 16712604Sbdestatic void 1687818Sdufaultconfigure_start() 1697818Sdufault{ 1707818Sdufault#if NSCBUS > 0 1717818Sdufault scsi_configure_start(); 1727818Sdufault#endif 1737818Sdufault} 1747818Sdufault 17512604Sbdestatic void 1767818Sdufaultconfigure_finish() 1777818Sdufault{ 1787818Sdufault#if NSCBUS > 0 1797818Sdufault scsi_configure_finish(); 1807818Sdufault#endif 1817818Sdufault} 1827818Sdufault 1834Srgrimes/* 1844Srgrimes * Determine i/o configuration for a machine. 1854Srgrimes */ 18610665Sbdestatic void 18710665Sbdeconfigure(dummy) 18810653Sdg void *dummy; 1894Srgrimes{ 19020641Sbde int i; 1914Srgrimes 1928015Sjulian configure_start(); 1938015Sjulian 19412791Sgibbs /* Allow all routines to decide for themselves if they want intrs */ 19527288Sfsmp#ifdef APIC_IO 19627288Sfsmp bsp_apic_configure(); 19725172Speter enable_intr(); 19827288Sfsmp#else 19927288Sfsmp enable_intr(); 20025172Speter INTREN(IRQ_SLAVE); 20127288Sfsmp#endif /* APIC_IO */ 20212791Sgibbs 20312091Sgibbs#if NEISA > 0 20412091Sgibbs eisa_configure(); 20512091Sgibbs#endif 20612091Sgibbs 2072430Sse#if NPCI > 0 2082430Sse pci_configure(); 2092430Sse#endif 2102430Sse 21129243Sjmg#if NPNP > 0 21229243Sjmg pnp_configure(); 21329243Sjmg#endif 21429243Sjmg 21512791Sgibbs#if NISA > 0 21612791Sgibbs isa_configure(); 21712791Sgibbs#endif 21812791Sgibbs 21922564Sbde#if NCRD > 0 22022564Sbde /* After everyone else has a chance at grabbing resources */ 22122564Sbde pccard_configure(); 22222564Sbde#endif 22322564Sbde 22417355Sbde if (setdumpdev(dumpdev) != 0) 22517355Sbde dumpdev = NODEV; 22617355Sbde 2277818Sdufault configure_finish(); 2287818Sdufault 22910665Sbde cninit_finish(); 23010665Sbde 23120641Sbde if (bootverbose) { 23227561Sfsmp 23327561Sfsmp#ifdef APIC_IO 23427615Sfsmp imen_dump(); 23527561Sfsmp#endif /* APIC_IO */ 23627561Sfsmp 23720641Sbde /* 23820641Sbde * Print out the BIOS's idea of the disk geometries. 23920641Sbde */ 24020641Sbde printf("BIOS Geometries:\n"); 24120641Sbde for (i = 0; i < N_BIOS_GEOM; i++) { 24220641Sbde unsigned long bios_geom; 24320641Sbde int max_cylinder, max_head, max_sector; 24420641Sbde 24520641Sbde bios_geom = bootinfo.bi_bios_geom[i]; 24620641Sbde 24720641Sbde /* 24820641Sbde * XXX the bootstrap punts a 1200K floppy geometry 24920641Sbde * when the get-disk-geometry interrupt fails. Skip 25020641Sbde * drives that have this geometry. 25120641Sbde */ 25220641Sbde if (bios_geom == 0x4f010f) 25320641Sbde continue; 25420641Sbde 25520641Sbde printf(" %x:%08lx ", i, bios_geom); 25620641Sbde max_cylinder = bios_geom >> 16; 25720641Sbde max_head = (bios_geom >> 8) & 0xff; 25820641Sbde max_sector = bios_geom & 0xff; 25920641Sbde printf( 26020641Sbde "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n", 26120641Sbde max_cylinder, max_cylinder + 1, 26220641Sbde max_head, max_head + 1, 26320641Sbde max_sector, max_sector); 26420641Sbde } 26520641Sbde printf(" %d accounted for\n", bootinfo.bi_n_bios_used); 26620641Sbde 26716075Sjoerg printf("Device configuration finished.\n"); 26820641Sbde } 26916075Sjoerg 2707731Sphk#ifdef CD9660 27122521Sdyson if ((boothowto & RB_CDROM)) { 27216075Sjoerg if (bootverbose) 27316075Sjoerg printf("Considering CD-ROM root f/s.\n"); 27425460Sjoerg /* NB: find_cdrom_root() sets rootdev if successful. */ 27525460Sjoerg if (find_cdrom_root() == 0) 27625460Sjoerg mountrootfsname = "cd9660"; 27725460Sjoerg else if (bootverbose) 27825460Sjoerg printf("No CD-ROM available as root f/s.\n"); 27916075Sjoerg } 2807731Sphk#endif 2818007Sphk 28212499Speter#ifdef MFS_ROOT 28322521Sdyson if (!mountrootfsname) { 28416075Sjoerg if (bootverbose) 28516075Sjoerg printf("Considering MFS root f/s.\n"); 28622521Sdyson mountrootfsname = "mfs"; 28712499Speter /* 28812499Speter * Ignore the -a flag if this kernel isn't compiled 28912499Speter * with a generic root/swap configuration: if we skip 29012499Speter * setroot() and we aren't a generic kernel, chaos 29112499Speter * will ensue because setconf() will be a no-op. 29212499Speter * (rootdev is always initialized to NODEV in a 29312499Speter * generic configuration, so we test for that.) 29412499Speter */ 29512499Speter if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 29612499Speter setroot(); 29712499Speter } 29812499Speter#endif 29922564Sbde 30025723Stegge#ifdef BOOTP_NFSROOT 30125723Stegge if (!mountrootfsname && !nfs_diskless_valid) { 30225723Stegge if (bootverbose) 30325723Stegge printf("Considering BOOTP NFS root f/s.\n"); 30425723Stegge mountrootfsname = "nfs"; 30525723Stegge } 30625723Stegge#endif /* BOOTP_NFSROOT */ 30722564Sbde#ifdef NFS 30822564Sbde if (!mountrootfsname && nfs_diskless_valid) { 30922564Sbde if (bootverbose) 31022564Sbde printf("Considering NFS root f/s.\n"); 31122564Sbde mountrootfsname = "nfs"; 31222564Sbde } 31322564Sbde#endif /* NFS */ 31422564Sbde 3154370Sphk#ifdef FFS 31622521Sdyson if (!mountrootfsname) { 31722521Sdyson mountrootfsname = "ufs"; 31816075Sjoerg if (bootverbose) 31916075Sjoerg printf("Considering FFS root f/s.\n"); 3206547Swpaul /* 3216547Swpaul * Ignore the -a flag if this kernel isn't compiled 3226547Swpaul * with a generic root/swap configuration: if we skip 3236547Swpaul * setroot() and we aren't a generic kernel, chaos 3246547Swpaul * will ensue because setconf() will be a no-op. 3256547Swpaul * (rootdev is always initialized to NODEV in a 3266547Swpaul * generic configuration, so we test for that.) 3276547Swpaul */ 3286547Swpaul if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 3295321Sjkh setroot(); 3303795Sphk } 3314Srgrimes#endif 33222564Sbde 33310358Sjulian#ifdef LFS 33422521Sdyson if (!mountrootfsname) { 33516075Sjoerg if (bootverbose) 33616075Sjoerg printf("Considering LFS root f/s.\n"); 33722521Sdyson mountrootfsname = "lfs"; 33810358Sjulian /* 33910358Sjulian * Ignore the -a flag if this kernel isn't compiled 34010358Sjulian * with a generic root/swap configuration: if we skip 34110358Sjulian * setroot() and we aren't a generic kernel, chaos 34210358Sjulian * will ensue because setconf() will be a no-op. 34310358Sjulian * (rootdev is always initialized to NODEV in a 34410358Sjulian * generic configuration, so we test for that.) 34510358Sjulian */ 34610358Sjulian if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 34710358Sjulian setroot(); 34810358Sjulian } 34910358Sjulian#endif 35022564Sbde 35122521Sdyson if (!mountrootfsname) { 3524370Sphk panic("Nobody wants to mount my root for me"); 3534370Sphk } 35417355Sbde 3558433Swpaul setconf(); 3564Srgrimes cold = 0; 35716075Sjoerg if (bootverbose) 35816075Sjoerg printf("configure() finished.\n"); 3594Srgrimes} 3604Srgrimes 36112722Sphkstatic int 3628833Sdgsetdumpdev(dev) 3638833Sdg dev_t dev; 3648481Swollman{ 3658833Sdg int maj, psize; 3668833Sdg long newdumplo; 3678833Sdg 3688833Sdg if (dev == NODEV) { 3698481Swollman dumpdev = dev; 3708833Sdg return (0); 3718481Swollman } 3728833Sdg maj = major(dev); 3738833Sdg if (maj >= nblkdev) 3748833Sdg return (ENXIO); 37512889Speter if (bdevsw[maj] == NULL) 37612889Speter return (ENXIO); /* XXX is this right? */ 37712813Sjulian if (bdevsw[maj]->d_psize == NULL) 37812889Speter return (ENXIO); /* XXX should be ENODEV ? */ 37912813Sjulian psize = bdevsw[maj]->d_psize(dev); 3808833Sdg if (psize == -1) 38112889Speter return (ENXIO); /* XXX should be ENODEV ? */ 38215538Sphk newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE; 3838833Sdg if (newdumplo < 0) 3848833Sdg return (ENOSPC); 3858833Sdg dumpdev = dev; 3868833Sdg dumplo = newdumplo; 3878833Sdg return (0); 3888876Srgrimes} 3898481Swollman 3908833Sdgu_long bootdev = 0; /* not a dev_t - encoding is different */ 3914Srgrimes 3924Srgrimesstatic char devname[][2] = { 3936105Sse {'w','d'}, /* 0 = wd */ 3946105Sse {'s','w'}, /* 1 = sw */ 3951289Sache#define FDMAJOR 2 3966105Sse {'f','d'}, /* 2 = fd */ 3976105Sse {'w','t'}, /* 3 = wt */ 3986105Sse {'s','d'}, /* 4 = sd -- new SCSI system */ 3994Srgrimes}; 4004Srgrimes 4014Srgrimes#define PARTITIONMASK 0x7 4024Srgrimes#define PARTITIONSHIFT 3 4031290Sache#define FDUNITSHIFT 6 4042400Sache#define RAW_PART 2 4054Srgrimes 4064Srgrimes/* 4074Srgrimes * Attempt to find the device from which we were booted. 4084Srgrimes * If we can do so, and not instructed not to do so, 4094Srgrimes * change rootdev to correspond to the load device. 4104Srgrimes */ 411798Swollmanstatic void 4124Srgrimessetroot() 4134Srgrimes{ 4144Srgrimes int majdev, mindev, unit, part, adaptor; 41512417Sphk dev_t orootdev; 4164Srgrimes 4174Srgrimes/*printf("howto %x bootdev %x ", boothowto, bootdev);*/ 4184Srgrimes if (boothowto & RB_DFLTROOT || 4194Srgrimes (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 4204Srgrimes return; 4214Srgrimes majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; 4224Srgrimes if (majdev > sizeof(devname) / sizeof(devname[0])) 4234Srgrimes return; 4244Srgrimes adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; 4254Srgrimes unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; 4261290Sache if (majdev == FDMAJOR) { 4272400Sache part = RAW_PART; 4281290Sache mindev = unit << FDUNITSHIFT; 4291290Sache } 4301290Sache else { 4311290Sache part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; 4321289Sache mindev = (unit << PARTITIONSHIFT) + part; 4331290Sache } 4344Srgrimes orootdev = rootdev; 4354Srgrimes rootdev = makedev(majdev, mindev); 4364Srgrimes /* 4374Srgrimes * If the original rootdev is the same as the one 4384Srgrimes * just calculated, don't need to adjust the swap configuration. 4394Srgrimes */ 4404Srgrimes if (rootdev == orootdev) 4414Srgrimes return; 4424Srgrimes printf("changing root device to %c%c%d%c\n", 4434Srgrimes devname[majdev][0], devname[majdev][1], 4441290Sache mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT), 4451290Sache part + 'a'); 4464Srgrimes} 44712649Speter 44812649Speterstatic int 44912649Spetersysctl_kern_dumpdev SYSCTL_HANDLER_ARGS 45012649Speter{ 45112649Speter int error; 45212649Speter dev_t ndumpdev; 45312649Speter 45412649Speter ndumpdev = dumpdev; 45512649Speter error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); 45617355Sbde if (error == 0 && req->newptr != NULL) 45712649Speter error = setdumpdev(ndumpdev); 45812649Speter return (error); 45912649Speter} 46012649Speter 46112649SpeterSYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, 46222564Sbde 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", ""); 463