autoconf.c revision 25723
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
3725723Stegge *	$Id: autoconf.c,v 1.67 1997/05/04 15:24:19 joerg 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"
4925460Sjoerg#include "opt_cd9660.h"
5025164Speter
512056Swollman#include <sys/param.h>
522056Swollman#include <sys/systm.h>
532056Swollman#include <sys/buf.h>
542056Swollman#include <sys/conf.h>
552056Swollman#include <sys/dmap.h>
562056Swollman#include <sys/reboot.h>
572056Swollman#include <sys/kernel.h>
5812604Sbde#include <sys/mount.h>
5922521Sdyson#include <sys/vnode.h>
6012649Speter#include <sys/sysctl.h>
614Srgrimes
6220641Sbde#include <machine/bootinfo.h>
6310665Sbde#include <machine/cons.h>
647090Sbde#include <machine/md_var.h>
6525164Speter#if defined(APIC_IO)
6625164Speter#include <machine/smp.h>
6725164Speter#endif /* APIC_IO */
6825172Speter#include <i386/isa/icu.h> /* For interrupts */
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
10525460Sjoerg#include <sys/fcntl.h>
10625460Sjoerg#include <sys/proc.h>
10725460Sjoerg#include <sys/stat.h>
10825460Sjoerg#include <machine/clock.h>
10922521Sdyson#include <isofs/cd9660/iso.h>
11022521Sdyson
11125460Sjoerg/*
11225460Sjoerg * XXX All this CD-ROM root stuff is fairly messy.  Ick.
11325460Sjoerg *
11425460Sjoerg * We need to try out all our potential CDROM drives, so we need a table.
11525460Sjoerg */
1167731Sphkstatic struct {
1177731Sphk	char *name;
1187731Sphk	int major;
1197731Sphk} try_cdrom[] = {
1207731Sphk	{ "cd", 6 },
1217731Sphk	{ "mcd", 7 },
1227731Sphk	{ "scd", 16 },
1237731Sphk	{ "matcd", 17 },
12425460Sjoerg	{ "wcd", 19 },
1257731Sphk	{ 0, 0}
1267731Sphk};
1277731Sphk
12825460Sjoergstatic int	find_cdrom_root __P((void));
12912604Sbde
13012604Sbdestatic int
13125460Sjoergfind_cdrom_root()
1327731Sphk{
13325460Sjoerg	int i, j, error;
13425460Sjoerg	struct bdevsw *bd;
13525460Sjoerg	dev_t orootdev;
1367731Sphk
13725460Sjoerg#if CD9660_ROOTDELAY > 0
13825460Sjoerg	DELAY(CD9660_ROOTDELAY * 1000000);
13925460Sjoerg#endif
14025460Sjoerg	orootdev = rootdev;
14125460Sjoerg	for (i = 0 ; i < 2; i++)
14225460Sjoerg		for (j = 0 ; try_cdrom[j].name ; j++) {
14325460Sjoerg			if (try_cdrom[j].major >= nblkdev)
14425460Sjoerg				continue;
14525460Sjoerg			rootdev = makedev(try_cdrom[j].major, i * 8);
14625460Sjoerg			bd = bdevsw[major(rootdev)];
14725460Sjoerg			if (bd == NULL || bd->d_open == NULL)
14825460Sjoerg				continue;
14925460Sjoerg			if (bootverbose)
15025460Sjoerg				printf("trying %s%d as rootdev (0x%x)\n",
15125460Sjoerg				       try_cdrom[j].name, i, rootdev);
15225460Sjoerg			error = (bd->d_open)(rootdev, FREAD, S_IFBLK, curproc);
15325460Sjoerg			if (error == 0) {
15425460Sjoerg				if (bd->d_close != NULL)
15525460Sjoerg					(bd->d_close)(rootdev, FREAD, S_IFBLK,
15625460Sjoerg						      curproc);
15725460Sjoerg				return 0;
15825460Sjoerg			}
1597731Sphk		}
16025460Sjoerg
16125460Sjoerg	rootdev = orootdev;
1627731Sphk	return EINVAL;
1637731Sphk}
1648007Sphk#endif /* CD9660 */
1657731Sphk
16612604Sbdestatic void
1677818Sdufaultconfigure_start()
1687818Sdufault{
1697818Sdufault#if NSCBUS > 0
1707818Sdufault	scsi_configure_start();
1717818Sdufault#endif
1727818Sdufault}
1737818Sdufault
17412604Sbdestatic void
1757818Sdufaultconfigure_finish()
1767818Sdufault{
1777818Sdufault#if NSCBUS > 0
1787818Sdufault	scsi_configure_finish();
1797818Sdufault#endif
1807818Sdufault}
1817818Sdufault
1824Srgrimes/*
1834Srgrimes * Determine i/o configuration for a machine.
1844Srgrimes */
18510665Sbdestatic void
18610665Sbdeconfigure(dummy)
18710653Sdg	void *dummy;
1884Srgrimes{
18920641Sbde	int i;
1904Srgrimes
1918015Sjulian	configure_start();
1928015Sjulian
19312791Sgibbs	/* Allow all routines to decide for themselves if they want intrs */
19425164Speter#if defined(APIC_IO)
19525164Speter	configure_local_apic();
19625164Speter#endif /* APIC_IO */
19725172Speter	enable_intr();
19825172Speter#if !defined(APIC_IO)
19925172Speter	INTREN(IRQ_SLAVE);
20025172Speter#endif /* !APIC_IO */
20112791Sgibbs
20212091Sgibbs#if NEISA > 0
20312091Sgibbs	eisa_configure();
20412091Sgibbs#endif
20512091Sgibbs
2062430Sse#if NPCI > 0
2072430Sse	pci_configure();
2082430Sse#endif
2092430Sse
21012791Sgibbs#if NISA > 0
21112791Sgibbs	isa_configure();
21212791Sgibbs#endif
21312791Sgibbs
21422564Sbde#if NCRD > 0
21522564Sbde	/* After everyone else has a chance at grabbing resources */
21622564Sbde	pccard_configure();
21722564Sbde#endif
21822564Sbde
21917355Sbde	if (setdumpdev(dumpdev) != 0)
22017355Sbde		dumpdev = NODEV;
22117355Sbde
2227818Sdufault	configure_finish();
2237818Sdufault
22410665Sbde	cninit_finish();
22510665Sbde
22620641Sbde	if (bootverbose) {
22720641Sbde		/*
22820641Sbde		 * Print out the BIOS's idea of the disk geometries.
22920641Sbde		 */
23020641Sbde		printf("BIOS Geometries:\n");
23120641Sbde		for (i = 0; i < N_BIOS_GEOM; i++) {
23220641Sbde			unsigned long bios_geom;
23320641Sbde			int max_cylinder, max_head, max_sector;
23420641Sbde
23520641Sbde			bios_geom = bootinfo.bi_bios_geom[i];
23620641Sbde
23720641Sbde			/*
23820641Sbde			 * XXX the bootstrap punts a 1200K floppy geometry
23920641Sbde			 * when the get-disk-geometry interrupt fails.  Skip
24020641Sbde			 * drives that have this geometry.
24120641Sbde			 */
24220641Sbde			if (bios_geom == 0x4f010f)
24320641Sbde				continue;
24420641Sbde
24520641Sbde			printf(" %x:%08lx ", i, bios_geom);
24620641Sbde			max_cylinder = bios_geom >> 16;
24720641Sbde			max_head = (bios_geom >> 8) & 0xff;
24820641Sbde			max_sector = bios_geom & 0xff;
24920641Sbde			printf(
25020641Sbde		"0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n",
25120641Sbde			       max_cylinder, max_cylinder + 1,
25220641Sbde			       max_head, max_head + 1,
25320641Sbde			       max_sector, max_sector);
25420641Sbde		}
25520641Sbde		printf(" %d accounted for\n", bootinfo.bi_n_bios_used);
25620641Sbde
25716075Sjoerg		printf("Device configuration finished.\n");
25820641Sbde	}
25916075Sjoerg
2607731Sphk#ifdef CD9660
26122521Sdyson	if ((boothowto & RB_CDROM)) {
26216075Sjoerg		if (bootverbose)
26316075Sjoerg			printf("Considering CD-ROM root f/s.\n");
26425460Sjoerg		/* NB: find_cdrom_root() sets rootdev if successful. */
26525460Sjoerg		if (find_cdrom_root() == 0)
26625460Sjoerg			mountrootfsname = "cd9660";
26725460Sjoerg		else if (bootverbose)
26825460Sjoerg			printf("No CD-ROM available as root f/s.\n");
26916075Sjoerg	}
2707731Sphk#endif
2718007Sphk
27212499Speter#ifdef MFS_ROOT
27322521Sdyson	if (!mountrootfsname) {
27416075Sjoerg		if (bootverbose)
27516075Sjoerg			printf("Considering MFS root f/s.\n");
27622521Sdyson		mountrootfsname = "mfs";
27712499Speter		/*
27812499Speter		 * Ignore the -a flag if this kernel isn't compiled
27912499Speter		 * with a generic root/swap configuration: if we skip
28012499Speter		 * setroot() and we aren't a generic kernel, chaos
28112499Speter		 * will ensue because setconf() will be a no-op.
28212499Speter		 * (rootdev is always initialized to NODEV in a
28312499Speter		 * generic configuration, so we test for that.)
28412499Speter		 */
28512499Speter		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
28612499Speter			setroot();
28712499Speter	}
28812499Speter#endif
28922564Sbde
29025723Stegge#ifdef BOOTP_NFSROOT
29125723Stegge	if (!mountrootfsname && !nfs_diskless_valid) {
29225723Stegge		if (bootverbose)
29325723Stegge			printf("Considering BOOTP NFS root f/s.\n");
29425723Stegge		mountrootfsname = "nfs";
29525723Stegge	}
29625723Stegge#endif /* BOOTP_NFSROOT */
29722564Sbde#ifdef NFS
29822564Sbde	if (!mountrootfsname && nfs_diskless_valid) {
29922564Sbde		if (bootverbose)
30022564Sbde			printf("Considering NFS root f/s.\n");
30122564Sbde		mountrootfsname = "nfs";
30222564Sbde	}
30322564Sbde#endif /* NFS */
30422564Sbde
3054370Sphk#ifdef FFS
30622521Sdyson	if (!mountrootfsname) {
30722521Sdyson		mountrootfsname = "ufs";
30816075Sjoerg		if (bootverbose)
30916075Sjoerg			printf("Considering FFS root f/s.\n");
3106547Swpaul		/*
3116547Swpaul		 * Ignore the -a flag if this kernel isn't compiled
3126547Swpaul		 * with a generic root/swap configuration: if we skip
3136547Swpaul		 * setroot() and we aren't a generic kernel, chaos
3146547Swpaul		 * will ensue because setconf() will be a no-op.
3156547Swpaul		 * (rootdev is always initialized to NODEV in a
3166547Swpaul		 * generic configuration, so we test for that.)
3176547Swpaul		 */
3186547Swpaul		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
3195321Sjkh			setroot();
3203795Sphk	}
3214Srgrimes#endif
32222564Sbde
32310358Sjulian#ifdef LFS
32422521Sdyson	if (!mountrootfsname) {
32516075Sjoerg		if (bootverbose)
32616075Sjoerg			printf("Considering LFS root f/s.\n");
32722521Sdyson		mountrootfsname = "lfs";
32810358Sjulian		/*
32910358Sjulian		 * Ignore the -a flag if this kernel isn't compiled
33010358Sjulian		 * with a generic root/swap configuration: if we skip
33110358Sjulian		 * setroot() and we aren't a generic kernel, chaos
33210358Sjulian		 * will ensue because setconf() will be a no-op.
33310358Sjulian		 * (rootdev is always initialized to NODEV in a
33410358Sjulian		 * generic configuration, so we test for that.)
33510358Sjulian		 */
33610358Sjulian		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
33710358Sjulian			setroot();
33810358Sjulian	}
33910358Sjulian#endif
34022564Sbde
34122521Sdyson	if (!mountrootfsname) {
3424370Sphk		panic("Nobody wants to mount my root for me");
3434370Sphk	}
34417355Sbde
3458433Swpaul	setconf();
3464Srgrimes	cold = 0;
34716075Sjoerg	if (bootverbose)
34816075Sjoerg		printf("configure() finished.\n");
3494Srgrimes}
3504Srgrimes
35112722Sphkstatic int
3528833Sdgsetdumpdev(dev)
3538833Sdg	dev_t dev;
3548481Swollman{
3558833Sdg	int maj, psize;
3568833Sdg	long newdumplo;
3578833Sdg
3588833Sdg	if (dev == NODEV) {
3598481Swollman		dumpdev = dev;
3608833Sdg		return (0);
3618481Swollman	}
3628833Sdg	maj = major(dev);
3638833Sdg	if (maj >= nblkdev)
3648833Sdg		return (ENXIO);
36512889Speter	if (bdevsw[maj] == NULL)
36612889Speter		return (ENXIO);		/* XXX is this right? */
36712813Sjulian	if (bdevsw[maj]->d_psize == NULL)
36812889Speter		return (ENXIO);		/* XXX should be ENODEV ? */
36912813Sjulian	psize = bdevsw[maj]->d_psize(dev);
3708833Sdg	if (psize == -1)
37112889Speter		return (ENXIO);		/* XXX should be ENODEV ? */
37215538Sphk	newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE;
3738833Sdg	if (newdumplo < 0)
3748833Sdg		return (ENOSPC);
3758833Sdg	dumpdev = dev;
3768833Sdg	dumplo = newdumplo;
3778833Sdg	return (0);
3788876Srgrimes}
3798481Swollman
3808833Sdgu_long	bootdev = 0;		/* not a dev_t - encoding is different */
3814Srgrimes
3824Srgrimesstatic	char devname[][2] = {
3836105Sse      {'w','d'},      /* 0 = wd */
3846105Sse      {'s','w'},      /* 1 = sw */
3851289Sache#define FDMAJOR 2
3866105Sse      {'f','d'},      /* 2 = fd */
3876105Sse      {'w','t'},      /* 3 = wt */
3886105Sse      {'s','d'},      /* 4 = sd -- new SCSI system */
3894Srgrimes};
3904Srgrimes
3914Srgrimes#define	PARTITIONMASK	0x7
3924Srgrimes#define	PARTITIONSHIFT	3
3931290Sache#define FDUNITSHIFT     6
3942400Sache#define RAW_PART        2
3954Srgrimes
3964Srgrimes/*
3974Srgrimes * Attempt to find the device from which we were booted.
3984Srgrimes * If we can do so, and not instructed not to do so,
3994Srgrimes * change rootdev to correspond to the load device.
4004Srgrimes */
401798Swollmanstatic void
4024Srgrimessetroot()
4034Srgrimes{
4044Srgrimes	int  majdev, mindev, unit, part, adaptor;
40512417Sphk	dev_t orootdev;
4064Srgrimes
4074Srgrimes/*printf("howto %x bootdev %x ", boothowto, bootdev);*/
4084Srgrimes	if (boothowto & RB_DFLTROOT ||
4094Srgrimes	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
4104Srgrimes		return;
4114Srgrimes	majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
4124Srgrimes	if (majdev > sizeof(devname) / sizeof(devname[0]))
4134Srgrimes		return;
4144Srgrimes	adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
4154Srgrimes	unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
4161290Sache	if (majdev == FDMAJOR) {
4172400Sache		part = RAW_PART;
4181290Sache		mindev = unit << FDUNITSHIFT;
4191290Sache	}
4201290Sache	else {
4211290Sache		part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
4221289Sache		mindev = (unit << PARTITIONSHIFT) + part;
4231290Sache	}
4244Srgrimes	orootdev = rootdev;
4254Srgrimes	rootdev = makedev(majdev, mindev);
4264Srgrimes	/*
4274Srgrimes	 * If the original rootdev is the same as the one
4284Srgrimes	 * just calculated, don't need to adjust the swap configuration.
4294Srgrimes	 */
4304Srgrimes	if (rootdev == orootdev)
4314Srgrimes		return;
4324Srgrimes	printf("changing root device to %c%c%d%c\n",
4334Srgrimes		devname[majdev][0], devname[majdev][1],
4341290Sache		mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT),
4351290Sache		part + 'a');
4364Srgrimes}
43712649Speter
43812649Speterstatic int
43912649Spetersysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
44012649Speter{
44112649Speter	int error;
44212649Speter	dev_t ndumpdev;
44312649Speter
44412649Speter	ndumpdev = dumpdev;
44512649Speter	error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req);
44617355Sbde	if (error == 0 && req->newptr != NULL)
44712649Speter		error = setdumpdev(ndumpdev);
44812649Speter	return (error);
44912649Speter}
45012649Speter
45112649SpeterSYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
45222564Sbde	0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", "");
453