3 /* tty_chu.c,v 3.1 1993/07/06 01:07:30 jbj Exp
4 * tty_chu.c - CHU line driver
10 #include "../h/param.h"
11 #include "../h/types.h"
12 #include "../h/systm.h"
14 #include "../h/user.h"
15 #include "../h/ioctl.h"
17 #include "../h/proc.h"
18 #include "../h/file.h"
19 #include "../h/conf.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.
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
];
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 */
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.
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
)
69 for (chu
= chu_data
; chu
< &chu_data
[NCHU
]; chu
++)
72 if (chu
>= &chu
[NCHU
])
75 chu
->lastindex
= chu
->curindex
= 0;
77 chu
->chubuf
[0].ncodechars
= 0;
78 tp
->T_LINEP
= (caddr_t
) chu
;
83 * Break down... called when discipline changed or from device
87 register struct tty
*tp
;
89 register int s
= spl5();
91 ((struct chudata
*) tp
->T_LINEP
)->used
= 0;
94 tp
->t_rawq
.c_cc
= 0; /* clear queues -- paranoid */
96 tp
->t_line
= 0; /* paranoid: avoid races */
101 * Read a CHU buffer. Sleep on the current buffer
104 register struct tty
*tp
;
107 register struct chudata
*chu
;
108 register struct chucode
*chucode
;
111 if ((tp
->t_state
&TS_CARR_ON
)==0)
114 chu
= (struct chudata
*) (tp
->T_LINEP
);
117 chucode
= &(chu
->chubuf
[chu
->lastindex
]);
118 while (chu
->curindex
== chu
->lastindex
) {
120 sleep((caddr_t
)chucode
, TTIPRI
);
123 if (++(chu
->lastindex
) >= NUMCHUBUFS
)
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.
138 register struct tty
*tp
;
140 register struct chudata
*chu
= (struct chudata
*) tp
->T_LINEP
;
141 register struct chucode
*chuc
;
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 */
158 * Call microtime() to get the current time of day
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
;
170 sec
= tv
.tv_sec
- chuc
->codetimes
[i
-1].tv_sec
;
171 usec
= tv
.tv_usec
- chuc
->codetimes
[i
-1].tv_usec
;
176 if (sec
!= 0 || usec
> CHUMAXUSEC
) {
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
;
196 * Mark this buffer full and point at next. If the
197 * next buffer is full we overwrite it by bumping the
200 chuc
->ncodechars
= NCHUCHARS
;
201 if (++(chu
->curindex
) >= NUMCHUBUFS
)
203 if (chu
->curindex
== chu
->lastindex
)
204 if (++(chu
->lastindex
) >= NUMCHUBUFS
)
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.
213 selwakeup(tp
->t_rsel
, tp
->t_state
&TS_RCOLL
);
214 tp
->t_state
&= ~TS_RCOLL
;
217 if (tp
->t_state
& TS_ASYNC
)
218 gsignal(tp
->t_pgrp
, SIGIO
);
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
)
244 return (ENOTTY
); /* not quite appropriate */
252 register struct tty
*tp
= &cdevsw
[major(dev
)].d_ttys
[minor(dev
)];
256 chu
= (struct chudata
*) (tp
->T_LINEP
);
261 if (chu
->curindex
!= chu
->lastindex
)
263 if (tp
->t_rsel
&& tp
->t_rsel
->p_wchan
== (caddr_t
)&selwait
)
264 tp
->t_state
|= TS_RCOLL
;
266 tp
->t_rsel
= u
.u_procp
;