autoconf.c revision 36809
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
3736809Sbde *	$Id: autoconf.c,v 1.97 1998/05/12 17:33:58 bde 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 */
4835323Sjulian#include "opt_devfs.h" /* for SLICE */
4932358Seivind#include "opt_bootp.h"
5032726Seivind#include "opt_ffs.h"
5125460Sjoerg#include "opt_cd9660.h"
5232726Seivind#include "opt_mfs.h"
5332726Seivind#include "opt_nfs.h"
5425164Speter
552056Swollman#include <sys/param.h>
562056Swollman#include <sys/systm.h>
572056Swollman#include <sys/conf.h>
5831328Speter#include <sys/disklabel.h>
5936809Sbde#include <sys/diskslice.h>
602056Swollman#include <sys/reboot.h>
612056Swollman#include <sys/kernel.h>
6236809Sbde#include <sys/malloc.h>
6312604Sbde#include <sys/mount.h>
6412649Speter#include <sys/sysctl.h>
654Srgrimes
6620641Sbde#include <machine/bootinfo.h>
6710665Sbde#include <machine/cons.h>
6831337Sbde#include <machine/ipl.h>
697090Sbde#include <machine/md_var.h>
7027288Sfsmp#ifdef APIC_IO
7125164Speter#include <machine/smp.h>
7225164Speter#endif /* APIC_IO */
7327288Sfsmp
7436809Sbde#include <i386/isa/icu.h>
7525164Speter
7612604Sbde#include "isa.h"
7712604Sbde#if NISA > 0
7812604Sbde#include <i386/isa/isa_device.h>
7912604Sbde#endif
8010665Sbde
8129243Sjmg#include "pnp.h"
8229243Sjmg#if NPNP > 0
8329243Sjmg#include <i386/isa/pnp.h>
8429243Sjmg#endif
8529243Sjmg
8612604Sbde#include "eisa.h"
8712604Sbde#if NEISA > 0
8812604Sbde#include <i386/eisa/eisaconf.h>
8912604Sbde#endif
9010665Sbde
9112604Sbde#include "pci.h"
9212604Sbde#if NPCI > 0
9312604Sbde#include <pci/pcivar.h>
9412604Sbde#endif
95798Swollman
9630720Snate#include "card.h"
9730720Snate#if NCARD > 0
9812604Sbde#include <pccard/driver.h>
9912604Sbde#endif
1004Srgrimes
10112604Sbde#include "scbus.h"
10212604Sbde#if NSCBUS > 0
10312604Sbde#include <scsi/scsiconf.h>
10412604Sbde#endif
10512604Sbde
10612604Sbdestatic void	configure __P((void *));
10712604SbdeSYSINIT(configure, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure, NULL)
10812604Sbde
10912848Sbdestatic void	configure_finish __P((void));
11012848Sbdestatic void	configure_start __P((void));
11112848Sbdestatic int	setdumpdev __P((dev_t dev));
11235319Sjulian#ifndef	SLICE
11312848Sbdestatic void	setroot __P((void));
11412848Sbde
1158007Sphk#ifdef CD9660
11622521Sdyson
11725460Sjoerg#include <sys/fcntl.h>
11825460Sjoerg#include <sys/proc.h>
11925460Sjoerg#include <sys/stat.h>
12025460Sjoerg#include <machine/clock.h>
12122521Sdyson
12225460Sjoerg/*
12325460Sjoerg * XXX All this CD-ROM root stuff is fairly messy.  Ick.
12425460Sjoerg *
12525460Sjoerg * We need to try out all our potential CDROM drives, so we need a table.
12625460Sjoerg */
1277731Sphkstatic struct {
1287731Sphk	char *name;
1297731Sphk	int major;
1307731Sphk} try_cdrom[] = {
1317731Sphk	{ "cd", 6 },
1327731Sphk	{ "mcd", 7 },
1337731Sphk	{ "scd", 16 },
1347731Sphk	{ "matcd", 17 },
13525460Sjoerg	{ "wcd", 19 },
1367731Sphk	{ 0, 0}
1377731Sphk};
1387731Sphk
13925460Sjoergstatic int	find_cdrom_root __P((void));
14012604Sbde
14112604Sbdestatic int
14225460Sjoergfind_cdrom_root()
1437731Sphk{
14425460Sjoerg	int i, j, error;
14525460Sjoerg	struct bdevsw *bd;
14625460Sjoerg	dev_t orootdev;
1477731Sphk
14825460Sjoerg#if CD9660_ROOTDELAY > 0
14925460Sjoerg	DELAY(CD9660_ROOTDELAY * 1000000);
15025460Sjoerg#endif
15125460Sjoerg	orootdev = rootdev;
15225460Sjoerg	for (i = 0 ; i < 2; i++)
15325460Sjoerg		for (j = 0 ; try_cdrom[j].name ; j++) {
15425460Sjoerg			if (try_cdrom[j].major >= nblkdev)
15525460Sjoerg				continue;
15625460Sjoerg			rootdev = makedev(try_cdrom[j].major, i * 8);
15725460Sjoerg			bd = bdevsw[major(rootdev)];
15825460Sjoerg			if (bd == NULL || bd->d_open == NULL)
15925460Sjoerg				continue;
16025460Sjoerg			if (bootverbose)
16125460Sjoerg				printf("trying %s%d as rootdev (0x%x)\n",
16225460Sjoerg				       try_cdrom[j].name, i, rootdev);
16325460Sjoerg			error = (bd->d_open)(rootdev, FREAD, S_IFBLK, curproc);
16425460Sjoerg			if (error == 0) {
16525460Sjoerg				if (bd->d_close != NULL)
16625460Sjoerg					(bd->d_close)(rootdev, FREAD, S_IFBLK,
16725460Sjoerg						      curproc);
16825460Sjoerg				return 0;
16925460Sjoerg			}
1707731Sphk		}
17125460Sjoerg
17225460Sjoerg	rootdev = orootdev;
1737731Sphk	return EINVAL;
1747731Sphk}
1758007Sphk#endif /* CD9660 */
17635319Sjulian#endif /* !SLICE */
1777731Sphk
17812604Sbdestatic void
1797818Sdufaultconfigure_start()
1807818Sdufault{
1817818Sdufault#if NSCBUS > 0
1827818Sdufault	scsi_configure_start();
1837818Sdufault#endif
1847818Sdufault}
1857818Sdufault
18612604Sbdestatic void
1877818Sdufaultconfigure_finish()
1887818Sdufault{
1897818Sdufault#if NSCBUS > 0
1907818Sdufault	scsi_configure_finish();
1917818Sdufault#endif
1927818Sdufault}
1937818Sdufault
1944Srgrimes/*
1954Srgrimes * Determine i/o configuration for a machine.
1964Srgrimes */
19710665Sbdestatic void
19810665Sbdeconfigure(dummy)
19910653Sdg	void *dummy;
2004Srgrimes{
20120641Sbde	int i;
2024Srgrimes
2038015Sjulian	configure_start();
2048015Sjulian
20512791Sgibbs	/* Allow all routines to decide for themselves if they want intrs */
20629675Sgibbs	/*
20729675Sgibbs	 * XXX Since this cannot be achieved on all architectures, we should
20829675Sgibbs	 * XXX go back to disabling all interrupts until configuration is
20929675Sgibbs	 * XXX completed and switch any devices that rely on the current
21029675Sgibbs	 * XXX behavior to no longer rely on interrupts or to register an
21129675Sgibbs	 * XXX interrupt_driven_config_hook for the task.
21229675Sgibbs	 */
21331336Sbde	/*
21431336Sbde	 * XXX The above is wrong, because we're implicitly at splhigh(),
21531336Sbde	 * XXX and should stay there, so enabling interrupts in the CPU
21631336Sbde	 * XXX and the ICU at most gives pending interrupts which just get
21731336Sbde	 * XXX in the way.
21831336Sbde	 */
21927288Sfsmp#ifdef APIC_IO
22027288Sfsmp	bsp_apic_configure();
22125172Speter	enable_intr();
22227288Sfsmp#else
22327288Sfsmp	enable_intr();
22425172Speter	INTREN(IRQ_SLAVE);
22527288Sfsmp#endif /* APIC_IO */
22612791Sgibbs
22712091Sgibbs#if NEISA > 0
22812091Sgibbs	eisa_configure();
22912091Sgibbs#endif
23012091Sgibbs
2312430Sse#if NPCI > 0
2322430Sse	pci_configure();
2332430Sse#endif
2342430Sse
23529243Sjmg#if NPNP > 0
23629243Sjmg	pnp_configure();
23729243Sjmg#endif
23829243Sjmg
23912791Sgibbs#if NISA > 0
24012791Sgibbs	isa_configure();
24112791Sgibbs#endif
24212791Sgibbs
24331336Sbde	/*
24431336Sbde	 * Now we're ready to handle (pending) interrupts.
24531336Sbde	 * XXX this is slightly misplaced.
24631336Sbde	 */
24731336Sbde	spl0();
24831336Sbde
24931337Sbde	/*
25031337Sbde	 * Allow lowering of the ipl to the lowest kernel level if we
25131337Sbde	 * panic (or call tsleep() before clearing `cold').  No level is
25231337Sbde	 * completely safe (since a panic may occur in a critical region
25331337Sbde	 * at splhigh()), but we want at least bio interrupts to work.
25431337Sbde	 */
25531337Sbde	safepri = cpl;
25631337Sbde
25730720Snate#if NCARD > 0
25822564Sbde	/* After everyone else has a chance at grabbing resources */
25922564Sbde	pccard_configure();
26022564Sbde#endif
26122564Sbde
2627818Sdufault	configure_finish();
2637818Sdufault
26410665Sbde	cninit_finish();
26510665Sbde
26620641Sbde	if (bootverbose) {
26727561Sfsmp
26827561Sfsmp#ifdef APIC_IO
26927615Sfsmp		imen_dump();
27027561Sfsmp#endif /* APIC_IO */
27127561Sfsmp
27220641Sbde		/*
27320641Sbde		 * Print out the BIOS's idea of the disk geometries.
27420641Sbde		 */
27520641Sbde		printf("BIOS Geometries:\n");
27620641Sbde		for (i = 0; i < N_BIOS_GEOM; i++) {
27720641Sbde			unsigned long bios_geom;
27820641Sbde			int max_cylinder, max_head, max_sector;
27920641Sbde
28020641Sbde			bios_geom = bootinfo.bi_bios_geom[i];
28120641Sbde
28220641Sbde			/*
28320641Sbde			 * XXX the bootstrap punts a 1200K floppy geometry
28420641Sbde			 * when the get-disk-geometry interrupt fails.  Skip
28520641Sbde			 * drives that have this geometry.
28620641Sbde			 */
28720641Sbde			if (bios_geom == 0x4f010f)
28820641Sbde				continue;
28920641Sbde
29020641Sbde			printf(" %x:%08lx ", i, bios_geom);
29120641Sbde			max_cylinder = bios_geom >> 16;
29220641Sbde			max_head = (bios_geom >> 8) & 0xff;
29320641Sbde			max_sector = bios_geom & 0xff;
29420641Sbde			printf(
29520641Sbde		"0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n",
29620641Sbde			       max_cylinder, max_cylinder + 1,
29720641Sbde			       max_head, max_head + 1,
29820641Sbde			       max_sector, max_sector);
29920641Sbde		}
30020641Sbde		printf(" %d accounted for\n", bootinfo.bi_n_bios_used);
30120641Sbde
30216075Sjoerg		printf("Device configuration finished.\n");
30320641Sbde	}
30429675Sgibbs	cold = 0;
30529675Sgibbs}
30616075Sjoerg
30735319Sjulian#ifndef SLICE
30835319Sjulian
30929675Sgibbsvoid
31029675Sgibbscpu_rootconf()
31129675Sgibbs{
31229675Sgibbs	/*
31329675Sgibbs	 * XXX NetBSD has a much cleaner approach to finding root.
31429675Sgibbs	 * XXX We should adopt their code.
31529675Sgibbs	 */
31632726Seivind#if defined(CD9660) || defined(CD9660_ROOT)
31722521Sdyson	if ((boothowto & RB_CDROM)) {
31816075Sjoerg		if (bootverbose)
31916075Sjoerg			printf("Considering CD-ROM root f/s.\n");
32025460Sjoerg		/* NB: find_cdrom_root() sets rootdev if successful. */
32125460Sjoerg		if (find_cdrom_root() == 0)
32225460Sjoerg			mountrootfsname = "cd9660";
32325460Sjoerg		else if (bootverbose)
32425460Sjoerg			printf("No CD-ROM available as root f/s.\n");
32516075Sjoerg	}
3267731Sphk#endif
3278007Sphk
32812499Speter#ifdef MFS_ROOT
32922521Sdyson	if (!mountrootfsname) {
33016075Sjoerg		if (bootverbose)
33116075Sjoerg			printf("Considering MFS root f/s.\n");
33222521Sdyson		mountrootfsname = "mfs";
33312499Speter		/*
33412499Speter		 * Ignore the -a flag if this kernel isn't compiled
33512499Speter		 * with a generic root/swap configuration: if we skip
33612499Speter		 * setroot() and we aren't a generic kernel, chaos
33712499Speter		 * will ensue because setconf() will be a no-op.
33812499Speter		 * (rootdev is always initialized to NODEV in a
33912499Speter		 * generic configuration, so we test for that.)
34012499Speter		 */
34112499Speter		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
34212499Speter			setroot();
34312499Speter	}
34412499Speter#endif
34522564Sbde
34625723Stegge#ifdef BOOTP_NFSROOT
34725723Stegge	if (!mountrootfsname && !nfs_diskless_valid) {
34825723Stegge		if (bootverbose)
34925723Stegge			printf("Considering BOOTP NFS root f/s.\n");
35025723Stegge		mountrootfsname = "nfs";
35125723Stegge	}
35225723Stegge#endif /* BOOTP_NFSROOT */
35332726Seivind#if defined(NFS) || defined(NFS_ROOT)
35422564Sbde	if (!mountrootfsname && nfs_diskless_valid) {
35522564Sbde		if (bootverbose)
35622564Sbde			printf("Considering NFS root f/s.\n");
35722564Sbde		mountrootfsname = "nfs";
35822564Sbde	}
35922564Sbde#endif /* NFS */
36022564Sbde
36132726Seivind#if defined(FFS) || defined(FFS_ROOT)
36222521Sdyson	if (!mountrootfsname) {
36322521Sdyson		mountrootfsname = "ufs";
36416075Sjoerg		if (bootverbose)
36516075Sjoerg			printf("Considering FFS root f/s.\n");
3666547Swpaul		/*
3676547Swpaul		 * Ignore the -a flag if this kernel isn't compiled
3686547Swpaul		 * with a generic root/swap configuration: if we skip
3696547Swpaul		 * setroot() and we aren't a generic kernel, chaos
3706547Swpaul		 * will ensue because setconf() will be a no-op.
3716547Swpaul		 * (rootdev is always initialized to NODEV in a
3726547Swpaul		 * generic configuration, so we test for that.)
3736547Swpaul		 */
3746547Swpaul		if ((boothowto & RB_ASKNAME) == 0 || rootdev != NODEV)
3755321Sjkh			setroot();
3763795Sphk	}
3774Srgrimes#endif
37822564Sbde
37922521Sdyson	if (!mountrootfsname) {
3804370Sphk		panic("Nobody wants to mount my root for me");
3814370Sphk	}
38229742Sbde
38329742Sbde	setconf();
38429675Sgibbs}
38517355Sbde
38636809Sbde#endif /* !SLICE */
38735319Sjulian
38829675Sgibbsvoid
38929675Sgibbscpu_dumpconf()
39029675Sgibbs{
39129675Sgibbs	if (setdumpdev(dumpdev) != 0)
39229675Sgibbs		dumpdev = NODEV;
3934Srgrimes}
3944Srgrimes
39512722Sphkstatic int
3968833Sdgsetdumpdev(dev)
3978833Sdg	dev_t dev;
3988481Swollman{
3998833Sdg	int maj, psize;
4008833Sdg	long newdumplo;
4018833Sdg
4028833Sdg	if (dev == NODEV) {
4038481Swollman		dumpdev = dev;
4048833Sdg		return (0);
4058481Swollman	}
4068833Sdg	maj = major(dev);
4078833Sdg	if (maj >= nblkdev)
4088833Sdg		return (ENXIO);
40912889Speter	if (bdevsw[maj] == NULL)
41012889Speter		return (ENXIO);		/* XXX is this right? */
41112813Sjulian	if (bdevsw[maj]->d_psize == NULL)
41212889Speter		return (ENXIO);		/* XXX should be ENODEV ? */
41312813Sjulian	psize = bdevsw[maj]->d_psize(dev);
4148833Sdg	if (psize == -1)
41512889Speter		return (ENXIO);		/* XXX should be ENODEV ? */
41631316Sbde	/*
41731316Sbde	 * XXX should clean up checking in dumpsys() to be more like this,
41831316Sbde	 * and nuke dodump sysctl (too many knobs), and move this to
41931316Sbde	 * kern_shutdown.c...
42031316Sbde	 */
42135974Sbde	if (dkpart(dev) != SWAP_PART)
42231316Sbde		return (ENODEV);
42315538Sphk	newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE;
4248833Sdg	if (newdumplo < 0)
4258833Sdg		return (ENOSPC);
4268833Sdg	dumpdev = dev;
4278833Sdg	dumplo = newdumplo;
4288833Sdg	return (0);
4298876Srgrimes}
4308481Swollman
43135319Sjulian#ifndef SLICE
43235319Sjulian
4338833Sdgu_long	bootdev = 0;		/* not a dev_t - encoding is different */
4344Srgrimes
4351289Sache#define FDMAJOR 2
4361290Sache#define FDUNITSHIFT     6
4374Srgrimes
4384Srgrimes/*
4394Srgrimes * Attempt to find the device from which we were booted.
4404Srgrimes * If we can do so, and not instructed not to do so,
44136809Sbde * set rootdevs[] and rootdevnames[] to correspond to the
44236809Sbde * boot device(s).
4434Srgrimes */
444798Swollmanstatic void
4454Srgrimessetroot()
4464Srgrimes{
44736809Sbde	int majdev, mindev, unit, slice, part;
44836809Sbde	dev_t newrootdev;
44936809Sbde	char partname[2];
45036809Sbde	char *sname;
4514Srgrimes
45236809Sbde	if (boothowto & RB_DFLTROOT || (bootdev & B_MAGICMASK) != B_DEVMAGIC)
4534Srgrimes		return;
45436809Sbde	majdev = B_TYPE(bootdev);
45536809Sbde	if (bdevsw[majdev] == NULL)
45636809Sbde		return;
45736809Sbde	unit = B_UNIT(bootdev);
45836809Sbde	slice = B_SLICE(bootdev);
45936809Sbde	if (slice == WHOLE_DISK_SLICE)
46034624Smsmith		slice = COMPATIBILITY_SLICE;
46136809Sbde	if (slice < 0 || slice >= MAX_SLICES)
4624Srgrimes		return;
46336809Sbde
46436809Sbde	/*
46536809Sbde	 * XXX kludge for inconsistent unit numbering and lack of slice
46636809Sbde	 * support for floppies.
46736809Sbde	 */
4681290Sache	if (majdev == FDMAJOR) {
46936809Sbde		slice = COMPATIBILITY_SLICE;
4702400Sache		part = RAW_PART;
4711290Sache		mindev = unit << FDUNITSHIFT;
47236809Sbde	} else {
47336809Sbde		part = B_PARTITION(bootdev);
47434622Smsmith		mindev = dkmakeminor(unit, slice, part);
4751290Sache	}
47636809Sbde
47736809Sbde	newrootdev = makedev(majdev, mindev);
47836809Sbde	rootdevs[0] = newrootdev;
47936809Sbde	sname = dsname(bdevsw[majdev]->d_name, unit, slice, part, partname);
48036809Sbde	rootdevnames[0] = malloc(strlen(sname) + 2, M_DEVBUF, M_NOWAIT);
48136809Sbde	sprintf(rootdevnames[0], "%s%s", sname, partname);
48236809Sbde
4834Srgrimes	/*
48436809Sbde	 * For properly dangerously dedicated disks (ones with a historical
48536809Sbde	 * bogus partition table), the boot blocks will give slice = 4, but
48636809Sbde	 * the kernel will only provide the compatibility slice since it
48736809Sbde	 * knows that slice 4 is not a real slice.  Arrange to try mounting
48836809Sbde	 * the compatibility slice as root if mounting the slice passed by
48936809Sbde	 * the boot blocks fails.  This handles the dangerously dedicated
49036809Sbde	 * case and perhaps others.
4914Srgrimes	 */
49236809Sbde	if (slice == COMPATIBILITY_SLICE)
4934Srgrimes		return;
49436809Sbde	slice = COMPATIBILITY_SLICE;
49536809Sbde	rootdevs[1] = dkmodslice(newrootdev, slice);
49636809Sbde	sname = dsname(bdevsw[majdev]->d_name, unit, slice, part, partname);
49736809Sbde	rootdevnames[1] = malloc(strlen(sname) + 2, M_DEVBUF, M_NOWAIT);
49836809Sbde	sprintf(rootdevnames[1], "%s%s", sname, partname);
4994Srgrimes}
50012649Speter
50136809Sbde#endif /* !SLICE */
50235319Sjulian
50312649Speterstatic int
50412649Spetersysctl_kern_dumpdev SYSCTL_HANDLER_ARGS
50512649Speter{
50612649Speter	int error;
50712649Speter	dev_t ndumpdev;
50812649Speter
50912649Speter	ndumpdev = dumpdev;
51012649Speter	error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req);
51117355Sbde	if (error == 0 && req->newptr != NULL)
51212649Speter		error = setdumpdev(ndumpdev);
51312649Speter	return (error);
51412649Speter}
51512649Speter
51612649SpeterSYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW,
51722564Sbde	0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", "");
518