The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/i386/autoconf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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: src/sys/i386/i386/autoconf.c,v 1.56.2.16 1999/09/05 08:11:02 peter 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 "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/disklabel.h>
   55 #include <sys/diskslice.h> /* for BASE_SLICE, MAX_SLICES */
   56 #include <sys/dmap.h>
   57 #include <sys/reboot.h>
   58 #include <sys/kernel.h>
   59 #include <sys/mount.h>
   60 #include <sys/sysctl.h>
   61 
   62 #include <machine/bootinfo.h>
   63 #include <machine/cons.h>
   64 #include <machine/md_var.h>
   65 #include <i386/isa/icu.h> /* For interrupts */
   66 
   67 #include "isa.h"
   68 #if NISA > 0
   69 #include <i386/isa/isa_device.h>
   70 #endif
   71 
   72 #include "pnp.h"
   73 #if NPNP > 0
   74 #include <i386/isa/pnp.h>
   75 #endif
   76  
   77 #include "eisa.h"
   78 #if NEISA > 0
   79 #include <i386/eisa/eisaconf.h>
   80 #endif
   81 
   82 #include "pci.h"
   83 #if NPCI > 0
   84 #include <pci/pcivar.h>
   85 #endif
   86 
   87 #include "card.h"
   88 #if NCARD > 0
   89 #include <pccard/driver.h>
   90 #endif
   91 
   92 #include "scbus.h"
   93 #if NSCBUS > 0
   94 #include <scsi/scsiconf.h>
   95 #endif
   96 
   97 static void     configure __P((void *));
   98 SYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL)
   99 
  100 #ifdef MFS_ROOT
  101 extern struct vfsops    mfs_vfsops;
  102 #endif
  103 #ifdef FFS
  104 extern struct vfsops    ufs_vfsops;
  105 #endif
  106 #ifdef LFS
  107 extern struct vfsops    lfs_vfsops;
  108 #endif
  109 #ifdef NFS
  110 extern int      nfs_mountroot __P((void *));
  111 #endif
  112 #ifdef MSDOSFS
  113 extern int      msdosfs_mountroot __P((void *));
  114 #endif
  115 
  116 static void     configure_finish __P((void));
  117 static void     configure_start __P((void));
  118 static int      setdumpdev __P((dev_t dev));
  119 static void     setroot __P((void));
  120 
  121 #ifdef CD9660
  122 
  123 #include <sys/fcntl.h>
  124 #include <sys/proc.h>
  125 #include <sys/stat.h>
  126 #include <sys/vnode.h>
  127 #include <machine/clock.h>
  128 #include <isofs/cd9660/iso.h>
  129 
  130 /*
  131  * XXX All this CD-ROM root stuff is fairly messy.  Ick.
  132  *
  133  * We need to try out all our potential CDROM drives, so we need a table.
  134  */
  135 static struct {
  136         char *name;
  137         int major;
  138 } try_cdrom[] = {
  139         { "cd", 6 },
  140         { "mcd", 7 },
  141         { "scd", 16 },
  142         { "matcd", 17 },
  143         { "wcd", 19 },
  144         { 0, 0}
  145 };
  146 
  147 static int      find_cdrom_root __P((void));
  148 
  149 static int
  150 find_cdrom_root()
  151 {
  152         int i, j, error;
  153         struct bdevsw *bd;
  154         dev_t orootdev;
  155 
  156 #if CD9660_ROOTDELAY > 0
  157         DELAY(CD9660_ROOTDELAY * 1000000);
  158 #endif
  159         orootdev = rootdev;
  160         for (i = 0 ; i < 2; i++)
  161                 for (j = 0 ; try_cdrom[j].name ; j++) {
  162                         if (try_cdrom[j].major >= nblkdev)
  163                                 continue;
  164                         rootdev = makedev(try_cdrom[j].major, i * 8);
  165                         bd = bdevsw[major(rootdev)];
  166                         if (bd == NULL || bd->d_open == NULL)
  167                                 continue;
  168                         if (bootverbose)
  169                                 printf("trying %s%d as rootdev (0x%x)\n",
  170                                        try_cdrom[j].name, i, rootdev);
  171                         error = (bd->d_open)(rootdev, FREAD, S_IFBLK, curproc);
  172                         if (error == 0) {
  173                                 if (bd->d_close != NULL)
  174                                         (bd->d_close)(rootdev, FREAD, S_IFBLK,
  175                                                       curproc);
  176                                 return 0;
  177                         }
  178                 }
  179 
  180         rootdev = orootdev;
  181         return EINVAL;
  182 }
  183 #endif /* CD9660 */
  184 
  185 static void
  186 configure_start()
  187 {
  188 #if NSCBUS > 0
  189         scsi_configure_start();
  190 #endif
  191 }
  192 
  193 static void
  194 configure_finish()
  195 {
  196 #if NSCBUS > 0
  197         scsi_configure_finish();
  198 #endif
  199 }
  200 
  201 /*
  202  * Determine i/o configuration for a machine.
  203  */
  204 static void
  205 configure(dummy)
  206         void *dummy;
  207 {
  208         int i;
  209 
  210         configure_start();
  211         /* Allow all routines to decide for themselves if they want intrs */
  212         /*
  213          * XXX Since this cannot be achieved on all architectures, we should
  214          * XXX go back to disabling all interrupts until configuration is
  215          * XXX completed and switch any devices that rely on the current
  216          * XXX behavior to no longer rely on interrupts or to register an
  217          * XXX interrupt_driven_config_hook for the task.
  218          */
  219         /*
  220          * XXX The above is wrong, because we're implicitly at splhigh(),
  221          * XXX and should stay there, so enabling interrupts in the CPU
  222          * XXX and the ICU at most gives pending interrupts which just get
  223          * XXX in the way.
  224          */
  225         enable_intr();
  226         INTREN(IRQ_SLAVE);
  227 
  228 #if NEISA > 0
  229         eisa_configure();
  230 #endif
  231 
  232 #if NPCI > 0
  233         pci_configure();
  234 #endif
  235 
  236 #if NPNP > 0
  237         pnp_configure();
  238 #endif
  239 
  240 #if NISA > 0
  241         isa_configure();
  242 #endif
  243 
  244 #if NCARD > 0
  245         /* After everyone else has a chance at grabbing resources */
  246         pccard_configure();
  247 #endif
  248 
  249         configure_finish();
  250 
  251         cninit_finish();
  252 
  253         if (bootverbose) {
  254                 /*
  255                  * Print out the BIOS's idea of the disk geometries.
  256                  */
  257                 printf("BIOS Geometries:\n");
  258                 for (i = 0; i < N_BIOS_GEOM; i++) {
  259                         unsigned long bios_geom;
  260                         int max_cylinder, max_head, max_sector;
  261 
  262                         bios_geom = bootinfo.bi_bios_geom[i];
  263 
  264                         /*
  265                          * XXX the bootstrap punts a 1200K floppy geometry
  266                          * when the get-disk-geometry interrupt fails.  Skip
  267                          * drives that have this geometry.
  268                          */
  269                         if (bios_geom == 0x4f010f)
  270                                 continue;
  271 
  272                         printf(" %x:%08lx ", i, bios_geom);
  273                         max_cylinder = bios_geom >> 16;
  274                         max_head = (bios_geom >> 8) & 0xff;
  275                         max_sector = bios_geom & 0xff;
  276                         printf(
  277                 "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n",
  278                                max_cylinder, max_cylinder + 1,
  279                                max_head, max_head + 1,
  280                                max_sector, max_sector);
  281                 }
  282                 printf(" %d accounted for\n", bootinfo.bi_n_bios_used);
  283 
  284                 printf("Device configuration finished.\n");
  285         }
  286         cold = 0;
  287 }
  288 
  289 void
  290 cpu_rootconf()
  291 {
  292         /*
  293          * XXX NetBSD has a much cleaner approach to finding root.
  294          * XXX We should adopt their code.
  295          */
  296 #ifdef CD9660
  297         if ((boothowto & RB_CDROM) != 0) {
  298                 if (bootverbose)
  299                         printf("Considering CD-ROM root f/s.\n");
  300                 /* NB: find_cdrom_root() sets rootdev if successful. */
  301                 if (find_cdrom_root() == 0)
  302                         mountroot = cd9660_mountroot;   /* XXX goes away*/
  303                 else if (bootverbose)
  304                         printf("No CD-ROM available as root f/s.\n");
  305         }
  306 #endif
  307 
  308 #ifdef MFS_ROOT
  309         if (!mountroot) {
  310                 if (bootverbose)
  311                         printf("Considering MFS root f/s.\n");
  312                 mountroot = vfs_mountroot;      /* XXX goes away*/
  313                 mountrootvfsops = &mfs_vfsops;
  314                 /*
  315                  * Ignore the -a flag if this kernel isn't compiled
  316                  * with a generic root/swap configuration: if we skip
  317                  * setroot() and we aren't a generic kernel, chaos
  318                  * will ensue because setconf() will be a no-op.
  319                  * (rootdev is always initialized to NODEV in a
  320                  * generic configuration, so we test for that.)
  321                  */
  322                 if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
  323                         setroot();
  324         }
  325 #endif
  326 
  327 #ifdef BOOTP_NFSROOT
  328         if (!mountroot && !nfs_diskless_valid) {
  329                 if (bootverbose)
  330                         printf("Considering BOOTP NFS root f/s.\n");
  331                 mountroot = nfs_mountroot;
  332         }
  333 #endif /* BOOTP_NFSROOT */
  334 
  335 #ifdef NFS
  336         if (!mountroot && nfs_diskless_valid) {
  337                 if (bootverbose)
  338                         printf("Considering NFS root f/s.\n");
  339                 mountroot = nfs_mountroot;
  340         }
  341 #endif /* NFS */
  342 
  343 #ifdef FFS
  344         if (!mountroot) {
  345                 if (bootverbose)
  346                         printf("Considering FFS root f/s.\n");
  347                 mountroot = vfs_mountroot;      /* XXX goes away*/
  348                 mountrootvfsops = &ufs_vfsops;
  349                 /*
  350                  * Ignore the -a flag if this kernel isn't compiled
  351                  * with a generic root/swap configuration: if we skip
  352                  * setroot() and we aren't a generic kernel, chaos
  353                  * will ensue because setconf() will be a no-op.
  354                  * (rootdev is always initialized to NODEV in a
  355                  * generic configuration, so we test for that.)
  356                  */
  357                 if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
  358                         setroot();
  359         }
  360 #endif
  361 #ifdef LFS
  362         if (!mountroot) {
  363                 if (bootverbose)
  364                         printf("Considering LFS root f/s.\n");
  365                 mountroot = vfs_mountroot;      /* XXX goes away*/
  366                 mountrootvfsops = &lfs_vfsops;
  367                 /*
  368                  * Ignore the -a flag if this kernel isn't compiled
  369                  * with a generic root/swap configuration: if we skip
  370                  * setroot() and we aren't a generic kernel, chaos
  371                  * will ensue because setconf() will be a no-op.
  372                  * (rootdev is always initialized to NODEV in a
  373                  * generic configuration, so we test for that.)
  374                  */
  375                 if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
  376                         setroot();
  377         }
  378 #endif
  379 
  380         if (!mountroot) {
  381                 panic("Nobody wants to mount my root for me");
  382         }
  383         setconf();
  384 }
  385 
  386 void
  387 cpu_dumpconf()
  388 {
  389         if (setdumpdev(dumpdev) != 0)
  390                 dumpdev = NODEV;
  391 }
  392 
  393 static int
  394 setdumpdev(dev)
  395         dev_t dev;
  396 {
  397         int maj, psize;
  398         long newdumplo;
  399 
  400         if (dev == NODEV) {
  401                 dumpdev = dev;
  402                 return (0);
  403         }
  404         maj = major(dev);
  405         if (maj >= nblkdev)
  406                 return (ENXIO);
  407         if (bdevsw[maj] == NULL)
  408                 return (ENXIO);         /* XXX is this right? */
  409         if (bdevsw[maj]->d_psize == NULL)
  410                 return (ENXIO);         /* XXX should be ENODEV ? */
  411         psize = bdevsw[maj]->d_psize(dev);
  412         if (psize == -1)
  413                 return (ENXIO);         /* XXX should be ENODEV ? */
  414         /*
  415          * XXX should clean up checking in dumpsys() to be more like this,
  416          * and nuke dodump sysctl (too many knobs), and move this to
  417          * kern_shutdown.c...
  418          */
  419         if (dkpart(dev) != SWAP_PART)
  420                 return (ENODEV);
  421         newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE;
  422         if (newdumplo < 0)
  423                 return (ENOSPC);
  424         dumpdev = dev;
  425         dumplo = newdumplo;
  426         return (0);
  427 }
  428 
  429 u_long  bootdev = 0;            /* not a dev_t - encoding is different */
  430 
  431 /* Name lookup for bootable majors */
  432 static char *devname[] = {
  433         "wd",
  434         "wfd",
  435 #define FDMAJOR 2
  436         "fd",
  437         "wt",
  438         "sd",
  439 };
  440 
  441 #define PARTITIONMASK   0x7
  442 #define PARTITIONSHIFT  3
  443 #define FDUNITSHIFT     6
  444 #define RAW_PART        2
  445 
  446 /*
  447  * Attempt to find the device from which we were booted.
  448  * If we can do so, and not instructed not to do so,
  449  * change rootdev to correspond to the load device.
  450  */
  451 static void
  452 setroot()
  453 {
  454         int  majdev, mindev, unit, part, adaptor, slice;
  455         dev_t orootdev;
  456         char *sname, partname[2];
  457 
  458 /*printf("howto %x bootdev %x ", boothowto, bootdev);*/
  459         if (boothowto & RB_DFLTROOT ||
  460             (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
  461                 return;
  462         majdev  = B_TYPE(bootdev);
  463         adaptor = B_ADAPTOR(bootdev);
  464         unit    = B_UNIT(bootdev);
  465         slice   = B_SLICE(bootdev);
  466         if ((slice < BASE_SLICE) || (slice >= MAX_SLICES))
  467                 slice = COMPATIBILITY_SLICE;
  468         if (majdev > sizeof(devname) / sizeof(devname[0]))
  469                 return;
  470         if (majdev == FDMAJOR) {
  471                 part = RAW_PART;
  472                 mindev = unit << FDUNITSHIFT;
  473         }
  474         else {
  475                 part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
  476                 mindev = dkmakeminor(unit, slice, part);
  477         }
  478         orootdev = rootdev;
  479         rootdev = makedev(majdev, mindev);
  480         /*
  481          * If the original rootdev is the same as the one
  482          * just calculated modulo the slice number, don't print an otherwise
  483          * confusing diagnostic.
  484          */
  485         if ((rootdev & ~0xff0000) == (orootdev & ~0xff0000))
  486                 return;
  487         sname = dsname(devname[majdev], unit, slice, part, partname);
  488         printf("changing root device to %s%s\n", sname, partname);
  489 }
  490 
  491 static int
  492 sysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
  493 {
  494         int error;
  495         dev_t ndumpdev;
  496 
  497         ndumpdev = dumpdev;
  498         error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req);
  499         if (error == 0 && req->newptr != NULL)
  500                 error = setdumpdev(ndumpdev);
  501         return (error);
  502 }
  503 
  504 SYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
  505         0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", "");

Cache object: 3875a2b779aac979d611e5b0dc729457


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.