autoconf.c revision 47444
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
3747444Sjb *	$Id: autoconf.c,v 1.122 1999/05/12 07:40:50 phk 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 */
4832358Seivind#include "opt_bootp.h"
4932726Seivind#include "opt_ffs.h"
5025460Sjoerg#include "opt_cd9660.h"
5137272Sjmg#include "opt_nfsroot.h"
5245720Speter#include "opt_bus.h"
5346806Sphk#include "opt_rootdevname.h"
5425164Speter
552056Swollman#include <sys/param.h>
562056Swollman#include <sys/systm.h>
5745720Speter#include <sys/bus.h>
582056Swollman#include <sys/conf.h>
5931328Speter#include <sys/disklabel.h>
6036809Sbde#include <sys/diskslice.h>
612056Swollman#include <sys/reboot.h>
622056Swollman#include <sys/kernel.h>
6336809Sbde#include <sys/malloc.h>
6412604Sbde#include <sys/mount.h>
6512649Speter#include <sys/sysctl.h>
664Srgrimes
6720641Sbde#include <machine/bootinfo.h>
6810665Sbde#include <machine/cons.h>
6931337Sbde#include <machine/ipl.h>
707090Sbde#include <machine/md_var.h>
7127288Sfsmp#ifdef APIC_IO
7225164Speter#include <machine/smp.h>
7325164Speter#endif /* APIC_IO */
7427288Sfsmp
7536809Sbde#include <i386/isa/icu.h>
7625164Speter
7729243Sjmg#include "pnp.h"
7829243Sjmg#if NPNP > 0
7946600Speter#include <i386/isa/isa_device.h>
8029243Sjmg#include <i386/isa/pnp.h>
8129243Sjmg#endif
8229243Sjmg
8312604Sbde#include "eisa.h"
8412604Sbde#if NEISA > 0
8512604Sbde#include <i386/eisa/eisaconf.h>
8612604Sbde#endif
8710665Sbde
8812604Sbde#include "pci.h"
8912604Sbde#if NPCI > 0
9012604Sbde#include <pci/pcivar.h>
9112604Sbde#endif
92798Swollman
9346915Speter#include "isa.h"
9446915Speter#if NISA > 0
9546915Speterdevice_t isa_bus_device = 0;
9646915Speter#endif
9746915Speter
9842817Speterstatic void	configure_first __P((void *));
9912604Sbdestatic void	configure __P((void *));
10042817Speterstatic void	configure_final __P((void *));
10112604Sbde
10212848Sbdestatic void	configure_finish __P((void));
10312848Sbdestatic void	configure_start __P((void));
10412848Sbdestatic int	setdumpdev __P((dev_t dev));
10547444Sjb#if defined(FFS) || defined(FFS_ROOT)
10612848Sbdestatic void	setroot __P((void));
10747444Sjb#endif
10846806Sphkstatic int	setrootbyname __P((char *name));
10946806Sphkstatic void	gets __P((char *));
11012848Sbde
11142817SpeterSYSINIT(configure1, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure_first, NULL);
11242817Speter/* SI_ORDER_SECOND is hookable */
11342817SpeterSYSINIT(configure2, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL);
11442817Speter/* SI_ORDER_MIDDLE is hookable */
11542817SpeterSYSINIT(configure3, SI_SUB_CONFIGURE, SI_ORDER_ANY, configure_final, NULL);
11642817Speter
11746806Sphkdev_t	rootdev = NODEV;
11846806Sphkdev_t	dumpdev = NODEV;
11942817Speter
12039982Sobrien#if defined(CD9660) || defined(CD9660_ROOT)
12122521Sdyson
12225460Sjoerg#include <sys/fcntl.h>
12325460Sjoerg#include <sys/proc.h>
12425460Sjoerg#include <sys/stat.h>
12525460Sjoerg#include <machine/clock.h>
12622521Sdyson
12725460Sjoerg/*
12825460Sjoerg * XXX All this CD-ROM root stuff is fairly messy.  Ick.
12925460Sjoerg *
13025460Sjoerg * We need to try out all our potential CDROM drives, so we need a table.
13125460Sjoerg */
1327731Sphkstatic struct {
1337731Sphk	char *name;
1347731Sphk	int major;
1357731Sphk} try_cdrom[] = {
1367731Sphk	{ "cd", 6 },
1377731Sphk	{ "mcd", 7 },
1387731Sphk	{ "scd", 16 },
1397731Sphk	{ "matcd", 17 },
14025460Sjoerg	{ "wcd", 19 },
1417731Sphk	{ 0, 0}
1427731Sphk};
1437731Sphk
14425460Sjoergstatic int	find_cdrom_root __P((void));
14512604Sbde
14612604Sbdestatic int
14725460Sjoergfind_cdrom_root()
1487731Sphk{
14925460Sjoerg	int i, j, error;
15037389Sjulian	struct cdevsw *bd;
15125460Sjoerg	dev_t orootdev;
1527731Sphk
15325460Sjoerg#if CD9660_ROOTDELAY > 0
15425460Sjoerg	DELAY(CD9660_ROOTDELAY * 1000000);
15525460Sjoerg#endif
15625460Sjoerg	orootdev = rootdev;
15725460Sjoerg	for (i = 0 ; i < 2; i++)
15825460Sjoerg		for (j = 0 ; try_cdrom[j].name ; j++) {
15925460Sjoerg			if (try_cdrom[j].major >= nblkdev)
16025460Sjoerg				continue;
16125460Sjoerg			rootdev = makedev(try_cdrom[j].major, i * 8);
16246676Sphk			bd = bdevsw(rootdev);
16325460Sjoerg			if (bd == NULL || bd->d_open == NULL)
16425460Sjoerg				continue;
16525460Sjoerg			if (bootverbose)
16625460Sjoerg				printf("trying %s%d as rootdev (0x%x)\n",
16725460Sjoerg				       try_cdrom[j].name, i, rootdev);
16825460Sjoerg			error = (bd->d_open)(rootdev, FREAD, S_IFBLK, curproc);
16925460Sjoerg			if (error == 0) {
17025460Sjoerg				if (bd->d_close != NULL)
17125460Sjoerg					(bd->d_close)(rootdev, FREAD, S_IFBLK,
17225460Sjoerg						      curproc);
17325460Sjoerg				return 0;
17425460Sjoerg			}
1757731Sphk		}
17625460Sjoerg
17725460Sjoerg	rootdev = orootdev;
1787731Sphk	return EINVAL;
1797731Sphk}
18039982Sobrien#endif /* CD9660 || CD9660_ROOT */
1817731Sphk
18212604Sbdestatic void
1837818Sdufaultconfigure_start()
1847818Sdufault{
1857818Sdufault}
1867818Sdufault
18712604Sbdestatic void
1887818Sdufaultconfigure_finish()
1897818Sdufault{
1907818Sdufault}
1917818Sdufault
19245720Speterdevice_t nexus_dev;
19345720Speter
1944Srgrimes/*
1954Srgrimes * Determine i/o configuration for a machine.
1964Srgrimes */
19710665Sbdestatic void
19842817Speterconfigure_first(dummy)
19942817Speter	void *dummy;
20042817Speter{
20142817Speter
20242817Speter	configure_start();		/* DDB hook? */
20342817Speter}
20442817Speter
20542817Speterstatic void
20610665Sbdeconfigure(dummy)
20710653Sdg	void *dummy;
2084Srgrimes{
2094Srgrimes
21012791Sgibbs	/* Allow all routines to decide for themselves if they want intrs */
21129675Sgibbs	/*
21229675Sgibbs	 * XXX Since this cannot be achieved on all architectures, we should
21329675Sgibbs	 * XXX go back to disabling all interrupts until configuration is
21429675Sgibbs	 * XXX completed and switch any devices that rely on the current
21529675Sgibbs	 * XXX behavior to no longer rely on interrupts or to register an
21629675Sgibbs	 * XXX interrupt_driven_config_hook for the task.
21729675Sgibbs	 */
21831336Sbde	/*
21931336Sbde	 * XXX The above is wrong, because we're implicitly at splhigh(),
22031336Sbde	 * XXX and should stay there, so enabling interrupts in the CPU
22131336Sbde	 * XXX and the ICU at most gives pending interrupts which just get
22231336Sbde	 * XXX in the way.
22331336Sbde	 */
22427288Sfsmp#ifdef APIC_IO
22527288Sfsmp	bsp_apic_configure();
22625172Speter	enable_intr();
22727288Sfsmp#else
22827288Sfsmp	enable_intr();
22925172Speter	INTREN(IRQ_SLAVE);
23027288Sfsmp#endif /* APIC_IO */
23112791Sgibbs
23229243Sjmg#if NPNP > 0
23329243Sjmg	pnp_configure();
23429243Sjmg#endif
23529243Sjmg
23645720Speter	/* nexus0 is the top of the i386 device tree */
23745720Speter	device_add_child(root_bus, "nexus", 0, 0);
23812791Sgibbs
23938779Snsouch	/* initialize new bus architecture */
24038779Snsouch	root_bus_configure();
24138779Snsouch
24245720Speter#if NISA > 0
24345720Speter	if (isa_bus_device)
24445720Speter		bus_generic_attach(isa_bus_device);
24545720Speter#endif
24645720Speter
24731336Sbde	/*
24831336Sbde	 * Now we're ready to handle (pending) interrupts.
24931336Sbde	 * XXX this is slightly misplaced.
25031336Sbde	 */
25131336Sbde	spl0();
25231336Sbde
25331337Sbde	/*
25431337Sbde	 * Allow lowering of the ipl to the lowest kernel level if we
25531337Sbde	 * panic (or call tsleep() before clearing `cold').  No level is
25631337Sbde	 * completely safe (since a panic may occur in a critical region
25731337Sbde	 * at splhigh()), but we want at least bio interrupts to work.
25831337Sbde	 */
25931337Sbde	safepri = cpl;
26042817Speter}
26131337Sbde
26242817Speterstatic void
26342817Speterconfigure_final(dummy)
26442817Speter	void *dummy;
26542817Speter{
26642817Speter	int i;
26722564Sbde
26842817Speter	configure_finish();			/* DDB hook? */
2697818Sdufault
27010665Sbde	cninit_finish();
27110665Sbde
27220641Sbde	if (bootverbose) {
27327561Sfsmp
27427561Sfsmp#ifdef APIC_IO
27527615Sfsmp		imen_dump();
27627561Sfsmp#endif /* APIC_IO */
27727561Sfsmp
27820641Sbde		/*
27920641Sbde		 * Print out the BIOS's idea of the disk geometries.
28020641Sbde		 */
28120641Sbde		printf("BIOS Geometries:\n");
28220641Sbde		for (i = 0; i < N_BIOS_GEOM; i++) {
28320641Sbde			unsigned long bios_geom;
28420641Sbde			int max_cylinder, max_head, max_sector;
28520641Sbde
28620641Sbde			bios_geom = bootinfo.bi_bios_geom[i];
28720641Sbde
28820641Sbde			/*
28920641Sbde			 * XXX the bootstrap punts a 1200K floppy geometry
29020641Sbde			 * when the get-disk-geometry interrupt fails.  Skip
29120641Sbde			 * drives that have this geometry.
29220641Sbde			 */
29320641Sbde			if (bios_geom == 0x4f010f)
29420641Sbde				continue;
29520641Sbde
29620641Sbde			printf(" %x:%08lx ", i, bios_geom);
29720641Sbde			max_cylinder = bios_geom >> 16;
29820641Sbde			max_head = (bios_geom >> 8) & 0xff;
29920641Sbde			max_sector = bios_geom & 0xff;
30020641Sbde			printf(
30120641Sbde		"0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n",
30220641Sbde			       max_cylinder, max_cylinder + 1,
30320641Sbde			       max_head, max_head + 1,
30420641Sbde			       max_sector, max_sector);
30520641Sbde		}
30620641Sbde		printf(" %d accounted for\n", bootinfo.bi_n_bios_used);
30720641Sbde
30816075Sjoerg		printf("Device configuration finished.\n");
30920641Sbde	}
31029675Sgibbs	cold = 0;
31129675Sgibbs}
31216075Sjoerg
31335319Sjulian
31429675Sgibbsvoid
31529675Sgibbscpu_rootconf()
31629675Sgibbs{
31729675Sgibbs	/*
31829675Sgibbs	 * XXX NetBSD has a much cleaner approach to finding root.
31929675Sgibbs	 * XXX We should adopt their code.
32029675Sgibbs	 */
32139982Sobrien#if defined(CD9660) || defined(CD9660_ROOT)
32222521Sdyson	if ((boothowto & RB_CDROM)) {
32316075Sjoerg		if (bootverbose)
32416075Sjoerg			printf("Considering CD-ROM root f/s.\n");
32525460Sjoerg		/* NB: find_cdrom_root() sets rootdev if successful. */
32625460Sjoerg		if (find_cdrom_root() == 0)
32725460Sjoerg			mountrootfsname = "cd9660";
32825460Sjoerg		else if (bootverbose)
32925460Sjoerg			printf("No CD-ROM available as root f/s.\n");
33016075Sjoerg	}
3317731Sphk#endif
3328007Sphk
33325723Stegge#ifdef BOOTP_NFSROOT
33425723Stegge	if (!mountrootfsname && !nfs_diskless_valid) {
33525723Stegge		if (bootverbose)
33625723Stegge			printf("Considering BOOTP NFS root f/s.\n");
33725723Stegge		mountrootfsname = "nfs";
33825723Stegge	}
33925723Stegge#endif /* BOOTP_NFSROOT */
34039982Sobrien#if defined(NFS) || defined(NFS_ROOT)
34122564Sbde	if (!mountrootfsname && nfs_diskless_valid) {
34222564Sbde		if (bootverbose)
34322564Sbde			printf("Considering NFS root f/s.\n");
34422564Sbde		mountrootfsname = "nfs";
34522564Sbde	}
34622564Sbde#endif /* NFS */
34722564Sbde
34839982Sobrien#if defined(FFS) || defined(FFS_ROOT)
34922521Sdyson	if (!mountrootfsname) {
35022521Sdyson		mountrootfsname = "ufs";
35116075Sjoerg		if (bootverbose)
35216075Sjoerg			printf("Considering FFS root f/s.\n");
35345703Sbde		if (boothowto & RB_ASKNAME)
35445703Sbde			setconf();
35545703Sbde		else
3565321Sjkh			setroot();
3573795Sphk	}
3584Srgrimes#endif
35922564Sbde
36022521Sdyson	if (!mountrootfsname) {
3614370Sphk		panic("Nobody wants to mount my root for me");
3624370Sphk	}
36329675Sgibbs}
36417355Sbde
36535319Sjulian
36629675Sgibbsvoid
36729675Sgibbscpu_dumpconf()
36829675Sgibbs{
36929675Sgibbs	if (setdumpdev(dumpdev) != 0)
37029675Sgibbs		dumpdev = NODEV;
3714Srgrimes}
3724Srgrimes
37312722Sphkstatic int
3748833Sdgsetdumpdev(dev)
3758833Sdg	dev_t dev;
3768481Swollman{
3778833Sdg	int maj, psize;
3788833Sdg	long newdumplo;
3798833Sdg
3808833Sdg	if (dev == NODEV) {
3818481Swollman		dumpdev = dev;
3828833Sdg		return (0);
3838481Swollman	}
3848833Sdg	maj = major(dev);
38546773Sphk	if (maj >= nblkdev || bdevsw(dev) == NULL)
38612889Speter		return (ENXIO);		/* XXX is this right? */
38746773Sphk	if (bdevsw(dev)->d_psize == NULL)
38812889Speter		return (ENXIO);		/* XXX should be ENODEV ? */
38946773Sphk	psize = bdevsw(dev)->d_psize(dev);
3908833Sdg	if (psize == -1)
39112889Speter		return (ENXIO);		/* XXX should be ENODEV ? */
39231316Sbde	/*
39331316Sbde	 * XXX should clean up checking in dumpsys() to be more like this,
39431316Sbde	 * and nuke dodump sysctl (too many knobs), and move this to
39531316Sbde	 * kern_shutdown.c...
39631316Sbde	 */
39715538Sphk	newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE;
3988833Sdg	if (newdumplo < 0)
3998833Sdg		return (ENOSPC);
4008833Sdg	dumpdev = dev;
4018833Sdg	dumplo = newdumplo;
4028833Sdg	return (0);
4038876Srgrimes}
4048481Swollman
40535319Sjulian
4068833Sdgu_long	bootdev = 0;		/* not a dev_t - encoding is different */
4074Srgrimes
4081289Sache#define FDMAJOR 2
4091290Sache#define FDUNITSHIFT     6
4104Srgrimes
41147444Sjb#if defined(FFS) || defined(FFS_ROOT)
4124Srgrimes/*
4134Srgrimes * Attempt to find the device from which we were booted.
4144Srgrimes * If we can do so, and not instructed not to do so,
41536809Sbde * set rootdevs[] and rootdevnames[] to correspond to the
41636809Sbde * boot device(s).
4174Srgrimes */
418798Swollmanstatic void
4194Srgrimessetroot()
4204Srgrimes{
42136809Sbde	int majdev, mindev, unit, slice, part;
42246773Sphk	dev_t newrootdev, dev;
42336809Sbde	char partname[2];
42436809Sbde	char *sname;
4254Srgrimes
42646806Sphk	if (boothowto & RB_DFLTROOT) {
42746808Sphk#ifdef ROOTDEVNAME
42846806Sphk		setrootbyname(ROOTDEVNAME);
42946808Sphk#else
43046808Sphk		setconf();
43146808Sphk#endif
4324Srgrimes		return;
43346806Sphk	}
43446806Sphk	if ((bootdev & B_MAGICMASK) != B_DEVMAGIC)
43546806Sphk		return;
43636809Sbde	majdev = B_TYPE(bootdev);
43746773Sphk	dev = makedev(majdev, 0);
43846773Sphk	if (majdev >= nblkdev || bdevsw(dev) == NULL)
43936809Sbde		return;
44036809Sbde	unit = B_UNIT(bootdev);
44136809Sbde	slice = B_SLICE(bootdev);
44236809Sbde	if (slice == WHOLE_DISK_SLICE)
44334624Smsmith		slice = COMPATIBILITY_SLICE;
44436809Sbde	if (slice < 0 || slice >= MAX_SLICES)
4454Srgrimes		return;
44636809Sbde
44736809Sbde	/*
44836809Sbde	 * XXX kludge for inconsistent unit numbering and lack of slice
44936809Sbde	 * support for floppies.
45036809Sbde	 */
4511290Sache	if (majdev == FDMAJOR) {
45236809Sbde		slice = COMPATIBILITY_SLICE;
4532400Sache		part = RAW_PART;
4541290Sache		mindev = unit << FDUNITSHIFT;
45536809Sbde	} else {
45636809Sbde		part = B_PARTITION(bootdev);
45734622Smsmith		mindev = dkmakeminor(unit, slice, part);
4581290Sache	}
45936809Sbde
46036809Sbde	newrootdev = makedev(majdev, mindev);
46136809Sbde	rootdevs[0] = newrootdev;
46246773Sphk	sname = dsname(bdevsw(newrootdev)->d_name, unit, slice, part, partname);
46336809Sbde	rootdevnames[0] = malloc(strlen(sname) + 2, M_DEVBUF, M_NOWAIT);
46436809Sbde	sprintf(rootdevnames[0], "%s%s", sname, partname);
46536809Sbde
4664Srgrimes	/*
46736809Sbde	 * For properly dangerously dedicated disks (ones with a historical
46836809Sbde	 * bogus partition table), the boot blocks will give slice = 4, but
46936809Sbde	 * the kernel will only provide the compatibility slice since it
47036809Sbde	 * knows that slice 4 is not a real slice.  Arrange to try mounting
47136809Sbde	 * the compatibility slice as root if mounting the slice passed by
47236809Sbde	 * the boot blocks fails.  This handles the dangerously dedicated
47336809Sbde	 * case and perhaps others.
4744Srgrimes	 */
47536809Sbde	if (slice == COMPATIBILITY_SLICE)
4764Srgrimes		return;
47736809Sbde	slice = COMPATIBILITY_SLICE;
47836809Sbde	rootdevs[1] = dkmodslice(newrootdev, slice);
47946773Sphk	sname = dsname(bdevsw(newrootdev)->d_name, unit, slice, part, partname);
48036809Sbde	rootdevnames[1] = malloc(strlen(sname) + 2, M_DEVBUF, M_NOWAIT);
48136809Sbde	sprintf(rootdevnames[1], "%s%s", sname, partname);
4824Srgrimes}
48347444Sjb#endif
48412649Speter
48535319Sjulian
48612649Speterstatic int
48712649Spetersysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
48812649Speter{
48912649Speter	int error;
49047048Sphk	udev_t ndumpdev;
49112649Speter
49247048Sphk	ndumpdev = dev2udev(dumpdev);
49312649Speter	error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req);
49417355Sbde	if (error == 0 && req->newptr != NULL)
49547048Sphk		error = setdumpdev(udev2dev(ndumpdev, 1));
49612649Speter	return (error);
49712649Speter}
49812649Speter
49912649SpeterSYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
50022564Sbde	0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", "");
50146806Sphk
50246806Sphk
50346806Sphk
50446806Sphkstatic int
50546806Sphksetrootbyname(char *name)
50646806Sphk{
50746806Sphk	char *cp;
50846806Sphk	int bd, unit, slice, part;
50946806Sphk	dev_t dev;
51046806Sphk
51146806Sphk	slice = 0;
51246806Sphk	part = 0;
51346806Sphk	cp = name;
51446806Sphk	while (cp != '\0' && (*cp < '0' || *cp > '9'))
51546806Sphk		cp++;
51646806Sphk	if (cp == name) {
51746806Sphk		printf("missing device name\n");
51846806Sphk		return(1);
51946806Sphk	}
52046806Sphk	if (*cp == '\0') {
52146806Sphk		printf("missing unit number\n");
52246806Sphk		return(1);
52346806Sphk	}
52446806Sphk	unit = *cp - '0';
52546806Sphk	*cp++ = '\0';
52646806Sphk	for (bd = 0; bd < nblkdev; bd++) {
52746806Sphk		dev = makedev(bd, 0);
52846806Sphk		if (bdevsw(dev) != NULL &&
52946806Sphk		    strcmp(bdevsw(dev)->d_name, name) == 0)
53046806Sphk			goto gotit;
53146806Sphk	}
53246806Sphk	return (2);
53346806Sphkgotit:
53446806Sphk	while (*cp >= '0' && *cp <= '9')
53546806Sphk		unit += 10 * unit + *cp++ - '0';
53646806Sphk	if (*cp == 's' && cp[1] >= '0' && cp[1] <= '9') {
53746806Sphk		slice = cp[1] - '0';
53846806Sphk		cp += 2;
53946806Sphk	}
54046806Sphk	if (*cp >= 'a' && *cp <= 'h') {
54146806Sphk		part = *cp - 'a';
54246806Sphk		cp++;
54346806Sphk	}
54446806Sphk	if (*cp != '\0') {
54546806Sphk		printf("junk after name\n");
54646806Sphk		return (1);
54746806Sphk	}
54846806Sphk	printf("driver=%s, unit=%d, slice=%d, part=%d\n",
54946806Sphk		name, unit, slice, part);
55046806Sphk	rootdev = makedev(bd, dkmakeminor(unit, slice, part));
55146806Sphk	return 0;
55246806Sphk}
55346806Sphk
55446806Sphkvoid
55546806Sphksetconf()
55646806Sphk{
55746806Sphk	char name[128];
55846806Sphk	int i;
55946806Sphk	dev_t dev;
56046806Sphk
56146806Sphk	for(;;) {
56246806Sphk		printf("root device? ");
56346806Sphk		gets(name);
56446806Sphk		i = setrootbyname(name);
56546806Sphk		if (!i)
56646806Sphk			return;
56746806Sphk
56846806Sphk		printf("use one of:\n");
56946806Sphk		for (i = 0; i < nblkdev; i++) {
57046806Sphk			dev = makedev(i, 0);
57146806Sphk			if (bdevsw(dev) != NULL)
57246806Sphk			    printf(" %s", bdevsw(dev)->d_name);
57346806Sphk		}
57446806Sphk		printf(" followed by a unit number...\n");
57546806Sphk	}
57646806Sphk}
57746806Sphk
57846806Sphkstatic void
57946806Sphkgets(cp)
58046806Sphk	char *cp;
58146806Sphk{
58246806Sphk	register char *lp;
58346806Sphk	register int c;
58446806Sphk
58546806Sphk	lp = cp;
58646806Sphk	for (;;) {
58746806Sphk		printf("%c", c = cngetc() & 0177);
58846806Sphk		switch (c) {
58946806Sphk		case -1:
59046806Sphk		case '\n':
59146806Sphk		case '\r':
59246806Sphk			*lp++ = '\0';
59346806Sphk			return;
59446806Sphk		case '\b':
59546806Sphk		case '\177':
59646806Sphk			if (lp > cp) {
59746806Sphk				printf(" \b");
59846806Sphk				lp--;
59946806Sphk			}
60046806Sphk			continue;
60146806Sphk		case '#':
60246806Sphk			lp--;
60346806Sphk			if (lp < cp)
60446806Sphk				lp = cp;
60546806Sphk			continue;
60646806Sphk		case '@':
60746806Sphk		case 'u' & 037:
60846806Sphk			lp = cp;
60946806Sphk			printf("%c", '\n');
61046806Sphk			continue;
61146806Sphk		default:
61246806Sphk			*lp++ = c;
61346806Sphk		}
61446806Sphk	}
61546806Sphk}
616