Annotation of embedaddon/ntp/kernel/tty_chu.c, revision 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>