xref: /freebsd/sys/dev/snp/snp.c (revision ed6232893c9dffec587a18afca04137d98328ab0)
1098ca2bdSWarner Losh /*-
2718cf2ccSPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3718cf2ccSPedro F. Giffuni  *
4932ef5b5SEd Schouten  * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
5932ef5b5SEd Schouten  * All rights reserved.
6dde8a05bSUgen J.S. Antsilevich  *
7932ef5b5SEd Schouten  * Redistribution and use in source and binary forms, with or without
8932ef5b5SEd Schouten  * modification, are permitted provided that the following conditions
9932ef5b5SEd Schouten  * are met:
10932ef5b5SEd Schouten  * 1. Redistributions of source code must retain the above copyright
11932ef5b5SEd Schouten  *    notice, this list of conditions and the following disclaimer.
12932ef5b5SEd Schouten  * 2. Redistributions in binary form must reproduce the above copyright
13932ef5b5SEd Schouten  *    notice, this list of conditions and the following disclaimer in the
14932ef5b5SEd Schouten  *    documentation and/or other materials provided with the distribution.
15dde8a05bSUgen J.S. Antsilevich  *
16932ef5b5SEd Schouten  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17932ef5b5SEd Schouten  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18932ef5b5SEd Schouten  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19932ef5b5SEd Schouten  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20932ef5b5SEd Schouten  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21932ef5b5SEd Schouten  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22932ef5b5SEd Schouten  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23932ef5b5SEd Schouten  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24932ef5b5SEd Schouten  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25932ef5b5SEd Schouten  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26932ef5b5SEd Schouten  * SUCH DAMAGE.
27dde8a05bSUgen J.S. Antsilevich  */
28dde8a05bSUgen J.S. Antsilevich 
29945ff31aSDavid E. O'Brien #include <sys/cdefs.h>
30945ff31aSDavid E. O'Brien __FBSDID("$FreeBSD$");
31945ff31aSDavid E. O'Brien 
32dde8a05bSUgen J.S. Antsilevich #include <sys/param.h>
33932ef5b5SEd Schouten #include <sys/conf.h>
341ef0fc1dSPoul-Henning Kamp #include <sys/fcntl.h>
3571455815SBruce Evans #include <sys/filio.h>
36dde8a05bSUgen J.S. Antsilevich #include <sys/kernel.h>
37932ef5b5SEd Schouten #include <sys/malloc.h>
38fe12f24bSPoul-Henning Kamp #include <sys/module.h>
39932ef5b5SEd Schouten #include <sys/poll.h>
40a9385ad1SAlexander Motin #include <sys/proc.h>
4187f6c662SJulian Elischer #include <sys/snoop.h>
42932ef5b5SEd Schouten #include <sys/sx.h>
43932ef5b5SEd Schouten #include <sys/systm.h>
44932ef5b5SEd Schouten #include <sys/tty.h>
451ef0fc1dSPoul-Henning Kamp #include <sys/uio.h>
4687f6c662SJulian Elischer 
47932ef5b5SEd Schouten static struct cdev	*snp_dev;
487fb6f685SEd Schouten static MALLOC_DEFINE(M_SNP, "snp", "tty snoop device");
497fb6f685SEd Schouten 
50932ef5b5SEd Schouten /* XXX: should be mtx, but TTY can be locked by Giant. */
517fb6f685SEd Schouten #if 0
527fb6f685SEd Schouten static struct mtx	snp_register_lock;
537fb6f685SEd Schouten MTX_SYSINIT(snp_register_lock, &snp_register_lock,
547fb6f685SEd Schouten     "tty snoop registration", MTX_DEF);
557fb6f685SEd Schouten #define	SNP_LOCK()	mtx_lock(&snp_register_lock)
567fb6f685SEd Schouten #define	SNP_UNLOCK()	mtx_unlock(&snp_register_lock)
577fb6f685SEd Schouten #else
58932ef5b5SEd Schouten static struct sx	snp_register_lock;
59932ef5b5SEd Schouten SX_SYSINIT(snp_register_lock, &snp_register_lock,
60932ef5b5SEd Schouten     "tty snoop registration");
617fb6f685SEd Schouten #define	SNP_LOCK()	sx_xlock(&snp_register_lock)
627fb6f685SEd Schouten #define	SNP_UNLOCK()	sx_xunlock(&snp_register_lock)
637fb6f685SEd Schouten #endif
64932ef5b5SEd Schouten 
6569921123SKonstantin Belousov #define	SNPGTYY_32DEV	_IOR('T', 89, uint32_t)
6669921123SKonstantin Belousov 
67932ef5b5SEd Schouten /*
68932ef5b5SEd Schouten  * There is no need to have a big input buffer. In most typical setups,
69932ef5b5SEd Schouten  * we won't inject much data into the TTY, because users can't type
70932ef5b5SEd Schouten  * really fast.
71932ef5b5SEd Schouten  */
72932ef5b5SEd Schouten #define SNP_INPUT_BUFSIZE	16
73932ef5b5SEd Schouten /*
74932ef5b5SEd Schouten  * The output buffer has to be really big. Right now we don't support
75932ef5b5SEd Schouten  * any form of flow control, which means we lost any data we can't
76932ef5b5SEd Schouten  * accept. We set the output buffer size to about twice the size of a
77932ef5b5SEd Schouten  * pseudo-terminal/virtual console's output buffer.
78932ef5b5SEd Schouten  */
79932ef5b5SEd Schouten #define SNP_OUTPUT_BUFSIZE	16384
80932ef5b5SEd Schouten 
81932ef5b5SEd Schouten static d_open_t		snp_open;
82932ef5b5SEd Schouten static d_read_t		snp_read;
83932ef5b5SEd Schouten static d_write_t	snp_write;
84932ef5b5SEd Schouten static d_ioctl_t	snp_ioctl;
85932ef5b5SEd Schouten static d_poll_t		snp_poll;
8687f6c662SJulian Elischer 
874e2f199eSPoul-Henning Kamp static struct cdevsw snp_cdevsw = {
88dc08ffecSPoul-Henning Kamp 	.d_version	= D_VERSION,
89932ef5b5SEd Schouten 	.d_open		= snp_open,
90932ef5b5SEd Schouten 	.d_read		= snp_read,
91932ef5b5SEd Schouten 	.d_write	= snp_write,
92932ef5b5SEd Schouten 	.d_ioctl	= snp_ioctl,
93932ef5b5SEd Schouten 	.d_poll		= snp_poll,
947ac40f5fSPoul-Henning Kamp 	.d_name		= "snp",
954e2f199eSPoul-Henning Kamp };
9687f6c662SJulian Elischer 
97932ef5b5SEd Schouten static th_getc_capture_t	snp_getc_capture;
98932ef5b5SEd Schouten 
99932ef5b5SEd Schouten static struct ttyhook snp_hook = {
100932ef5b5SEd Schouten 	.th_getc_capture	= snp_getc_capture,
101f09f49f1SDima Dorfman };
10253ac6efbSJulian Elischer 
103101f105dSDima Dorfman /*
104932ef5b5SEd Schouten  * Per-instance structure.
105932ef5b5SEd Schouten  *
106932ef5b5SEd Schouten  * List of locks
107932ef5b5SEd Schouten  * (r)	locked by snp_register_lock on assignment
108932ef5b5SEd Schouten  * (t)	locked by tty_lock
109101f105dSDima Dorfman  */
110932ef5b5SEd Schouten struct snp_softc {
111932ef5b5SEd Schouten 	struct tty	*snp_tty;	/* (r) TTY we're snooping. */
112932ef5b5SEd Schouten 	struct ttyoutq	snp_outq;	/* (t) Output queue. */
113932ef5b5SEd Schouten 	struct cv	snp_outwait;	/* (t) Output wait queue. */
114932ef5b5SEd Schouten 	struct selinfo	snp_outpoll;	/* (t) Output polling. */
115101f105dSDima Dorfman };
116101f105dSDima Dorfman 
1172e37c8eaSEd Schouten static void
1182e37c8eaSEd Schouten snp_dtor(void *data)
1192e37c8eaSEd Schouten {
120932ef5b5SEd Schouten 	struct snp_softc *ss = data;
121932ef5b5SEd Schouten 	struct tty *tp;
1222e37c8eaSEd Schouten 
123932ef5b5SEd Schouten 	tp = ss->snp_tty;
124932ef5b5SEd Schouten 	if (tp != NULL) {
125932ef5b5SEd Schouten 		tty_lock(tp);
126932ef5b5SEd Schouten 		ttyoutq_free(&ss->snp_outq);
127932ef5b5SEd Schouten 		ttyhook_unregister(tp);
128932ef5b5SEd Schouten 	}
129932ef5b5SEd Schouten 
130932ef5b5SEd Schouten 	cv_destroy(&ss->snp_outwait);
131932ef5b5SEd Schouten 	free(ss, M_SNP);
132932ef5b5SEd Schouten }
133932ef5b5SEd Schouten 
134932ef5b5SEd Schouten /*
135932ef5b5SEd Schouten  * Snoop device node routines.
136932ef5b5SEd Schouten  */
137932ef5b5SEd Schouten 
138932ef5b5SEd Schouten static int
139932ef5b5SEd Schouten snp_open(struct cdev *dev, int flag, int mode, struct thread *td)
140932ef5b5SEd Schouten {
141932ef5b5SEd Schouten 	struct snp_softc *ss;
142932ef5b5SEd Schouten 
143932ef5b5SEd Schouten 	/* Allocate per-snoop data. */
144932ef5b5SEd Schouten 	ss = malloc(sizeof(struct snp_softc), M_SNP, M_WAITOK|M_ZERO);
145932ef5b5SEd Schouten 	cv_init(&ss->snp_outwait, "snp out");
146932ef5b5SEd Schouten 
147932ef5b5SEd Schouten 	devfs_set_cdevpriv(ss, snp_dtor);
148932ef5b5SEd Schouten 
149932ef5b5SEd Schouten 	return (0);
1502e37c8eaSEd Schouten }
1512e37c8eaSEd Schouten 
15287f6c662SJulian Elischer static int
153932ef5b5SEd Schouten snp_read(struct cdev *dev, struct uio *uio, int flag)
154dde8a05bSUgen J.S. Antsilevich {
155932ef5b5SEd Schouten 	int error, oresid = uio->uio_resid;
156932ef5b5SEd Schouten 	struct snp_softc *ss;
157932ef5b5SEd Schouten 	struct tty *tp;
158dde8a05bSUgen J.S. Antsilevich 
159932ef5b5SEd Schouten 	if (uio->uio_resid == 0)
160932ef5b5SEd Schouten 		return (0);
161932ef5b5SEd Schouten 
162932ef5b5SEd Schouten 	error = devfs_get_cdevpriv((void **)&ss);
163932ef5b5SEd Schouten 	if (error != 0)
164932ef5b5SEd Schouten 		return (error);
165932ef5b5SEd Schouten 
166932ef5b5SEd Schouten 	tp = ss->snp_tty;
167932ef5b5SEd Schouten 	if (tp == NULL || tty_gone(tp))
168932ef5b5SEd Schouten 		return (EIO);
169932ef5b5SEd Schouten 
170932ef5b5SEd Schouten 	tty_lock(tp);
171932ef5b5SEd Schouten 	for (;;) {
172932ef5b5SEd Schouten 		error = ttyoutq_read_uio(&ss->snp_outq, tp, uio);
173932ef5b5SEd Schouten 		if (error != 0 || uio->uio_resid != oresid)
174932ef5b5SEd Schouten 			break;
175932ef5b5SEd Schouten 
176932ef5b5SEd Schouten 		/* Wait for more data. */
177932ef5b5SEd Schouten 		if (flag & O_NONBLOCK) {
178932ef5b5SEd Schouten 			error = EWOULDBLOCK;
179932ef5b5SEd Schouten 			break;
180932ef5b5SEd Schouten 		}
181*ed623289SKyle Evans 		error = cv_wait_sig(&ss->snp_outwait, tty_getlock(tp));
182932ef5b5SEd Schouten 		if (error != 0)
183932ef5b5SEd Schouten 			break;
184932ef5b5SEd Schouten 		if (tty_gone(tp)) {
185932ef5b5SEd Schouten 			error = EIO;
186932ef5b5SEd Schouten 			break;
187932ef5b5SEd Schouten 		}
188932ef5b5SEd Schouten 	}
189932ef5b5SEd Schouten 	tty_unlock(tp);
190932ef5b5SEd Schouten 
1912e37c8eaSEd Schouten 	return (error);
1922e37c8eaSEd Schouten }
19377f77631SPaul Traina 
194932ef5b5SEd Schouten static int
195932ef5b5SEd Schouten snp_write(struct cdev *dev, struct uio *uio, int flag)
196019b4d63SUgen J.S. Antsilevich {
197932ef5b5SEd Schouten 	struct snp_softc *ss;
198019b4d63SUgen J.S. Antsilevich 	struct tty *tp;
1995c67885aSEd Schouten 	int error, len;
200932ef5b5SEd Schouten 	char in[SNP_INPUT_BUFSIZE];
201019b4d63SUgen J.S. Antsilevich 
202932ef5b5SEd Schouten 	error = devfs_get_cdevpriv((void **)&ss);
203932ef5b5SEd Schouten 	if (error != 0)
204932ef5b5SEd Schouten 		return (error);
205932ef5b5SEd Schouten 
206932ef5b5SEd Schouten 	tp = ss->snp_tty;
207932ef5b5SEd Schouten 	if (tp == NULL || tty_gone(tp))
208932ef5b5SEd Schouten 		return (EIO);
209932ef5b5SEd Schouten 
210932ef5b5SEd Schouten 	while (uio->uio_resid > 0) {
211932ef5b5SEd Schouten 		/* Read new data. */
212932ef5b5SEd Schouten 		len = imin(uio->uio_resid, sizeof in);
213932ef5b5SEd Schouten 		error = uiomove(in, len, uio);
214932ef5b5SEd Schouten 		if (error != 0)
215932ef5b5SEd Schouten 			return (error);
216932ef5b5SEd Schouten 
217932ef5b5SEd Schouten 		tty_lock(tp);
218932ef5b5SEd Schouten 
219932ef5b5SEd Schouten 		/* Driver could have abandoned the TTY in the mean time. */
220932ef5b5SEd Schouten 		if (tty_gone(tp)) {
221932ef5b5SEd Schouten 			tty_unlock(tp);
222932ef5b5SEd Schouten 			return (ENXIO);
223932ef5b5SEd Schouten 		}
224019b4d63SUgen J.S. Antsilevich 
225019b4d63SUgen J.S. Antsilevich 		/*
226932ef5b5SEd Schouten 		 * Deliver data to the TTY. Ignore errors for now,
227932ef5b5SEd Schouten 		 * because we shouldn't bail out when we're running
228932ef5b5SEd Schouten 		 * close to the watermarks.
229019b4d63SUgen J.S. Antsilevich 		 */
2305c67885aSEd Schouten 		ttydisc_rint_simple(tp, in, len);
231932ef5b5SEd Schouten 		ttydisc_rint_done(tp);
2325c67885aSEd Schouten 
233932ef5b5SEd Schouten 		tty_unlock(tp);
23476e90dbcSBrian Feldman 	}
235dde8a05bSUgen J.S. Antsilevich 
236542a8db5SKonstantin Belousov 	return (0);
237964587caSUgen J.S. Antsilevich }
238dde8a05bSUgen J.S. Antsilevich 
23987f6c662SJulian Elischer static int
240932ef5b5SEd Schouten snp_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags,
2417409f6cdSCraig Rodrigues     struct thread *td)
242dde8a05bSUgen J.S. Antsilevich {
243932ef5b5SEd Schouten 	struct snp_softc *ss;
244316d90a3SKonstantin Belousov 	struct tty *tp;
245932ef5b5SEd Schouten 	int error;
246dde8a05bSUgen J.S. Antsilevich 
247932ef5b5SEd Schouten 	error = devfs_get_cdevpriv((void **)&ss);
2482e37c8eaSEd Schouten 	if (error != 0)
2492e37c8eaSEd Schouten 		return (error);
2502e37c8eaSEd Schouten 
251dde8a05bSUgen J.S. Antsilevich 	switch (cmd) {
252dde8a05bSUgen J.S. Antsilevich 	case SNPSTTY:
253932ef5b5SEd Schouten 		/* Bind TTY to snoop instance. */
2547fb6f685SEd Schouten 		SNP_LOCK();
255932ef5b5SEd Schouten 		if (ss->snp_tty != NULL) {
2567fb6f685SEd Schouten 			SNP_UNLOCK();
257932ef5b5SEd Schouten 			return (EBUSY);
25830ce1aadSOlivier Houchard 		}
259a9d2f8d8SRobert Watson 		/*
260a9d2f8d8SRobert Watson 		 * XXXRW / XXXJA: no capability check here.
261a9d2f8d8SRobert Watson 		 */
262aa16f86cSEd Schouten 		error = ttyhook_register(&ss->snp_tty, td->td_proc,
263aa16f86cSEd Schouten 		    *(int *)data, &snp_hook, ss);
2647fb6f685SEd Schouten 		SNP_UNLOCK();
265932ef5b5SEd Schouten 		if (error != 0)
266932ef5b5SEd Schouten 			return (error);
267964587caSUgen J.S. Antsilevich 
268932ef5b5SEd Schouten 		/* Now that went okay, allocate a buffer for the queue. */
269932ef5b5SEd Schouten 		tp = ss->snp_tty;
270932ef5b5SEd Schouten 		tty_lock(tp);
271932ef5b5SEd Schouten 		ttyoutq_setsize(&ss->snp_outq, tp, SNP_OUTPUT_BUFSIZE);
272932ef5b5SEd Schouten 		tty_unlock(tp);
273316d90a3SKonstantin Belousov 
274932ef5b5SEd Schouten 		return (0);
275dde8a05bSUgen J.S. Antsilevich 	case SNPGTTY:
276932ef5b5SEd Schouten 		/* Obtain device number of associated TTY. */
277932ef5b5SEd Schouten 		if (ss->snp_tty == NULL)
278932ef5b5SEd Schouten 			*(dev_t *)data = NODEV;
279dde8a05bSUgen J.S. Antsilevich 		else
280932ef5b5SEd Schouten 			*(dev_t *)data = tty_udev(ss->snp_tty);
281932ef5b5SEd Schouten 		return (0);
28269921123SKonstantin Belousov 	case SNPGTYY_32DEV:
28369921123SKonstantin Belousov 		if (ss->snp_tty == NULL)
28469921123SKonstantin Belousov 			*(uint32_t *)data = -1;
28569921123SKonstantin Belousov 		else
28669921123SKonstantin Belousov 			*(uint32_t *)data = tty_udev(ss->snp_tty); /* trunc */
28769921123SKonstantin Belousov 		return (0);
288dde8a05bSUgen J.S. Antsilevich 	case FIONREAD:
289932ef5b5SEd Schouten 		tp = ss->snp_tty;
290932ef5b5SEd Schouten 		if (tp != NULL) {
291932ef5b5SEd Schouten 			tty_lock(tp);
292932ef5b5SEd Schouten 			*(int *)data = ttyoutq_bytesused(&ss->snp_outq);
293932ef5b5SEd Schouten 			tty_unlock(tp);
294964587caSUgen J.S. Antsilevich 		} else {
295932ef5b5SEd Schouten 			*(int *)data = 0;
296964587caSUgen J.S. Antsilevich 		}
297932ef5b5SEd Schouten 		return (0);
298dde8a05bSUgen J.S. Antsilevich 	default:
299dde8a05bSUgen J.S. Antsilevich 		return (ENOTTY);
300dde8a05bSUgen J.S. Antsilevich 	}
301dde8a05bSUgen J.S. Antsilevich }
302dde8a05bSUgen J.S. Antsilevich 
30387f6c662SJulian Elischer static int
304932ef5b5SEd Schouten snp_poll(struct cdev *dev, int events, struct thread *td)
305dde8a05bSUgen J.S. Antsilevich {
306932ef5b5SEd Schouten 	struct snp_softc *ss;
307932ef5b5SEd Schouten 	struct tty *tp;
308f09f49f1SDima Dorfman 	int revents;
309dde8a05bSUgen J.S. Antsilevich 
310932ef5b5SEd Schouten 	if (devfs_get_cdevpriv((void **)&ss) != 0)
3112e37c8eaSEd Schouten 		return (events &
3122e37c8eaSEd Schouten 		    (POLLHUP|POLLIN|POLLRDNORM|POLLOUT|POLLWRNORM));
3132e37c8eaSEd Schouten 
314f09f49f1SDima Dorfman 	revents = 0;
315932ef5b5SEd Schouten 
316dfd5dee1SPeter Wemm 	if (events & (POLLIN | POLLRDNORM)) {
317932ef5b5SEd Schouten 		tp = ss->snp_tty;
318932ef5b5SEd Schouten 		if (tp != NULL) {
319932ef5b5SEd Schouten 			tty_lock(tp);
320932ef5b5SEd Schouten 			if (ttyoutq_bytesused(&ss->snp_outq) > 0)
321659ffb48SPeter Wemm 				revents |= events & (POLLIN | POLLRDNORM);
322932ef5b5SEd Schouten 			tty_unlock(tp);
323dfd5dee1SPeter Wemm 		}
324932ef5b5SEd Schouten 	}
325932ef5b5SEd Schouten 
326932ef5b5SEd Schouten 	if (revents == 0)
327932ef5b5SEd Schouten 		selrecord(td, &ss->snp_outpoll);
328932ef5b5SEd Schouten 
329659ffb48SPeter Wemm 	return (revents);
330dde8a05bSUgen J.S. Antsilevich }
331dde8a05bSUgen J.S. Antsilevich 
332932ef5b5SEd Schouten /*
333932ef5b5SEd Schouten  * TTY hook events.
334932ef5b5SEd Schouten  */
335932ef5b5SEd Schouten 
33647eaa5f5SDima Dorfman static int
3377409f6cdSCraig Rodrigues snp_modevent(module_t mod, int type, void *data)
33853ac6efbSJulian Elischer {
33953ac6efbSJulian Elischer 
34047eaa5f5SDima Dorfman 	switch (type) {
34147eaa5f5SDima Dorfman 	case MOD_LOAD:
342932ef5b5SEd Schouten 		snp_dev = make_dev(&snp_cdevsw, 0,
343932ef5b5SEd Schouten 		    UID_ROOT, GID_WHEEL, 0600, "snp");
344932ef5b5SEd Schouten 		return (0);
34547eaa5f5SDima Dorfman 	case MOD_UNLOAD:
346932ef5b5SEd Schouten 		/* XXX: Make existing users leave. */
347932ef5b5SEd Schouten 		destroy_dev(snp_dev);
348932ef5b5SEd Schouten 		return (0);
34947eaa5f5SDima Dorfman 	default:
3503e019deaSPoul-Henning Kamp 		return (EOPNOTSUPP);
35147eaa5f5SDima Dorfman 	}
352932ef5b5SEd Schouten }
353932ef5b5SEd Schouten 
354932ef5b5SEd Schouten static void
355932ef5b5SEd Schouten snp_getc_capture(struct tty *tp, const void *buf, size_t len)
356932ef5b5SEd Schouten {
357932ef5b5SEd Schouten 	struct snp_softc *ss = ttyhook_softc(tp);
358932ef5b5SEd Schouten 
359932ef5b5SEd Schouten 	ttyoutq_write(&ss->snp_outq, buf, len);
360932ef5b5SEd Schouten 
361932ef5b5SEd Schouten 	cv_broadcast(&ss->snp_outwait);
362932ef5b5SEd Schouten 	selwakeup(&ss->snp_outpoll);
3637198bf47SJulian Elischer }
36453ac6efbSJulian Elischer 
36547eaa5f5SDima Dorfman static moduledata_t snp_mod = {
36647eaa5f5SDima Dorfman 	"snp",
36747eaa5f5SDima Dorfman 	snp_modevent,
36847eaa5f5SDima Dorfman 	NULL
36947eaa5f5SDima Dorfman };
370932ef5b5SEd Schouten 
371b0b03348SPoul-Henning Kamp DECLARE_MODULE(snp, snp_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
372