autoconf.c revision 25172
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
3725172Speter *	$Id: autoconf.c,v 1.65 1997/04/26 11:45:02 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>
6425164Speter#if defined(APIC_IO)
6525164Speter#include <machine/smp.h>
6625164Speter#endif /* APIC_IO */
6725172Speter#include <i386/isa/icu.h> /* For interrupts */
6825164Speter
6912604Sbde#include "isa.h"
7012604Sbde#if NISA > 0
7112604Sbde#include <i386/isa/isa_device.h>
7212604Sbde#endif
7310665Sbde
7412604Sbde#include "eisa.h"
7512604Sbde#if NEISA > 0
7612604Sbde#include <i386/eisa/eisaconf.h>
7712604Sbde#endif
7810665Sbde
7912604Sbde#include "pci.h"
8012604Sbde#if NPCI > 0
8112604Sbde#include <pci/pcivar.h>
8212604Sbde#endif
83798Swollman
8412604Sbde#include "crd.h"
8512604Sbde#if NCRD > 0
8612604Sbde#include <pccard/driver.h>
8712604Sbde#endif
884Srgrimes
8912604Sbde#include "scbus.h"
9012604Sbde#if NSCBUS > 0
9112604Sbde#include <scsi/scsiconf.h>
9212604Sbde#endif
9312604Sbde
9412604Sbdestatic void	configure __P((void *));
9512604SbdeSYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL)
9612604Sbde
9712848Sbdestatic void	configure_finish __P((void));
9812848Sbdestatic void	configure_start __P((void));
9912848Sbdestatic int	setdumpdev __P((dev_t dev));
10012848Sbdestatic void	setroot __P((void));
10112848Sbde
1028007Sphk#ifdef CD9660
10322521Sdyson
10422521Sdyson#include <isofs/cd9660/iso.h>
10522521Sdyson
1067731Sphk/* We need to try out all our potential CDROM drives, so we need a table. */
1077731Sphkstatic struct {
1087731Sphk	char *name;
1097731Sphk	int major;
1107731Sphk} try_cdrom[] = {
1117731Sphk	{ "cd", 6 },
1127731Sphk	{ "mcd", 7 },
1137731Sphk	{ "scd", 16 },
1147731Sphk	{ "matcd", 17 },
1157731Sphk	{ 0, 0}
1167731Sphk};
1177731Sphk
11812604Sbdestatic int	find_cdrom_root __P((void *));
11912604Sbde
12012604Sbdestatic int
12110653Sdgfind_cdrom_root(dummy)
12210653Sdg	void *dummy;
1237731Sphk{
1247731Sphk	int i,j,k;
1257731Sphk
1267731Sphk	for (j = 0 ; j < 2; j++)
1277731Sphk		for (k = 0 ; try_cdrom[k].name ; k++) {
1287731Sphk			rootdev = makedev(try_cdrom[k].major,j*8);
1298456Srgrimes			printf("trying rootdev=0x%lx (%s%d)\n",
1307731Sphk				rootdev, try_cdrom[k].name,j);
13122521Sdyson			i = (*cd9660_mountroot)();
1327731Sphk			if (!i) return i;
1337731Sphk		}
1347731Sphk	return EINVAL;
1357731Sphk}
1368007Sphk#endif /* CD9660 */
1377731Sphk
13812604Sbdestatic void
1397818Sdufaultconfigure_start()
1407818Sdufault{
1417818Sdufault#if NSCBUS > 0
1427818Sdufault	scsi_configure_start();
1437818Sdufault#endif
1447818Sdufault}
1457818Sdufault
14612604Sbdestatic void
1477818Sdufaultconfigure_finish()
1487818Sdufault{
1497818Sdufault#if NSCBUS > 0
1507818Sdufault	scsi_configure_finish();
1517818Sdufault#endif
1527818Sdufault}
1537818Sdufault
1544Srgrimes/*
1554Srgrimes * Determine i/o configuration for a machine.
1564Srgrimes */
15710665Sbdestatic void
15810665Sbdeconfigure(dummy)
15910653Sdg	void *dummy;
1604Srgrimes{
16120641Sbde	int i;
1624Srgrimes
1638015Sjulian	configure_start();
1648015Sjulian
16512791Sgibbs	/* Allow all routines to decide for themselves if they want intrs */
16625164Speter#if defined(APIC_IO)
16725164Speter	configure_local_apic();
16825164Speter#endif /* APIC_IO */
16925172Speter	enable_intr();
17025172Speter#if !defined(APIC_IO)
17125172Speter	INTREN(IRQ_SLAVE);
17225172Speter#endif /* !APIC_IO */
17312791Sgibbs
17412091Sgibbs#if NEISA > 0
17512091Sgibbs	eisa_configure();
17612091Sgibbs#endif
17712091Sgibbs
1782430Sse#if NPCI > 0
1792430Sse	pci_configure();
1802430Sse#endif
1812430Sse
18212791Sgibbs#if NISA > 0
18312791Sgibbs	isa_configure();
18412791Sgibbs#endif
18512791Sgibbs
18622564Sbde#if NCRD > 0
18722564Sbde	/* After everyone else has a chance at grabbing resources */
18822564Sbde	pccard_configure();
18922564Sbde#endif
19022564Sbde
19117355Sbde	if (setdumpdev(dumpdev) != 0)
19217355Sbde		dumpdev = NODEV;
19317355Sbde
1947818Sdufault	configure_finish();
1957818Sdufault
19610665Sbde	cninit_finish();
19710665Sbde
19820641Sbde	if (bootverbose) {
19920641Sbde		/*
20020641Sbde		 * Print out the BIOS's idea of the disk geometries.
20120641Sbde		 */
20220641Sbde		printf("BIOS Geometries:\n");
20320641Sbde		for (i = 0; i < N_BIOS_GEOM; i++) {
20420641Sbde			unsigned long bios_geom;
20520641Sbde			int max_cylinder, max_head, max_sector;
20620641Sbde
20720641Sbde			bios_geom = bootinfo.bi_bios_geom[i];
20820641Sbde
20920641Sbde			/*
21020641Sbde			 * XXX the bootstrap punts a 1200K floppy geometry
21120641Sbde			 * when the get-disk-geometry interrupt fails.  Skip
21220641Sbde			 * drives that have this geometry.
21320641Sbde			 */
21420641Sbde			if (bios_geom == 0x4f010f)
21520641Sbde				continue;
21620641Sbde
21720641Sbde			printf(" %x:%08lx ", i, bios_geom);
21820641Sbde			max_cylinder = bios_geom >> 16;
21920641Sbde			max_head = (bios_geom >> 8) & 0xff;
22020641Sbde			max_sector = bios_geom & 0xff;
22120641Sbde			printf(
22220641Sbde		"0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n",
22320641Sbde			       max_cylinder, max_cylinder + 1,
22420641Sbde			       max_head, max_head + 1,
22520641Sbde			       max_sector, max_sector);
22620641Sbde		}
22720641Sbde		printf(" %d accounted for\n", bootinfo.bi_n_bios_used);
22820641Sbde
22916075Sjoerg		printf("Device configuration finished.\n");
23020641Sbde	}
23116075Sjoerg
2327731Sphk#ifdef CD9660
23322521Sdyson	if ((boothowto & RB_CDROM)) {
23416075Sjoerg		if (bootverbose)
23516075Sjoerg			printf("Considering CD-ROM root f/s.\n");
23622521Sdyson		mountrootfsname = "cd9660";
23716075Sjoerg	}
2387731Sphk#endif
2398007Sphk
24012499Speter#ifdef MFS_ROOT
24122521Sdyson	if (!mountrootfsname) {
24216075Sjoerg		if (bootverbose)
24316075Sjoerg			printf("Considering MFS root f/s.\n");
24422521Sdyson		mountrootfsname = "mfs";
24512499Speter		/*
24612499Speter		 * Ignore the -a flag if this kernel isn't compiled
24712499Speter		 * with a generic root/swap configuration: if we skip
24812499Speter		 * setroot() and we aren't a generic kernel, chaos
24912499Speter		 * will ensue because setconf() will be a no-op.
25012499Speter		 * (rootdev is always initialized to NODEV in a
25112499Speter		 * generic configuration, so we test for that.)
25212499Speter		 */
25312499Speter		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
25412499Speter			setroot();
25512499Speter	}
25612499Speter#endif
25722564Sbde
25822564Sbde#ifdef NFS
25922564Sbde	if (!mountrootfsname && nfs_diskless_valid) {
26022564Sbde		if (bootverbose)
26122564Sbde			printf("Considering NFS root f/s.\n");
26222564Sbde		mountrootfsname = "nfs";
26322564Sbde	}
26422564Sbde#endif /* NFS */
26522564Sbde
2664370Sphk#ifdef FFS
26722521Sdyson	if (!mountrootfsname) {
26822521Sdyson		mountrootfsname = "ufs";
26916075Sjoerg		if (bootverbose)
27016075Sjoerg			printf("Considering FFS root f/s.\n");
2716547Swpaul		/*
2726547Swpaul		 * Ignore the -a flag if this kernel isn't compiled
2736547Swpaul		 * with a generic root/swap configuration: if we skip
2746547Swpaul		 * setroot() and we aren't a generic kernel, chaos
2756547Swpaul		 * will ensue because setconf() will be a no-op.
2766547Swpaul		 * (rootdev is always initialized to NODEV in a
2776547Swpaul		 * generic configuration, so we test for that.)
2786547Swpaul		 */
2796547Swpaul		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
2805321Sjkh			setroot();
2813795Sphk	}
2824Srgrimes#endif
28322564Sbde
28410358Sjulian#ifdef LFS
28522521Sdyson	if (!mountrootfsname) {
28616075Sjoerg		if (bootverbose)
28716075Sjoerg			printf("Considering LFS root f/s.\n");
28822521Sdyson		mountrootfsname = "lfs";
28910358Sjulian		/*
29010358Sjulian		 * Ignore the -a flag if this kernel isn't compiled
29110358Sjulian		 * with a generic root/swap configuration: if we skip
29210358Sjulian		 * setroot() and we aren't a generic kernel, chaos
29310358Sjulian		 * will ensue because setconf() will be a no-op.
29410358Sjulian		 * (rootdev is always initialized to NODEV in a
29510358Sjulian		 * generic configuration, so we test for that.)
29610358Sjulian		 */
29710358Sjulian		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
29810358Sjulian			setroot();
29910358Sjulian	}
30010358Sjulian#endif
30122564Sbde
30222521Sdyson	if (!mountrootfsname) {
3034370Sphk		panic("Nobody wants to mount my root for me");
3044370Sphk	}
30517355Sbde
3068433Swpaul	setconf();
3074Srgrimes	cold = 0;
30816075Sjoerg	if (bootverbose)
30916075Sjoerg		printf("configure() finished.\n");
3104Srgrimes}
3114Srgrimes
31212722Sphkstatic int
3138833Sdgsetdumpdev(dev)
3148833Sdg	dev_t dev;
3158481Swollman{
3168833Sdg	int maj, psize;
3178833Sdg	long newdumplo;
3188833Sdg
3198833Sdg	if (dev == NODEV) {
3208481Swollman		dumpdev = dev;
3218833Sdg		return (0);
3228481Swollman	}
3238833Sdg	maj = major(dev);
3248833Sdg	if (maj >= nblkdev)
3258833Sdg		return (ENXIO);
32612889Speter	if (bdevsw[maj] == NULL)
32712889Speter		return (ENXIO);		/* XXX is this right? */
32812813Sjulian	if (bdevsw[maj]->d_psize == NULL)
32912889Speter		return (ENXIO);		/* XXX should be ENODEV ? */
33012813Sjulian	psize = bdevsw[maj]->d_psize(dev);
3318833Sdg	if (psize == -1)
33212889Speter		return (ENXIO);		/* XXX should be ENODEV ? */
33315538Sphk	newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE;
3348833Sdg	if (newdumplo < 0)
3358833Sdg		return (ENOSPC);
3368833Sdg	dumpdev = dev;
3378833Sdg	dumplo = newdumplo;
3388833Sdg	return (0);
3398876Srgrimes}
3408481Swollman
3418833Sdgu_long	bootdev = 0;		/* not a dev_t - encoding is different */
3424Srgrimes
3434Srgrimesstatic	char devname[][2] = {
3446105Sse      {'w','d'},      /* 0 = wd */
3456105Sse      {'s','w'},      /* 1 = sw */
3461289Sache#define FDMAJOR 2
3476105Sse      {'f','d'},      /* 2 = fd */
3486105Sse      {'w','t'},      /* 3 = wt */
3496105Sse      {'s','d'},      /* 4 = sd -- new SCSI system */
3504Srgrimes};
3514Srgrimes
3524Srgrimes#define	PARTITIONMASK	0x7
3534Srgrimes#define	PARTITIONSHIFT	3
3541290Sache#define FDUNITSHIFT     6
3552400Sache#define RAW_PART        2
3564Srgrimes
3574Srgrimes/*
3584Srgrimes * Attempt to find the device from which we were booted.
3594Srgrimes * If we can do so, and not instructed not to do so,
3604Srgrimes * change rootdev to correspond to the load device.
3614Srgrimes */
362798Swollmanstatic void
3634Srgrimessetroot()
3644Srgrimes{
3654Srgrimes	int  majdev, mindev, unit, part, adaptor;
36612417Sphk	dev_t orootdev;
3674Srgrimes
3684Srgrimes/*printf("howto %x bootdev %x ", boothowto, bootdev);*/
3694Srgrimes	if (boothowto & RB_DFLTROOT ||
3704Srgrimes	    (bootdev & B_MAGICMASK) != (u_long)B_DEVMAGIC)
3714Srgrimes		return;
3724Srgrimes	majdev = (bootdev >> B_TYPESHIFT) & B_TYPEMASK;
3734Srgrimes	if (majdev > sizeof(devname) / sizeof(devname[0]))
3744Srgrimes		return;
3754Srgrimes	adaptor = (bootdev >> B_ADAPTORSHIFT) & B_ADAPTORMASK;
3764Srgrimes	unit = (bootdev >> B_UNITSHIFT) & B_UNITMASK;
3771290Sache	if (majdev == FDMAJOR) {
3782400Sache		part = RAW_PART;
3791290Sache		mindev = unit << FDUNITSHIFT;
3801290Sache	}
3811290Sache	else {
3821290Sache		part = (bootdev >> B_PARTITIONSHIFT) & B_PARTITIONMASK;
3831289Sache		mindev = (unit << PARTITIONSHIFT) + part;
3841290Sache	}
3854Srgrimes	orootdev = rootdev;
3864Srgrimes	rootdev = makedev(majdev, mindev);
3874Srgrimes	/*
3884Srgrimes	 * If the original rootdev is the same as the one
3894Srgrimes	 * just calculated, don't need to adjust the swap configuration.
3904Srgrimes	 */
3914Srgrimes	if (rootdev == orootdev)
3924Srgrimes		return;
3934Srgrimes	printf("changing root device to %c%c%d%c\n",
3944Srgrimes		devname[majdev][0], devname[majdev][1],
3951290Sache		mindev >> (majdev == FDMAJOR ? FDUNITSHIFT : PARTITIONSHIFT),
3961290Sache		part + 'a');
3974Srgrimes}
39812649Speter
39912649Speterstatic int
40012649Spetersysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
40112649Speter{
40212649Speter	int error;
40312649Speter	dev_t ndumpdev;
40412649Speter
40512649Speter	ndumpdev = dumpdev;
40612649Speter	error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req);
40717355Sbde	if (error == 0 && req->newptr != NULL)
40812649Speter		error = setdumpdev(ndumpdev);
40912649Speter	return (error);
41012649Speter}
41112649Speter
41212649SpeterSYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
41322564Sbde	0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", "");
414