autoconf.c revision 29243
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
3729243Sjmg *	$Id: autoconf.c,v 1.74 1997/07/22 20:12:32 fsmp 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 */
4825460Sjoerg#include "opt_cd9660.h"
4925164Speter
502056Swollman#include <sys/param.h>
512056Swollman#include <sys/systm.h>
522056Swollman#include <sys/conf.h>
532056Swollman#include <sys/reboot.h>
542056Swollman#include <sys/kernel.h>
5512604Sbde#include <sys/mount.h>
5612649Speter#include <sys/sysctl.h>
574Srgrimes
5820641Sbde#include <machine/bootinfo.h>
5910665Sbde#include <machine/cons.h>
607090Sbde#include <machine/md_var.h>
6127288Sfsmp#ifdef APIC_IO
6225164Speter#include <machine/smp.h>
6325164Speter#endif /* APIC_IO */
6427288Sfsmp
6525172Speter#include <i386/isa/icu.h> /* For interrupts */
6625164Speter
6712604Sbde#include "isa.h"
6812604Sbde#if NISA > 0
6912604Sbde#include <i386/isa/isa_device.h>
7012604Sbde#endif
7110665Sbde
7229243Sjmg#include "pnp.h"
7329243Sjmg#if NPNP > 0
7429243Sjmg#include <i386/isa/pnp.h>
7529243Sjmg#endif
7629243Sjmg
7712604Sbde#include "eisa.h"
7812604Sbde#if NEISA > 0
7912604Sbde#include <i386/eisa/eisaconf.h>
8012604Sbde#endif
8110665Sbde
8212604Sbde#include "pci.h"
8312604Sbde#if NPCI > 0
8412604Sbde#include <pci/pcivar.h>
8512604Sbde#endif
86798Swollman
8712604Sbde#include "crd.h"
8812604Sbde#if NCRD > 0
8912604Sbde#include <pccard/driver.h>
9012604Sbde#endif
914Srgrimes
9212604Sbde#include "scbus.h"
9312604Sbde#if NSCBUS > 0
9412604Sbde#include <scsi/scsiconf.h>
9512604Sbde#endif
9612604Sbde
9712604Sbdestatic void	configure __P((void *));
9812604SbdeSYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL)
9912604Sbde
10012848Sbdestatic void	configure_finish __P((void));
10112848Sbdestatic void	configure_start __P((void));
10212848Sbdestatic int	setdumpdev __P((dev_t dev));
10312848Sbdestatic void	setroot __P((void));
10412848Sbde
1058007Sphk#ifdef CD9660
10622521Sdyson
10725460Sjoerg#include <sys/fcntl.h>
10825460Sjoerg#include <sys/proc.h>
10925460Sjoerg#include <sys/stat.h>
11025460Sjoerg#include <machine/clock.h>
11122521Sdyson
11225460Sjoerg/*
11325460Sjoerg * XXX All this CD-ROM root stuff is fairly messy.  Ick.
11425460Sjoerg *
11525460Sjoerg * We need to try out all our potential CDROM drives, so we need a table.
11625460Sjoerg */
1177731Sphkstatic struct {
1187731Sphk	char *name;
1197731Sphk	int major;
1207731Sphk} try_cdrom[] = {
1217731Sphk	{ "cd", 6 },
1227731Sphk	{ "mcd", 7 },
1237731Sphk	{ "scd", 16 },
1247731Sphk	{ "matcd", 17 },
12525460Sjoerg	{ "wcd", 19 },
1267731Sphk	{ 0, 0}
1277731Sphk};
1287731Sphk
12925460Sjoergstatic int	find_cdrom_root __P((void));
13012604Sbde
13112604Sbdestatic int
13225460Sjoergfind_cdrom_root()
1337731Sphk{
13425460Sjoerg	int i, j, error;
13525460Sjoerg	struct bdevsw *bd;
13625460Sjoerg	dev_t orootdev;
1377731Sphk
13825460Sjoerg#if CD9660_ROOTDELAY > 0
13925460Sjoerg	DELAY(CD9660_ROOTDELAY * 1000000);
14025460Sjoerg#endif
14125460Sjoerg	orootdev = rootdev;
14225460Sjoerg	for (i = 0 ; i < 2; i++)
14325460Sjoerg		for (j = 0 ; try_cdrom[j].name ; j++) {
14425460Sjoerg			if (try_cdrom[j].major >= nblkdev)
14525460Sjoerg				continue;
14625460Sjoerg			rootdev = makedev(try_cdrom[j].major, i * 8);
14725460Sjoerg			bd = bdevsw[major(rootdev)];
14825460Sjoerg			if (bd == NULL || bd->d_open == NULL)
14925460Sjoerg				continue;
15025460Sjoerg			if (bootverbose)
15125460Sjoerg				printf("trying %s%d as rootdev (0x%x)\n",
15225460Sjoerg				       try_cdrom[j].name, i, rootdev);
15325460Sjoerg			error = (bd->d_open)(rootdev, FREAD, S_IFBLK, curproc);
15425460Sjoerg			if (error == 0) {
15525460Sjoerg				if (bd->d_close != NULL)
15625460Sjoerg					(bd->d_close)(rootdev, FREAD, S_IFBLK,
15725460Sjoerg						      curproc);
15825460Sjoerg				return 0;
15925460Sjoerg			}
1607731Sphk		}
16125460Sjoerg
16225460Sjoerg	rootdev = orootdev;
1637731Sphk	return EINVAL;
1647731Sphk}
1658007Sphk#endif /* CD9660 */
1667731Sphk
16712604Sbdestatic void
1687818Sdufaultconfigure_start()
1697818Sdufault{
1707818Sdufault#if NSCBUS > 0
1717818Sdufault	scsi_configure_start();
1727818Sdufault#endif
1737818Sdufault}
1747818Sdufault
17512604Sbdestatic void
1767818Sdufaultconfigure_finish()
1777818Sdufault{
1787818Sdufault#if NSCBUS > 0
1797818Sdufault	scsi_configure_finish();
1807818Sdufault#endif
1817818Sdufault}
1827818Sdufault
1834Srgrimes/*
1844Srgrimes * Determine i/o configuration for a machine.
1854Srgrimes */
18610665Sbdestatic void
18710665Sbdeconfigure(dummy)
18810653Sdg	void *dummy;
1894Srgrimes{
19020641Sbde	int i;
1914Srgrimes
1928015Sjulian	configure_start();
1938015Sjulian
19412791Sgibbs	/* Allow all routines to decide for themselves if they want intrs */
19527288Sfsmp#ifdef APIC_IO
19627288Sfsmp	bsp_apic_configure();
19725172Speter	enable_intr();
19827288Sfsmp#else
19927288Sfsmp	enable_intr();
20025172Speter	INTREN(IRQ_SLAVE);
20127288Sfsmp#endif /* APIC_IO */
20212791Sgibbs
20312091Sgibbs#if NEISA > 0
20412091Sgibbs	eisa_configure();
20512091Sgibbs#endif
20612091Sgibbs
2072430Sse#if NPCI > 0
2082430Sse	pci_configure();
2092430Sse#endif
2102430Sse
21129243Sjmg#if NPNP > 0
21229243Sjmg	pnp_configure();
21329243Sjmg#endif
21429243Sjmg
21512791Sgibbs#if NISA > 0
21612791Sgibbs	isa_configure();
21712791Sgibbs#endif
21812791Sgibbs
21922564Sbde#if NCRD > 0
22022564Sbde	/* After everyone else has a chance at grabbing resources */
22122564Sbde	pccard_configure();
22222564Sbde#endif
22322564Sbde
22417355Sbde	if (setdumpdev(dumpdev) != 0)
22517355Sbde		dumpdev = NODEV;
22617355Sbde
2277818Sdufault	configure_finish();
2287818Sdufault
22910665Sbde	cninit_finish();
23010665Sbde
23120641Sbde	if (bootverbose) {
23227561Sfsmp
23327561Sfsmp#ifdef APIC_IO
23427615Sfsmp		imen_dump();
23527561Sfsmp#endif /* APIC_IO */
23627561Sfsmp
23720641Sbde		/*
23820641Sbde		 * Print out the BIOS's idea of the disk geometries.
23920641Sbde		 */
24020641Sbde		printf("BIOS Geometries:\n");
24120641Sbde		for (i = 0; i < N_BIOS_GEOM; i++) {
24220641Sbde			unsigned long bios_geom;
24320641Sbde			int max_cylinder, max_head, max_sector;
24420641Sbde
24520641Sbde			bios_geom = bootinfo.bi_bios_geom[i];
24620641Sbde
24720641Sbde			/*
24820641Sbde			 * XXX the bootstrap punts a 1200K floppy geometry
24920641Sbde			 * when the get-disk-geometry interrupt fails.  Skip
25020641Sbde			 * drives that have this geometry.
25120641Sbde			 */
25220641Sbde			if (bios_geom == 0x4f010f)
25320641Sbde				continue;
25420641Sbde
25520641Sbde			printf(" %x:%08lx ", i, bios_geom);
25620641Sbde			max_cylinder = bios_geom >> 16;
25720641Sbde			max_head = (bios_geom >> 8) & 0xff;
25820641Sbde			max_sector = bios_geom & 0xff;
25920641Sbde			printf(
26020641Sbde		"0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n",
26120641Sbde			       max_cylinder, max_cylinder + 1,
26220641Sbde			       max_head, max_head + 1,
26320641Sbde			       max_sector, max_sector);
26420641Sbde		}
26520641Sbde		printf(" %d accounted for\n", bootinfo.bi_n_bios_used);
26620641Sbde
26716075Sjoerg		printf("Device configuration finished.\n");
26820641Sbde	}
26916075Sjoerg
2707731Sphk#ifdef CD9660
27122521Sdyson	if ((boothowto & RB_CDROM)) {
27216075Sjoerg		if (bootverbose)
27316075Sjoerg			printf("Considering CD-ROM root f/s.\n");
27425460Sjoerg		/* NB: find_cdrom_root() sets rootdev if successful. */
27525460Sjoerg		if (find_cdrom_root() == 0)
27625460Sjoerg			mountrootfsname = "cd9660";
27725460Sjoerg		else if (bootverbose)
27825460Sjoerg			printf("No CD-ROM available as root f/s.\n");
27916075Sjoerg	}
2807731Sphk#endif
2818007Sphk
28212499Speter#ifdef MFS_ROOT
28322521Sdyson	if (!mountrootfsname) {
28416075Sjoerg		if (bootverbose)
28516075Sjoerg			printf("Considering MFS root f/s.\n");
28622521Sdyson		mountrootfsname = "mfs";
28712499Speter		/*
28812499Speter		 * Ignore the -a flag if this kernel isn't compiled
28912499Speter		 * with a generic root/swap configuration: if we skip
29012499Speter		 * setroot() and we aren't a generic kernel, chaos
29112499Speter		 * will ensue because setconf() will be a no-op.
29212499Speter		 * (rootdev is always initialized to NODEV in a
29312499Speter		 * generic configuration, so we test for that.)
29412499Speter		 */
29512499Speter		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
29612499Speter			setroot();
29712499Speter	}
29812499Speter#endif
29922564Sbde
30025723Stegge#ifdef BOOTP_NFSROOT
30125723Stegge	if (!mountrootfsname && !nfs_diskless_valid) {
30225723Stegge		if (bootverbose)
30325723Stegge			printf("Considering BOOTP NFS root f/s.\n");
30425723Stegge		mountrootfsname = "nfs";
30525723Stegge	}
30625723Stegge#endif /* BOOTP_NFSROOT */
30722564Sbde#ifdef NFS
30822564Sbde	if (!mountrootfsname && nfs_diskless_valid) {
30922564Sbde		if (bootverbose)
31022564Sbde			printf("Considering NFS root f/s.\n");
31122564Sbde		mountrootfsname = "nfs";
31222564Sbde	}
31322564Sbde#endif /* NFS */
31422564Sbde
3154370Sphk#ifdef FFS
31622521Sdyson	if (!mountrootfsname) {
31722521Sdyson		mountrootfsname = "ufs";
31816075Sjoerg		if (bootverbose)
31916075Sjoerg			printf("Considering FFS root f/s.\n");
3206547Swpaul		/*
3216547Swpaul		 * Ignore the -a flag if this kernel isn't compiled
3226547Swpaul		 * with a generic root/swap configuration: if we skip
3236547Swpaul		 * setroot() and we aren't a generic kernel, chaos
3246547Swpaul		 * will ensue because setconf() will be a no-op.
3256547Swpaul		 * (rootdev is always initialized to NODEV in a
3266547Swpaul		 * generic configuration, so we test for that.)
3276547Swpaul		 */
3286547Swpaul		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
3295321Sjkh			setroot();
3303795Sphk	}
3314Srgrimes#endif
33222564Sbde
33310358Sjulian#ifdef LFS
33422521Sdyson	if (!mountrootfsname) {
33516075Sjoerg		if (bootverbose)
33616075Sjoerg			printf("Considering LFS root f/s.\n");
33722521Sdyson		mountrootfsname = "lfs";
33810358Sjulian		/*
33910358Sjulian		 * Ignore the -a flag if this kernel isn't compiled
34010358Sjulian		 * with a generic root/swap configuration: if we skip
34110358Sjulian		 * setroot() and we aren't a generic kernel, chaos
34210358Sjulian		 * will ensue because setconf() will be a no-op.
34310358Sjulian		 * (rootdev is always initialized to NODEV in a
34410358Sjulian		 * generic configuration, so we test for that.)
34510358Sjulian		 */
34610358Sjulian		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
34710358Sjulian			setroot();
34810358Sjulian	}
34910358Sjulian#endif
35022564Sbde
35122521Sdyson	if (!mountrootfsname) {
3524370Sphk		panic("Nobody wants to mount my root for me");
3534370Sphk	}
35417355Sbde
3558433Swpaul	setconf();
3564Srgrimes	cold = 0;
35716075Sjoerg	if (bootverbose)
35816075Sjoerg		printf("configure() finished.\n");
3594Srgrimes}
3604Srgrimes
36112722Sphkstatic int
3628833Sdgsetdumpdev(dev)
3638833Sdg	dev_t dev;
3648481Swollman{
3658833Sdg	int maj, psize;
3668833Sdg	long newdumplo;
3678833Sdg
3688833Sdg	if (dev == NODEV) {
3698481Swollman		dumpdev = dev;
3708833Sdg		return (0);
3718481Swollman	}
3728833Sdg	maj = major(dev);
3738833Sdg	if (maj >= nblkdev)
3748833Sdg		return (ENXIO);
37512889Speter	if (bdevsw[maj] == NULL)
37612889Speter		return (ENXIO);		/* XXX is this right? */
37712813Sjulian	if (bdevsw[maj]->d_psize == NULL)
37812889Speter		return (ENXIO);		/* XXX should be ENODEV ? */
37912813Sjulian	psize = bdevsw[maj]->d_psize(dev);
3808833Sdg	if (psize == -1)
38112889Speter		return (ENXIO);		/* XXX should be ENODEV ? */
38215538Sphk	newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE;
3838833Sdg	if (newdumplo < 0)
3848833Sdg		return (ENOSPC);
3858833Sdg	dumpdev = dev;
3868833Sdg	dumplo = newdumplo;
3878833Sdg	return (0);
3888876Srgrimes}
3898481Swollman
3908833Sdgu_long	bootdev = 0;		/* not a dev_t - encoding is different */
3914Srgrimes
3924Srgrimesstatic	char devname[][2] = {
3936105Sse      {'w','d'},      /* 0 = wd */
3946105Sse      {'s','w'},      /* 1 = sw */
3951289Sache#define FDMAJOR 2
3966105Sse      {'f','d'},      /* 2 = fd */
3976105Sse      {'w','t'},      /* 3 = wt */
3986105Sse      {'s','d'},      /* 4 = sd -- new SCSI system */
3994Srgrimes};
4004Srgrimes
4014Srgrimes#define	PARTITIONMASK	0x7
4024Srgrimes#define	PARTITIONSHIFT	3
4031290Sache#define FDUNITSHIFT     6
4042400Sache#define RAW_PART        2
4054Srgrimes
4064Srgrimes/*
4074Srgrimes * Attempt to find the device from which we were booted.
4084Srgrimes * If we can do so, and not instructed not to do so,
4094Srgrimes * change rootdev to correspond to the load device.
4104Srgrimes */
411798Swollmanstatic void
4124Srgrimessetroot()
4134Srgrimes{
4144Srgrimes	int  majdev, mindev, unit, part, adaptor;
41512417Sphk	dev_t orootdev;
4164Srgrimes
4174Srgrimes/*printf("howto %x bootdev %x ", boothowto, bootdev);*/
4184Srgrimes	if (boothowto & RB_DFLTROOT ||
4194Srgrimes	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
4204Srgrimes		return;
4214Srgrimes	majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
4224Srgrimes	if (majdev > sizeof(devname) / sizeof(devname[0]))
4234Srgrimes		return;
4244Srgrimes	adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
4254Srgrimes	unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
4261290Sache	if (majdev == FDMAJOR) {
4272400Sache		part = RAW_PART;
4281290Sache		mindev = unit << FDUNITSHIFT;
4291290Sache	}
4301290Sache	else {
4311290Sache		part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
4321289Sache		mindev = (unit << PARTITIONSHIFT) + part;
4331290Sache	}
4344Srgrimes	orootdev = rootdev;
4354Srgrimes	rootdev = makedev(majdev, mindev);
4364Srgrimes	/*
4374Srgrimes	 * If the original rootdev is the same as the one
4384Srgrimes	 * just calculated, don't need to adjust the swap configuration.
4394Srgrimes	 */
4404Srgrimes	if (rootdev == orootdev)
4414Srgrimes		return;
4424Srgrimes	printf("changing root device to %c%c%d%c\n",
4434Srgrimes		devname[majdev][0], devname[majdev][1],
4441290Sache		mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT),
4451290Sache		part + 'a');
4464Srgrimes}
44712649Speter
44812649Speterstatic int
44912649Spetersysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
45012649Speter{
45112649Speter	int error;
45212649Speter	dev_t ndumpdev;
45312649Speter
45412649Speter	ndumpdev = dumpdev;
45512649Speter	error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req);
45617355Sbde	if (error == 0 && req->newptr != NULL)
45712649Speter		error = setdumpdev(ndumpdev);
45812649Speter	return (error);
45912649Speter}
46012649Speter
46112649SpeterSYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
46222564Sbde	0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", "");
463