autoconf.c revision 39982
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 3739976Sobrien * $Id: autoconf.c,v 1.106 1998/09/15 10:03:42 gibbs 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 */ 4832358Seivind#include "opt_bootp.h" 4932726Seivind#include "opt_ffs.h" 5025460Sjoerg#include "opt_cd9660.h" 5132726Seivind#include "opt_mfs.h" 5237272Sjmg#include "opt_nfsroot.h" 5325164Speter 542056Swollman#include <sys/param.h> 552056Swollman#include <sys/systm.h> 562056Swollman#include <sys/conf.h> 5731328Speter#include <sys/disklabel.h> 5836809Sbde#include <sys/diskslice.h> 592056Swollman#include <sys/reboot.h> 602056Swollman#include <sys/kernel.h> 6136809Sbde#include <sys/malloc.h> 6212604Sbde#include <sys/mount.h> 6312649Speter#include <sys/sysctl.h> 644Srgrimes 6520641Sbde#include <machine/bootinfo.h> 6610665Sbde#include <machine/cons.h> 6731337Sbde#include <machine/ipl.h> 687090Sbde#include <machine/md_var.h> 6927288Sfsmp#ifdef APIC_IO 7025164Speter#include <machine/smp.h> 7125164Speter#endif /* APIC_IO */ 7227288Sfsmp 7336809Sbde#include <i386/isa/icu.h> 7425164Speter 7512604Sbde#include "isa.h" 7612604Sbde#if NISA > 0 7712604Sbde#include <i386/isa/isa_device.h> 7812604Sbde#endif 7910665Sbde 8029243Sjmg#include "pnp.h" 8129243Sjmg#if NPNP > 0 8229243Sjmg#include <i386/isa/pnp.h> 8329243Sjmg#endif 8429243Sjmg 8512604Sbde#include "eisa.h" 8612604Sbde#if NEISA > 0 8712604Sbde#include <i386/eisa/eisaconf.h> 8812604Sbde#endif 8910665Sbde 9012604Sbde#include "pci.h" 9112604Sbde#if NPCI > 0 9212604Sbde#include <pci/pcivar.h> 9312604Sbde#endif 94798Swollman 9530720Snate#include "card.h" 9630720Snate#if NCARD > 0 9712604Sbde#include <pccard/driver.h> 9812604Sbde#endif 994Srgrimes 10012604Sbde#include "scbus.h" 10112604Sbde 10238779Snsouch#include <sys/bus.h> 10338779Snsouch 10412604Sbdestatic void configure __P((void *)); 10512604SbdeSYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL) 10612604Sbde 10712848Sbdestatic void configure_finish __P((void)); 10812848Sbdestatic void configure_start __P((void)); 10912848Sbdestatic int setdumpdev __P((dev_t dev)); 11012848Sbdestatic void setroot __P((void)); 11112848Sbde 11239982Sobrien#if defined(CD9660) || defined(CD9660_ROOT) 11322521Sdyson 11425460Sjoerg#include <sys/fcntl.h> 11525460Sjoerg#include <sys/proc.h> 11625460Sjoerg#include <sys/stat.h> 11725460Sjoerg#include <machine/clock.h> 11822521Sdyson 11925460Sjoerg/* 12025460Sjoerg * XXX All this CD-ROM root stuff is fairly messy. Ick. 12125460Sjoerg * 12225460Sjoerg * We need to try out all our potential CDROM drives, so we need a table. 12325460Sjoerg */ 1247731Sphkstatic struct { 1257731Sphk char *name; 1267731Sphk int major; 1277731Sphk} try_cdrom[] = { 1287731Sphk { "cd", 6 }, 1297731Sphk { "mcd", 7 }, 1307731Sphk { "scd", 16 }, 1317731Sphk { "matcd", 17 }, 13225460Sjoerg { "wcd", 19 }, 1337731Sphk { 0, 0} 1347731Sphk}; 1357731Sphk 13625460Sjoergstatic int find_cdrom_root __P((void)); 13712604Sbde 13812604Sbdestatic int 13925460Sjoergfind_cdrom_root() 1407731Sphk{ 14125460Sjoerg int i, j, error; 14237389Sjulian struct cdevsw *bd; 14325460Sjoerg dev_t orootdev; 1447731Sphk 14525460Sjoerg#if CD9660_ROOTDELAY > 0 14625460Sjoerg DELAY(CD9660_ROOTDELAY * 1000000); 14725460Sjoerg#endif 14825460Sjoerg orootdev = rootdev; 14925460Sjoerg for (i = 0 ; i < 2; i++) 15025460Sjoerg for (j = 0 ; try_cdrom[j].name ; j++) { 15125460Sjoerg if (try_cdrom[j].major >= nblkdev) 15225460Sjoerg continue; 15325460Sjoerg rootdev = makedev(try_cdrom[j].major, i * 8); 15425460Sjoerg bd = bdevsw[major(rootdev)]; 15525460Sjoerg if (bd == NULL || bd->d_open == NULL) 15625460Sjoerg continue; 15725460Sjoerg if (bootverbose) 15825460Sjoerg printf("trying %s%d as rootdev (0x%x)\n", 15925460Sjoerg try_cdrom[j].name, i, rootdev); 16025460Sjoerg error = (bd->d_open)(rootdev, FREAD, S_IFBLK, curproc); 16125460Sjoerg if (error == 0) { 16225460Sjoerg if (bd->d_close != NULL) 16325460Sjoerg (bd->d_close)(rootdev, FREAD, S_IFBLK, 16425460Sjoerg curproc); 16525460Sjoerg return 0; 16625460Sjoerg } 1677731Sphk } 16825460Sjoerg 16925460Sjoerg rootdev = orootdev; 1707731Sphk return EINVAL; 1717731Sphk} 17239982Sobrien#endif /* CD9660 || CD9660_ROOT */ 1737731Sphk 17439243Sgibbsextern void xpt_init __P((void)); 17539243Sgibbs 17612604Sbdestatic void 1777818Sdufaultconfigure_start() 1787818Sdufault{ 1797818Sdufault#if NSCBUS > 0 18039243Sgibbs xpt_init(); 1817818Sdufault#endif 1827818Sdufault} 1837818Sdufault 18412604Sbdestatic void 1857818Sdufaultconfigure_finish() 1867818Sdufault{ 1877818Sdufault} 1887818Sdufault 1894Srgrimes/* 1904Srgrimes * Determine i/o configuration for a machine. 1914Srgrimes */ 19210665Sbdestatic void 19310665Sbdeconfigure(dummy) 19410653Sdg void *dummy; 1954Srgrimes{ 19620641Sbde int i; 1974Srgrimes 1988015Sjulian configure_start(); 1998015Sjulian 20012791Sgibbs /* Allow all routines to decide for themselves if they want intrs */ 20129675Sgibbs /* 20229675Sgibbs * XXX Since this cannot be achieved on all architectures, we should 20329675Sgibbs * XXX go back to disabling all interrupts until configuration is 20429675Sgibbs * XXX completed and switch any devices that rely on the current 20529675Sgibbs * XXX behavior to no longer rely on interrupts or to register an 20629675Sgibbs * XXX interrupt_driven_config_hook for the task. 20729675Sgibbs */ 20831336Sbde /* 20931336Sbde * XXX The above is wrong, because we're implicitly at splhigh(), 21031336Sbde * XXX and should stay there, so enabling interrupts in the CPU 21131336Sbde * XXX and the ICU at most gives pending interrupts which just get 21231336Sbde * XXX in the way. 21331336Sbde */ 21427288Sfsmp#ifdef APIC_IO 21527288Sfsmp bsp_apic_configure(); 21625172Speter enable_intr(); 21727288Sfsmp#else 21827288Sfsmp enable_intr(); 21925172Speter INTREN(IRQ_SLAVE); 22027288Sfsmp#endif /* APIC_IO */ 22112791Sgibbs 22212091Sgibbs#if NEISA > 0 22312091Sgibbs eisa_configure(); 22412091Sgibbs#endif 22512091Sgibbs 2262430Sse#if NPCI > 0 2272430Sse pci_configure(); 2282430Sse#endif 2292430Sse 23029243Sjmg#if NPNP > 0 23129243Sjmg pnp_configure(); 23229243Sjmg#endif 23329243Sjmg 23412791Sgibbs#if NISA > 0 23512791Sgibbs isa_configure(); 23612791Sgibbs#endif 23712791Sgibbs 23838779Snsouch /* initialize new bus architecture */ 23938779Snsouch root_bus_configure(); 24038779Snsouch 24131336Sbde /* 24231336Sbde * Now we're ready to handle (pending) interrupts. 24331336Sbde * XXX this is slightly misplaced. 24431336Sbde */ 24531336Sbde spl0(); 24631336Sbde 24731337Sbde /* 24831337Sbde * Allow lowering of the ipl to the lowest kernel level if we 24931337Sbde * panic (or call tsleep() before clearing `cold'). No level is 25031337Sbde * completely safe (since a panic may occur in a critical region 25131337Sbde * at splhigh()), but we want at least bio interrupts to work. 25231337Sbde */ 25331337Sbde safepri = cpl; 25431337Sbde 25530720Snate#if NCARD > 0 25622564Sbde /* After everyone else has a chance at grabbing resources */ 25722564Sbde pccard_configure(); 25822564Sbde#endif 25922564Sbde 2607818Sdufault configure_finish(); 2617818Sdufault 26210665Sbde cninit_finish(); 26310665Sbde 26420641Sbde if (bootverbose) { 26527561Sfsmp 26627561Sfsmp#ifdef APIC_IO 26727615Sfsmp imen_dump(); 26827561Sfsmp#endif /* APIC_IO */ 26927561Sfsmp 27020641Sbde /* 27120641Sbde * Print out the BIOS's idea of the disk geometries. 27220641Sbde */ 27320641Sbde printf("BIOS Geometries:\n"); 27420641Sbde for (i = 0; i < N_BIOS_GEOM; i++) { 27520641Sbde unsigned long bios_geom; 27620641Sbde int max_cylinder, max_head, max_sector; 27720641Sbde 27820641Sbde bios_geom = bootinfo.bi_bios_geom[i]; 27920641Sbde 28020641Sbde /* 28120641Sbde * XXX the bootstrap punts a 1200K floppy geometry 28220641Sbde * when the get-disk-geometry interrupt fails. Skip 28320641Sbde * drives that have this geometry. 28420641Sbde */ 28520641Sbde if (bios_geom == 0x4f010f) 28620641Sbde continue; 28720641Sbde 28820641Sbde printf(" %x:%08lx ", i, bios_geom); 28920641Sbde max_cylinder = bios_geom >> 16; 29020641Sbde max_head = (bios_geom >> 8) & 0xff; 29120641Sbde max_sector = bios_geom & 0xff; 29220641Sbde printf( 29320641Sbde "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n", 29420641Sbde max_cylinder, max_cylinder + 1, 29520641Sbde max_head, max_head + 1, 29620641Sbde max_sector, max_sector); 29720641Sbde } 29820641Sbde printf(" %d accounted for\n", bootinfo.bi_n_bios_used); 29920641Sbde 30016075Sjoerg printf("Device configuration finished.\n"); 30120641Sbde } 30229675Sgibbs cold = 0; 30329675Sgibbs} 30416075Sjoerg 30535319Sjulian 30629675Sgibbsvoid 30729675Sgibbscpu_rootconf() 30829675Sgibbs{ 30929675Sgibbs /* 31029675Sgibbs * XXX NetBSD has a much cleaner approach to finding root. 31129675Sgibbs * XXX We should adopt their code. 31229675Sgibbs */ 31339982Sobrien#if defined(CD9660) || defined(CD9660_ROOT) 31422521Sdyson if ((boothowto & RB_CDROM)) { 31516075Sjoerg if (bootverbose) 31616075Sjoerg printf("Considering CD-ROM root f/s.\n"); 31725460Sjoerg /* NB: find_cdrom_root() sets rootdev if successful. */ 31825460Sjoerg if (find_cdrom_root() == 0) 31925460Sjoerg mountrootfsname = "cd9660"; 32025460Sjoerg else if (bootverbose) 32125460Sjoerg printf("No CD-ROM available as root f/s.\n"); 32216075Sjoerg } 3237731Sphk#endif 3248007Sphk 32512499Speter#ifdef MFS_ROOT 32622521Sdyson if (!mountrootfsname) { 32716075Sjoerg if (bootverbose) 32816075Sjoerg printf("Considering MFS root f/s.\n"); 32922521Sdyson mountrootfsname = "mfs"; 33012499Speter /* 33112499Speter * Ignore the -a flag if this kernel isn't compiled 33212499Speter * with a generic root/swap configuration: if we skip 33312499Speter * setroot() and we aren't a generic kernel, chaos 33412499Speter * will ensue because setconf() will be a no-op. 33512499Speter * (rootdev is always initialized to NODEV in a 33612499Speter * generic configuration, so we test for that.) 33712499Speter */ 33812499Speter if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 33912499Speter setroot(); 34012499Speter } 34112499Speter#endif 34222564Sbde 34325723Stegge#ifdef BOOTP_NFSROOT 34425723Stegge if (!mountrootfsname && !nfs_diskless_valid) { 34525723Stegge if (bootverbose) 34625723Stegge printf("Considering BOOTP NFS root f/s.\n"); 34725723Stegge mountrootfsname = "nfs"; 34825723Stegge } 34925723Stegge#endif /* BOOTP_NFSROOT */ 35039982Sobrien#if defined(NFS) || defined(NFS_ROOT) 35122564Sbde if (!mountrootfsname && nfs_diskless_valid) { 35222564Sbde if (bootverbose) 35322564Sbde printf("Considering NFS root f/s.\n"); 35422564Sbde mountrootfsname = "nfs"; 35522564Sbde } 35622564Sbde#endif /* NFS */ 35722564Sbde 35839982Sobrien#if defined(FFS) || defined(FFS_ROOT) 35922521Sdyson if (!mountrootfsname) { 36022521Sdyson mountrootfsname = "ufs"; 36116075Sjoerg if (bootverbose) 36216075Sjoerg printf("Considering FFS root f/s.\n"); 3636547Swpaul /* 3646547Swpaul * Ignore the -a flag if this kernel isn't compiled 3656547Swpaul * with a generic root/swap configuration: if we skip 3666547Swpaul * setroot() and we aren't a generic kernel, chaos 3676547Swpaul * will ensue because setconf() will be a no-op. 3686547Swpaul * (rootdev is always initialized to NODEV in a 3696547Swpaul * generic configuration, so we test for that.) 3706547Swpaul */ 3716547Swpaul if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 3725321Sjkh setroot(); 3733795Sphk } 3744Srgrimes#endif 37522564Sbde 37622521Sdyson if (!mountrootfsname) { 3774370Sphk panic("Nobody wants to mount my root for me"); 3784370Sphk } 37929742Sbde 38029742Sbde setconf(); 38129675Sgibbs} 38217355Sbde 38335319Sjulian 38429675Sgibbsvoid 38529675Sgibbscpu_dumpconf() 38629675Sgibbs{ 38729675Sgibbs if (setdumpdev(dumpdev) != 0) 38829675Sgibbs dumpdev = NODEV; 3894Srgrimes} 3904Srgrimes 39112722Sphkstatic int 3928833Sdgsetdumpdev(dev) 3938833Sdg dev_t dev; 3948481Swollman{ 3958833Sdg int maj, psize; 3968833Sdg long newdumplo; 3978833Sdg 3988833Sdg if (dev == NODEV) { 3998481Swollman dumpdev = dev; 4008833Sdg return (0); 4018481Swollman } 4028833Sdg maj = major(dev); 4038833Sdg if (maj >= nblkdev) 4048833Sdg return (ENXIO); 40512889Speter if (bdevsw[maj] == NULL) 40612889Speter return (ENXIO); /* XXX is this right? */ 40712813Sjulian if (bdevsw[maj]->d_psize == NULL) 40812889Speter return (ENXIO); /* XXX should be ENODEV ? */ 40912813Sjulian psize = bdevsw[maj]->d_psize(dev); 4108833Sdg if (psize == -1) 41112889Speter return (ENXIO); /* XXX should be ENODEV ? */ 41231316Sbde /* 41331316Sbde * XXX should clean up checking in dumpsys() to be more like this, 41431316Sbde * and nuke dodump sysctl (too many knobs), and move this to 41531316Sbde * kern_shutdown.c... 41631316Sbde */ 41715538Sphk newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE; 4188833Sdg if (newdumplo < 0) 4198833Sdg return (ENOSPC); 4208833Sdg dumpdev = dev; 4218833Sdg dumplo = newdumplo; 4228833Sdg return (0); 4238876Srgrimes} 4248481Swollman 42535319Sjulian 4268833Sdgu_long bootdev = 0; /* not a dev_t - encoding is different */ 4274Srgrimes 4281289Sache#define FDMAJOR 2 4291290Sache#define FDUNITSHIFT 6 4304Srgrimes 4314Srgrimes/* 4324Srgrimes * Attempt to find the device from which we were booted. 4334Srgrimes * If we can do so, and not instructed not to do so, 43436809Sbde * set rootdevs[] and rootdevnames[] to correspond to the 43536809Sbde * boot device(s). 4364Srgrimes */ 437798Swollmanstatic void 4384Srgrimessetroot() 4394Srgrimes{ 44036809Sbde int majdev, mindev, unit, slice, part; 44136809Sbde dev_t newrootdev; 44236809Sbde char partname[2]; 44336809Sbde char *sname; 4444Srgrimes 44536809Sbde if (boothowto & RB_DFLTROOT || (bootdev & B_MAGICMASK) != B_DEVMAGIC) 4464Srgrimes return; 44736809Sbde majdev = B_TYPE(bootdev); 44836809Sbde if (bdevsw[majdev] == NULL) 44936809Sbde return; 45036809Sbde unit = B_UNIT(bootdev); 45136809Sbde slice = B_SLICE(bootdev); 45236809Sbde if (slice == WHOLE_DISK_SLICE) 45334624Smsmith slice = COMPATIBILITY_SLICE; 45436809Sbde if (slice < 0 || slice >= MAX_SLICES) 4554Srgrimes return; 45636809Sbde 45736809Sbde /* 45836809Sbde * XXX kludge for inconsistent unit numbering and lack of slice 45936809Sbde * support for floppies. 46036809Sbde */ 4611290Sache if (majdev == FDMAJOR) { 46236809Sbde slice = COMPATIBILITY_SLICE; 4632400Sache part = RAW_PART; 4641290Sache mindev = unit << FDUNITSHIFT; 46536809Sbde } else { 46636809Sbde part = B_PARTITION(bootdev); 46734622Smsmith mindev = dkmakeminor(unit, slice, part); 4681290Sache } 46936809Sbde 47036809Sbde newrootdev = makedev(majdev, mindev); 47136809Sbde rootdevs[0] = newrootdev; 47236809Sbde sname = dsname(bdevsw[majdev]->d_name, unit, slice, part, partname); 47336809Sbde rootdevnames[0] = malloc(strlen(sname) + 2, M_DEVBUF, M_NOWAIT); 47436809Sbde sprintf(rootdevnames[0], "%s%s", sname, partname); 47536809Sbde 4764Srgrimes /* 47736809Sbde * For properly dangerously dedicated disks (ones with a historical 47836809Sbde * bogus partition table), the boot blocks will give slice = 4, but 47936809Sbde * the kernel will only provide the compatibility slice since it 48036809Sbde * knows that slice 4 is not a real slice. Arrange to try mounting 48136809Sbde * the compatibility slice as root if mounting the slice passed by 48236809Sbde * the boot blocks fails. This handles the dangerously dedicated 48336809Sbde * case and perhaps others. 4844Srgrimes */ 48536809Sbde if (slice == COMPATIBILITY_SLICE) 4864Srgrimes return; 48736809Sbde slice = COMPATIBILITY_SLICE; 48836809Sbde rootdevs[1] = dkmodslice(newrootdev, slice); 48936809Sbde sname = dsname(bdevsw[majdev]->d_name, unit, slice, part, partname); 49036809Sbde rootdevnames[1] = malloc(strlen(sname) + 2, M_DEVBUF, M_NOWAIT); 49136809Sbde sprintf(rootdevnames[1], "%s%s", sname, partname); 4924Srgrimes} 49312649Speter 49435319Sjulian 49512649Speterstatic int 49612649Spetersysctl_kern_dumpdev SYSCTL_HANDLER_ARGS 49712649Speter{ 49812649Speter int error; 49912649Speter dev_t ndumpdev; 50012649Speter 50112649Speter ndumpdev = dumpdev; 50212649Speter error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); 50317355Sbde if (error == 0 && req->newptr != NULL) 50412649Speter error = setdumpdev(ndumpdev); 50512649Speter return (error); 50612649Speter} 50712649Speter 50812649SpeterSYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, 50922564Sbde 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", ""); 510