autoconf.c revision 22521
176575Smarkm/*- 276575Smarkm * Copyright (c) 1990 The Regents of the University of California. 376575Smarkm * All rights reserved. 476575Smarkm * 576575Smarkm * This code is derived from software contributed to Berkeley by 676575Smarkm * William Jolitz. 776575Smarkm * 876575Smarkm * Redistribution and use in source and binary forms, with or without 976575Smarkm * modification, are permitted provided that the following conditions 1076575Smarkm * are met: 1176575Smarkm * 1. Redistributions of source code must retain the above copyright 1276575Smarkm * notice, this list of conditions and the following disclaimer. 1376575Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1476575Smarkm * notice, this list of conditions and the following disclaimer in the 1576575Smarkm * documentation and/or other materials provided with the distribution. 1676575Smarkm * 3. All advertising materials mentioning features or use of this software 1776575Smarkm * must display the following acknowledgement: 1876575Smarkm * This product includes software developed by the University of 1976575Smarkm * California, Berkeley and its contributors. 2076575Smarkm * 4. Neither the name of the University nor the names of its contributors 2176575Smarkm * may be used to endorse or promote products derived from this software 2276575Smarkm * without specific prior written permission. 2376575Smarkm * 2476575Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2576575Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2676575Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27112044Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28112044Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29112044Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3076575Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3176575Smarkm * 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 * $FreeBSD: head/sys/i386/i386/autoconf.c 22521 1997-02-10 02:22:35Z dyson $ 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/conf.h> 52#include <sys/dmap.h> 53#include <sys/reboot.h> 54#include <sys/kernel.h> 55#include <sys/mount.h> 56#include <sys/vnode.h> 57#include <sys/sysctl.h> 58 59#include <machine/bootinfo.h> 60#include <machine/cons.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 92static void configure_finish __P((void)); 93static void configure_start __P((void)); 94static int setdumpdev __P((dev_t dev)); 95static void setroot __P((void)); 96 97#ifdef CD9660 98 99#include <isofs/cd9660/iso.h> 100 101/* We need to try out all our potential CDROM drives, so we need a table. */ 102static struct { 103 char *name; 104 int major; 105} try_cdrom[] = { 106 { "cd", 6 }, 107 { "mcd", 7 }, 108 { "scd", 16 }, 109 { "matcd", 17 }, 110 { 0, 0} 111}; 112 113static int find_cdrom_root __P((void *)); 114 115static int 116find_cdrom_root(dummy) 117 void *dummy; 118{ 119 int i,j,k; 120 121 for (j = 0 ; j < 2; j++) 122 for (k = 0 ; try_cdrom[k].name ; k++) { 123 rootdev = makedev(try_cdrom[k].major,j*8); 124 printf("trying rootdev=0x%lx (%s%d)\n", 125 rootdev, try_cdrom[k].name,j); 126 i = (*cd9660_mountroot)(); 127 if (!i) return i; 128 } 129 return EINVAL; 130} 131#endif /* CD9660 */ 132 133static void 134configure_start() 135{ 136#if NSCBUS > 0 137 scsi_configure_start(); 138#endif 139} 140 141static void 142configure_finish() 143{ 144#if NSCBUS > 0 145 scsi_configure_finish(); 146#endif 147} 148 149/* 150 * Determine i/o configuration for a machine. 151 */ 152static void 153configure(dummy) 154 void *dummy; 155{ 156 int i; 157 158 configure_start(); 159 160 /* Allow all routines to decide for themselves if they want intrs */ 161 enable_intr(); 162 INTREN(IRQ_SLAVE); 163 164#if NCRD > 0 165 /* Before isa_configure to avoid ISA drivers finding our cards */ 166 pccard_configure(); 167#endif 168 169#if NEISA > 0 170 eisa_configure(); 171#endif 172 173#if NPCI > 0 174 pci_configure(); 175#endif 176 177#if NISA > 0 178 isa_configure(); 179#endif 180 181 if (setdumpdev(dumpdev) != 0) 182 dumpdev = NODEV; 183 184 configure_finish(); 185 186 cninit_finish(); 187 188 if (bootverbose) { 189 /* 190 * Print out the BIOS's idea of the disk geometries. 191 */ 192 printf("BIOS Geometries:\n"); 193 for (i = 0; i < N_BIOS_GEOM; i++) { 194 unsigned long bios_geom; 195 int max_cylinder, max_head, max_sector; 196 197 bios_geom = bootinfo.bi_bios_geom[i]; 198 199 /* 200 * XXX the bootstrap punts a 1200K floppy geometry 201 * when the get-disk-geometry interrupt fails. Skip 202 * drives that have this geometry. 203 */ 204 if (bios_geom == 0x4f010f) 205 continue; 206 207 printf(" %x:%08lx ", i, bios_geom); 208 max_cylinder = bios_geom >> 16; 209 max_head = (bios_geom >> 8) & 0xff; 210 max_sector = bios_geom & 0xff; 211 printf( 212 "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n", 213 max_cylinder, max_cylinder + 1, 214 max_head, max_head + 1, 215 max_sector, max_sector); 216 } 217 printf(" %d accounted for\n", bootinfo.bi_n_bios_used); 218 219 printf("Device configuration finished.\n"); 220 } 221 222#ifdef CD9660 223 if ((boothowto & RB_CDROM)) { 224 if (bootverbose) 225 printf("Considering CD-ROM root f/s.\n"); 226 mountrootfsname = "cd9660"; 227 } 228#endif 229 230#ifdef NFS 231 if (!mountrootfsname && nfs_diskless_valid) { 232 if (bootverbose) 233 printf("Considering NFS root f/s.\n"); 234 mountrootfsname = "nfs"; 235 } 236#endif /* NFS */ 237 238#ifdef MFS_ROOT 239 if (!mountrootfsname) { 240 if (bootverbose) 241 printf("Considering MFS root f/s.\n"); 242 mountrootfsname = "mfs"; 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 FFS 256 if (!mountrootfsname) { 257 mountrootfsname = "ufs"; 258 if (bootverbose) 259 printf("Considering FFS root f/s.\n"); 260 /* 261 * Ignore the -a flag if this kernel isn't compiled 262 * with a generic root/swap configuration: if we skip 263 * setroot() and we aren't a generic kernel, chaos 264 * will ensue because setconf() will be a no-op. 265 * (rootdev is always initialized to NODEV in a 266 * generic configuration, so we test for that.) 267 */ 268 if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 269 setroot(); 270 } 271#endif 272#ifdef LFS 273 if (!mountrootfsname) { 274 if (bootverbose) 275 printf("Considering LFS root f/s.\n"); 276 mountrootfsname = "lfs"; 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 if (!mountrootfsname) { 290 panic("Nobody wants to mount my root for me"); 291 } 292 293 setconf(); 294 cold = 0; 295 if (bootverbose) 296 printf("configure() finished.\n"); 297} 298 299static int 300setdumpdev(dev) 301 dev_t dev; 302{ 303 int maj, psize; 304 long newdumplo; 305 306 if (dev == NODEV) { 307 dumpdev = dev; 308 return (0); 309 } 310 maj = major(dev); 311 if (maj >= nblkdev) 312 return (ENXIO); 313 if (bdevsw[maj] == NULL) 314 return (ENXIO); /* XXX is this right? */ 315 if (bdevsw[maj]->d_psize == NULL) 316 return (ENXIO); /* XXX should be ENODEV ? */ 317 psize = bdevsw[maj]->d_psize(dev); 318 if (psize == -1) 319 return (ENXIO); /* XXX should be ENODEV ? */ 320 newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE; 321 if (newdumplo < 0) 322 return (ENOSPC); 323 dumpdev = dev; 324 dumplo = newdumplo; 325 return (0); 326} 327 328u_long bootdev = 0; /* not a dev_t - encoding is different */ 329 330static char devname[][2] = { 331 {'w','d'}, /* 0 = wd */ 332 {'s','w'}, /* 1 = sw */ 333#define FDMAJOR 2 334 {'f','d'}, /* 2 = fd */ 335 {'w','t'}, /* 3 = wt */ 336 {'s','d'}, /* 4 = sd -- new SCSI system */ 337}; 338 339#define PARTITIONMASK 0x7 340#define PARTITIONSHIFT 3 341#define FDUNITSHIFT 6 342#define RAW_PART 2 343 344/* 345 * Attempt to find the device from which we were booted. 346 * If we can do so, and not instructed not to do so, 347 * change rootdev to correspond to the load device. 348 */ 349static void 350setroot() 351{ 352 int majdev, mindev, unit, part, adaptor; 353 dev_t orootdev; 354 355/*printf("howto %x bootdev %x ", boothowto, bootdev);*/ 356 if (boothowto & RB_DFLTROOT || 357 (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 358 return; 359 majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; 360 if (majdev > sizeof(devname) / sizeof(devname[0])) 361 return; 362 adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; 363 unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; 364 if (majdev == FDMAJOR) { 365 part = RAW_PART; 366 mindev = unit << FDUNITSHIFT; 367 } 368 else { 369 part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; 370 mindev = (unit << PARTITIONSHIFT) + part; 371 } 372 orootdev = rootdev; 373 rootdev = makedev(majdev, mindev); 374 /* 375 * If the original rootdev is the same as the one 376 * just calculated, don't need to adjust the swap configuration. 377 */ 378 if (rootdev == orootdev) 379 return; 380 printf("changing root device to %c%c%d%c\n", 381 devname[majdev][0], devname[majdev][1], 382 mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT), 383 part + 'a'); 384} 385 386static int 387sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS 388{ 389 int error; 390 dev_t ndumpdev; 391 392 ndumpdev = dumpdev; 393 error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); 394 if (error == 0 && req->newptr != NULL) 395 error = setdumpdev(ndumpdev); 396 return (error); 397} 398 399SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, 400 0, sizeof dumpdev, sysctl_kern_dumpdev, "I", ""); 401