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