autoconf.c revision 12848
14Srgrimes/*-
24Srgrimes * Copyright (c) 1990 The Regents of the University of California.
34Srgrimes * All rights reserved.
44Srgrimes *
54Srgrimes * This code is derived from software contributed to Berkeley by
64Srgrimes * William Jolitz.
74Srgrimes *
84Srgrimes * Redistribution and use in source and binary forms, with or without
94Srgrimes * modification, are permitted provided that the following conditions
104Srgrimes * are met:
114Srgrimes * 1. Redistributions of source code must retain the above copyright
124Srgrimes *    notice, this list of conditions and the following disclaimer.
134Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
144Srgrimes *    notice, this list of conditions and the following disclaimer in the
154Srgrimes *    documentation and/or other materials provided with the distribution.
164Srgrimes * 3. All advertising materials mentioning features or use of this software
174Srgrimes *    must display the following acknowledgement:
184Srgrimes *	This product includes software developed by the University of
194Srgrimes *	California, Berkeley and its contributors.
204Srgrimes * 4. Neither the name of the University nor the names of its contributors
214Srgrimes *    may be used to endorse or promote products derived from this software
224Srgrimes *    without specific prior written permission.
234Srgrimes *
244Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
254Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
264Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
274Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
284Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
294Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
304Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
314Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
324Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
334Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
344Srgrimes * SUCH DAMAGE.
354Srgrimes *
36620Srgrimes *	from: @(#)autoconf.c	7.1 (Berkeley) 5/9/91
3712848Sbde *	$Id: autoconf.c,v 1.49 1995/12/13 15:12:13 julian Exp $
384Srgrimes */
394Srgrimes
404Srgrimes/*
414Srgrimes * Setup the system to run on the current machine.
424Srgrimes *
438876Srgrimes * Configure() is called at boot time and initializes the vba
444Srgrimes * device tables and the memory controller monitoring.  Available
454Srgrimes * devices are determined (from possibilities mentioned in ioconf.c),
464Srgrimes * and the drivers are initialized.
474Srgrimes */
482056Swollman#include <sys/param.h>
492056Swollman#include <sys/systm.h>
502056Swollman#include <sys/buf.h>
512056Swollman#include <sys/dkstat.h>
522056Swollman#include <sys/conf.h>
532056Swollman#include <sys/dmap.h>
542056Swollman#include <sys/reboot.h>
552056Swollman#include <sys/kernel.h>
5612604Sbde#include <sys/mount.h>
5712649Speter#include <sys/sysctl.h>
584Srgrimes
5910665Sbde#include <machine/cons.h>
607090Sbde#include <machine/md_var.h>
612056Swollman#include <machine/pte.h>
6212791Sgibbs#include <i386/isa/icu.h> /* For interrupts */
634Srgrimes
6412604Sbde#include "isa.h"
6512604Sbde#if NISA > 0
6612604Sbde#include <i386/isa/isa_device.h>
6712604Sbde#endif
6810665Sbde
6912604Sbde#include "eisa.h"
7012604Sbde#if NEISA > 0
7112604Sbde#include <i386/eisa/eisaconf.h>
7212604Sbde#endif
7310665Sbde
7412604Sbde#include "pci.h"
7512604Sbde#if NPCI > 0
7612604Sbde#include <pci/pcivar.h>
7712604Sbde#endif
78798Swollman
7912604Sbde#include "crd.h"
8012604Sbde#if NCRD > 0
8112604Sbde#include <pccard/driver.h>
8212604Sbde#endif
834Srgrimes
8412604Sbde#include "scbus.h"
8512604Sbde#if NSCBUS > 0
8612604Sbde#include <scsi/scsiconf.h>
8712604Sbde#endif
8812604Sbde
8912604Sbdestatic void	configure __P((void *));
9012604SbdeSYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL)
9112604Sbde
9212499Speter#ifdef MFS_ROOT
9312499Speterextern struct vfsops	mfs_vfsops;
9412499Speter#endif
954370Sphk#ifdef FFS
9610358Sjulianextern struct vfsops	ufs_vfsops;
974370Sphk#endif
9810358Sjulian#ifdef LFS
9910358Sjulianextern struct vfsops	lfs_vfsops;
10010358Sjulian#endif
1014370Sphk#ifdef NFS
10212604Sbdeextern int	nfs_mountroot __P((void *));
1034370Sphk#endif
1047731Sphk#ifdef CD9660
10512604Sbdeextern int	cd9660_mountroot __P((void *));
1067731Sphk#endif
1078055Sphk#ifdef MSDOSFS
10812604Sbdeextern int	msdosfs_mountroot __P((void *));
1098055Sphk#endif
1104370Sphk
11112848Sbdestatic void	configure_finish __P((void));
11212848Sbdestatic void	configure_start __P((void));
11312848Sbdestatic int	setdumpdev __P((dev_t dev));
11412848Sbdestatic void	setroot __P((void));
11512848Sbde
1168007Sphk#ifdef CD9660
1177731Sphk/* We need to try out all our potential CDROM drives, so we need a table. */
1187731Sphkstatic struct {
1197731Sphk	char *name;
1207731Sphk	int major;
1217731Sphk} try_cdrom[] = {
1227731Sphk	{ "cd", 6 },
1237731Sphk	{ "mcd", 7 },
1247731Sphk	{ "scd", 16 },
1257731Sphk	{ "matcd", 17 },
1267731Sphk	{ 0, 0}
1277731Sphk};
1287731Sphk
12912604Sbdestatic int	find_cdrom_root __P((void *));
13012604Sbde
13112604Sbdestatic int
13210653Sdgfind_cdrom_root(dummy)
13310653Sdg	void *dummy;
1347731Sphk{
1357731Sphk	int i,j,k;
1367731Sphk
1377731Sphk	for (j = 0 ; j < 2; j++)
1387731Sphk		for (k = 0 ; try_cdrom[k].name ; k++) {
1397731Sphk			rootdev = makedev(try_cdrom[k].major,j*8);
1408456Srgrimes			printf("trying rootdev=0x%lx (%s%d)\n",
1417731Sphk				rootdev, try_cdrom[k].name,j);
14210665Sbde			i = (*cd9660_mountroot)((void *)NULL);
1437731Sphk			if (!i) return i;
1447731Sphk		}
1457731Sphk	return EINVAL;
1467731Sphk}
1478007Sphk#endif /* CD9660 */
1487731Sphk
14912604Sbdestatic void
1507818Sdufaultconfigure_start()
1517818Sdufault{
1527818Sdufault#if NSCBUS > 0
1537818Sdufault	scsi_configure_start();
1547818Sdufault#endif
1557818Sdufault}
1567818Sdufault
15712604Sbdestatic void
1587818Sdufaultconfigure_finish()
1597818Sdufault{
1607818Sdufault#if NSCBUS > 0
1617818Sdufault	scsi_configure_finish();
1627818Sdufault#endif
1637818Sdufault}
1647818Sdufault
1654Srgrimes/*
1664Srgrimes * Determine i/o configuration for a machine.
1674Srgrimes */
16810665Sbdestatic void
16910665Sbdeconfigure(dummy)
17010653Sdg	void *dummy;
1714Srgrimes{
1724Srgrimes
1738015Sjulian	configure_start();
1748015Sjulian
17512791Sgibbs	/* Allow all routines to decide for themselves if they want intrs */
17612791Sgibbs        enable_intr();
17712791Sgibbs        INTREN(IRQ_SLAVE);
17812791Sgibbs
17911602Sphk#if NCRD > 0
18011602Sphk	/* Before isa_configure to avoid ISA drivers finding our cards */
18111602Sphk	pccard_configure();
18211602Sphk#endif
1837818Sdufault
18412091Sgibbs#if NEISA > 0
18512091Sgibbs	eisa_configure();
18612091Sgibbs#endif
18712091Sgibbs
1882430Sse#if NPCI > 0
1892430Sse	pci_configure();
1902430Sse#endif
1912430Sse
19212791Sgibbs#if NISA > 0
19312791Sgibbs	isa_configure();
19412791Sgibbs#endif
19512791Sgibbs
1967818Sdufault	configure_finish();
1977818Sdufault
19810665Sbde	cninit_finish();
19910665Sbde
2007731Sphk#ifdef CD9660
2018007Sphk	if ((boothowto & RB_CDROM) && !mountroot)
2027731Sphk		mountroot = find_cdrom_root;
2037731Sphk#endif
2048007Sphk
2054370Sphk#ifdef NFS
2067731Sphk	if (!mountroot && nfs_diskless_valid)
2073795Sphk		mountroot = nfs_mountroot;
2084370Sphk#endif /* NFS */
2098007Sphk
21012499Speter#ifdef MFS_ROOT
21112499Speter	if (!mountroot) {
21212499Speter		mountroot = vfs_mountroot;	/* XXX goes away*/
21312499Speter		mountrootvfsops = &mfs_vfsops;
21412499Speter		/*
21512499Speter		 * Ignore the -a flag if this kernel isn't compiled
21612499Speter		 * with a generic root/swap configuration: if we skip
21712499Speter		 * setroot() and we aren't a generic kernel, chaos
21812499Speter		 * will ensue because setconf() will be a no-op.
21912499Speter		 * (rootdev is always initialized to NODEV in a
22012499Speter		 * generic configuration, so we test for that.)
22112499Speter		 */
22212499Speter		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
22312499Speter			setroot();
22412499Speter	}
22512499Speter#endif
2264370Sphk#ifdef FFS
2274370Sphk	if (!mountroot) {
22810358Sjulian		mountroot = vfs_mountroot;	/* XXX goes away*/
22910358Sjulian		mountrootvfsops = &ufs_vfsops;
2306547Swpaul		/*
2316547Swpaul		 * Ignore the -a flag if this kernel isn't compiled
2326547Swpaul		 * with a generic root/swap configuration: if we skip
2336547Swpaul		 * setroot() and we aren't a generic kernel, chaos
2346547Swpaul		 * will ensue because setconf() will be a no-op.
2356547Swpaul		 * (rootdev is always initialized to NODEV in a
2366547Swpaul		 * generic configuration, so we test for that.)
2376547Swpaul		 */
2386547Swpaul		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
2395321Sjkh			setroot();
2403795Sphk	}
2414Srgrimes#endif
24210358Sjulian#ifdef LFS
2434370Sphk	if (!mountroot) {
24410358Sjulian		mountroot = vfs_mountroot;	/* XXX goes away*/
24510358Sjulian		mountrootvfsops = &lfs_vfsops;
24610358Sjulian		/*
24710358Sjulian		 * Ignore the -a flag if this kernel isn't compiled
24810358Sjulian		 * with a generic root/swap configuration: if we skip
24910358Sjulian		 * setroot() and we aren't a generic kernel, chaos
25010358Sjulian		 * will ensue because setconf() will be a no-op.
25110358Sjulian		 * (rootdev is always initialized to NODEV in a
25210358Sjulian		 * generic configuration, so we test for that.)
25310358Sjulian		 */
25410358Sjulian		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
25510358Sjulian			setroot();
25610358Sjulian	}
25710358Sjulian#endif
25810358Sjulian	if (!mountroot) {
2594370Sphk		panic("Nobody wants to mount my root for me");
2604370Sphk	}
2614Srgrimes	/*
2624Srgrimes	 * Configure swap area and related system
2634Srgrimes	 * parameter based on device(s) used.
2644Srgrimes	 */
2658433Swpaul	setconf();
2664Srgrimes	cold = 0;
2674Srgrimes}
2684Srgrimes
26912722Sphkstatic int
2708833Sdgsetdumpdev(dev)
2718833Sdg	dev_t dev;
2728481Swollman{
2738833Sdg	int maj, psize;
2748833Sdg	long newdumplo;
2758833Sdg
2768833Sdg	if (dev == NODEV) {
2778481Swollman		dumpdev = dev;
2788481Swollman		dumplo = 0;
2798833Sdg		return (0);
2808481Swollman	}
2818833Sdg	maj = major(dev);
2828833Sdg	if (maj >= nblkdev)
2838833Sdg		return (ENXIO);
28412813Sjulian	if (bdevsw[maj]->d_psize == NULL)
2858833Sdg		return (ENXIO);		/* XXX should sometimes be ENODEV */
28612813Sjulian	psize = bdevsw[maj]->d_psize(dev);
2878833Sdg	if (psize == -1)
2888833Sdg		return (ENXIO);		/* XXX should sometimes be ENODEV */
2898833Sdg	newdumplo = psize - Maxmem * NBPG / DEV_BSIZE;
2908833Sdg	if (newdumplo < 0)
2918833Sdg		return (ENOSPC);
2928833Sdg	dumpdev = dev;
2938833Sdg	dumplo = newdumplo;
2948833Sdg	return (0);
2958876Srgrimes}
2968481Swollman
2978833Sdgu_long	bootdev = 0;		/* not a dev_t - encoding is different */
2984Srgrimes
2994Srgrimesstatic	char devname[][2] = {
3006105Sse      {'w','d'},      /* 0 = wd */
3016105Sse      {'s','w'},      /* 1 = sw */
3021289Sache#define FDMAJOR 2
3036105Sse      {'f','d'},      /* 2 = fd */
3046105Sse      {'w','t'},      /* 3 = wt */
3056105Sse      {'s','d'},      /* 4 = sd -- new SCSI system */
3064Srgrimes};
3074Srgrimes
3084Srgrimes#define	PARTITIONMASK	0x7
3094Srgrimes#define	PARTITIONSHIFT	3
3101290Sache#define FDUNITSHIFT     6
3112400Sache#define RAW_PART        2
3124Srgrimes
3134Srgrimes/*
3144Srgrimes * Attempt to find the device from which we were booted.
3154Srgrimes * If we can do so, and not instructed not to do so,
3164Srgrimes * change rootdev to correspond to the load device.
3174Srgrimes */
318798Swollmanstatic void
3194Srgrimessetroot()
3204Srgrimes{
3214Srgrimes	int  majdev, mindev, unit, part, adaptor;
32212417Sphk	dev_t orootdev;
3234Srgrimes
3244Srgrimes/*printf("howto %x bootdev %x ", boothowto, bootdev);*/
3254Srgrimes	if (boothowto & RB_DFLTROOT ||
3264Srgrimes	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
3274Srgrimes		return;
3284Srgrimes	majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
3294Srgrimes	if (majdev > sizeof(devname) / sizeof(devname[0]))
3304Srgrimes		return;
3314Srgrimes	adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
3324Srgrimes	unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
3331290Sache	if (majdev == FDMAJOR) {
3342400Sache		part = RAW_PART;
3351290Sache		mindev = unit << FDUNITSHIFT;
3361290Sache	}
3371290Sache	else {
3381290Sache		part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
3391289Sache		mindev = (unit << PARTITIONSHIFT) + part;
3401290Sache	}
3414Srgrimes	orootdev = rootdev;
3424Srgrimes	rootdev = makedev(majdev, mindev);
3434Srgrimes	/*
3444Srgrimes	 * If the original rootdev is the same as the one
3454Srgrimes	 * just calculated, don't need to adjust the swap configuration.
3464Srgrimes	 */
3474Srgrimes	if (rootdev == orootdev)
3484Srgrimes		return;
3494Srgrimes	printf("changing root device to %c%c%d%c\n",
3504Srgrimes		devname[majdev][0], devname[majdev][1],
3511290Sache		mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT),
3521290Sache		part + 'a');
3534Srgrimes}
35412649Speter
35512649Speterstatic int
35612649Spetersysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
35712649Speter{
35812649Speter	int error;
35912649Speter	dev_t ndumpdev;
36012649Speter
36112649Speter	ndumpdev = dumpdev;
36212649Speter	error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req);
36312649Speter	if (!error && ndumpdev != dumpdev) {
36412649Speter		error = setdumpdev(ndumpdev);
36512649Speter	}
36612649Speter	return (error);
36712649Speter}
36812649Speter
36912649SpeterSYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
37012649Speter	0, sizeof dumpdev, sysctl_kern_dumpdev, "I", "");
371