PageRenderTime 22ms CodeModel.GetById 1ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 0ms

/contrib/ntp/kernel/tty_chu.c

https://bitbucket.org/freebsd/freebsd-head/
C | 276 lines | 175 code | 31 blank | 70 comment | 34 complexity | 170faa1cdf4dc93336873598760fef06 MD5 | raw file
  1/* tty_chu.c,v 3.1 1993/07/06 01:07:30 jbj Exp
  2 * tty_chu.c - CHU line driver
  3 */
  4
  5#include "chu.h"
  6#if NCHU > 0
  7
  8#include "../h/param.h"
  9#include "../h/types.h"
 10#include "../h/systm.h"
 11#include "../h/dir.h"
 12#include "../h/user.h"
 13#include "../h/ioctl.h"
 14#include "../h/tty.h"
 15#include "../h/proc.h"
 16#include "../h/file.h"
 17#include "../h/conf.h"
 18#include "../h/buf.h"
 19#include "../h/uio.h"
 20
 21#include "../h/chudefs.h"
 22
 23/*
 24 * Line discipline for receiving CHU time codes.
 25 * Does elementary noise elimination, takes time stamps after
 26 * the arrival of each character, returns a buffer full of the
 27 * received 10 character code and the associated time stamps.
 28 */
 29#define	NUMCHUBUFS	3
 30
 31struct chudata {
 32	u_char used;		/* Set to 1 when structure in use */
 33	u_char lastindex;	/* least recently used buffer */
 34	u_char curindex;	/* buffer to use */
 35	u_char sleeping;	/* set to 1 when we're sleeping on a buffer */
 36	struct chucode chubuf[NUMCHUBUFS];
 37} chu_data[NCHU];
 38
 39/*
 40 * Number of microseconds we allow between
 41 * character arrivals.  The speed is 300 baud
 42 * so this should be somewhat more than 30 msec
 43 */
 44#define	CHUMAXUSEC	(50*1000)	/* 50 msec */
 45
 46int chu_debug = 0;
 47
 48/*
 49 * Open as CHU time discipline.  Called when discipline changed
 50 * with ioctl, and changes the interpretation of the information
 51 * in the tty structure.
 52 */
 53/*ARGSUSED*/
 54chuopen(dev, tp)
 55	dev_t dev;
 56	register struct tty *tp;
 57{
 58	register struct chudata *chu;
 59
 60	/*
 61	 * Don't allow multiple opens.  This will also protect us
 62	 * from someone opening /dev/tty
 63	 */
 64	if (tp->t_line == CHULDISC)
 65		return (EBUSY);
 66	ttywflush(tp);
 67	for (chu = chu_data; chu < &chu_data[NCHU]; chu++)
 68		if (!chu->used)
 69			break;
 70	if (chu >= &chu[NCHU])
 71		return (EBUSY);
 72	chu->used++;
 73	chu->lastindex = chu->curindex = 0;
 74	chu->sleeping = 0;
 75	chu->chubuf[0].ncodechars = 0;
 76	tp->T_LINEP = (caddr_t) chu;
 77	return (0);
 78}
 79
 80/*
 81 * Break down... called when discipline changed or from device
 82 * close routine.
 83 */
 84chuclose(tp)
 85	register struct tty *tp;
 86{
 87	register int s = spl5();
 88
 89	((struct chudata *) tp->T_LINEP)->used = 0;
 90	tp->t_cp = 0;
 91	tp->t_inbuf = 0;
 92	tp->t_rawq.c_cc = 0;		/* clear queues -- paranoid */
 93	tp->t_canq.c_cc = 0;
 94	tp->t_line = 0;			/* paranoid: avoid races */
 95	splx(s);
 96}
 97
 98/*
 99 * Read a CHU buffer.  Sleep on the current buffer
100 */
101churead(tp, uio)
102	register struct tty *tp;
103	struct uio *uio;
104{
105	register struct chudata *chu;
106	register struct chucode *chucode;
107	register int s;
108
109	if ((tp->t_state&TS_CARR_ON)==0)
110		return (EIO);
111
112	chu = (struct chudata *) (tp->T_LINEP);
113
114	s = spl5();
115	chucode = &(chu->chubuf[chu->lastindex]);
116	while (chu->curindex == chu->lastindex) {
117		chu->sleeping = 1;
118		sleep((caddr_t)chucode, TTIPRI);
119	}
120	chu->sleeping = 0;
121	if (++(chu->lastindex) >= NUMCHUBUFS)
122		chu->lastindex = 0;
123	splx(s);
124
125	return (uiomove((caddr_t)chucode, sizeof(*chucode), UIO_READ, uio));
126}
127
128/*
129 * Low level character input routine.
130 * If the character looks okay, grab a time stamp.  If the stuff in
131 * the buffer is too old, dump it and start fresh.  If the character is
132 * non-BCDish, everything in the buffer too.
133 */
134chuinput(c, tp)
135	register int c;
136	register struct tty *tp;
137{
138	register struct chudata *chu = (struct chudata *) tp->T_LINEP;
139	register struct chucode *chuc;
140	register int i;
141	long sec, usec;
142	struct timeval tv;
143
144	/*
145	 * Do a check on the BSDness of the character.  This delays
146	 * the time stamp a bit but saves a fair amount of overhead
147	 * when the static is bad.
148	 */
149	if (((c) & 0xf) > 9 || (((c)>>4) & 0xf) > 9) {
150		chuc = &(chu->chubuf[chu->curindex]);
151		chuc->ncodechars = 0;	/* blow all previous away */
152		return;
153	}
154
155	/*
156	 * Call microtime() to get the current time of day
157	 */
158	microtime(&tv);
159
160	/*
161	 * Compute the difference in this character's time stamp
162	 * and the last.  If it exceeds the margin, blow away all
163	 * the characters currently in the buffer.
164	 */
165	chuc = &(chu->chubuf[chu->curindex]);
166	i = (int)chuc->ncodechars;
167	if (i > 0) {
168		sec = tv.tv_sec - chuc->codetimes[i-1].tv_sec;
169		usec = tv.tv_usec - chuc->codetimes[i-1].tv_usec;
170		if (usec < 0) {
171			sec -= 1;
172			usec += 1000000;
173		}
174		if (sec != 0 || usec > CHUMAXUSEC) {
175			i = 0;
176			chuc->ncodechars = 0;
177		}
178	}
179
180	/*
181	 * Store the character.  If we're done, have to tell someone
182	 */
183	chuc->codechars[i] = (u_char)c;
184	chuc->codetimes[i] = tv;
185
186	if (++i < NCHUCHARS) {
187		/*
188		 * Not much to do here.  Save the count and wait
189		 * for another character.
190		 */
191		chuc->ncodechars = (u_char)i;
192	} else {
193		/*
194		 * Mark this buffer full and point at next.  If the
195		 * next buffer is full we overwrite it by bumping the
196		 * next pointer.
197		 */
198		chuc->ncodechars = NCHUCHARS;
199		if (++(chu->curindex) >= NUMCHUBUFS)
200			chu->curindex = 0;
201		if (chu->curindex == chu->lastindex)
202			if (++(chu->lastindex) >= NUMCHUBUFS)
203				chu->lastindex = 0;
204		chu->chubuf[chu->curindex].ncodechars = 0;
205
206		/*
207		 * Wake up anyone sleeping on this.  Also wake up
208		 * selectors and/or deliver a SIGIO as required.
209		 */
210		if (tp->t_rsel) {
211			selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
212			tp->t_state &= ~TS_RCOLL;
213			tp->t_rsel = 0;
214		}
215		if (tp->t_state & TS_ASYNC)
216			gsignal(tp->t_pgrp, SIGIO);
217		if (chu->sleeping)
218			(void) wakeup((caddr_t)chuc);
219	}
220}
221
222/*
223 * Handle ioctls.  We reject all tty-style except those that
224 * change the line discipline.
225 */
226chuioctl(tp, cmd, data, flag)
227	struct tty *tp;
228	int cmd;
229	caddr_t data;
230	int flag;
231{
232
233	if ((cmd>>8) != 't')
234		return (-1);
235	switch (cmd) {
236	case TIOCSETD:
237	case TIOCGETD:
238	case TIOCGETP:
239	case TIOCGETC:
240		return (-1);
241	}
242	return (ENOTTY);	/* not quite appropriate */
243}
244
245
246chuselect(dev, rw)
247	dev_t dev;
248	int rw;
249{
250	register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
251	struct chudata *chu;
252	int s = spl5();
253
254	chu = (struct chudata *) (tp->T_LINEP);
255
256	switch (rw) {
257
258	case FREAD:
259		if (chu->curindex != chu->lastindex)
260			goto win;
261		if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
262			tp->t_state |= TS_RCOLL;
263		else
264			tp->t_rsel = u.u_procp;
265		break;
266
267	case FWRITE:
268		goto win;
269	}
270	splx(s);
271	return (0);
272win:
273	splx(s);
274	return (1);
275}
276#endif NCHU