autoconf.c revision 22564
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 * $FreeBSD: head/sys/i386/i386/autoconf.c 22564 1997-02-11 15:03:31Z bde $ 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 NEISA > 0 165 eisa_configure(); 166#endif 167 168#if NPCI > 0 169 pci_configure(); 170#endif 171 172#if NISA > 0 173 isa_configure(); 174#endif 175 176#if NCRD > 0 177 /* After everyone else has a chance at grabbing resources */ 178 pccard_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 MFS_ROOT 231 if (!mountrootfsname) { 232 if (bootverbose) 233 printf("Considering MFS root f/s.\n"); 234 mountrootfsname = "mfs"; 235 /* 236 * Ignore the -a flag if this kernel isn't compiled 237 * with a generic root/swap configuration: if we skip 238 * setroot() and we aren't a generic kernel, chaos 239 * will ensue because setconf() will be a no-op. 240 * (rootdev is always initialized to NODEV in a 241 * generic configuration, so we test for that.) 242 */ 243 if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 244 setroot(); 245 } 246#endif 247 248#ifdef NFS 249 if (!mountrootfsname && nfs_diskless_valid) { 250 if (bootverbose) 251 printf("Considering NFS root f/s.\n"); 252 mountrootfsname = "nfs"; 253 } 254#endif /* NFS */ 255 256#ifdef FFS 257 if (!mountrootfsname) { 258 mountrootfsname = "ufs"; 259 if (bootverbose) 260 printf("Considering FFS root f/s.\n"); 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 274#ifdef LFS 275 if (!mountrootfsname) { 276 if (bootverbose) 277 printf("Considering LFS root f/s.\n"); 278 mountrootfsname = "lfs"; 279 /* 280 * Ignore the -a flag if this kernel isn't compiled 281 * with a generic root/swap configuration: if we skip 282 * setroot() and we aren't a generic kernel, chaos 283 * will ensue because setconf() will be a no-op. 284 * (rootdev is always initialized to NODEV in a 285 * generic configuration, so we test for that.) 286 */ 287 if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV) 288 setroot(); 289 } 290#endif 291 292 if (!mountrootfsname) { 293 panic("Nobody wants to mount my root for me"); 294 } 295 296 setconf(); 297 cold = 0; 298 if (bootverbose) 299 printf("configure() finished.\n"); 300} 301 302static int 303setdumpdev(dev) 304 dev_t dev; 305{ 306 int maj, psize; 307 long newdumplo; 308 309 if (dev == NODEV) { 310 dumpdev = dev; 311 return (0); 312 } 313 maj = major(dev); 314 if (maj >= nblkdev) 315 return (ENXIO); 316 if (bdevsw[maj] == NULL) 317 return (ENXIO); /* XXX is this right? */ 318 if (bdevsw[maj]->d_psize == NULL) 319 return (ENXIO); /* XXX should be ENODEV ? */ 320 psize = bdevsw[maj]->d_psize(dev); 321 if (psize == -1) 322 return (ENXIO); /* XXX should be ENODEV ? */ 323 newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE; 324 if (newdumplo < 0) 325 return (ENOSPC); 326 dumpdev = dev; 327 dumplo = newdumplo; 328 return (0); 329} 330 331u_long bootdev = 0; /* not a dev_t - encoding is different */ 332 333static char devname[][2] = { 334 {'w','d'}, /* 0 = wd */ 335 {'s','w'}, /* 1 = sw */ 336#define FDMAJOR 2 337 {'f','d'}, /* 2 = fd */ 338 {'w','t'}, /* 3 = wt */ 339 {'s','d'}, /* 4 = sd -- new SCSI system */ 340}; 341 342#define PARTITIONMASK 0x7 343#define PARTITIONSHIFT 3 344#define FDUNITSHIFT 6 345#define RAW_PART 2 346 347/* 348 * Attempt to find the device from which we were booted. 349 * If we can do so, and not instructed not to do so, 350 * change rootdev to correspond to the load device. 351 */ 352static void 353setroot() 354{ 355 int majdev, mindev, unit, part, adaptor; 356 dev_t orootdev; 357 358/*printf("howto %x bootdev %x ", boothowto, bootdev);*/ 359 if (boothowto & RB_DFLTROOT || 360 (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC) 361 return; 362 majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK; 363 if (majdev > sizeof(devname) / sizeof(devname[0])) 364 return; 365 adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK; 366 unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK; 367 if (majdev == FDMAJOR) { 368 part = RAW_PART; 369 mindev = unit << FDUNITSHIFT; 370 } 371 else { 372 part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK; 373 mindev = (unit << PARTITIONSHIFT) + part; 374 } 375 orootdev = rootdev; 376 rootdev = makedev(majdev, mindev); 377 /* 378 * If the original rootdev is the same as the one 379 * just calculated, don't need to adjust the swap configuration. 380 */ 381 if (rootdev == orootdev) 382 return; 383 printf("changing root device to %c%c%d%c\n", 384 devname[majdev][0], devname[majdev][1], 385 mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT), 386 part + 'a'); 387} 388 389static int 390sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS 391{ 392 int error; 393 dev_t ndumpdev; 394 395 ndumpdev = dumpdev; 396 error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); 397 if (error == 0 && req->newptr != NULL) 398 error = setdumpdev(ndumpdev); 399 return (error); 400} 401 402SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, 403 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", ""); 404