1: #define USER 1 2: #include <stdio.h> 3: #include <sys/pk.p> 4: #include <sys/param.h> 5: #include <sys/pk.h> 6: #include <sys/buf.h> 7: #include <setjmp.h> 8: #include <signal.h> 9: 10: #define PKTIME 10 11: int Errorrate; 12: int Conbad = 0; 13: int Ntimeout = 0; 14: #define CONBAD 5 15: #define NTIMEOUT 50 16: /* 17: * packet driver support routines 18: * 19: */ 20: 21: struct pack *pklines[NPLINES]; 22: 23: /* 24: * start initial synchronization. 25: */ 26: 27: struct pack * 28: pkopen(ifn, ofn) 29: int ifn, ofn; 30: { 31: struct pack *pk; 32: char **bp; 33: int i; 34: 35: if (++pkactive >= NPLINES) 36: return(NULL); 37: if ((pk = (struct pack *) malloc(sizeof (struct pack))) == NULL) 38: return(NULL); 39: pkzero((caddr_t) pk, sizeof (struct pack)); 40: pk->p_ifn = ifn; 41: pk->p_ofn = ofn; 42: pk->p_xsize = pk->p_rsize = PACKSIZE; 43: pk->p_rwindow = pk->p_swindow = WINDOWS; 44: /* allocate input windows */ 45: for (i = 0; i < pk->p_rwindow; i++) { 46: if ((bp = (char **) GETEPACK) == NULL) 47: break; 48: *bp = (char *) pk->p_ipool; 49: pk->p_ipool = bp; 50: } 51: if (i == 0) 52: return(NULL); 53: pk->p_rwindow = i; 54: 55: /* start synchronization */ 56: pk->p_msg = pk->p_rmsg = M_INITA; 57: for (i = 0; i < NPLINES; i++) { 58: if (pklines[i] == NULL) { 59: pklines[i] = pk; 60: break; 61: } 62: } 63: if (i >= NPLINES) 64: return(NULL); 65: pkoutput(pk); 66: 67: while ((pk->p_state & LIVE) == 0) { 68: PKGETPKT(pk); 69: } 70: 71: pkreset(pk); 72: return(pk); 73: } 74: 75: 76: /* 77: * input framing and block checking. 78: * frame layout for most devices is: 79: * 80: * S|K|X|Y|C|Z| ... data ... | 81: * 82: * where S == initial synch byte 83: * K == encoded frame size (indexes pksizes[]) 84: * X, Y == block check bytes 85: * C == control byte 86: * Z == XOR of header (K^X^Y^C) 87: * data == 0 or more data bytes 88: * 89: */ 90: 91: int pksizes[] = { 92: 1, 32, 64, 128, 256, 512, 1024, 2048, 4096, 1 93: }; 94: 95: #define GETRIES 5 96: /* 97: * Pseudo-dma byte collection. 98: */ 99: 100: pkgetpack(ipk) 101: struct pack *ipk; 102: { 103: int ret, k, tries; 104: register char *p; 105: struct pack *pk; 106: struct header *h; 107: unsigned short sum; 108: int ifn; 109: char **bp; 110: char hdchk; 111: 112: if (Conbad > CONBAD /* || Ntimeout > NTIMEOUT */) 113: pkfail(); 114: pk = PADDR; 115: ifn = pk->p_ifn; 116: 117: /* find HEADER */ 118: for (tries = 0; tries < GETRIES; ) { 119: p = (caddr_t) &pk->p_ihbuf; 120: if ((ret = pkcget(ifn, p, 1)) < 0) { 121: /* set up retransmit or REJ */ 122: tries++; 123: pk->p_msg |= pk->p_rmsg; 124: if (pk->p_msg == 0) 125: pk->p_msg |= M_RR; 126: if ((pk->p_state & LIVE) == LIVE) 127: pk->p_state |= RXMIT; 128: pkoutput(pk); 129: continue; 130: } 131: if (*p != SYN) 132: continue; 133: p++; 134: ret = pkcget(ifn, p, HDRSIZ - 1); 135: if (ret == -1) 136: continue; 137: break; 138: } 139: if (tries >= GETRIES) { 140: PKDEBUG(4, "tries = %d\n", tries); 141: pkfail(); 142: } 143: 144: h = (struct header * ) &pk->p_ihbuf; 145: p = (caddr_t) h; 146: hdchk = p[1] ^ p[2] ^ p[3] ^ p[4]; 147: p += 2; 148: sum = (unsigned) *p++; 149: sum |= (unsigned) *p << 8; 150: h->sum = sum; 151: PKDEBUG(7, "rec h->cntl %o\n", (unsigned) h->cntl); 152: k = h->ksize; 153: if (hdchk != h->ccntl) { 154: /* bad header */ 155: PKDEBUG(7, "bad header %o,", hdchk); 156: PKDEBUG(7, "h->ccntl %o\n", h->ccntl); 157: Conbad++; 158: return; 159: } 160: if (k == 9) { 161: if (h->sum + h->cntl == CHECK) { 162: pkcntl(h->cntl, pk); 163: Conbad = 0; 164: PKDEBUG(7, "state - %o\n", pk->p_state); 165: } 166: else { 167: /* bad header */ 168: Conbad++; 169: PKDEBUG(7, "bad header %o\n", h->cntl); 170: pk->p_state |= BADFRAME; 171: } 172: return; 173: } 174: if (k && pksizes[k] == pk->p_rsize) { 175: pk->p_rpr = h->cntl & MOD8; 176: pksack(pk); 177: Conbad = 0; 178: bp = pk->p_ipool; 179: pk->p_ipool = (char **) *bp; 180: if (bp == NULL) { 181: PKDEBUG(7, "bp NULL %s\n", ""); 182: return; 183: } 184: } 185: else { 186: Conbad++; 187: return; 188: } 189: ret = pkcget(pk->p_ifn, (char *) bp, pk->p_rsize); 190: PKASSERT(ret != -1, "PKGETPKT CAN't READ %d", ret); 191: pkdata(h->cntl, h->sum, pk, (char *) bp); 192: return; 193: } 194: 195: 196: pkdata(c, sum, pk, bp) 197: char c; 198: short sum; 199: register struct pack *pk; 200: char **bp; 201: { 202: register x; 203: int t; 204: char m; 205: 206: if (pk->p_state & DRAINO || !(pk->p_state & LIVE)) { 207: pk->p_msg |= pk->p_rmsg; 208: pkoutput(pk); 209: goto drop; 210: } 211: t = next[pk->p_pr]; 212: for(x=pk->p_pr; x!=t; x = (x-1)&7) { 213: if (pk->p_is[x] == 0) 214: goto slot; 215: } 216: drop: 217: *bp = (char *)pk->p_ipool; 218: pk->p_ipool = bp; 219: return; 220: 221: slot: 222: m = mask[x]; 223: pk->p_imap |= m; 224: pk->p_is[x] = c; 225: pk->p_isum[x] = sum; 226: pk->p_ib[x] = (char *)bp; 227: return; 228: } 229: 230: 231: 232: /* 233: * setup input transfers 234: */ 235: pkrstart(pk) 236: {} 237: 238: /* 239: * Start transmission on output device associated with pk. 240: * For asynch devices (t_line==1) framing is 241: * imposed. For devices with framing and crc 242: * in the driver (t_line==2) the transfer is 243: * passed on to the driver. 244: */ 245: pkxstart(pk, cntl, x) 246: struct pack *pk; 247: char cntl; 248: register x; 249: { 250: register char *p; 251: int ret; 252: short checkword; 253: char hdchk; 254: 255: p = (caddr_t) &pk->p_ohbuf; 256: *p++ = SYN; 257: if (x < 0) { 258: *p++ = hdchk = 9; 259: checkword = cntl; 260: } 261: else { 262: *p++ = hdchk = pk->p_lpsize; 263: checkword = pk->p_osum[x] ^ (unsigned)cntl; 264: } 265: checkword = CHECK - checkword; 266: *p = checkword; 267: hdchk ^= *p++; 268: *p = checkword>>8; 269: hdchk ^= *p++; 270: *p = cntl; 271: hdchk ^= *p++; 272: *p = hdchk; 273: /* writes */ 274: PKDEBUG(7, "send %o\n", (unsigned) cntl); 275: p = (caddr_t) & pk->p_ohbuf; 276: if (x < 0) { 277: GENERROR(p, HDRSIZ); 278: ret = write(pk->p_ofn, p, HDRSIZ); 279: PKASSERT(ret == HDRSIZ, "PKXSTART ret %d", ret); 280: } 281: else { 282: char buf[PACKSIZE + HDRSIZ], *b; 283: int i; 284: for (i = 0, b = buf; i < HDRSIZ; i++) 285: *b++ = *p++; 286: for (i = 0, p = pk->p_ob[x]; i < pk->p_rsize; i++) 287: *b++ = *p++; 288: GENERROR(buf, pk->p_rsize + HDRSIZ); 289: ret = write(pk->p_ofn, buf, pk->p_rsize + HDRSIZ); 290: PKASSERT(ret == pk->p_rsize + HDRSIZ, 291: "PKXSTART ret %d", ret); 292: } 293: if (pk->p_msg) 294: pkoutput(pk); 295: return; 296: } 297: 298: 299: pkmove(p1, p2, count, flag) 300: char *p1, *p2; 301: int count, flag; 302: { 303: char *s, *d; 304: int i; 305: if (flag == B_WRITE) { 306: s = p2; 307: d = p1; 308: } 309: else { 310: s = p1; 311: d = p2; 312: } 313: for (i = 0; i < count; i++) 314: *d++ = *s++; 315: return; 316: } 317: 318: 319: /*** 320: * pkcget(fn, b, n) get n characters from input 321: * char *b; - buffer for characters 322: * int fn; - file descriptor 323: * int n; - requested number of characters 324: * 325: * return codes: 326: * n - number of characters returned 327: * 0 - end of file 328: */ 329: 330: jmp_buf Getjbuf; 331: cgalarm() { longjmp(Getjbuf, 1); } 332: 333: pkcget(fn, b, n) 334: int fn, n; 335: char *b; 336: { 337: int nchars, ret; 338: 339: if (setjmp(Getjbuf)) { 340: Ntimeout++; 341: PKDEBUG(4, "alarm %d\n", Ntimeout); 342: return(-1); 343: } 344: signal(SIGALRM, cgalarm); 345: 346: for (nchars = 0; nchars < n; nchars += ret) { 347: alarm(PKTIME); 348: ret = read(fn, b, n - nchars); 349: if (ret == 0) { 350: alarm(0); 351: return(-1); 352: } 353: PKASSERT(ret > 0, "PKCGET READ %d", ret); 354: b += ret; 355: } 356: alarm(0); 357: return(0); 358: } 359: 360: 361: generror(p, s) 362: char *p; 363: int s; 364: { 365: int r; 366: if (Errorrate != 0 && (rand() % Errorrate) == 0) { 367: r = rand() % s; 368: fprintf(stderr, "gen err at %o, (%o), ", r, (unsigned) *(p + r)); 369: *(p + r) += 1; 370: } 371: return; 372: }