autoconf.c revision 12889
129088Smarkm/*- 229088Smarkm * Copyright (c) 1990 The Regents of the University of California. 329088Smarkm * All rights reserved. 429088Smarkm * 529088Smarkm * This code is derived from software contributed to Berkeley by 629088Smarkm * William Jolitz. 729088Smarkm * 829088Smarkm * Redistribution and use in source and binary forms, with or without 929088Smarkm * modification, are permitted provided that the following conditions 1029088Smarkm * are met: 1129088Smarkm * 1. Redistributions of source code must retain the above copyright 1229088Smarkm * notice, this list of conditions and the following disclaimer. 1329088Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1429088Smarkm * notice, this list of conditions and the following disclaimer in the 1529088Smarkm * documentation and/or other materials provided with the distribution. 1629088Smarkm * 3. All advertising materials mentioning features or use of this software 1729088Smarkm * must display the following acknowledgement: 1829088Smarkm * This product includes software developed by the University of 1929088Smarkm * California, Berkeley and its contributors. 2029088Smarkm * 4. Neither the name of the University nor the names of its contributors 2129088Smarkm * may be used to endorse or promote products derived from this software 2229088Smarkm * without specific prior written permission. 2329088Smarkm * 2429088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2529088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2629088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2729088Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2829088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2929088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3029088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3129088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3229088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3329088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3429088Smarkm * SUCH DAMAGE. 3529181Smarkm * 3629088Smarkm * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 3729088Smarkm * $Id: autoconf.c,v 1.50 1995/12/14 23:35:17 bde Exp $ 3829088Smarkm */ 3929088Smarkm 4029088Smarkm/* 4129088Smarkm * Setup the system to run on the current machine. 4229088Smarkm * 4329088Smarkm * Configure() is called at boot time and initializes the vba 4429088Smarkm * device tables and the memory controller monitoring. Available 4529088Smarkm * devices are determined (from possibilities mentioned in ioconf.c), 4629088Smarkm * and the drivers are initialized. 4729088Smarkm */ 4829088Smarkm#include <sys/param.h> 4929088Smarkm#include <sys/systm.h> 5029088Smarkm#include <sys/buf.h> 5129088Smarkm#include <sys/dkstat.h> 5229088Smarkm#include <sys/conf.h> 5329088Smarkm#include <sys/dmap.h> 5429088Smarkm#include <sys/reboot.h> 5529088Smarkm#include <sys/kernel.h> 5629088Smarkm#include <sys/mount.h> 5729088Smarkm#include <sys/sysctl.h> 5829088Smarkm 5929181Smarkm#include <machine/cons.h> 6029181Smarkm#include <machine/md_var.h> 6129088Smarkm#include <machine/pte.h> 6229088Smarkm#include <i386/isa/icu.h> /* For interrupts */ 6329088Smarkm 6429088Smarkm#include "isa.h" 6529088Smarkm#if NISA > 0 6629088Smarkm#include <i386/isa/isa_device.h> 6729088Smarkm#endif 6829088Smarkm 6929088Smarkm#include "eisa.h" 7029088Smarkm#if NEISA > 0 7129088Smarkm#include <i386/eisa/eisaconf.h> 7229181Smarkm#endif 7329181Smarkm 7429181Smarkm#include "pci.h" 7529181Smarkm#if NPCI > 0 7629181Smarkm#include <pci/pcivar.h> 7729181Smarkm#endif 7829181Smarkm 7929088Smarkm#include "crd.h" 8029088Smarkm#if NCRD > 0 8129088Smarkm#include <pccard/driver.h> 8229088Smarkm#endif 8329088Smarkm 8429088Smarkm#include "scbus.h" 8529088Smarkm#if NSCBUS > 0 8629088Smarkm#include <scsi/scsiconf.h> 8729088Smarkm#endif 8829088Smarkm 8929088Smarkmstatic void configure __P((void *)); 9029088SmarkmSYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL) 9129088Smarkm 9229088Smarkm#ifdef MFS_ROOT 9329088Smarkmextern struct vfsops mfs_vfsops; 9429088Smarkm#endif 9529088Smarkm#ifdef FFS 9629088Smarkmextern struct vfsops ufs_vfsops; 9729088Smarkm#endif 9829088Smarkm#ifdef LFS 9929088Smarkmextern struct vfsops lfs_vfsops; 10029088Smarkm#endif 10129088Smarkm#ifdef NFS 10229088Smarkmextern int nfs_mountroot __P((void *)); 10329088Smarkm#endif 10429088Smarkm#ifdef CD9660 10529181Smarkmextern int cd9660_mountroot __P((void *)); 10629181Smarkm#endif 10729181Smarkm#ifdef MSDOSFS 10829088Smarkmextern int msdosfs_mountroot __P((void *)); 10929181Smarkm#endif 11029181Smarkm 11129088Smarkmstatic void configure_finish __P((void)); 11229088Smarkmstatic void configure_start __P((void)); 11329088Smarkmstatic int setdumpdev __P((dev_t dev)); 11429088Smarkmstatic void setroot __P((void)); 11529088Smarkm 11629088Smarkm#ifdef CD9660 11729088Smarkm/* We need to try out all our potential CDROM drives, so we need a table. */ 11829088Smarkmstatic struct { 11929088Smarkm char *name; 12029088Smarkm int major; 12129088Smarkm} try_cdrom[] = { 12229088Smarkm { "cd", 6 }, 12329181Smarkm { "mcd", 7 }, 12429181Smarkm { "scd", 16 }, 12529181Smarkm { "matcd", 17 }, 12629181Smarkm { 0, 0} 12729181Smarkm}; 12829181Smarkm 12929181Smarkmstatic int find_cdrom_root __P((void *)); 13029181Smarkm 13129181Smarkmstatic int 13229181Smarkmfind_cdrom_root(dummy) 13329181Smarkm void *dummy; 13429181Smarkm{ 13529181Smarkm int i,j,k; 13629181Smarkm 13729181Smarkm for (j = 0 ; j < 2; j++) 13829181Smarkm for (k = 0 ; try_cdrom[k].name ; k++) { 13929181Smarkm rootdev = makedev(try_cdrom[k].major,j*8); 14029181Smarkm printf("trying rootdev=0x%lx (%s%d)\n", 14129181Smarkm rootdev, try_cdrom[k].name,j); 14229181Smarkm i = (*cd9660_mountroot)((void *)NULL); 14329181Smarkm if (!i) return i; 14429181Smarkm } 14529181Smarkm return EINVAL; 14629181Smarkm} 14729181Smarkm#endif /* CD9660 */ 14829181Smarkm 14929181Smarkmstatic void 15029181Smarkmconfigure_start() 15129181Smarkm{ 15229181Smarkm#if NSCBUS > 0 15329181Smarkm scsi_configure_start(); 15429088Smarkm#endif 15529088Smarkm} 15629088Smarkm 15729088Smarkmstatic void 15829088Smarkmconfigure_finish() 15929088Smarkm{ 16029088Smarkm#if NSCBUS > 0 16129088Smarkm scsi_configure_finish(); 16229088Smarkm#endif 16329088Smarkm} 16429088Smarkm 16529088Smarkm/* 16629088Smarkm * Determine i/o configuration for a machine. 16729088Smarkm */ 16829181Smarkmstatic void 16929088Smarkmconfigure(dummy) 17029088Smarkm void *dummy; 17129088Smarkm{ 17229088Smarkm 17329088Smarkm configure_start(); 17429088Smarkm 17529088Smarkm /* Allow all routines to decide for themselves if they want intrs */ 17629088Smarkm enable_intr(); 17729088Smarkm INTREN(IRQ_SLAVE); 17829088Smarkm 17929088Smarkm#if NCRD > 0 18029088Smarkm /* Before isa_configure to avoid ISA drivers finding our cards */ 18129088Smarkm pccard_configure(); 18229088Smarkm#endif 18329088Smarkm 18429088Smarkm#if NEISA > 0 18529088Smarkm eisa_configure(); 18629088Smarkm#endif 18729088Smarkm 18829088Smarkm#if NPCI > 0 18929088Smarkm pci_configure(); 19029088Smarkm#endif 19129088Smarkm 19229088Smarkm#if NISA > 0 19329088Smarkm isa_configure(); 19429088Smarkm#endif 19529088Smarkm 19629088Smarkm configure_finish(); 19729088Smarkm 19829088Smarkm cninit_finish(); 19929088Smarkm 20029088Smarkm#ifdef CD9660 20129088Smarkm if ((boothowto & RB_CDROM) && !mountroot) 20229088Smarkm mountroot = find_cdrom_root; 20329088Smarkm#endif 20429088Smarkm 20529088Smarkm#ifdef NFS 20629088Smarkm if (!mountroot && nfs_diskless_valid) 20729088Smarkm mountroot = nfs_mountroot; 20829088Smarkm#endif /* NFS */ 20929088Smarkm 21029088Smarkm#ifdef MFS_ROOT 21129181Smarkm if (!mountroot) { 21229088Smarkm mountroot = vfs_mountroot; /* XXX goes away*/ 21329088Smarkm mountrootvfsops = &mfs_vfsops; 21429088Smarkm /* 21529088Smarkm * Ignore the -a flag if this kernel isn't compiled 21629088Smarkm * with a generic root/swap configuration: if we skip 21729088Smarkm * setroot() and we aren't a generic kernel, chaos 21829088Smarkm * will ensue because setconf() will be a no-op. 21929088Smarkm * (rootdev is always initialized to NODEV in a 22029088Smarkm * generic configuration, so we test for that.) 22129088Smarkm */ 22229088Smarkm if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 22329088Smarkm setroot(); 22429088Smarkm } 22529088Smarkm#endif 22629088Smarkm#ifdef FFS 22729088Smarkm if (!mountroot) { 22829088Smarkm mountroot = vfs_mountroot; /* XXX goes away*/ 22929088Smarkm mountrootvfsops = &ufs_vfsops; 23029088Smarkm /* 23129088Smarkm * Ignore the -a flag if this kernel isn't compiled 23229088Smarkm * with a generic root/swap configuration: if we skip 23329088Smarkm * setroot() and we aren't a generic kernel, chaos 23429088Smarkm * will ensue because setconf() will be a no-op. 23529088Smarkm * (rootdev is always initialized to NODEV in a 23629088Smarkm * generic configuration, so we test for that.) 23729088Smarkm */ 23829088Smarkm if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 23929088Smarkm setroot(); 24029088Smarkm } 24129088Smarkm#endif 24229088Smarkm#ifdef LFS 24329088Smarkm if (!mountroot) { 24429088Smarkm mountroot = vfs_mountroot; /* XXX goes away*/ 24529088Smarkm mountrootvfsops = &lfs_vfsops; 24629088Smarkm /* 24729088Smarkm * Ignore the -a flag if this kernel isn't compiled 24829088Smarkm * with a generic root/swap configuration: if we skip 24929088Smarkm * setroot() and we aren't a generic kernel, chaos 25029088Smarkm * will ensue because setconf() will be a no-op. 25129088Smarkm * (rootdev is always initialized to NODEV in a 25229088Smarkm * generic configuration, so we test for that.) 25329088Smarkm */ 25429088Smarkm if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 25529088Smarkm setroot(); 25629088Smarkm } 25729088Smarkm#endif 25829088Smarkm if (!mountroot) { 25929088Smarkm panic("Nobody wants to mount my root for me"); 26029088Smarkm } 26129088Smarkm /* 26229088Smarkm * Configure swap area and related system 26329088Smarkm * parameter based on device(s) used. 26429088Smarkm */ 26529088Smarkm setconf(); 26629088Smarkm cold = 0; 26729088Smarkm} 26829088Smarkm 26929088Smarkmstatic int 27029088Smarkmsetdumpdev(dev) 27129088Smarkm dev_t dev; 27229088Smarkm{ 27329088Smarkm int maj, psize; 27429088Smarkm long newdumplo; 27529088Smarkm 27629088Smarkm if (dev == NODEV) { 27729088Smarkm dumpdev = dev; 27829088Smarkm dumplo = 0; 27929088Smarkm return (0); 28029088Smarkm } 28129088Smarkm maj = major(dev); 28229088Smarkm if (maj >= nblkdev) 28329088Smarkm return (ENXIO); 28429088Smarkm if (bdevsw[maj] == NULL) 28529088Smarkm return (ENXIO); /* XXX is this right? */ 28629088Smarkm if (bdevsw[maj]->d_psize == NULL) 28729088Smarkm return (ENXIO); /* XXX should be ENODEV ? */ 28829088Smarkm psize = bdevsw[maj]->d_psize(dev); 28929088Smarkm if (psize == -1) 29029088Smarkm return (ENXIO); /* XXX should be ENODEV ? */ 29129088Smarkm newdumplo = psize - Maxmem * NBPG / DEV_BSIZE; 29229088Smarkm if (newdumplo < 0) 29329088Smarkm return (ENOSPC); 29429088Smarkm dumpdev = dev; 29529088Smarkm dumplo = newdumplo; 29629088Smarkm return (0); 29729088Smarkm} 29829088Smarkm 29929088Smarkmu_long bootdev = 0; /* not a dev_t - encoding is different */ 30029088Smarkm 30129088Smarkmstatic char devname[][2] = { 30229088Smarkm {'w','d'}, /* 0 = wd */ 30329088Smarkm {'s','w'}, /* 1 = sw */ 30429088Smarkm#define FDMAJOR 2 30529088Smarkm {'f','d'}, /* 2 = fd */ 30629088Smarkm {'w','t'}, /* 3 = wt */ 30729088Smarkm {'s','d'}, /* 4 = sd -- new SCSI system */ 30829088Smarkm}; 30929088Smarkm 31029088Smarkm#define PARTITIONMASK 0x7 31129088Smarkm#define PARTITIONSHIFT 3 31229088Smarkm#define FDUNITSHIFT 6 31329088Smarkm#define RAW_PART 2 31429088Smarkm 31529088Smarkm/* 31629088Smarkm * Attempt to find the device from which we were booted. 31729088Smarkm * If we can do so, and not instructed not to do so, 31829088Smarkm * change rootdev to correspond to the load device. 31929088Smarkm */ 32029088Smarkmstatic void 32129088Smarkmsetroot() 32229088Smarkm{ 32329088Smarkm int majdev, mindev, unit, part, adaptor; 32429088Smarkm dev_t orootdev; 32529088Smarkm 32629088Smarkm/*printf("howto %x bootdev %x ", boothowto, bootdev);*/ 32729088Smarkm if (boothowto & RB_DFLTROOT || 32829088Smarkm (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 32929088Smarkm return; 33029088Smarkm majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; 33129088Smarkm if (majdev > sizeof(devname) / sizeof(devname[0])) 33229088Smarkm return; 33329088Smarkm adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; 33429088Smarkm unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; 33529088Smarkm if (majdev == FDMAJOR) { 33629088Smarkm part = RAW_PART; 33729088Smarkm mindev = unit << FDUNITSHIFT; 33829088Smarkm } 33929088Smarkm else { 34029088Smarkm part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; 34129088Smarkm mindev = (unit << PARTITIONSHIFT) + part; 34229088Smarkm } 34329088Smarkm orootdev = rootdev; 34429088Smarkm rootdev = makedev(majdev, mindev); 34529088Smarkm /* 34629088Smarkm * If the original rootdev is the same as the one 34729088Smarkm * just calculated, don't need to adjust the swap configuration. 34829088Smarkm */ 34929088Smarkm if (rootdev == orootdev) 35029088Smarkm return; 35129088Smarkm printf("changing root device to %c%c%d%c\n", 35229088Smarkm devname[majdev][0], devname[majdev][1], 35329088Smarkm mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT), 35429088Smarkm part + 'a'); 35529088Smarkm} 35629088Smarkm 35729088Smarkmstatic int 35829088Smarkmsysctl_kern_dumpdev SYSCTL_HANDLER_ARGS 35929088Smarkm{ 36029088Smarkm int error; 36129088Smarkm dev_t ndumpdev; 36229088Smarkm 36329088Smarkm ndumpdev = dumpdev; 36429088Smarkm error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); 36529088Smarkm if (!error && ndumpdev != dumpdev) { 36629088Smarkm error = setdumpdev(ndumpdev); 36729088Smarkm } 36829088Smarkm return (error); 36929088Smarkm} 37029088Smarkm 37129088SmarkmSYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, 37229088Smarkm 0, sizeof dumpdev, sysctl_kern_dumpdev, "I", ""); 37329088Smarkm