autoconf.c revision 16075
1/*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * William Jolitz. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 37 * $Id: autoconf.c,v 1.53 1996/05/02 14:19:39 phk Exp $ 38 */ 39 40/* 41 * Setup the system to run on the current machine. 42 * 43 * Configure() is called at boot time and initializes the vba 44 * device tables and the memory controller monitoring. Available 45 * devices are determined (from possibilities mentioned in ioconf.c), 46 * and the drivers are initialized. 47 */ 48#include <sys/param.h> 49#include <sys/systm.h> 50#include <sys/buf.h> 51#include <sys/dkstat.h> 52#include <sys/conf.h> 53#include <sys/dmap.h> 54#include <sys/reboot.h> 55#include <sys/kernel.h> 56#include <sys/mount.h> 57#include <sys/sysctl.h> 58 59#include <machine/cons.h> 60#include <machine/cpu.h> 61#include <machine/md_var.h> 62#include <i386/isa/icu.h> /* For interrupts */ 63 64#include "isa.h" 65#if NISA > 0 66#include <i386/isa/isa_device.h> 67#endif 68 69#include "eisa.h" 70#if NEISA > 0 71#include <i386/eisa/eisaconf.h> 72#endif 73 74#include "pci.h" 75#if NPCI > 0 76#include <pci/pcivar.h> 77#endif 78 79#include "crd.h" 80#if NCRD > 0 81#include <pccard/driver.h> 82#endif 83 84#include "scbus.h" 85#if NSCBUS > 0 86#include <scsi/scsiconf.h> 87#endif 88 89static void configure __P((void *)); 90SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL) 91 92#ifdef MFS_ROOT 93extern struct vfsops mfs_vfsops; 94#endif 95#ifdef FFS 96extern struct vfsops ufs_vfsops; 97#endif 98#ifdef LFS 99extern struct vfsops lfs_vfsops; 100#endif 101#ifdef NFS 102extern int nfs_mountroot __P((void *)); 103#endif 104#ifdef CD9660 105extern int cd9660_mountroot __P((void *)); 106#endif 107#ifdef MSDOSFS 108extern int msdosfs_mountroot __P((void *)); 109#endif 110 111static void configure_finish __P((void)); 112static void configure_start __P((void)); 113static int setdumpdev __P((dev_t dev)); 114static void setroot __P((void)); 115 116#ifdef CD9660 117/* We need to try out all our potential CDROM drives, so we need a table. */ 118static struct { 119 char *name; 120 int major; 121} try_cdrom[] = { 122 { "cd", 6 }, 123 { "mcd", 7 }, 124 { "scd", 16 }, 125 { "matcd", 17 }, 126 { 0, 0} 127}; 128 129static int find_cdrom_root __P((void *)); 130 131static int 132find_cdrom_root(dummy) 133 void *dummy; 134{ 135 int i,j,k; 136 137 for (j = 0 ; j < 2; j++) 138 for (k = 0 ; try_cdrom[k].name ; k++) { 139 rootdev = makedev(try_cdrom[k].major,j*8); 140 printf("trying rootdev=0x%lx (%s%d)\n", 141 rootdev, try_cdrom[k].name,j); 142 i = (*cd9660_mountroot)((void *)NULL); 143 if (!i) return i; 144 } 145 return EINVAL; 146} 147#endif /* CD9660 */ 148 149static void 150configure_start() 151{ 152#if NSCBUS > 0 153 scsi_configure_start(); 154#endif 155} 156 157static void 158configure_finish() 159{ 160#if NSCBUS > 0 161 scsi_configure_finish(); 162#endif 163} 164 165/* 166 * Determine i/o configuration for a machine. 167 */ 168static void 169configure(dummy) 170 void *dummy; 171{ 172 173 configure_start(); 174 175 /* Allow all routines to decide for themselves if they want intrs */ 176 enable_intr(); 177 INTREN(IRQ_SLAVE); 178 179#if NCRD > 0 180 /* Before isa_configure to avoid ISA drivers finding our cards */ 181 pccard_configure(); 182#endif 183 184#if NEISA > 0 185 eisa_configure(); 186#endif 187 188#if NPCI > 0 189 pci_configure(); 190#endif 191 192#if NISA > 0 193 isa_configure(); 194#endif 195 196 configure_finish(); 197 198 cninit_finish(); 199 200 if (bootverbose) 201 printf("Device configuration finished.\n"); 202 203#ifdef CD9660 204 if ((boothowto & RB_CDROM) && !mountroot) { 205 if (bootverbose) 206 printf("Considering CD-ROM root f/s.\n"); 207 mountroot = find_cdrom_root; 208 } 209#endif 210 211#ifdef NFS 212 if (!mountroot && nfs_diskless_valid) { 213 if (bootverbose) 214 printf("Considering NFS root f/s.\n"); 215 mountroot = nfs_mountroot; 216 } 217#endif /* NFS */ 218 219#ifdef MFS_ROOT 220 if (!mountroot) { 221 if (bootverbose) 222 printf("Considering MFS root f/s.\n"); 223 mountroot = vfs_mountroot; /* XXX goes away*/ 224 mountrootvfsops = &mfs_vfsops; 225 /* 226 * Ignore the -a flag if this kernel isn't compiled 227 * with a generic root/swap configuration: if we skip 228 * setroot() and we aren't a generic kernel, chaos 229 * will ensue because setconf() will be a no-op. 230 * (rootdev is always initialized to NODEV in a 231 * generic configuration, so we test for that.) 232 */ 233 if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 234 setroot(); 235 } 236#endif 237#ifdef FFS 238 if (!mountroot) { 239 if (bootverbose) 240 printf("Considering FFS root f/s.\n"); 241 mountroot = vfs_mountroot; /* XXX goes away*/ 242 mountrootvfsops = &ufs_vfsops; 243 /* 244 * Ignore the -a flag if this kernel isn't compiled 245 * with a generic root/swap configuration: if we skip 246 * setroot() and we aren't a generic kernel, chaos 247 * will ensue because setconf() will be a no-op. 248 * (rootdev is always initialized to NODEV in a 249 * generic configuration, so we test for that.) 250 */ 251 if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 252 setroot(); 253 } 254#endif 255#ifdef LFS 256 if (!mountroot) { 257 if (bootverbose) 258 printf("Considering LFS root f/s.\n"); 259 mountroot = vfs_mountroot; /* XXX goes away*/ 260 mountrootvfsops = &lfs_vfsops; 261 /* 262 * Ignore the -a flag if this kernel isn't compiled 263 * with a generic root/swap configuration: if we skip 264 * setroot() and we aren't a generic kernel, chaos 265 * will ensue because setconf() will be a no-op. 266 * (rootdev is always initialized to NODEV in a 267 * generic configuration, so we test for that.) 268 */ 269 if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 270 setroot(); 271 } 272#endif 273 if (!mountroot) { 274 panic("Nobody wants to mount my root for me"); 275 } 276 /* 277 * Configure swap area and related system 278 * parameter based on device(s) used. 279 */ 280 if (bootverbose) 281 printf("Configuring root and swap devs.\n"); 282 setconf(); 283 cold = 0; 284 if (bootverbose) 285 printf("configure() finished.\n"); 286} 287 288static int 289setdumpdev(dev) 290 dev_t dev; 291{ 292 int maj, psize; 293 long newdumplo; 294 295 if (dev == NODEV) { 296 dumpdev = dev; 297 dumplo = 0; 298 return (0); 299 } 300 maj = major(dev); 301 if (maj >= nblkdev) 302 return (ENXIO); 303 if (bdevsw[maj] == NULL) 304 return (ENXIO); /* XXX is this right? */ 305 if (bdevsw[maj]->d_psize == NULL) 306 return (ENXIO); /* XXX should be ENODEV ? */ 307 psize = bdevsw[maj]->d_psize(dev); 308 if (psize == -1) 309 return (ENXIO); /* XXX should be ENODEV ? */ 310 newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE; 311 if (newdumplo < 0) 312 return (ENOSPC); 313 dumpdev = dev; 314 dumplo = newdumplo; 315 return (0); 316} 317 318u_long bootdev = 0; /* not a dev_t - encoding is different */ 319 320static char devname[][2] = { 321 {'w','d'}, /* 0 = wd */ 322 {'s','w'}, /* 1 = sw */ 323#define FDMAJOR 2 324 {'f','d'}, /* 2 = fd */ 325 {'w','t'}, /* 3 = wt */ 326 {'s','d'}, /* 4 = sd -- new SCSI system */ 327}; 328 329#define PARTITIONMASK 0x7 330#define PARTITIONSHIFT 3 331#define FDUNITSHIFT 6 332#define RAW_PART 2 333 334/* 335 * Attempt to find the device from which we were booted. 336 * If we can do so, and not instructed not to do so, 337 * change rootdev to correspond to the load device. 338 */ 339static void 340setroot() 341{ 342 int majdev, mindev, unit, part, adaptor; 343 dev_t orootdev; 344 345/*printf("howto %x bootdev %x ", boothowto, bootdev);*/ 346 if (boothowto & RB_DFLTROOT || 347 (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 348 return; 349 majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; 350 if (majdev > sizeof(devname) / sizeof(devname[0])) 351 return; 352 adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; 353 unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; 354 if (majdev == FDMAJOR) { 355 part = RAW_PART; 356 mindev = unit << FDUNITSHIFT; 357 } 358 else { 359 part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; 360 mindev = (unit << PARTITIONSHIFT) + part; 361 } 362 orootdev = rootdev; 363 rootdev = makedev(majdev, mindev); 364 /* 365 * If the original rootdev is the same as the one 366 * just calculated, don't need to adjust the swap configuration. 367 */ 368 if (rootdev == orootdev) 369 return; 370 printf("changing root device to %c%c%d%c\n", 371 devname[majdev][0], devname[majdev][1], 372 mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT), 373 part + 'a'); 374} 375 376static int 377sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS 378{ 379 int error; 380 dev_t ndumpdev; 381 382 ndumpdev = dumpdev; 383 error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); 384 if (!error && ndumpdev != dumpdev) { 385 error = setdumpdev(ndumpdev); 386 } 387 return (error); 388} 389 390SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, 391 0, sizeof dumpdev, sysctl_kern_dumpdev, "I", ""); 392