autoconf.c revision 25164
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
3725164Speter *	$Id: autoconf.c,v 1.64 1997/02/22 09:32:08 peter 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 */
4825164Speter#include "opt_smp.h"
4925164Speter
502056Swollman#include <sys/param.h>
512056Swollman#include <sys/systm.h>
522056Swollman#include <sys/buf.h>
532056Swollman#include <sys/conf.h>
542056Swollman#include <sys/dmap.h>
552056Swollman#include <sys/reboot.h>
562056Swollman#include <sys/kernel.h>
5712604Sbde#include <sys/mount.h>
5822521Sdyson#include <sys/vnode.h>
5912649Speter#include <sys/sysctl.h>
604Srgrimes
6120641Sbde#include <machine/bootinfo.h>
6210665Sbde#include <machine/cons.h>
637090Sbde#include <machine/md_var.h>
6412791Sgibbs#include <i386/isa/icu.h> /* For interrupts */
654Srgrimes
6625164Speter#if defined(APIC_IO)
6725164Speter#include <machine/smp.h>
6825164Speter#endif /* APIC_IO */
6925164Speter
7012604Sbde#include "isa.h"
7112604Sbde#if NISA > 0
7212604Sbde#include <i386/isa/isa_device.h>
7312604Sbde#endif
7410665Sbde
7512604Sbde#include "eisa.h"
7612604Sbde#if NEISA > 0
7712604Sbde#include <i386/eisa/eisaconf.h>
7812604Sbde#endif
7910665Sbde
8012604Sbde#include "pci.h"
8112604Sbde#if NPCI > 0
8212604Sbde#include <pci/pcivar.h>
8312604Sbde#endif
84798Swollman
8512604Sbde#include "crd.h"
8612604Sbde#if NCRD > 0
8712604Sbde#include <pccard/driver.h>
8812604Sbde#endif
894Srgrimes
9012604Sbde#include "scbus.h"
9112604Sbde#if NSCBUS > 0
9212604Sbde#include <scsi/scsiconf.h>
9312604Sbde#endif
9412604Sbde
9512604Sbdestatic void	configure __P((void *));
9612604SbdeSYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL)
9712604Sbde
9812848Sbdestatic void	configure_finish __P((void));
9912848Sbdestatic void	configure_start __P((void));
10012848Sbdestatic int	setdumpdev __P((dev_t dev));
10112848Sbdestatic void	setroot __P((void));
10212848Sbde
1038007Sphk#ifdef CD9660
10422521Sdyson
10522521Sdyson#include <isofs/cd9660/iso.h>
10622521Sdyson
1077731Sphk/* We need to try out all our potential CDROM drives, so we need a table. */
1087731Sphkstatic struct {
1097731Sphk	char *name;
1107731Sphk	int major;
1117731Sphk} try_cdrom[] = {
1127731Sphk	{ "cd", 6 },
1137731Sphk	{ "mcd", 7 },
1147731Sphk	{ "scd", 16 },
1157731Sphk	{ "matcd", 17 },
1167731Sphk	{ 0, 0}
1177731Sphk};
1187731Sphk
11912604Sbdestatic int	find_cdrom_root __P((void *));
12012604Sbde
12112604Sbdestatic int
12210653Sdgfind_cdrom_root(dummy)
12310653Sdg	void *dummy;
1247731Sphk{
1257731Sphk	int i,j,k;
1267731Sphk
1277731Sphk	for (j = 0 ; j < 2; j++)
1287731Sphk		for (k = 0 ; try_cdrom[k].name ; k++) {
1297731Sphk			rootdev = makedev(try_cdrom[k].major,j*8);
1308456Srgrimes			printf("trying rootdev=0x%lx (%s%d)\n",
1317731Sphk				rootdev, try_cdrom[k].name,j);
13222521Sdyson			i = (*cd9660_mountroot)();
1337731Sphk			if (!i) return i;
1347731Sphk		}
1357731Sphk	return EINVAL;
1367731Sphk}
1378007Sphk#endif /* CD9660 */
1387731Sphk
13912604Sbdestatic void
1407818Sdufaultconfigure_start()
1417818Sdufault{
1427818Sdufault#if NSCBUS > 0
1437818Sdufault	scsi_configure_start();
1447818Sdufault#endif
1457818Sdufault}
1467818Sdufault
14712604Sbdestatic void
1487818Sdufaultconfigure_finish()
1497818Sdufault{
1507818Sdufault#if NSCBUS > 0
1517818Sdufault	scsi_configure_finish();
1527818Sdufault#endif
1537818Sdufault}
1547818Sdufault
1554Srgrimes/*
1564Srgrimes * Determine i/o configuration for a machine.
1574Srgrimes */
15810665Sbdestatic void
15910665Sbdeconfigure(dummy)
16010653Sdg	void *dummy;
1614Srgrimes{
16220641Sbde	int i;
1634Srgrimes
1648015Sjulian	configure_start();
1658015Sjulian
16612791Sgibbs	/* Allow all routines to decide for themselves if they want intrs */
16725164Speter#if defined(APIC_IO)
16825164Speter	configure_local_apic();
16912791Sgibbs        enable_intr();
17025164Speter#else
17125164Speter        enable_intr();
17212791Sgibbs        INTREN(IRQ_SLAVE);
17325164Speter#endif /* APIC_IO */
17412791Sgibbs
17525164Speter#if NCRD > 0
17625164Speter	/* Before isa_configure to avoid ISA drivers finding our cards */
17725164Speter	pccard_configure();
17825164Speter#endif
17925164Speter
18012091Sgibbs#if NEISA > 0
18112091Sgibbs	eisa_configure();
18212091Sgibbs#endif
18312091Sgibbs
1842430Sse#if NPCI > 0
1852430Sse	pci_configure();
1862430Sse#endif
1872430Sse
18812791Sgibbs#if NISA > 0
18912791Sgibbs	isa_configure();
19012791Sgibbs#endif
19112791Sgibbs
19222564Sbde#if NCRD > 0
19322564Sbde	/* After everyone else has a chance at grabbing resources */
19422564Sbde	pccard_configure();
19522564Sbde#endif
19622564Sbde
19717355Sbde	if (setdumpdev(dumpdev) != 0)
19817355Sbde		dumpdev = NODEV;
19917355Sbde
2007818Sdufault	configure_finish();
2017818Sdufault
20210665Sbde	cninit_finish();
20310665Sbde
20420641Sbde	if (bootverbose) {
20520641Sbde		/*
20620641Sbde		 * Print out the BIOS's idea of the disk geometries.
20720641Sbde		 */
20820641Sbde		printf("BIOS Geometries:\n");
20920641Sbde		for (i = 0; i < N_BIOS_GEOM; i++) {
21020641Sbde			unsigned long bios_geom;
21120641Sbde			int max_cylinder, max_head, max_sector;
21220641Sbde
21320641Sbde			bios_geom = bootinfo.bi_bios_geom[i];
21420641Sbde
21520641Sbde			/*
21620641Sbde			 * XXX the bootstrap punts a 1200K floppy geometry
21720641Sbde			 * when the get-disk-geometry interrupt fails.  Skip
21820641Sbde			 * drives that have this geometry.
21920641Sbde			 */
22020641Sbde			if (bios_geom == 0x4f010f)
22120641Sbde				continue;
22220641Sbde
22320641Sbde			printf(" %x:%08lx ", i, bios_geom);
22420641Sbde			max_cylinder = bios_geom >> 16;
22520641Sbde			max_head = (bios_geom >> 8) & 0xff;
22620641Sbde			max_sector = bios_geom & 0xff;
22720641Sbde			printf(
22820641Sbde		"0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n",
22920641Sbde			       max_cylinder, max_cylinder + 1,
23020641Sbde			       max_head, max_head + 1,
23120641Sbde			       max_sector, max_sector);
23220641Sbde		}
23320641Sbde		printf(" %d accounted for\n", bootinfo.bi_n_bios_used);
23420641Sbde
23516075Sjoerg		printf("Device configuration finished.\n");
23620641Sbde	}
23716075Sjoerg
2387731Sphk#ifdef CD9660
23922521Sdyson	if ((boothowto & RB_CDROM)) {
24016075Sjoerg		if (bootverbose)
24116075Sjoerg			printf("Considering CD-ROM root f/s.\n");
24222521Sdyson		mountrootfsname = "cd9660";
24316075Sjoerg	}
2447731Sphk#endif
2458007Sphk
24612499Speter#ifdef MFS_ROOT
24722521Sdyson	if (!mountrootfsname) {
24816075Sjoerg		if (bootverbose)
24916075Sjoerg			printf("Considering MFS root f/s.\n");
25022521Sdyson		mountrootfsname = "mfs";
25112499Speter		/*
25212499Speter		 * Ignore the -a flag if this kernel isn't compiled
25312499Speter		 * with a generic root/swap configuration: if we skip
25412499Speter		 * setroot() and we aren't a generic kernel, chaos
25512499Speter		 * will ensue because setconf() will be a no-op.
25612499Speter		 * (rootdev is always initialized to NODEV in a
25712499Speter		 * generic configuration, so we test for that.)
25812499Speter		 */
25912499Speter		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
26012499Speter			setroot();
26112499Speter	}
26212499Speter#endif
26322564Sbde
26422564Sbde#ifdef NFS
26522564Sbde	if (!mountrootfsname && nfs_diskless_valid) {
26622564Sbde		if (bootverbose)
26722564Sbde			printf("Considering NFS root f/s.\n");
26822564Sbde		mountrootfsname = "nfs";
26922564Sbde	}
27022564Sbde#endif /* NFS */
27122564Sbde
2724370Sphk#ifdef FFS
27322521Sdyson	if (!mountrootfsname) {
27422521Sdyson		mountrootfsname = "ufs";
27516075Sjoerg		if (bootverbose)
27616075Sjoerg			printf("Considering FFS root f/s.\n");
2776547Swpaul		/*
2786547Swpaul		 * Ignore the -a flag if this kernel isn't compiled
2796547Swpaul		 * with a generic root/swap configuration: if we skip
2806547Swpaul		 * setroot() and we aren't a generic kernel, chaos
2816547Swpaul		 * will ensue because setconf() will be a no-op.
2826547Swpaul		 * (rootdev is always initialized to NODEV in a
2836547Swpaul		 * generic configuration, so we test for that.)
2846547Swpaul		 */
2856547Swpaul		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
2865321Sjkh			setroot();
2873795Sphk	}
2884Srgrimes#endif
28922564Sbde
29010358Sjulian#ifdef LFS
29122521Sdyson	if (!mountrootfsname) {
29216075Sjoerg		if (bootverbose)
29316075Sjoerg			printf("Considering LFS root f/s.\n");
29422521Sdyson		mountrootfsname = "lfs";
29510358Sjulian		/*
29610358Sjulian		 * Ignore the -a flag if this kernel isn't compiled
29710358Sjulian		 * with a generic root/swap configuration: if we skip
29810358Sjulian		 * setroot() and we aren't a generic kernel, chaos
29910358Sjulian		 * will ensue because setconf() will be a no-op.
30010358Sjulian		 * (rootdev is always initialized to NODEV in a
30110358Sjulian		 * generic configuration, so we test for that.)
30210358Sjulian		 */
30310358Sjulian		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
30410358Sjulian			setroot();
30510358Sjulian	}
30610358Sjulian#endif
30722564Sbde
30822521Sdyson	if (!mountrootfsname) {
3094370Sphk		panic("Nobody wants to mount my root for me");
3104370Sphk	}
31117355Sbde
3128433Swpaul	setconf();
3134Srgrimes	cold = 0;
31416075Sjoerg	if (bootverbose)
31516075Sjoerg		printf("configure() finished.\n");
3164Srgrimes}
3174Srgrimes
31812722Sphkstatic int
3198833Sdgsetdumpdev(dev)
3208833Sdg	dev_t dev;
3218481Swollman{
3228833Sdg	int maj, psize;
3238833Sdg	long newdumplo;
3248833Sdg
3258833Sdg	if (dev == NODEV) {
3268481Swollman		dumpdev = dev;
3278833Sdg		return (0);
3288481Swollman	}
3298833Sdg	maj = major(dev);
3308833Sdg	if (maj >= nblkdev)
3318833Sdg		return (ENXIO);
33212889Speter	if (bdevsw[maj] == NULL)
33312889Speter		return (ENXIO);		/* XXX is this right? */
33412813Sjulian	if (bdevsw[maj]->d_psize == NULL)
33512889Speter		return (ENXIO);		/* XXX should be ENODEV ? */
33612813Sjulian	psize = bdevsw[maj]->d_psize(dev);
3378833Sdg	if (psize == -1)
33812889Speter		return (ENXIO);		/* XXX should be ENODEV ? */
33915538Sphk	newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE;
3408833Sdg	if (newdumplo < 0)
3418833Sdg		return (ENOSPC);
3428833Sdg	dumpdev = dev;
3438833Sdg	dumplo = newdumplo;
3448833Sdg	return (0);
3458876Srgrimes}
3468481Swollman
3478833Sdgu_long	bootdev = 0;		/* not a dev_t - encoding is different */
3484Srgrimes
3494Srgrimesstatic	char devname[][2] = {
3506105Sse      {'w','d'},      /* 0 = wd */
3516105Sse      {'s','w'},      /* 1 = sw */
3521289Sache#define FDMAJOR 2
3536105Sse      {'f','d'},      /* 2 = fd */
3546105Sse      {'w','t'},      /* 3 = wt */
3556105Sse      {'s','d'},      /* 4 = sd -- new SCSI system */
3564Srgrimes};
3574Srgrimes
3584Srgrimes#define	PARTITIONMASK	0x7
3594Srgrimes#define	PARTITIONSHIFT	3
3601290Sache#define FDUNITSHIFT     6
3612400Sache#define RAW_PART        2
3624Srgrimes
3634Srgrimes/*
3644Srgrimes * Attempt to find the device from which we were booted.
3654Srgrimes * If we can do so, and not instructed not to do so,
3664Srgrimes * change rootdev to correspond to the load device.
3674Srgrimes */
368798Swollmanstatic void
3694Srgrimessetroot()
3704Srgrimes{
3714Srgrimes	int  majdev, mindev, unit, part, adaptor;
37212417Sphk	dev_t orootdev;
3734Srgrimes
3744Srgrimes/*printf("howto %x bootdev %x ", boothowto, bootdev);*/
3754Srgrimes	if (boothowto & RB_DFLTROOT ||
3764Srgrimes	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
3774Srgrimes		return;
3784Srgrimes	majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
3794Srgrimes	if (majdev > sizeof(devname) / sizeof(devname[0]))
3804Srgrimes		return;
3814Srgrimes	adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
3824Srgrimes	unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
3831290Sache	if (majdev == FDMAJOR) {
3842400Sache		part = RAW_PART;
3851290Sache		mindev = unit << FDUNITSHIFT;
3861290Sache	}
3871290Sache	else {
3881290Sache		part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
3891289Sache		mindev = (unit << PARTITIONSHIFT) + part;
3901290Sache	}
3914Srgrimes	orootdev = rootdev;
3924Srgrimes	rootdev = makedev(majdev, mindev);
3934Srgrimes	/*
3944Srgrimes	 * If the original rootdev is the same as the one
3954Srgrimes	 * just calculated, don't need to adjust the swap configuration.
3964Srgrimes	 */
3974Srgrimes	if (rootdev == orootdev)
3984Srgrimes		return;
3994Srgrimes	printf("changing root device to %c%c%d%c\n",
4004Srgrimes		devname[majdev][0], devname[majdev][1],
4011290Sache		mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT),
4021290Sache		part + 'a');
4034Srgrimes}
40412649Speter
40512649Speterstatic int
40612649Spetersysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
40712649Speter{
40812649Speter	int error;
40912649Speter	dev_t ndumpdev;
41012649Speter
41112649Speter	ndumpdev = dumpdev;
41212649Speter	error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req);
41317355Sbde	if (error == 0 && req->newptr != NULL)
41412649Speter		error = setdumpdev(ndumpdev);
41512649Speter	return (error);
41612649Speter}
41712649Speter
41812649SpeterSYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
41922564Sbde	0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", "");
420