autoconf.c revision 27288
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.2 1997/07/08 23:40:04 smp Exp smp $ 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 "opt_cd9660.h" 49 50#include <sys/param.h> 51#include <sys/systm.h> 52#include <sys/buf.h> 53#include <sys/conf.h> 54#include <sys/dmap.h> 55#include <sys/reboot.h> 56#include <sys/kernel.h> 57#include <sys/mount.h> 58#include <sys/vnode.h> 59#include <sys/sysctl.h> 60 61#include <machine/bootinfo.h> 62#include <machine/cons.h> 63#include <machine/md_var.h> 64#ifdef APIC_IO 65#include <machine/smp.h> 66#endif /* APIC_IO */ 67 68#include <i386/isa/icu.h> /* For interrupts */ 69 70#include "isa.h" 71#if NISA > 0 72#include <i386/isa/isa_device.h> 73#endif 74 75#include "eisa.h" 76#if NEISA > 0 77#include <i386/eisa/eisaconf.h> 78#endif 79 80#include "pci.h" 81#if NPCI > 0 82#include <pci/pcivar.h> 83#endif 84 85#include "crd.h" 86#if NCRD > 0 87#include <pccard/driver.h> 88#endif 89 90#include "scbus.h" 91#if NSCBUS > 0 92#include <scsi/scsiconf.h> 93#endif 94 95static void configure __P((void *)); 96SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL) 97 98static void configure_finish __P((void)); 99static void configure_start __P((void)); 100static int setdumpdev __P((dev_t dev)); 101static void setroot __P((void)); 102 103#ifdef CD9660 104 105#include <sys/fcntl.h> 106#include <sys/proc.h> 107#include <sys/stat.h> 108#include <machine/clock.h> 109#include <isofs/cd9660/iso.h> 110 111/* 112 * XXX All this CD-ROM root stuff is fairly messy. Ick. 113 * 114 * We need to try out all our potential CDROM drives, so we need a table. 115 */ 116static struct { 117 char *name; 118 int major; 119} try_cdrom[] = { 120 { "cd", 6 }, 121 { "mcd", 7 }, 122 { "scd", 16 }, 123 { "matcd", 17 }, 124 { "wcd", 19 }, 125 { 0, 0} 126}; 127 128static int find_cdrom_root __P((void)); 129 130static int 131find_cdrom_root() 132{ 133 int i, j, error; 134 struct bdevsw *bd; 135 dev_t orootdev; 136 137#if CD9660_ROOTDELAY > 0 138 DELAY(CD9660_ROOTDELAY * 1000000); 139#endif 140 orootdev = rootdev; 141 for (i = 0 ; i < 2; i++) 142 for (j = 0 ; try_cdrom[j].name ; j++) { 143 if (try_cdrom[j].major >= nblkdev) 144 continue; 145 rootdev = makedev(try_cdrom[j].major, i * 8); 146 bd = bdevsw[major(rootdev)]; 147 if (bd == NULL || bd->d_open == NULL) 148 continue; 149 if (bootverbose) 150 printf("trying %s%d as rootdev (0x%x)\n", 151 try_cdrom[j].name, i, rootdev); 152 error = (bd->d_open)(rootdev, FREAD, S_IFBLK, curproc); 153 if (error == 0) { 154 if (bd->d_close != NULL) 155 (bd->d_close)(rootdev, FREAD, S_IFBLK, 156 curproc); 157 return 0; 158 } 159 } 160 161 rootdev = orootdev; 162 return EINVAL; 163} 164#endif /* CD9660 */ 165 166static void 167configure_start() 168{ 169#if NSCBUS > 0 170 scsi_configure_start(); 171#endif 172} 173 174static void 175configure_finish() 176{ 177#if NSCBUS > 0 178 scsi_configure_finish(); 179#endif 180} 181 182/* 183 * Determine i/o configuration for a machine. 184 */ 185static void 186configure(dummy) 187 void *dummy; 188{ 189 int i; 190 191 configure_start(); 192 193 /* Allow all routines to decide for themselves if they want intrs */ 194#ifdef APIC_IO 195 bsp_apic_configure(); 196 enable_intr(); 197#else 198 enable_intr(); 199 INTREN(IRQ_SLAVE); 200#endif /* APIC_IO */ 201 202#if NEISA > 0 203 eisa_configure(); 204#endif 205 206#if NPCI > 0 207 pci_configure(); 208#endif 209 210#if NISA > 0 211 isa_configure(); 212#endif 213 214#if NCRD > 0 215 /* After everyone else has a chance at grabbing resources */ 216 pccard_configure(); 217#endif 218 219 if (setdumpdev(dumpdev) != 0) 220 dumpdev = NODEV; 221 222 configure_finish(); 223 224 cninit_finish(); 225 226 if (bootverbose) { 227 /* 228 * Print out the BIOS's idea of the disk geometries. 229 */ 230 printf("BIOS Geometries:\n"); 231 for (i = 0; i < N_BIOS_GEOM; i++) { 232 unsigned long bios_geom; 233 int max_cylinder, max_head, max_sector; 234 235 bios_geom = bootinfo.bi_bios_geom[i]; 236 237 /* 238 * XXX the bootstrap punts a 1200K floppy geometry 239 * when the get-disk-geometry interrupt fails. Skip 240 * drives that have this geometry. 241 */ 242 if (bios_geom == 0x4f010f) 243 continue; 244 245 printf(" %x:%08lx ", i, bios_geom); 246 max_cylinder = bios_geom >> 16; 247 max_head = (bios_geom >> 8) & 0xff; 248 max_sector = bios_geom & 0xff; 249 printf( 250 "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n", 251 max_cylinder, max_cylinder + 1, 252 max_head, max_head + 1, 253 max_sector, max_sector); 254 } 255 printf(" %d accounted for\n", bootinfo.bi_n_bios_used); 256 257 printf("Device configuration finished.\n"); 258 } 259 260#ifdef CD9660 261 if ((boothowto & RB_CDROM)) { 262 if (bootverbose) 263 printf("Considering CD-ROM root f/s.\n"); 264 /* NB: find_cdrom_root() sets rootdev if successful. */ 265 if (find_cdrom_root() == 0) 266 mountrootfsname = "cd9660"; 267 else if (bootverbose) 268 printf("No CD-ROM available as root f/s.\n"); 269 } 270#endif 271 272#ifdef MFS_ROOT 273 if (!mountrootfsname) { 274 if (bootverbose) 275 printf("Considering MFS root f/s.\n"); 276 mountrootfsname = "mfs"; 277 /* 278 * Ignore the -a flag if this kernel isn't compiled 279 * with a generic root/swap configuration: if we skip 280 * setroot() and we aren't a generic kernel, chaos 281 * will ensue because setconf() will be a no-op. 282 * (rootdev is always initialized to NODEV in a 283 * generic configuration, so we test for that.) 284 */ 285 if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 286 setroot(); 287 } 288#endif 289 290#ifdef BOOTP_NFSROOT 291 if (!mountrootfsname && !nfs_diskless_valid) { 292 if (bootverbose) 293 printf("Considering BOOTP NFS root f/s.\n"); 294 mountrootfsname = "nfs"; 295 } 296#endif /* BOOTP_NFSROOT */ 297#ifdef NFS 298 if (!mountrootfsname && nfs_diskless_valid) { 299 if (bootverbose) 300 printf("Considering NFS root f/s.\n"); 301 mountrootfsname = "nfs"; 302 } 303#endif /* NFS */ 304 305#ifdef FFS 306 if (!mountrootfsname) { 307 mountrootfsname = "ufs"; 308 if (bootverbose) 309 printf("Considering FFS root f/s.\n"); 310 /* 311 * Ignore the -a flag if this kernel isn't compiled 312 * with a generic root/swap configuration: if we skip 313 * setroot() and we aren't a generic kernel, chaos 314 * will ensue because setconf() will be a no-op. 315 * (rootdev is always initialized to NODEV in a 316 * generic configuration, so we test for that.) 317 */ 318 if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 319 setroot(); 320 } 321#endif 322 323#ifdef LFS 324 if (!mountrootfsname) { 325 if (bootverbose) 326 printf("Considering LFS root f/s.\n"); 327 mountrootfsname = "lfs"; 328 /* 329 * Ignore the -a flag if this kernel isn't compiled 330 * with a generic root/swap configuration: if we skip 331 * setroot() and we aren't a generic kernel, chaos 332 * will ensue because setconf() will be a no-op. 333 * (rootdev is always initialized to NODEV in a 334 * generic configuration, so we test for that.) 335 */ 336 if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 337 setroot(); 338 } 339#endif 340 341 if (!mountrootfsname) { 342 panic("Nobody wants to mount my root for me"); 343 } 344 345 setconf(); 346 cold = 0; 347 if (bootverbose) 348 printf("configure() finished.\n"); 349} 350 351static int 352setdumpdev(dev) 353 dev_t dev; 354{ 355 int maj, psize; 356 long newdumplo; 357 358 if (dev == NODEV) { 359 dumpdev = dev; 360 return (0); 361 } 362 maj = major(dev); 363 if (maj >= nblkdev) 364 return (ENXIO); 365 if (bdevsw[maj] == NULL) 366 return (ENXIO); /* XXX is this right? */ 367 if (bdevsw[maj]->d_psize == NULL) 368 return (ENXIO); /* XXX should be ENODEV ? */ 369 psize = bdevsw[maj]->d_psize(dev); 370 if (psize == -1) 371 return (ENXIO); /* XXX should be ENODEV ? */ 372 newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE; 373 if (newdumplo < 0) 374 return (ENOSPC); 375 dumpdev = dev; 376 dumplo = newdumplo; 377 return (0); 378} 379 380u_long bootdev = 0; /* not a dev_t - encoding is different */ 381 382static char devname[][2] = { 383 {'w','d'}, /* 0 = wd */ 384 {'s','w'}, /* 1 = sw */ 385#define FDMAJOR 2 386 {'f','d'}, /* 2 = fd */ 387 {'w','t'}, /* 3 = wt */ 388 {'s','d'}, /* 4 = sd -- new SCSI system */ 389}; 390 391#define PARTITIONMASK 0x7 392#define PARTITIONSHIFT 3 393#define FDUNITSHIFT 6 394#define RAW_PART 2 395 396/* 397 * Attempt to find the device from which we were booted. 398 * If we can do so, and not instructed not to do so, 399 * change rootdev to correspond to the load device. 400 */ 401static void 402setroot() 403{ 404 int majdev, mindev, unit, part, adaptor; 405 dev_t orootdev; 406 407/*printf("howto %x bootdev %x ", boothowto, bootdev);*/ 408 if (boothowto & RB_DFLTROOT || 409 (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 410 return; 411 majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; 412 if (majdev > sizeof(devname) / sizeof(devname[0])) 413 return; 414 adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; 415 unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; 416 if (majdev == FDMAJOR) { 417 part = RAW_PART; 418 mindev = unit << FDUNITSHIFT; 419 } 420 else { 421 part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; 422 mindev = (unit << PARTITIONSHIFT) + part; 423 } 424 orootdev = rootdev; 425 rootdev = makedev(majdev, mindev); 426 /* 427 * If the original rootdev is the same as the one 428 * just calculated, don't need to adjust the swap configuration. 429 */ 430 if (rootdev == orootdev) 431 return; 432 printf("changing root device to %c%c%d%c\n", 433 devname[majdev][0], devname[majdev][1], 434 mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT), 435 part + 'a'); 436} 437 438static int 439sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS 440{ 441 int error; 442 dev_t ndumpdev; 443 444 ndumpdev = dumpdev; 445 error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); 446 if (error == 0 && req->newptr != NULL) 447 error = setdumpdev(ndumpdev); 448 return (error); 449} 450 451SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, 452 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", ""); 453