Annotation of embedaddon/ntp/kernel/tty_chu.c, revision 1.1.1.1
1.1 misho 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:
31: struct 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:
46: int 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*/
54: chuopen(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: */
84: chuclose(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: */
101: churead(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: */
134: chuinput(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: */
226: chuioctl(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:
246: chuselect(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);
272: win:
273: splx(s);
274: return (1);
275: }
276: #endif NCHU
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>