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