162052Smarkm/*-
262052Smarkm * Copyright (c) 2000 Mark R. V. Murray & Jeroen C. van Gelderen
3130788Smarkm * Copyright (c) 2001-2004 Mark R. V. Murray
462052Smarkm * All rights reserved.
562052Smarkm *
662052Smarkm * Redistribution and use in source and binary forms, with or without
762052Smarkm * modification, are permitted provided that the following conditions
862052Smarkm * are met:
962052Smarkm * 1. Redistributions of source code must retain the above copyright
1062052Smarkm *    notice, this list of conditions and the following disclaimer
1162052Smarkm *    in this position and unchanged.
1262052Smarkm * 2. Redistributions in binary form must reproduce the above copyright
1362052Smarkm *    notice, this list of conditions and the following disclaimer in the
1462052Smarkm *    documentation and/or other materials provided with the distribution.
1562052Smarkm *
1662052Smarkm * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
1762052Smarkm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1862052Smarkm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1962052Smarkm * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2062052Smarkm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2162052Smarkm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2262052Smarkm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2362052Smarkm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2462052Smarkm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2562052Smarkm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2662052Smarkm *
2762052Smarkm */
2862052Smarkm
29119418Sobrien#include <sys/cdefs.h>
30119418Sobrien__FBSDID("$FreeBSD$");
31119418Sobrien
3262052Smarkm#include <sys/param.h>
3362052Smarkm#include <sys/systm.h>
3462052Smarkm#include <sys/conf.h>
3562052Smarkm#include <sys/uio.h>
3662052Smarkm#include <sys/kernel.h>
3762052Smarkm#include <sys/malloc.h>
3862052Smarkm#include <sys/module.h>
39164033Srwatson#include <sys/priv.h>
4094182Sphk#include <sys/disk.h>
4162052Smarkm#include <sys/bus.h>
42229965Sgnn#include <sys/filio.h>
43221855Smdf
4462052Smarkm#include <machine/bus.h>
45221855Smdf#include <machine/vmparam.h>
4662052Smarkm
4762052Smarkm/* For use with destroy_dev(9). */
48130585Sphkstatic struct cdev *null_dev;
49130585Sphkstatic struct cdev *zero_dev;
5062052Smarkm
5162843Smarkmstatic d_write_t null_write;
5293496Sphkstatic d_ioctl_t null_ioctl;
53229965Sgnnstatic d_ioctl_t zero_ioctl;
5462843Smarkmstatic d_read_t zero_read;
5562052Smarkm
5662052Smarkmstatic struct cdevsw null_cdevsw = {
57126080Sphk	.d_version =	D_VERSION,
58121856Smarkm	.d_read =	(d_read_t *)nullop,
59111815Sphk	.d_write =	null_write,
60111815Sphk	.d_ioctl =	null_ioctl,
61111815Sphk	.d_name =	"null",
6262052Smarkm};
6362052Smarkm
6462052Smarkmstatic struct cdevsw zero_cdevsw = {
65126080Sphk	.d_version =	D_VERSION,
66111815Sphk	.d_read =	zero_read,
67111815Sphk	.d_write =	null_write,
68229965Sgnn	.d_ioctl =	zero_ioctl,
69111815Sphk	.d_name =	"zero",
70126080Sphk	.d_flags =	D_MMAP_ANON,
7162052Smarkm};
7262052Smarkm
73121189Smarkm/* ARGSUSED */
74111758Sphkstatic int
75130585Sphknull_write(struct cdev *dev __unused, struct uio *uio, int flags __unused)
7662052Smarkm{
7762052Smarkm	uio->uio_resid = 0;
78130788Smarkm
79130788Smarkm	return (0);
8062052Smarkm}
8162052Smarkm
82121189Smarkm/* ARGSUSED */
8362052Smarkmstatic int
84130585Sphknull_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data __unused,
85121189Smarkm    int flags __unused, struct thread *td)
8693496Sphk{
8793496Sphk	int error;
88229965Sgnn	error = 0;
8993496Sphk
90229965Sgnn	switch (cmd) {
91229965Sgnn	case DIOCSKERNELDUMP:
92229965Sgnn		error = priv_check(td, PRIV_SETDUMPER);
93229965Sgnn		if (error == 0)
94242439Salfred			error = set_dumper(NULL, NULL);
95229965Sgnn		break;
96229965Sgnn	case FIONBIO:
97229965Sgnn		break;
98229965Sgnn	case FIOASYNC:
99229965Sgnn		if (*(int *)data != 0)
100229965Sgnn			error = EINVAL;
101229965Sgnn		break;
102229965Sgnn	default:
103229965Sgnn		error = ENOIOCTL;
104229965Sgnn	}
105229965Sgnn	return (error);
10693496Sphk}
10793496Sphk
108111630Smarkm/* ARGSUSED */
10993496Sphkstatic int
110229965Sgnnzero_ioctl(struct cdev *dev __unused, u_long cmd, caddr_t data __unused,
111229965Sgnn	   int flags __unused, struct thread *td)
112229965Sgnn{
113229965Sgnn	int error;
114229965Sgnn	error = 0;
115229965Sgnn
116229965Sgnn	switch (cmd) {
117229965Sgnn	case FIONBIO:
118229965Sgnn		break;
119229965Sgnn	case FIOASYNC:
120229965Sgnn		if (*(int *)data != 0)
121229965Sgnn			error = EINVAL;
122229965Sgnn		break;
123229965Sgnn	default:
124229965Sgnn		error = ENOIOCTL;
125229965Sgnn	}
126229965Sgnn	return (error);
127229965Sgnn}
128229965Sgnn
129229965Sgnn
130229965Sgnn/* ARGSUSED */
131229965Sgnnstatic int
132130585Sphkzero_read(struct cdev *dev __unused, struct uio *uio, int flags __unused)
13362052Smarkm{
134221853Smdf	void *zbuf;
135221853Smdf	ssize_t len;
13662052Smarkm	int error = 0;
13762052Smarkm
138221853Smdf	KASSERT(uio->uio_rw == UIO_READ,
139221853Smdf	    ("Can't be in %s for write", __func__));
140221853Smdf	zbuf = __DECONST(void *, zero_region);
141221853Smdf	while (uio->uio_resid > 0 && error == 0) {
142221853Smdf		len = uio->uio_resid;
143221853Smdf		if (len > ZERO_REGION_SIZE)
144221853Smdf			len = ZERO_REGION_SIZE;
145221853Smdf		error = uiomove(zbuf, len, uio);
146221853Smdf	}
147130788Smarkm
148130788Smarkm	return (error);
14962052Smarkm}
15062052Smarkm
151111630Smarkm/* ARGSUSED */
15262052Smarkmstatic int
153111630Smarkmnull_modevent(module_t mod __unused, int type, void *data __unused)
15462052Smarkm{
15562052Smarkm	switch(type) {
15662052Smarkm	case MOD_LOAD:
15762052Smarkm		if (bootverbose)
15866709Sjhb			printf("null: <null device, zero device>\n");
159210926Skib		null_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &null_cdevsw, 0,
160210926Skib		    NULL, UID_ROOT, GID_WHEEL, 0666, "null");
161210926Skib		zero_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD, &zero_cdevsw, 0,
162210926Skib		    NULL, UID_ROOT, GID_WHEEL, 0666, "zero");
163130788Smarkm		break;
16462052Smarkm
16562052Smarkm	case MOD_UNLOAD:
16662052Smarkm		destroy_dev(null_dev);
16762052Smarkm		destroy_dev(zero_dev);
168130788Smarkm		break;
16962052Smarkm
17062052Smarkm	case MOD_SHUTDOWN:
171130788Smarkm		break;
17262052Smarkm
173132199Sphk	default:
174132199Sphk		return (EOPNOTSUPP);
17562052Smarkm	}
176130788Smarkm
177130788Smarkm	return (0);
17862052Smarkm}
17962052Smarkm
18066560SjhbDEV_MODULE(null, null_modevent, NULL);
181133033SmarkmMODULE_VERSION(null, 1);
182