|
|
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.