autoconf.c revision 12889
129088Smarkm/*-
229088Smarkm * Copyright (c) 1990 The Regents of the University of California.
329088Smarkm * All rights reserved.
429088Smarkm *
529088Smarkm * This code is derived from software contributed to Berkeley by
629088Smarkm * William Jolitz.
729088Smarkm *
829088Smarkm * Redistribution and use in source and binary forms, with or without
929088Smarkm * modification, are permitted provided that the following conditions
1029088Smarkm * are met:
1129088Smarkm * 1. Redistributions of source code must retain the above copyright
1229088Smarkm *    notice, this list of conditions and the following disclaimer.
1329088Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1429088Smarkm *    notice, this list of conditions and the following disclaimer in the
1529088Smarkm *    documentation and/or other materials provided with the distribution.
1629088Smarkm * 3. All advertising materials mentioning features or use of this software
1729088Smarkm *    must display the following acknowledgement:
1829088Smarkm *	This product includes software developed by the University of
1929088Smarkm *	California, Berkeley and its contributors.
2029088Smarkm * 4. Neither the name of the University nor the names of its contributors
2129088Smarkm *    may be used to endorse or promote products derived from this software
2229088Smarkm *    without specific prior written permission.
2329088Smarkm *
2429088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2529088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2629088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2729088Smarkm * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2829088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2929088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3029088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3129088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3229088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3329088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3429088Smarkm * SUCH DAMAGE.
3529181Smarkm *
3629088Smarkm *	from: @(#)autoconf.c	7.1 (Berkeley) 5/9/91
3729088Smarkm *	$Id: autoconf.c,v 1.50 1995/12/14 23:35:17 bde Exp $
3829088Smarkm */
3929088Smarkm
4029088Smarkm/*
4129088Smarkm * Setup the system to run on the current machine.
4229088Smarkm *
4329088Smarkm * Configure() is called at boot time and initializes the vba
4429088Smarkm * device tables and the memory controller monitoring.  Available
4529088Smarkm * devices are determined (from possibilities mentioned in ioconf.c),
4629088Smarkm * and the drivers are initialized.
4729088Smarkm */
4829088Smarkm#include <sys/param.h>
4929088Smarkm#include <sys/systm.h>
5029088Smarkm#include <sys/buf.h>
5129088Smarkm#include <sys/dkstat.h>
5229088Smarkm#include <sys/conf.h>
5329088Smarkm#include <sys/dmap.h>
5429088Smarkm#include <sys/reboot.h>
5529088Smarkm#include <sys/kernel.h>
5629088Smarkm#include <sys/mount.h>
5729088Smarkm#include <sys/sysctl.h>
5829088Smarkm
5929181Smarkm#include <machine/cons.h>
6029181Smarkm#include <machine/md_var.h>
6129088Smarkm#include <machine/pte.h>
6229088Smarkm#include <i386/isa/icu.h> /* For interrupts */
6329088Smarkm
6429088Smarkm#include "isa.h"
6529088Smarkm#if NISA > 0
6629088Smarkm#include <i386/isa/isa_device.h>
6729088Smarkm#endif
6829088Smarkm
6929088Smarkm#include "eisa.h"
7029088Smarkm#if NEISA > 0
7129088Smarkm#include <i386/eisa/eisaconf.h>
7229181Smarkm#endif
7329181Smarkm
7429181Smarkm#include "pci.h"
7529181Smarkm#if NPCI > 0
7629181Smarkm#include <pci/pcivar.h>
7729181Smarkm#endif
7829181Smarkm
7929088Smarkm#include "crd.h"
8029088Smarkm#if NCRD > 0
8129088Smarkm#include <pccard/driver.h>
8229088Smarkm#endif
8329088Smarkm
8429088Smarkm#include "scbus.h"
8529088Smarkm#if NSCBUS > 0
8629088Smarkm#include <scsi/scsiconf.h>
8729088Smarkm#endif
8829088Smarkm
8929088Smarkmstatic void	configure __P((void *));
9029088SmarkmSYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL)
9129088Smarkm
9229088Smarkm#ifdef MFS_ROOT
9329088Smarkmextern struct vfsops	mfs_vfsops;
9429088Smarkm#endif
9529088Smarkm#ifdef FFS
9629088Smarkmextern struct vfsops	ufs_vfsops;
9729088Smarkm#endif
9829088Smarkm#ifdef LFS
9929088Smarkmextern struct vfsops	lfs_vfsops;
10029088Smarkm#endif
10129088Smarkm#ifdef NFS
10229088Smarkmextern int	nfs_mountroot __P((void *));
10329088Smarkm#endif
10429088Smarkm#ifdef CD9660
10529181Smarkmextern int	cd9660_mountroot __P((void *));
10629181Smarkm#endif
10729181Smarkm#ifdef MSDOSFS
10829088Smarkmextern int	msdosfs_mountroot __P((void *));
10929181Smarkm#endif
11029181Smarkm
11129088Smarkmstatic void	configure_finish __P((void));
11229088Smarkmstatic void	configure_start __P((void));
11329088Smarkmstatic int	setdumpdev __P((dev_t dev));
11429088Smarkmstatic void	setroot __P((void));
11529088Smarkm
11629088Smarkm#ifdef CD9660
11729088Smarkm/* We need to try out all our potential CDROM drives, so we need a table. */
11829088Smarkmstatic struct {
11929088Smarkm	char *name;
12029088Smarkm	int major;
12129088Smarkm} try_cdrom[] = {
12229088Smarkm	{ "cd", 6 },
12329181Smarkm	{ "mcd", 7 },
12429181Smarkm	{ "scd", 16 },
12529181Smarkm	{ "matcd", 17 },
12629181Smarkm	{ 0, 0}
12729181Smarkm};
12829181Smarkm
12929181Smarkmstatic int	find_cdrom_root __P((void *));
13029181Smarkm
13129181Smarkmstatic int
13229181Smarkmfind_cdrom_root(dummy)
13329181Smarkm	void *dummy;
13429181Smarkm{
13529181Smarkm	int i,j,k;
13629181Smarkm
13729181Smarkm	for (j = 0 ; j < 2; j++)
13829181Smarkm		for (k = 0 ; try_cdrom[k].name ; k++) {
13929181Smarkm			rootdev = makedev(try_cdrom[k].major,j*8);
14029181Smarkm			printf("trying rootdev=0x%lx (%s%d)\n",
14129181Smarkm				rootdev, try_cdrom[k].name,j);
14229181Smarkm			i = (*cd9660_mountroot)((void *)NULL);
14329181Smarkm			if (!i) return i;
14429181Smarkm		}
14529181Smarkm	return EINVAL;
14629181Smarkm}
14729181Smarkm#endif /* CD9660 */
14829181Smarkm
14929181Smarkmstatic void
15029181Smarkmconfigure_start()
15129181Smarkm{
15229181Smarkm#if NSCBUS > 0
15329181Smarkm	scsi_configure_start();
15429088Smarkm#endif
15529088Smarkm}
15629088Smarkm
15729088Smarkmstatic void
15829088Smarkmconfigure_finish()
15929088Smarkm{
16029088Smarkm#if NSCBUS > 0
16129088Smarkm	scsi_configure_finish();
16229088Smarkm#endif
16329088Smarkm}
16429088Smarkm
16529088Smarkm/*
16629088Smarkm * Determine i/o configuration for a machine.
16729088Smarkm */
16829181Smarkmstatic void
16929088Smarkmconfigure(dummy)
17029088Smarkm	void *dummy;
17129088Smarkm{
17229088Smarkm
17329088Smarkm	configure_start();
17429088Smarkm
17529088Smarkm	/* Allow all routines to decide for themselves if they want intrs */
17629088Smarkm        enable_intr();
17729088Smarkm        INTREN(IRQ_SLAVE);
17829088Smarkm
17929088Smarkm#if NCRD > 0
18029088Smarkm	/* Before isa_configure to avoid ISA drivers finding our cards */
18129088Smarkm	pccard_configure();
18229088Smarkm#endif
18329088Smarkm
18429088Smarkm#if NEISA > 0
18529088Smarkm	eisa_configure();
18629088Smarkm#endif
18729088Smarkm
18829088Smarkm#if NPCI > 0
18929088Smarkm	pci_configure();
19029088Smarkm#endif
19129088Smarkm
19229088Smarkm#if NISA > 0
19329088Smarkm	isa_configure();
19429088Smarkm#endif
19529088Smarkm
19629088Smarkm	configure_finish();
19729088Smarkm
19829088Smarkm	cninit_finish();
19929088Smarkm
20029088Smarkm#ifdef CD9660
20129088Smarkm	if ((boothowto & RB_CDROM) && !mountroot)
20229088Smarkm		mountroot = find_cdrom_root;
20329088Smarkm#endif
20429088Smarkm
20529088Smarkm#ifdef NFS
20629088Smarkm	if (!mountroot && nfs_diskless_valid)
20729088Smarkm		mountroot = nfs_mountroot;
20829088Smarkm#endif /* NFS */
20929088Smarkm
21029088Smarkm#ifdef MFS_ROOT
21129181Smarkm	if (!mountroot) {
21229088Smarkm		mountroot = vfs_mountroot;	/* XXX goes away*/
21329088Smarkm		mountrootvfsops = &mfs_vfsops;
21429088Smarkm		/*
21529088Smarkm		 * Ignore the -a flag if this kernel isn't compiled
21629088Smarkm		 * with a generic root/swap configuration: if we skip
21729088Smarkm		 * setroot() and we aren't a generic kernel, chaos
21829088Smarkm		 * will ensue because setconf() will be a no-op.
21929088Smarkm		 * (rootdev is always initialized to NODEV in a
22029088Smarkm		 * generic configuration, so we test for that.)
22129088Smarkm		 */
22229088Smarkm		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
22329088Smarkm			setroot();
22429088Smarkm	}
22529088Smarkm#endif
22629088Smarkm#ifdef FFS
22729088Smarkm	if (!mountroot) {
22829088Smarkm		mountroot = vfs_mountroot;	/* XXX goes away*/
22929088Smarkm		mountrootvfsops = &ufs_vfsops;
23029088Smarkm		/*
23129088Smarkm		 * Ignore the -a flag if this kernel isn't compiled
23229088Smarkm		 * with a generic root/swap configuration: if we skip
23329088Smarkm		 * setroot() and we aren't a generic kernel, chaos
23429088Smarkm		 * will ensue because setconf() will be a no-op.
23529088Smarkm		 * (rootdev is always initialized to NODEV in a
23629088Smarkm		 * generic configuration, so we test for that.)
23729088Smarkm		 */
23829088Smarkm		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
23929088Smarkm			setroot();
24029088Smarkm	}
24129088Smarkm#endif
24229088Smarkm#ifdef LFS
24329088Smarkm	if (!mountroot) {
24429088Smarkm		mountroot = vfs_mountroot;	/* XXX goes away*/
24529088Smarkm		mountrootvfsops = &lfs_vfsops;
24629088Smarkm		/*
24729088Smarkm		 * Ignore the -a flag if this kernel isn't compiled
24829088Smarkm		 * with a generic root/swap configuration: if we skip
24929088Smarkm		 * setroot() and we aren't a generic kernel, chaos
25029088Smarkm		 * will ensue because setconf() will be a no-op.
25129088Smarkm		 * (rootdev is always initialized to NODEV in a
25229088Smarkm		 * generic configuration, so we test for that.)
25329088Smarkm		 */
25429088Smarkm		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
25529088Smarkm			setroot();
25629088Smarkm	}
25729088Smarkm#endif
25829088Smarkm	if (!mountroot) {
25929088Smarkm		panic("Nobody wants to mount my root for me");
26029088Smarkm	}
26129088Smarkm	/*
26229088Smarkm	 * Configure swap area and related system
26329088Smarkm	 * parameter based on device(s) used.
26429088Smarkm	 */
26529088Smarkm	setconf();
26629088Smarkm	cold = 0;
26729088Smarkm}
26829088Smarkm
26929088Smarkmstatic int
27029088Smarkmsetdumpdev(dev)
27129088Smarkm	dev_t dev;
27229088Smarkm{
27329088Smarkm	int maj, psize;
27429088Smarkm	long newdumplo;
27529088Smarkm
27629088Smarkm	if (dev == NODEV) {
27729088Smarkm		dumpdev = dev;
27829088Smarkm		dumplo = 0;
27929088Smarkm		return (0);
28029088Smarkm	}
28129088Smarkm	maj = major(dev);
28229088Smarkm	if (maj >= nblkdev)
28329088Smarkm		return (ENXIO);
28429088Smarkm	if (bdevsw[maj] == NULL)
28529088Smarkm		return (ENXIO);		/* XXX is this right? */
28629088Smarkm	if (bdevsw[maj]->d_psize == NULL)
28729088Smarkm		return (ENXIO);		/* XXX should be ENODEV ? */
28829088Smarkm	psize = bdevsw[maj]->d_psize(dev);
28929088Smarkm	if (psize == -1)
29029088Smarkm		return (ENXIO);		/* XXX should be ENODEV ? */
29129088Smarkm	newdumplo = psize - Maxmem * NBPG / DEV_BSIZE;
29229088Smarkm	if (newdumplo < 0)
29329088Smarkm		return (ENOSPC);
29429088Smarkm	dumpdev = dev;
29529088Smarkm	dumplo = newdumplo;
29629088Smarkm	return (0);
29729088Smarkm}
29829088Smarkm
29929088Smarkmu_long	bootdev = 0;		/* not a dev_t - encoding is different */
30029088Smarkm
30129088Smarkmstatic	char devname[][2] = {
30229088Smarkm      {'w','d'},      /* 0 = wd */
30329088Smarkm      {'s','w'},      /* 1 = sw */
30429088Smarkm#define FDMAJOR 2
30529088Smarkm      {'f','d'},      /* 2 = fd */
30629088Smarkm      {'w','t'},      /* 3 = wt */
30729088Smarkm      {'s','d'},      /* 4 = sd -- new SCSI system */
30829088Smarkm};
30929088Smarkm
31029088Smarkm#define	PARTITIONMASK	0x7
31129088Smarkm#define	PARTITIONSHIFT	3
31229088Smarkm#define FDUNITSHIFT     6
31329088Smarkm#define RAW_PART        2
31429088Smarkm
31529088Smarkm/*
31629088Smarkm * Attempt to find the device from which we were booted.
31729088Smarkm * If we can do so, and not instructed not to do so,
31829088Smarkm * change rootdev to correspond to the load device.
31929088Smarkm */
32029088Smarkmstatic void
32129088Smarkmsetroot()
32229088Smarkm{
32329088Smarkm	int  majdev, mindev, unit, part, adaptor;
32429088Smarkm	dev_t orootdev;
32529088Smarkm
32629088Smarkm/*printf("howto %x bootdev %x ", boothowto, bootdev);*/
32729088Smarkm	if (boothowto & RB_DFLTROOT ||
32829088Smarkm	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
32929088Smarkm		return;
33029088Smarkm	majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
33129088Smarkm	if (majdev > sizeof(devname) / sizeof(devname[0]))
33229088Smarkm		return;
33329088Smarkm	adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
33429088Smarkm	unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
33529088Smarkm	if (majdev == FDMAJOR) {
33629088Smarkm		part = RAW_PART;
33729088Smarkm		mindev = unit << FDUNITSHIFT;
33829088Smarkm	}
33929088Smarkm	else {
34029088Smarkm		part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
34129088Smarkm		mindev = (unit << PARTITIONSHIFT) + part;
34229088Smarkm	}
34329088Smarkm	orootdev = rootdev;
34429088Smarkm	rootdev = makedev(majdev, mindev);
34529088Smarkm	/*
34629088Smarkm	 * If the original rootdev is the same as the one
34729088Smarkm	 * just calculated, don't need to adjust the swap configuration.
34829088Smarkm	 */
34929088Smarkm	if (rootdev == orootdev)
35029088Smarkm		return;
35129088Smarkm	printf("changing root device to %c%c%d%c\n",
35229088Smarkm		devname[majdev][0], devname[majdev][1],
35329088Smarkm		mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT),
35429088Smarkm		part + 'a');
35529088Smarkm}
35629088Smarkm
35729088Smarkmstatic int
35829088Smarkmsysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
35929088Smarkm{
36029088Smarkm	int error;
36129088Smarkm	dev_t ndumpdev;
36229088Smarkm
36329088Smarkm	ndumpdev = dumpdev;
36429088Smarkm	error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req);
36529088Smarkm	if (!error && ndumpdev != dumpdev) {
36629088Smarkm		error = setdumpdev(ndumpdev);
36729088Smarkm	}
36829088Smarkm	return (error);
36929088Smarkm}
37029088Smarkm
37129088SmarkmSYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
37229088Smarkm	0, sizeof dumpdev, sysctl_kern_dumpdev, "I", "");
37329088Smarkm