xref: /freebsd/sys/dev/snp/snp.c (revision 019b4d63aedf08b1954bc918b93f256097c5d0f5)
1dde8a05bSUgen J.S. Antsilevich /*
2dde8a05bSUgen J.S. Antsilevich  * Copyright (c) 1995 Ugen J.S.Antsilevich
3dde8a05bSUgen J.S. Antsilevich  *
4dde8a05bSUgen J.S. Antsilevich  * Redistribution and use in source forms, with and without modification,
5dde8a05bSUgen J.S. Antsilevich  * are permitted provided that this entire comment appears intact.
6dde8a05bSUgen J.S. Antsilevich  *
7dde8a05bSUgen J.S. Antsilevich  * Redistribution in binary form may occur without any restrictions.
8dde8a05bSUgen J.S. Antsilevich  * Obviously, it would be nice if you gave credit where credit is due
9dde8a05bSUgen J.S. Antsilevich  * but requiring it would be too onerous.
10dde8a05bSUgen J.S. Antsilevich  *
11dde8a05bSUgen J.S. Antsilevich  * This software is provided ``AS IS'' without any warranties of any kind.
12dde8a05bSUgen J.S. Antsilevich  *
13dde8a05bSUgen J.S. Antsilevich  * Snoop stuff.
14dde8a05bSUgen J.S. Antsilevich  */
15dde8a05bSUgen J.S. Antsilevich 
16dde8a05bSUgen J.S. Antsilevich #include "snp.h"
17dde8a05bSUgen J.S. Antsilevich 
18019b4d63SUgen J.S. Antsilevich #if NSNP > 0
19dde8a05bSUgen J.S. Antsilevich 
20dde8a05bSUgen J.S. Antsilevich #include <sys/param.h>
21dde8a05bSUgen J.S. Antsilevich #include <sys/systm.h>
22dde8a05bSUgen J.S. Antsilevich #include <sys/ioctl.h>
23dde8a05bSUgen J.S. Antsilevich #include <sys/ioctl_compat.h>	/* Oooh..We need O/NTTYDISC	 */
24dde8a05bSUgen J.S. Antsilevich #include <sys/proc.h>
25dde8a05bSUgen J.S. Antsilevich #define TTYDEFCHARS
26dde8a05bSUgen J.S. Antsilevich #include <sys/tty.h>
27dde8a05bSUgen J.S. Antsilevich #undef  TTYDEFCHARS
28dde8a05bSUgen J.S. Antsilevich #include <sys/file.h>
29dde8a05bSUgen J.S. Antsilevich #include <sys/conf.h>
30dde8a05bSUgen J.S. Antsilevich #include <sys/uio.h>
31dde8a05bSUgen J.S. Antsilevich #include <sys/kernel.h>
32dde8a05bSUgen J.S. Antsilevich #include <sys/malloc.h>
33dde8a05bSUgen J.S. Antsilevich 
34dde8a05bSUgen J.S. Antsilevich #include <sys/snoop.h>
35dde8a05bSUgen J.S. Antsilevich 
36dde8a05bSUgen J.S. Antsilevich 
37dde8a05bSUgen J.S. Antsilevich 
38dde8a05bSUgen J.S. Antsilevich #ifdef ST_PTY
39dde8a05bSUgen J.S. Antsilevich /*
40dde8a05bSUgen J.S. Antsilevich  * This should be same as in "kern/tty_pty.c"
41dde8a05bSUgen J.S. Antsilevich  */
42dde8a05bSUgen J.S. Antsilevich #include "pty.h"
43dde8a05bSUgen J.S. Antsilevich 
44dde8a05bSUgen J.S. Antsilevich #if NPTY == 1
45dde8a05bSUgen J.S. Antsilevich #undef NPTY
46dde8a05bSUgen J.S. Antsilevich #define NPTY 	32
47dde8a05bSUgen J.S. Antsilevich #endif
48dde8a05bSUgen J.S. Antsilevich 
49dde8a05bSUgen J.S. Antsilevich extern struct tty pt_tty[];
50dde8a05bSUgen J.S. Antsilevich #endif				/* ST_PTY */
51dde8a05bSUgen J.S. Antsilevich 
52dde8a05bSUgen J.S. Antsilevich 
53dde8a05bSUgen J.S. Antsilevich #ifdef ST_SIO
54dde8a05bSUgen J.S. Antsilevich /*
55dde8a05bSUgen J.S. Antsilevich  * This should be same as "i386/isa/sio.c"
56dde8a05bSUgen J.S. Antsilevich  */
57dde8a05bSUgen J.S. Antsilevich #include "sio.h"
58dde8a05bSUgen J.S. Antsilevich 
59dde8a05bSUgen J.S. Antsilevich extern struct tty sio_tty[];
60dde8a05bSUgen J.S. Antsilevich #endif				/* ST_SIO */
61dde8a05bSUgen J.S. Antsilevich 
62dde8a05bSUgen J.S. Antsilevich 
63dde8a05bSUgen J.S. Antsilevich #ifdef ST_VTY
64dde8a05bSUgen J.S. Antsilevich /*
65dde8a05bSUgen J.S. Antsilevich  * This should match "i386/isa/sc.c"
66dde8a05bSUgen J.S. Antsilevich  */
67dde8a05bSUgen J.S. Antsilevich 
68dde8a05bSUgen J.S. Antsilevich #if !defined(MAXCONS)
69dde8a05bSUgen J.S. Antsilevich #define MAXCONS 16
70dde8a05bSUgen J.S. Antsilevich #endif
71dde8a05bSUgen J.S. Antsilevich 
72dde8a05bSUgen J.S. Antsilevich extern struct tty sccons[];
73dde8a05bSUgen J.S. Antsilevich #endif				/* ST_VTY */
74dde8a05bSUgen J.S. Antsilevich 
75dde8a05bSUgen J.S. Antsilevich 
76dde8a05bSUgen J.S. Antsilevich /*
77019b4d63SUgen J.S. Antsilevich  * This is local structure to hold data for all tty arrays we serve.
78dde8a05bSUgen J.S. Antsilevich  */
79dde8a05bSUgen J.S. Antsilevich typedef struct tty tty_arr[];
80dde8a05bSUgen J.S. Antsilevich struct tty_tab {
81dde8a05bSUgen J.S. Antsilevich 	int             lt_max;
82dde8a05bSUgen J.S. Antsilevich 	tty_arr        *lt_tab;
83dde8a05bSUgen J.S. Antsilevich };
84dde8a05bSUgen J.S. Antsilevich 
85dde8a05bSUgen J.S. Antsilevich static struct tty_tab tty_tabs[] = {
86dde8a05bSUgen J.S. Antsilevich #ifdef ST_PTY
87dde8a05bSUgen J.S. Antsilevich 	{NPTY, &pt_tty},
88dde8a05bSUgen J.S. Antsilevich #else
89dde8a05bSUgen J.S. Antsilevich 	{-1, NULL},
90dde8a05bSUgen J.S. Antsilevich #endif
91dde8a05bSUgen J.S. Antsilevich #ifdef ST_VTY
92dde8a05bSUgen J.S. Antsilevich 	{MAXCONS, &sccons},
93dde8a05bSUgen J.S. Antsilevich #else
94dde8a05bSUgen J.S. Antsilevich 	{-1, NULL},
95dde8a05bSUgen J.S. Antsilevich #endif
96dde8a05bSUgen J.S. Antsilevich #ifdef	ST_SIO
97dde8a05bSUgen J.S. Antsilevich 	{NSIO, &sio_tty}
98dde8a05bSUgen J.S. Antsilevich #else
99dde8a05bSUgen J.S. Antsilevich 	{-1, NULL}
100dde8a05bSUgen J.S. Antsilevich #endif
101dde8a05bSUgen J.S. Antsilevich };
102dde8a05bSUgen J.S. Antsilevich 
103dde8a05bSUgen J.S. Antsilevich 
104dde8a05bSUgen J.S. Antsilevich #ifndef MIN
105dde8a05bSUgen J.S. Antsilevich #define MIN(a,b) (((a)<(b))?(a):(b))
106dde8a05bSUgen J.S. Antsilevich #endif
107dde8a05bSUgen J.S. Antsilevich 
108dde8a05bSUgen J.S. Antsilevich 
109dde8a05bSUgen J.S. Antsilevich static struct snoop snoopsw[NSNP];
110dde8a05bSUgen J.S. Antsilevich 
111dde8a05bSUgen J.S. Antsilevich int
112dde8a05bSUgen J.S. Antsilevich snpread(dev, uio, flag)
113dde8a05bSUgen J.S. Antsilevich 	dev_t           dev;
114dde8a05bSUgen J.S. Antsilevich 	struct uio     *uio;
115dde8a05bSUgen J.S. Antsilevich 	int             flag;
116dde8a05bSUgen J.S. Antsilevich {
117dde8a05bSUgen J.S. Antsilevich 	int             unit = minor(dev), s;
118dde8a05bSUgen J.S. Antsilevich 	struct snoop   *snp = &snoopsw[unit];
119dde8a05bSUgen J.S. Antsilevich 	int             len, n, nblen, error = 0;
120dde8a05bSUgen J.S. Antsilevich 	caddr_t         from;
121dde8a05bSUgen J.S. Antsilevich 	char           *nbuf;
122dde8a05bSUgen J.S. Antsilevich 
123dde8a05bSUgen J.S. Antsilevich #ifdef DIAGNOSTIC
124dde8a05bSUgen J.S. Antsilevich 	if ((snp->snp_len + snp->snp_base) > snp->snp_blen)
125dde8a05bSUgen J.S. Antsilevich 		panic("snoop buffer error");
126dde8a05bSUgen J.S. Antsilevich #endif
127dde8a05bSUgen J.S. Antsilevich 	if (snp->snp_unit == -1)
128dde8a05bSUgen J.S. Antsilevich 		return (EIO);
129dde8a05bSUgen J.S. Antsilevich 
130dde8a05bSUgen J.S. Antsilevich 	snp->snp_flags &= ~SNOOP_RWAIT;
131dde8a05bSUgen J.S. Antsilevich 
132dde8a05bSUgen J.S. Antsilevich 	do {
133dde8a05bSUgen J.S. Antsilevich 		if (snp->snp_len == 0) {
134dde8a05bSUgen J.S. Antsilevich 			if (snp->snp_flags & SNOOP_NBIO) {
135dde8a05bSUgen J.S. Antsilevich 				return EWOULDBLOCK;
136dde8a05bSUgen J.S. Antsilevich 			}
137dde8a05bSUgen J.S. Antsilevich 			snp->snp_flags |= SNOOP_RWAIT;
138dde8a05bSUgen J.S. Antsilevich 			tsleep((caddr_t) snp, (PZERO + 1) | PCATCH, "snoopread", 0);
139dde8a05bSUgen J.S. Antsilevich 		}
140dde8a05bSUgen J.S. Antsilevich 	} while (snp->snp_len == 0);
141dde8a05bSUgen J.S. Antsilevich 
142019b4d63SUgen J.S. Antsilevich 	n = snp->snp_len;
143dde8a05bSUgen J.S. Antsilevich 
144dde8a05bSUgen J.S. Antsilevich 	while (snp->snp_len > 0 && uio->uio_resid > 0 && error == 0) {
145dde8a05bSUgen J.S. Antsilevich 		len = MIN(uio->uio_resid, snp->snp_len);
146dde8a05bSUgen J.S. Antsilevich 		from = (caddr_t) (snp->snp_buf + snp->snp_base);
147dde8a05bSUgen J.S. Antsilevich 		if (len == 0)
148dde8a05bSUgen J.S. Antsilevich 			break;
149dde8a05bSUgen J.S. Antsilevich 
150dde8a05bSUgen J.S. Antsilevich 		error = uiomove(from, len, uio);
151dde8a05bSUgen J.S. Antsilevich 		snp->snp_base += len;
152dde8a05bSUgen J.S. Antsilevich 		snp->snp_len -= len;
153dde8a05bSUgen J.S. Antsilevich 	}
154019b4d63SUgen J.S. Antsilevich 	if ((snp->snp_flags & SNOOP_OFLOW) && (n < snp->snp_len)) {
155dde8a05bSUgen J.S. Antsilevich 		snp->snp_flags &= ~SNOOP_OFLOW;
156019b4d63SUgen J.S. Antsilevich 	}
157dde8a05bSUgen J.S. Antsilevich 	s = spltty();
158dde8a05bSUgen J.S. Antsilevich 	nblen = snp->snp_blen;
159dde8a05bSUgen J.S. Antsilevich 	if (((nblen / 2) >= SNOOP_MINLEN) && (nblen / 2) >= snp->snp_len) {
160dde8a05bSUgen J.S. Antsilevich 		while (((nblen / 2) >= snp->snp_len) && ((nblen / 2) >= SNOOP_MINLEN))
161dde8a05bSUgen J.S. Antsilevich 			nblen = nblen / 2;
162dde8a05bSUgen J.S. Antsilevich 		if (nbuf = malloc(nblen, M_TTYS, M_NOWAIT)) {
163dde8a05bSUgen J.S. Antsilevich 			bcopy(snp->snp_buf + snp->snp_base, nbuf, snp->snp_len);
164dde8a05bSUgen J.S. Antsilevich 			free(snp->snp_buf, M_TTYS);
165dde8a05bSUgen J.S. Antsilevich 			snp->snp_buf = nbuf;
166dde8a05bSUgen J.S. Antsilevich 			snp->snp_blen = nblen;
167dde8a05bSUgen J.S. Antsilevich 			snp->snp_base = 0;
168dde8a05bSUgen J.S. Antsilevich 		}
169dde8a05bSUgen J.S. Antsilevich 	}
170dde8a05bSUgen J.S. Antsilevich 	splx(s);
171dde8a05bSUgen J.S. Antsilevich 
172dde8a05bSUgen J.S. Antsilevich 	return error;
173dde8a05bSUgen J.S. Antsilevich }
174dde8a05bSUgen J.S. Antsilevich 
175dde8a05bSUgen J.S. Antsilevich 
176dde8a05bSUgen J.S. Antsilevich int
177dde8a05bSUgen J.S. Antsilevich snpin(snp, buf, n)
178dde8a05bSUgen J.S. Antsilevich 	struct snoop   *snp;
179dde8a05bSUgen J.S. Antsilevich 	char           *buf;
180dde8a05bSUgen J.S. Antsilevich 	int             n;
181dde8a05bSUgen J.S. Antsilevich {
182dde8a05bSUgen J.S. Antsilevich 	int             s_free, s_tail;
183dde8a05bSUgen J.S. Antsilevich 	int             s, len, nblen;
184dde8a05bSUgen J.S. Antsilevich 	caddr_t         from, to;
185dde8a05bSUgen J.S. Antsilevich 	char           *nbuf;
186dde8a05bSUgen J.S. Antsilevich 	struct tty_tab *l_tty;
187dde8a05bSUgen J.S. Antsilevich 	struct tty     *tp;
188dde8a05bSUgen J.S. Antsilevich 
189dde8a05bSUgen J.S. Antsilevich 
190dde8a05bSUgen J.S. Antsilevich 	if (n == 0)
191dde8a05bSUgen J.S. Antsilevich 		return 0;
192dde8a05bSUgen J.S. Antsilevich 
193dde8a05bSUgen J.S. Antsilevich #ifdef DIAGNOSTIC
194dde8a05bSUgen J.S. Antsilevich 	if (n < 0)
195dde8a05bSUgen J.S. Antsilevich 		panic("bad snoop char count");
196dde8a05bSUgen J.S. Antsilevich 
197019b4d63SUgen J.S. Antsilevich 	if (!(snp->snp_flags & SNOOP_OPEN)) {
198019b4d63SUgen J.S. Antsilevich 		printf("Snoop: data coming to closed device.\n");
199019b4d63SUgen J.S. Antsilevich 		return 0;
200dde8a05bSUgen J.S. Antsilevich 	}
201019b4d63SUgen J.S. Antsilevich #endif
202019b4d63SUgen J.S. Antsilevich 	if (snp->snp_flags & SNOOP_DOWN) {
203019b4d63SUgen J.S. Antsilevich 		printf("Snoop: more data to down interface.\n");
204019b4d63SUgen J.S. Antsilevich 		return 0;
205019b4d63SUgen J.S. Antsilevich 	}
206019b4d63SUgen J.S. Antsilevich 	if (snp->snp_flags & SNOOP_OFLOW) {
207019b4d63SUgen J.S. Antsilevich 		printf("Snoop: buffer overflow.\n");
208019b4d63SUgen J.S. Antsilevich 		/*
209019b4d63SUgen J.S. Antsilevich 		 * On overflow we just repeat the standart close
210019b4d63SUgen J.S. Antsilevich 		 * procedure...yes , this is waste of space but.. Then next
211019b4d63SUgen J.S. Antsilevich 		 * read from device will fail if one would recall he is
212019b4d63SUgen J.S. Antsilevich 		 * snooping and retry...
213019b4d63SUgen J.S. Antsilevich 		 */
214dde8a05bSUgen J.S. Antsilevich 
215019b4d63SUgen J.S. Antsilevich 		snp->snp_blen = SNOOP_MINLEN;
216019b4d63SUgen J.S. Antsilevich 		free(snp->snp_buf, M_TTYS);
217019b4d63SUgen J.S. Antsilevich 		snp->snp_buf = malloc(SNOOP_MINLEN, M_TTYS, M_WAITOK);
218019b4d63SUgen J.S. Antsilevich 		snp->snp_flags |= SNOOP_DOWN;
219019b4d63SUgen J.S. Antsilevich 		snp->snp_flags &= ~SNOOP_OFLOW;
220019b4d63SUgen J.S. Antsilevich 
221019b4d63SUgen J.S. Antsilevich 		return (snp_detach(snp));
222019b4d63SUgen J.S. Antsilevich 	}
223019b4d63SUgen J.S. Antsilevich 	s_tail = snp->snp_blen - (snp->snp_len + snp->snp_base);
224019b4d63SUgen J.S. Antsilevich 	s_free = snp->snp_blen - snp->snp_len;
225dde8a05bSUgen J.S. Antsilevich 
226dde8a05bSUgen J.S. Antsilevich 
227dde8a05bSUgen J.S. Antsilevich 	if (n > s_free) {
228dde8a05bSUgen J.S. Antsilevich 		s = spltty();
229dde8a05bSUgen J.S. Antsilevich 		nblen = snp->snp_blen;
230dde8a05bSUgen J.S. Antsilevich 		while ((n > s_free) && ((nblen * 2) <= SNOOP_MAXLEN)) {
231dde8a05bSUgen J.S. Antsilevich 			nblen = snp->snp_blen * 2;
232dde8a05bSUgen J.S. Antsilevich 			s_free = nblen - (snp->snp_len + snp->snp_base);
233dde8a05bSUgen J.S. Antsilevich 		}
234dde8a05bSUgen J.S. Antsilevich 		if ((n <= s_free) && (nbuf = malloc(nblen, M_TTYS, M_NOWAIT))) {
235dde8a05bSUgen J.S. Antsilevich 			bcopy(snp->snp_buf + snp->snp_base, nbuf, snp->snp_len);
236dde8a05bSUgen J.S. Antsilevich 			free(snp->snp_buf, M_TTYS);
237dde8a05bSUgen J.S. Antsilevich 			snp->snp_buf = nbuf;
238dde8a05bSUgen J.S. Antsilevich 			snp->snp_blen = nblen;
239dde8a05bSUgen J.S. Antsilevich 			snp->snp_base = 0;
240dde8a05bSUgen J.S. Antsilevich 		} else {
241dde8a05bSUgen J.S. Antsilevich 			snp->snp_flags |= SNOOP_OFLOW;
242dde8a05bSUgen J.S. Antsilevich 			if (snp->snp_flags & SNOOP_RWAIT) {
243dde8a05bSUgen J.S. Antsilevich 				snp->snp_flags &= ~SNOOP_RWAIT;
244dde8a05bSUgen J.S. Antsilevich 				wakeup((caddr_t) snp);
245dde8a05bSUgen J.S. Antsilevich 			}
246dde8a05bSUgen J.S. Antsilevich 			splx(s);
247dde8a05bSUgen J.S. Antsilevich 			return 0;
248dde8a05bSUgen J.S. Antsilevich 		}
249dde8a05bSUgen J.S. Antsilevich 		splx(s);
250dde8a05bSUgen J.S. Antsilevich 	}
251dde8a05bSUgen J.S. Antsilevich 	if (n > s_tail) {
252dde8a05bSUgen J.S. Antsilevich 		from = (caddr_t) (snp->snp_buf + snp->snp_base);
253dde8a05bSUgen J.S. Antsilevich 		to = (caddr_t) (snp->snp_buf);
254dde8a05bSUgen J.S. Antsilevich 		len = snp->snp_len;
255dde8a05bSUgen J.S. Antsilevich 		bcopy(from, to, len);
256dde8a05bSUgen J.S. Antsilevich 		snp->snp_base = 0;
257dde8a05bSUgen J.S. Antsilevich 	}
258dde8a05bSUgen J.S. Antsilevich 	to = (caddr_t) (snp->snp_buf + snp->snp_base + snp->snp_len);
259dde8a05bSUgen J.S. Antsilevich 	bcopy(buf, to, n);
260dde8a05bSUgen J.S. Antsilevich 	snp->snp_len += n;
261dde8a05bSUgen J.S. Antsilevich 
262dde8a05bSUgen J.S. Antsilevich 	if (snp->snp_flags & SNOOP_RWAIT) {
263dde8a05bSUgen J.S. Antsilevich 		snp->snp_flags &= ~SNOOP_RWAIT;
264dde8a05bSUgen J.S. Antsilevich 		wakeup((caddr_t) snp);
265dde8a05bSUgen J.S. Antsilevich 	}
266dde8a05bSUgen J.S. Antsilevich 	selwakeup(&snp->snp_sel);
267dde8a05bSUgen J.S. Antsilevich 	snp->snp_sel.si_pid = 0;
268dde8a05bSUgen J.S. Antsilevich 
269dde8a05bSUgen J.S. Antsilevich 	return n;
270dde8a05bSUgen J.S. Antsilevich }
271dde8a05bSUgen J.S. Antsilevich 
272dde8a05bSUgen J.S. Antsilevich int
273dde8a05bSUgen J.S. Antsilevich snpopen(dev, flag, mode, p)
274dde8a05bSUgen J.S. Antsilevich 	dev_t           dev;
275dde8a05bSUgen J.S. Antsilevich 	int             flag, mode;
276dde8a05bSUgen J.S. Antsilevich 	struct proc    *p;
277dde8a05bSUgen J.S. Antsilevich {
278dde8a05bSUgen J.S. Antsilevich 	struct snoop   *snp;
279dde8a05bSUgen J.S. Antsilevich 	register int    unit, error;
280dde8a05bSUgen J.S. Antsilevich 
281dde8a05bSUgen J.S. Antsilevich 	if (error = suser(p->p_ucred, &p->p_acflag))
282dde8a05bSUgen J.S. Antsilevich 		return (error);
283dde8a05bSUgen J.S. Antsilevich 
284dde8a05bSUgen J.S. Antsilevich 	if ((unit = minor(dev)) >= NSNP)
285dde8a05bSUgen J.S. Antsilevich 		return (ENXIO);
286dde8a05bSUgen J.S. Antsilevich 	snp = &snoopsw[unit];
287dde8a05bSUgen J.S. Antsilevich 	if (snp->snp_flags & SNOOP_OPEN)
288dde8a05bSUgen J.S. Antsilevich 		return (ENXIO);
289019b4d63SUgen J.S. Antsilevich 	/*
290019b4d63SUgen J.S. Antsilevich 	 * We intentionally do not OR flags with SNOOP_OPEN,but set them so
291019b4d63SUgen J.S. Antsilevich 	 * all previous settings (especially SNOOP_OFLOW) will be cleared.
292019b4d63SUgen J.S. Antsilevich 	 */
293019b4d63SUgen J.S. Antsilevich 	snp->snp_flags = SNOOP_OPEN;
294dde8a05bSUgen J.S. Antsilevich 
295dde8a05bSUgen J.S. Antsilevich 	snp->snp_buf = malloc(SNOOP_MINLEN, M_TTYS, M_WAITOK);
296dde8a05bSUgen J.S. Antsilevich 	snp->snp_blen = SNOOP_MINLEN;
297dde8a05bSUgen J.S. Antsilevich 	snp->snp_base = 0;
298dde8a05bSUgen J.S. Antsilevich 	snp->snp_len = 0;
299dde8a05bSUgen J.S. Antsilevich 
300dde8a05bSUgen J.S. Antsilevich 	/*
301019b4d63SUgen J.S. Antsilevich 	 * unit == -1  is for inactive snoop devices.
302dde8a05bSUgen J.S. Antsilevich 	 */
303dde8a05bSUgen J.S. Antsilevich 	snp->snp_unit = -1;
304dde8a05bSUgen J.S. Antsilevich 
305dde8a05bSUgen J.S. Antsilevich 	return (0);
306dde8a05bSUgen J.S. Antsilevich }
307dde8a05bSUgen J.S. Antsilevich 
308019b4d63SUgen J.S. Antsilevich 
309019b4d63SUgen J.S. Antsilevich int
310019b4d63SUgen J.S. Antsilevich snp_detach(snp)
311019b4d63SUgen J.S. Antsilevich 	struct snoop   *snp;
312019b4d63SUgen J.S. Antsilevich {
313019b4d63SUgen J.S. Antsilevich 	struct tty     *tp;
314019b4d63SUgen J.S. Antsilevich 	struct tty_tab *l_tty;
315019b4d63SUgen J.S. Antsilevich 
316019b4d63SUgen J.S. Antsilevich 
317019b4d63SUgen J.S. Antsilevich 	snp->snp_base = 0;
318019b4d63SUgen J.S. Antsilevich 	snp->snp_len = 0;
319019b4d63SUgen J.S. Antsilevich 
320019b4d63SUgen J.S. Antsilevich 	/*
321019b4d63SUgen J.S. Antsilevich 	 * If line disc. changed we do not touch this pointer,SLIP/PPP will
322019b4d63SUgen J.S. Antsilevich 	 * change it anyway.
323019b4d63SUgen J.S. Antsilevich 	 */
324019b4d63SUgen J.S. Antsilevich 
325019b4d63SUgen J.S. Antsilevich 	if (snp->snp_unit == -1)
326019b4d63SUgen J.S. Antsilevich 		goto destroy_notty;
327019b4d63SUgen J.S. Antsilevich 
328019b4d63SUgen J.S. Antsilevich 
329019b4d63SUgen J.S. Antsilevich 	l_tty = &tty_tabs[snp->snp_type];
330019b4d63SUgen J.S. Antsilevich 	tp = &((*l_tty->lt_tab)[snp->snp_unit]);
331019b4d63SUgen J.S. Antsilevich 
332019b4d63SUgen J.S. Antsilevich 	if ((tp->t_sc == snp) && (tp->t_state & TS_SNOOP) &&
333019b4d63SUgen J.S. Antsilevich 	    (tp->t_line == OTTYDISC || tp->t_line == NTTYDISC)) {
334019b4d63SUgen J.S. Antsilevich 		tp->t_sc = NULL;
335019b4d63SUgen J.S. Antsilevich 		tp->t_state &= ~TS_SNOOP;
336019b4d63SUgen J.S. Antsilevich 	} else
337019b4d63SUgen J.S. Antsilevich 		printf("Snoop: bad attached tty data.\n");
338019b4d63SUgen J.S. Antsilevich 
339019b4d63SUgen J.S. Antsilevich 	snp->snp_unit = -1;
340019b4d63SUgen J.S. Antsilevich 
341019b4d63SUgen J.S. Antsilevich destroy_notty:
342019b4d63SUgen J.S. Antsilevich 	selwakeup(&snp->snp_sel);
343019b4d63SUgen J.S. Antsilevich 	snp->snp_sel.si_pid = 0;
344019b4d63SUgen J.S. Antsilevich 
345019b4d63SUgen J.S. Antsilevich 	return (0);
346019b4d63SUgen J.S. Antsilevich }
347019b4d63SUgen J.S. Antsilevich 
348dde8a05bSUgen J.S. Antsilevich int
349dde8a05bSUgen J.S. Antsilevich snpclose(dev, flag)
350dde8a05bSUgen J.S. Antsilevich 	dev_t           dev;
351dde8a05bSUgen J.S. Antsilevich 	int             flag;
352dde8a05bSUgen J.S. Antsilevich {
353dde8a05bSUgen J.S. Antsilevich 	register int    unit = minor(dev);
354dde8a05bSUgen J.S. Antsilevich 	struct snoop   *snp = &snoopsw[unit];
355dde8a05bSUgen J.S. Antsilevich 
356dde8a05bSUgen J.S. Antsilevich 	snp->snp_blen = 0;
357dde8a05bSUgen J.S. Antsilevich 	free(snp->snp_buf, M_TTYS);
358019b4d63SUgen J.S. Antsilevich 	snp->snp_flags &= ~SNOOP_OPEN;
359dde8a05bSUgen J.S. Antsilevich 
360019b4d63SUgen J.S. Antsilevich 	return (snp_detach(snp));
361dde8a05bSUgen J.S. Antsilevich }
362dde8a05bSUgen J.S. Antsilevich 
363dde8a05bSUgen J.S. Antsilevich 
364dde8a05bSUgen J.S. Antsilevich 
365dde8a05bSUgen J.S. Antsilevich 
366dde8a05bSUgen J.S. Antsilevich int
367dde8a05bSUgen J.S. Antsilevich snpioctl(dev, cmd, data, flag)
368dde8a05bSUgen J.S. Antsilevich 	dev_t           dev;
369dde8a05bSUgen J.S. Antsilevich 	int             cmd;
370dde8a05bSUgen J.S. Antsilevich 	caddr_t         data;
371dde8a05bSUgen J.S. Antsilevich 	int             flag;
372dde8a05bSUgen J.S. Antsilevich {
373dde8a05bSUgen J.S. Antsilevich 	int             unit = minor(dev), s;
374dde8a05bSUgen J.S. Antsilevich 	int             tunit, ttype;
375dde8a05bSUgen J.S. Antsilevich 	struct snoop   *snp = &snoopsw[unit];
376dde8a05bSUgen J.S. Antsilevich 	struct tty     *tp, *tpo;
377dde8a05bSUgen J.S. Antsilevich 	struct tty_tab *l_tty, *l_otty;
378dde8a05bSUgen J.S. Antsilevich 
379dde8a05bSUgen J.S. Antsilevich 	switch (cmd) {
380dde8a05bSUgen J.S. Antsilevich 	case SNPSTTY:
381dde8a05bSUgen J.S. Antsilevich 		tunit = ((struct snptty *) data)->st_unit;
382dde8a05bSUgen J.S. Antsilevich 		ttype = ((struct snptty *) data)->st_type;
383dde8a05bSUgen J.S. Antsilevich 
384dde8a05bSUgen J.S. Antsilevich 		if (ttype < 0 || ttype > ST_MAXTYPE)
385dde8a05bSUgen J.S. Antsilevich 			return (EINVAL);
386dde8a05bSUgen J.S. Antsilevich 
387dde8a05bSUgen J.S. Antsilevich 		l_tty = &tty_tabs[ttype];
388dde8a05bSUgen J.S. Antsilevich 		if (l_tty->lt_tab == NULL)
389dde8a05bSUgen J.S. Antsilevich 			return (EINVAL);
390dde8a05bSUgen J.S. Antsilevich 
391dde8a05bSUgen J.S. Antsilevich 		if (tunit < 0 || tunit >= l_tty->lt_max)
392dde8a05bSUgen J.S. Antsilevich 			return (EINVAL);
393dde8a05bSUgen J.S. Antsilevich 
394dde8a05bSUgen J.S. Antsilevich 		tp = &((*l_tty->lt_tab)[tunit]);
395dde8a05bSUgen J.S. Antsilevich 
396dde8a05bSUgen J.S. Antsilevich 		if (tp->t_sc != (caddr_t) snp && (tp->t_state & TS_SNOOP))
397dde8a05bSUgen J.S. Antsilevich 			return (EBUSY);
398dde8a05bSUgen J.S. Antsilevich 
399dde8a05bSUgen J.S. Antsilevich 		if (tp->t_line != OTTYDISC && tp->t_line != NTTYDISC)
400dde8a05bSUgen J.S. Antsilevich 			return (EBUSY);
401dde8a05bSUgen J.S. Antsilevich 
402dde8a05bSUgen J.S. Antsilevich 		s = spltty();
403dde8a05bSUgen J.S. Antsilevich 		if (snp->snp_unit != -1) {
404dde8a05bSUgen J.S. Antsilevich 			l_otty = &tty_tabs[snp->snp_type];
405dde8a05bSUgen J.S. Antsilevich 			tpo = &((*l_otty->lt_tab)[snp->snp_unit]);
406dde8a05bSUgen J.S. Antsilevich 			tpo->t_state &= ~TS_SNOOP;
407dde8a05bSUgen J.S. Antsilevich 		}
408dde8a05bSUgen J.S. Antsilevich 		tp->t_sc = (caddr_t) snp;
409dde8a05bSUgen J.S. Antsilevich 		tp->t_state |= TS_SNOOP;
410dde8a05bSUgen J.S. Antsilevich 		snp->snp_unit = tunit;
411019b4d63SUgen J.S. Antsilevich 		snp->snp_type = ttype;
412019b4d63SUgen J.S. Antsilevich 		snp->snp_flags &= ~SNOOP_DOWN;
413dde8a05bSUgen J.S. Antsilevich 		splx(s);
414dde8a05bSUgen J.S. Antsilevich 
415dde8a05bSUgen J.S. Antsilevich 		break;
416dde8a05bSUgen J.S. Antsilevich 	case SNPGTTY:
417dde8a05bSUgen J.S. Antsilevich 		((struct snptty *) data)->st_unit = snp->snp_unit;
418dde8a05bSUgen J.S. Antsilevich 		((struct snptty *) data)->st_type = snp->snp_type;
419dde8a05bSUgen J.S. Antsilevich 		break;
420dde8a05bSUgen J.S. Antsilevich 
421dde8a05bSUgen J.S. Antsilevich 	case FIONBIO:
422dde8a05bSUgen J.S. Antsilevich 		if (*(int *) data)
423dde8a05bSUgen J.S. Antsilevich 			snp->snp_flags |= SNOOP_NBIO;
424dde8a05bSUgen J.S. Antsilevich 		else
425dde8a05bSUgen J.S. Antsilevich 			snp->snp_flags &= ~SNOOP_NBIO;
426dde8a05bSUgen J.S. Antsilevich 		break;
427dde8a05bSUgen J.S. Antsilevich 	case FIOASYNC:
428dde8a05bSUgen J.S. Antsilevich 		if (*(int *) data)
429dde8a05bSUgen J.S. Antsilevich 			snp->snp_flags |= SNOOP_ASYNC;
430dde8a05bSUgen J.S. Antsilevich 		else
431dde8a05bSUgen J.S. Antsilevich 			snp->snp_flags &= ~SNOOP_ASYNC;
432dde8a05bSUgen J.S. Antsilevich 		break;
433dde8a05bSUgen J.S. Antsilevich 	case FIONREAD:
434dde8a05bSUgen J.S. Antsilevich 		s = spltty();
435dde8a05bSUgen J.S. Antsilevich 		if (snp->snp_unit != -1)
436dde8a05bSUgen J.S. Antsilevich 			*(int *) data = snp->snp_len;
437019b4d63SUgen J.S. Antsilevich 		else if (snp->snp_flags & SNOOP_DOWN)
438019b4d63SUgen J.S. Antsilevich 			*(int *) data = -1;
439dde8a05bSUgen J.S. Antsilevich 		else
440dde8a05bSUgen J.S. Antsilevich 			*(int *) data = 0;
441dde8a05bSUgen J.S. Antsilevich 		splx(s);
442dde8a05bSUgen J.S. Antsilevich 		break;
443dde8a05bSUgen J.S. Antsilevich 	default:
444dde8a05bSUgen J.S. Antsilevich 		return (ENOTTY);
445dde8a05bSUgen J.S. Antsilevich 	}
446dde8a05bSUgen J.S. Antsilevich 	return (0);
447dde8a05bSUgen J.S. Antsilevich }
448dde8a05bSUgen J.S. Antsilevich 
449dde8a05bSUgen J.S. Antsilevich 
450dde8a05bSUgen J.S. Antsilevich int
451dde8a05bSUgen J.S. Antsilevich snpselect(dev, rw, p)
452dde8a05bSUgen J.S. Antsilevich 	dev_t           dev;
453dde8a05bSUgen J.S. Antsilevich 	int             rw;
454dde8a05bSUgen J.S. Antsilevich 	struct proc    *p;
455dde8a05bSUgen J.S. Antsilevich {
456dde8a05bSUgen J.S. Antsilevich 	int             unit = minor(dev), s;
457dde8a05bSUgen J.S. Antsilevich 	struct snoop   *snp = &snoopsw[unit];
458dde8a05bSUgen J.S. Antsilevich 
459dde8a05bSUgen J.S. Antsilevich 	if (rw != FREAD) {
460dde8a05bSUgen J.S. Antsilevich 		return 0;
461dde8a05bSUgen J.S. Antsilevich 	}
462dde8a05bSUgen J.S. Antsilevich 	if (snp->snp_len > 0) {
463dde8a05bSUgen J.S. Antsilevich 		return 1;
464dde8a05bSUgen J.S. Antsilevich 	}
465019b4d63SUgen J.S. Antsilevich 	/*
466019b4d63SUgen J.S. Antsilevich 	 * If snoop is down,we don't want to select() forever so we return 1.
467019b4d63SUgen J.S. Antsilevich 	 * Caller should see if we down via FIONREAD ioctl().The last should
468019b4d63SUgen J.S. Antsilevich 	 * return -1 to indicate down state.
469019b4d63SUgen J.S. Antsilevich 	 */
470019b4d63SUgen J.S. Antsilevich 	if (snp->snp_flags & SNOOP_DOWN) {
471019b4d63SUgen J.S. Antsilevich 		return 1;
472019b4d63SUgen J.S. Antsilevich 	}
473dde8a05bSUgen J.S. Antsilevich 	selrecord(p, &snp->snp_sel);
474dde8a05bSUgen J.S. Antsilevich 	return 0;
475dde8a05bSUgen J.S. Antsilevich }
476dde8a05bSUgen J.S. Antsilevich 
477dde8a05bSUgen J.S. Antsilevich #endif
478