|
|
1.1 root 1: /*
2: * Line discipline for Datakit TDK protocol
3: */
4: #define NDT 16
5: #define TR(x) /**/
6:
7: #include "../h/param.h"
8: #include "../h/stream.h"
9: #include "../h/conf.h"
10: #include "../h/ioctl.h"
11: #include "../h/ttyld.h"
12:
13: struct dt {
14: char nack;
15: char cack;
16: char nchar;
17: char state;
18: short lastecho;
19: struct queue *queue;
20: } dt[NDT];
21:
22: /* states */
23: #define CLOG1 01
24: #define CLOG2 02
25: #define STOP 04
26: #define USE 010
27:
28: /* DK control packet codes */
29: #define D_BREAK 07
30: #define D_ECHO 010
31: #define D_ACK 020
32: #define D_DELAY 030
33: #define D_SNDBRK 03
34: #define DKDATA 0400
35:
36: #define DTNC 32 /* chars sent between ECHO requests */
37:
38: int dtliput(), dtlisrv(), dtlopen(), dtlclose(), putq(), dtlosrv();
39: static struct qinit dtlrinit = {dtliput, dtlisrv, dtlopen, dtlclose, 129, 129};
40: static struct qinit dtlwinit = {putq, dtlosrv, dtlopen, dtlclose, 129, 65};
41: struct streamtab dtlinfo = {&dtlrinit, &dtlwinit};
42:
43: /*
44: * open
45: */
46: dtlopen(q, dev)
47: register struct queue *q;
48: {
49: register struct dt *dp;
50: extern int dtltimer(), hz;
51: static timer_on = 0;
52:
53: if (timer_on==0) {
54: timeout(dtltimer, (caddr_t)NULL, 10*hz);
55: timer_on = 1;
56: }
57: dp = (struct dt *)q->ptr;
58: if (dp)
59: return(1);
60: for (dp = dt; dp < &dt[NDT]; dp++) {
61: if ((dp->state&USE)==0) {
62: dp->state = USE;
63: dp->lastecho = 0;
64: dp->cack = 0;
65: dp->nack = 0;
66: q->ptr = (caddr_t)dp;
67: WR(q)->ptr = (caddr_t)dp;
68: dp->queue = WR(q);
69: q->flag &= ~QNOENB;
70: return(1);
71: }
72: }
73: return(0);
74: }
75:
76: dtlclose(q)
77: register struct queue *q;
78: {
79: register struct dt *dp = (struct dt *)q->ptr;
80:
81: dp->state = 0;
82: }
83:
84:
85: /*
86: * output server
87: */
88: dtlosrv(q)
89: register struct queue *q;
90: {
91: register struct block *bp;
92: register struct dt *dp;
93: register c;
94:
95: dp = (struct dt *)q->ptr;
96: for (;;) {
97: if (q->next->flag & QFULL) /* unlikely for DK */
98: return;
99: if ((bp = getq(q)) == NULL)
100: return;
101: if (dp->state & (STOP|CLOG1)) {
102: switch (bp->type) {
103:
104: case M_DATA:
105: case M_BREAK:
106: case M_DELAY:
107: putbq(q, bp);
108: q->flag |= QWANTR;
109: return;
110: }
111: }
112: switch (bp->type) {
113:
114: case M_STOP:
115: freeb(bp);
116: dp->state |= STOP;
117: q->flag |= QWANTR;
118: continue; /* in case there is a START */
119:
120: case M_START:
121: freeb(bp);
122: dp->state &= ~STOP;
123: continue;
124:
125: case M_FLUSH:
126: flushq(q, 0);
127: freeb(bp);
128: dp->state &= ~STOP;
129: continue;
130:
131: case M_DATA:
132: if (bp->wptr - bp->rptr <= DTNC - dp->nchar) {
133: TR(bp->wptr-bp->rptr);
134: dp->nchar += bp->wptr - bp->rptr;
135: (*q->next->qinfo->putp)(q->next, bp);
136: } else if (dp->nchar < DTNC) {
137: register struct block *bp1;
138: bp1 = allocb(DTNC);
139: if (bp1==NULL) {
140: putbq(q, bp);
141: dp->state |= CLOG1;
142: return;
143: }
144: bcopy(bp->rptr, bp1->wptr, DTNC-dp->nchar);
145: bp->rptr += DTNC-dp->nchar;
146: bp1->wptr += DTNC-dp->nchar;
147: dp->nchar = DTNC;
148: TR(bp1->wptr-bp1->rptr);
149: (*q->next->qinfo->putp)(q->next, bp1);
150: putbq(q, bp);
151: }
152: break;
153:
154: case M_BREAK:
155: bp->type = M_CTL;
156: *bp->wptr++ = D_SNDBRK;
157: (*q->next->qinfo->putp)(q->next, bp);
158: dp->nchar++;
159: break;
160:
161: case M_DELAY:
162: c = *bp->rptr;
163: *bp->rptr = D_DELAY;
164: bp->type = M_CTL;
165: while (c) {
166: (*bp->rptr)++;
167: c >>= 1;
168: }
169: TR(0377);
170: (*q->next->qinfo->putp)(q->next, bp);
171: dp->nchar++;
172: break;
173:
174: case M_DELIM:
175: freeb(bp);
176: continue;
177:
178: case M_IOCTL:
179: switch (((union stmsg *)bp->rptr)->ioc0.com) {
180:
181: case TIOCSETP:
182: case TIOCSETN:
183: bp->wptr = bp->rptr;
184: case TIOCGETP:
185: bp->type = M_IOCACK;
186: qreply(q, bp);
187: continue;
188: }
189: /* flow through to */
190: default:
191: dp->nchar += bp->wptr - bp->rptr;
192: (*q->next->qinfo->putp)(q->next, bp);
193: break;
194: }
195: if (dp->nchar >= DTNC) {
196: if ((bp = allocb(1)) == NULL) {
197: dp->state |= CLOG1;
198: return;
199: }
200: dp->nchar -= DTNC;
201: dp->nack++;
202: dp->nack &= 03;
203: if (dp->cack == ((dp->nack+2) & 03))
204: dp->state |= CLOG1;
205: TR(0200+dp->nack+(((dp->state&CLOG1)!=0)<<5));
206: bp->type = M_CTL;
207: *bp->wptr++ = D_ECHO + dp->nack;
208: (*q->next->qinfo->putp)(q->next, bp);
209: }
210: }
211: }
212:
213: /*
214: * put procedure for input.
215: */
216: dtliput(q, bp)
217: register struct queue *q;
218: register struct block *bp;
219: {
220: register struct dt *dp;
221: register c;
222:
223: dp = (struct dt *)q->ptr;
224: switch (bp->type) {
225:
226: case M_CTL:
227: bp->type = M_DATA;
228: c = *bp->rptr++;
229: if ((c & 0370) == D_ACK) { /* resp to my ECHO */
230: dp->cack = c&03;
231: if (dp->state & CLOG1) {
232: dp->state &= ~(CLOG1|CLOG2);
233: qenable(WR(q));
234: }
235: TR(0300+dp->cack);
236: } else if ((c & 0370) == D_ECHO) { /* request for an ACK */
237: dp->lastecho = D_ACK + (c&07);
238: qenable(q);
239: } else if (c == D_BREAK) {
240: flushq(q, 0);
241: putctl(q->next, M_BREAK);
242: } else
243: printf("DT unkn ctrl %o\n", c);
244: break;
245:
246: case M_DATA:
247: break;
248:
249: case M_IOCACK:
250: case M_IOCNAK:
251: case M_HANGUP:
252: (*q->next->qinfo->putp)(q->next, bp);
253: return;
254:
255: default:
256: printf("unknown msg type %d in dtliput\n", bp->type);
257: freeb(bp);
258: return;
259: }
260: if (bp->wptr > bp->rptr && (q->flag&QFULL)==0)
261: putq(q, bp);
262: else
263: freeb(bp);
264: }
265:
266: /*
267: * DT input server
268: * -- copy data; send out latest ack if next queue is not full.
269: */
270: dtlisrv(q)
271: register struct queue *q;
272: {
273: register struct block *bp;
274: register struct dt *dp;
275: register s;
276:
277: while ((q->next->flag & QFULL) == 0) {
278: bp = getq(q);
279: if (bp == NULL) {
280: dp = (struct dt *)q->ptr;
281: s = spl5();
282: if (dp->lastecho) {
283: putctl1(WR(q)->next, M_CTL, dp->lastecho);
284: dp->lastecho = 0;
285: }
286: splx(s);
287: return;
288: }
289: (*q->next->qinfo->putp)(q->next, bp);
290: }
291: }
292:
293: dtltimer()
294: {
295: register struct dt *dp;
296:
297: for (dp = dt; dp < &dt[NDT]; dp++) {
298: if ((dp->state&(USE|CLOG1)) == (USE|CLOG1)) {
299: if (dp->state&CLOG2) {
300: register struct queue *q = dp->queue;
301: putctl1(q->next, M_CTL, D_ECHO + dp->nack);
302: TR(0340+dp->nack);
303: }
304: dp->state |= CLOG2;
305: }
306: }
307: timeout(dtltimer, (caddr_t)NULL, 10*hz);
308: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.