autoconf.c revision 25172
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 3725172Speter * $Id: autoconf.c,v 1.65 1997/04/26 11:45:02 peter 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" 4925164Speter 502056Swollman#include <sys/param.h> 512056Swollman#include <sys/systm.h> 522056Swollman#include <sys/buf.h> 532056Swollman#include <sys/conf.h> 542056Swollman#include <sys/dmap.h> 552056Swollman#include <sys/reboot.h> 562056Swollman#include <sys/kernel.h> 5712604Sbde#include <sys/mount.h> 5822521Sdyson#include <sys/vnode.h> 5912649Speter#include <sys/sysctl.h> 604Srgrimes 6120641Sbde#include <machine/bootinfo.h> 6210665Sbde#include <machine/cons.h> 637090Sbde#include <machine/md_var.h> 6425164Speter#if defined(APIC_IO) 6525164Speter#include <machine/smp.h> 6625164Speter#endif /* APIC_IO */ 6725172Speter#include <i386/isa/icu.h> /* For interrupts */ 6825164Speter 6912604Sbde#include "isa.h" 7012604Sbde#if NISA > 0 7112604Sbde#include <i386/isa/isa_device.h> 7212604Sbde#endif 7310665Sbde 7412604Sbde#include "eisa.h" 7512604Sbde#if NEISA > 0 7612604Sbde#include <i386/eisa/eisaconf.h> 7712604Sbde#endif 7810665Sbde 7912604Sbde#include "pci.h" 8012604Sbde#if NPCI > 0 8112604Sbde#include <pci/pcivar.h> 8212604Sbde#endif 83798Swollman 8412604Sbde#include "crd.h" 8512604Sbde#if NCRD > 0 8612604Sbde#include <pccard/driver.h> 8712604Sbde#endif 884Srgrimes 8912604Sbde#include "scbus.h" 9012604Sbde#if NSCBUS > 0 9112604Sbde#include <scsi/scsiconf.h> 9212604Sbde#endif 9312604Sbde 9412604Sbdestatic void configure __P((void *)); 9512604SbdeSYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL) 9612604Sbde 9712848Sbdestatic void configure_finish __P((void)); 9812848Sbdestatic void configure_start __P((void)); 9912848Sbdestatic int setdumpdev __P((dev_t dev)); 10012848Sbdestatic void setroot __P((void)); 10112848Sbde 1028007Sphk#ifdef CD9660 10322521Sdyson 10422521Sdyson#include <isofs/cd9660/iso.h> 10522521Sdyson 1067731Sphk/* We need to try out all our potential CDROM drives, so we need a table. */ 1077731Sphkstatic struct { 1087731Sphk char *name; 1097731Sphk int major; 1107731Sphk} try_cdrom[] = { 1117731Sphk { "cd", 6 }, 1127731Sphk { "mcd", 7 }, 1137731Sphk { "scd", 16 }, 1147731Sphk { "matcd", 17 }, 1157731Sphk { 0, 0} 1167731Sphk}; 1177731Sphk 11812604Sbdestatic int find_cdrom_root __P((void *)); 11912604Sbde 12012604Sbdestatic int 12110653Sdgfind_cdrom_root(dummy) 12210653Sdg void *dummy; 1237731Sphk{ 1247731Sphk int i,j,k; 1257731Sphk 1267731Sphk for (j = 0 ; j < 2; j++) 1277731Sphk for (k = 0 ; try_cdrom[k].name ; k++) { 1287731Sphk rootdev = makedev(try_cdrom[k].major,j*8); 1298456Srgrimes printf("trying rootdev=0x%lx (%s%d)\n", 1307731Sphk rootdev, try_cdrom[k].name,j); 13122521Sdyson i = (*cd9660_mountroot)(); 1327731Sphk if (!i) return i; 1337731Sphk } 1347731Sphk return EINVAL; 1357731Sphk} 1368007Sphk#endif /* CD9660 */ 1377731Sphk 13812604Sbdestatic void 1397818Sdufaultconfigure_start() 1407818Sdufault{ 1417818Sdufault#if NSCBUS > 0 1427818Sdufault scsi_configure_start(); 1437818Sdufault#endif 1447818Sdufault} 1457818Sdufault 14612604Sbdestatic void 1477818Sdufaultconfigure_finish() 1487818Sdufault{ 1497818Sdufault#if NSCBUS > 0 1507818Sdufault scsi_configure_finish(); 1517818Sdufault#endif 1527818Sdufault} 1537818Sdufault 1544Srgrimes/* 1554Srgrimes * Determine i/o configuration for a machine. 1564Srgrimes */ 15710665Sbdestatic void 15810665Sbdeconfigure(dummy) 15910653Sdg void *dummy; 1604Srgrimes{ 16120641Sbde int i; 1624Srgrimes 1638015Sjulian configure_start(); 1648015Sjulian 16512791Sgibbs /* Allow all routines to decide for themselves if they want intrs */ 16625164Speter#if defined(APIC_IO) 16725164Speter configure_local_apic(); 16825164Speter#endif /* APIC_IO */ 16925172Speter enable_intr(); 17025172Speter#if !defined(APIC_IO) 17125172Speter INTREN(IRQ_SLAVE); 17225172Speter#endif /* !APIC_IO */ 17312791Sgibbs 17412091Sgibbs#if NEISA > 0 17512091Sgibbs eisa_configure(); 17612091Sgibbs#endif 17712091Sgibbs 1782430Sse#if NPCI > 0 1792430Sse pci_configure(); 1802430Sse#endif 1812430Sse 18212791Sgibbs#if NISA > 0 18312791Sgibbs isa_configure(); 18412791Sgibbs#endif 18512791Sgibbs 18622564Sbde#if NCRD > 0 18722564Sbde /* After everyone else has a chance at grabbing resources */ 18822564Sbde pccard_configure(); 18922564Sbde#endif 19022564Sbde 19117355Sbde if (setdumpdev(dumpdev) != 0) 19217355Sbde dumpdev = NODEV; 19317355Sbde 1947818Sdufault configure_finish(); 1957818Sdufault 19610665Sbde cninit_finish(); 19710665Sbde 19820641Sbde if (bootverbose) { 19920641Sbde /* 20020641Sbde * Print out the BIOS's idea of the disk geometries. 20120641Sbde */ 20220641Sbde printf("BIOS Geometries:\n"); 20320641Sbde for (i = 0; i < N_BIOS_GEOM; i++) { 20420641Sbde unsigned long bios_geom; 20520641Sbde int max_cylinder, max_head, max_sector; 20620641Sbde 20720641Sbde bios_geom = bootinfo.bi_bios_geom[i]; 20820641Sbde 20920641Sbde /* 21020641Sbde * XXX the bootstrap punts a 1200K floppy geometry 21120641Sbde * when the get-disk-geometry interrupt fails. Skip 21220641Sbde * drives that have this geometry. 21320641Sbde */ 21420641Sbde if (bios_geom == 0x4f010f) 21520641Sbde continue; 21620641Sbde 21720641Sbde printf(" %x:%08lx ", i, bios_geom); 21820641Sbde max_cylinder = bios_geom >> 16; 21920641Sbde max_head = (bios_geom >> 8) & 0xff; 22020641Sbde max_sector = bios_geom & 0xff; 22120641Sbde printf( 22220641Sbde "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n", 22320641Sbde max_cylinder, max_cylinder + 1, 22420641Sbde max_head, max_head + 1, 22520641Sbde max_sector, max_sector); 22620641Sbde } 22720641Sbde printf(" %d accounted for\n", bootinfo.bi_n_bios_used); 22820641Sbde 22916075Sjoerg printf("Device configuration finished.\n"); 23020641Sbde } 23116075Sjoerg 2327731Sphk#ifdef CD9660 23322521Sdyson if ((boothowto & RB_CDROM)) { 23416075Sjoerg if (bootverbose) 23516075Sjoerg printf("Considering CD-ROM root f/s.\n"); 23622521Sdyson mountrootfsname = "cd9660"; 23716075Sjoerg } 2387731Sphk#endif 2398007Sphk 24012499Speter#ifdef MFS_ROOT 24122521Sdyson if (!mountrootfsname) { 24216075Sjoerg if (bootverbose) 24316075Sjoerg printf("Considering MFS root f/s.\n"); 24422521Sdyson mountrootfsname = "mfs"; 24512499Speter /* 24612499Speter * Ignore the -a flag if this kernel isn't compiled 24712499Speter * with a generic root/swap configuration: if we skip 24812499Speter * setroot() and we aren't a generic kernel, chaos 24912499Speter * will ensue because setconf() will be a no-op. 25012499Speter * (rootdev is always initialized to NODEV in a 25112499Speter * generic configuration, so we test for that.) 25212499Speter */ 25312499Speter if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 25412499Speter setroot(); 25512499Speter } 25612499Speter#endif 25722564Sbde 25822564Sbde#ifdef NFS 25922564Sbde if (!mountrootfsname && nfs_diskless_valid) { 26022564Sbde if (bootverbose) 26122564Sbde printf("Considering NFS root f/s.\n"); 26222564Sbde mountrootfsname = "nfs"; 26322564Sbde } 26422564Sbde#endif /* NFS */ 26522564Sbde 2664370Sphk#ifdef FFS 26722521Sdyson if (!mountrootfsname) { 26822521Sdyson mountrootfsname = "ufs"; 26916075Sjoerg if (bootverbose) 27016075Sjoerg printf("Considering FFS root f/s.\n"); 2716547Swpaul /* 2726547Swpaul * Ignore the -a flag if this kernel isn't compiled 2736547Swpaul * with a generic root/swap configuration: if we skip 2746547Swpaul * setroot() and we aren't a generic kernel, chaos 2756547Swpaul * will ensue because setconf() will be a no-op. 2766547Swpaul * (rootdev is always initialized to NODEV in a 2776547Swpaul * generic configuration, so we test for that.) 2786547Swpaul */ 2796547Swpaul if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 2805321Sjkh setroot(); 2813795Sphk } 2824Srgrimes#endif 28322564Sbde 28410358Sjulian#ifdef LFS 28522521Sdyson if (!mountrootfsname) { 28616075Sjoerg if (bootverbose) 28716075Sjoerg printf("Considering LFS root f/s.\n"); 28822521Sdyson mountrootfsname = "lfs"; 28910358Sjulian /* 29010358Sjulian * Ignore the -a flag if this kernel isn't compiled 29110358Sjulian * with a generic root/swap configuration: if we skip 29210358Sjulian * setroot() and we aren't a generic kernel, chaos 29310358Sjulian * will ensue because setconf() will be a no-op. 29410358Sjulian * (rootdev is always initialized to NODEV in a 29510358Sjulian * generic configuration, so we test for that.) 29610358Sjulian */ 29710358Sjulian if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 29810358Sjulian setroot(); 29910358Sjulian } 30010358Sjulian#endif 30122564Sbde 30222521Sdyson if (!mountrootfsname) { 3034370Sphk panic("Nobody wants to mount my root for me"); 3044370Sphk } 30517355Sbde 3068433Swpaul setconf(); 3074Srgrimes cold = 0; 30816075Sjoerg if (bootverbose) 30916075Sjoerg printf("configure() finished.\n"); 3104Srgrimes} 3114Srgrimes 31212722Sphkstatic int 3138833Sdgsetdumpdev(dev) 3148833Sdg dev_t dev; 3158481Swollman{ 3168833Sdg int maj, psize; 3178833Sdg long newdumplo; 3188833Sdg 3198833Sdg if (dev == NODEV) { 3208481Swollman dumpdev = dev; 3218833Sdg return (0); 3228481Swollman } 3238833Sdg maj = major(dev); 3248833Sdg if (maj >= nblkdev) 3258833Sdg return (ENXIO); 32612889Speter if (bdevsw[maj] == NULL) 32712889Speter return (ENXIO); /* XXX is this right? */ 32812813Sjulian if (bdevsw[maj]->d_psize == NULL) 32912889Speter return (ENXIO); /* XXX should be ENODEV ? */ 33012813Sjulian psize = bdevsw[maj]->d_psize(dev); 3318833Sdg if (psize == -1) 33212889Speter return (ENXIO); /* XXX should be ENODEV ? */ 33315538Sphk newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE; 3348833Sdg if (newdumplo < 0) 3358833Sdg return (ENOSPC); 3368833Sdg dumpdev = dev; 3378833Sdg dumplo = newdumplo; 3388833Sdg return (0); 3398876Srgrimes} 3408481Swollman 3418833Sdgu_long bootdev = 0; /* not a dev_t - encoding is different */ 3424Srgrimes 3434Srgrimesstatic char devname[][2] = { 3446105Sse {'w','d'}, /* 0 = wd */ 3456105Sse {'s','w'}, /* 1 = sw */ 3461289Sache#define FDMAJOR 2 3476105Sse {'f','d'}, /* 2 = fd */ 3486105Sse {'w','t'}, /* 3 = wt */ 3496105Sse {'s','d'}, /* 4 = sd -- new SCSI system */ 3504Srgrimes}; 3514Srgrimes 3524Srgrimes#define PARTITIONMASK 0x7 3534Srgrimes#define PARTITIONSHIFT 3 3541290Sache#define FDUNITSHIFT 6 3552400Sache#define RAW_PART 2 3564Srgrimes 3574Srgrimes/* 3584Srgrimes * Attempt to find the device from which we were booted. 3594Srgrimes * If we can do so, and not instructed not to do so, 3604Srgrimes * change rootdev to correspond to the load device. 3614Srgrimes */ 362798Swollmanstatic void 3634Srgrimessetroot() 3644Srgrimes{ 3654Srgrimes int majdev, mindev, unit, part, adaptor; 36612417Sphk dev_t orootdev; 3674Srgrimes 3684Srgrimes/*printf("howto %x bootdev %x ", boothowto, bootdev);*/ 3694Srgrimes if (boothowto & RB_DFLTROOT || 3704Srgrimes (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 3714Srgrimes return; 3724Srgrimes majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; 3734Srgrimes if (majdev > sizeof(devname) / sizeof(devname[0])) 3744Srgrimes return; 3754Srgrimes adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; 3764Srgrimes unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; 3771290Sache if (majdev == FDMAJOR) { 3782400Sache part = RAW_PART; 3791290Sache mindev = unit << FDUNITSHIFT; 3801290Sache } 3811290Sache else { 3821290Sache part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; 3831289Sache mindev = (unit << PARTITIONSHIFT) + part; 3841290Sache } 3854Srgrimes orootdev = rootdev; 3864Srgrimes rootdev = makedev(majdev, mindev); 3874Srgrimes /* 3884Srgrimes * If the original rootdev is the same as the one 3894Srgrimes * just calculated, don't need to adjust the swap configuration. 3904Srgrimes */ 3914Srgrimes if (rootdev == orootdev) 3924Srgrimes return; 3934Srgrimes printf("changing root device to %c%c%d%c\n", 3944Srgrimes devname[majdev][0], devname[majdev][1], 3951290Sache mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT), 3961290Sache part + 'a'); 3974Srgrimes} 39812649Speter 39912649Speterstatic int 40012649Spetersysctl_kern_dumpdev SYSCTL_HANDLER_ARGS 40112649Speter{ 40212649Speter int error; 40312649Speter dev_t ndumpdev; 40412649Speter 40512649Speter ndumpdev = dumpdev; 40612649Speter error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); 40717355Sbde if (error == 0 && req->newptr != NULL) 40812649Speter error = setdumpdev(ndumpdev); 40912649Speter return (error); 41012649Speter} 41112649Speter 41212649SpeterSYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, 41322564Sbde 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", ""); 414