1: #define KERNEL 1 2: #include <sys/pk.p> 3: 4: #ifdef UCB_SCCSID 5: static char sccs_id[] = "@(#)pk0.c 3.1"; 6: #endif 7: 8: 9: /* 10: * packet driver 11: */ 12: 13: char next[8] ={ 1,2,3,4,5,6,7,0}; /* packet sequence numbers */ 14: char mask[8] ={ 1,2,4,010,020,040,0100,0200 }; 15: 16: struct pack *pklines[NPLINES]; 17: 18: 19: /* 20: * receive control messages 21: */ 22: 23: pkcntl(cntl, pk) 24: register cntl; 25: register struct pack *pk; 26: { 27: register val; 28: register m; 29: 30: val = cntl & MOD8; 31: 32: if ( NOTCNTL(cntl) ) { 33: pkbadframe(pk); 34: return; 35: } 36: 37: cntl >>= 3; 38: pk->p_state &= ~BADFRAME; 39: m = pk->p_msg; 40: 41: switch(cntl) { 42: 43: case INITB: 44: val++; 45: pk->p_xsize = pksizes[val]; 46: pk->p_lpsize = val; 47: pk->p_bits = DTOM(pk->p_xsize); 48: if (pk->p_state & LIVE) { 49: pk->p_msg |= M_INITC; 50: break; 51: } 52: pk->p_state |= INITb; 53: if ((pk->p_state & INITa)==0) { 54: break; 55: } 56: pk->p_rmsg &= ~M_INITA; 57: pk->p_msg |= M_INITC; 58: break; 59: 60: case INITC: 61: if ((pk->p_state&INITab)==INITab) { 62: pk->p_state = LIVE; 63: WAKEUP(&pk->p_state); 64: pk->p_rmsg &= ~(M_INITA|M_INITB); 65: } else 66: if ((pk->p_state&LIVE)==0) 67: pk->p_msg |= M_INITB; 68: if (val) 69: pk->p_swindow = val; 70: break; 71: case INITA: 72: if (val==0 && pk->p_state&LIVE) { 73: printf("alloc change\n"); 74: break; 75: } 76: if (val) { 77: pk->p_state |= INITa; 78: pk->p_msg |= M_INITB; 79: pk->p_rmsg |= M_INITB; 80: pk->p_swindow = val; 81: } 82: break; 83: case RJ: 84: pk->p_state |= RXMIT; 85: pk->p_msg |= M_RR; 86: case RR: 87: pk->p_rpr = val; 88: if (pksack(pk)==0) { 89: WAKEUP(&pk->p_ps); 90: } 91: break; 92: case CLOSE: 93: pk->p_state = DOWN+RCLOSE; 94: pk->p_rmsg = 0; 95: WAKEUP(&pk->p_pr); 96: WAKEUP(&pk->p_ps); 97: WAKEUP(&pk->p_state); 98: return; 99: } 100: if (pk->p_msg==0) 101: pk->p_msg |= pk->p_rmsg; 102: 103: 104: if (m==0 && pk->p_msg) 105: pkoutput(pk); 106: } 107: 108: 109: /* 110: * Send RJ message on first framing error. 111: * Cleared by receiving a good frame 112: * (pkcntl or pkdata). 113: */ 114: pkbadframe(pk) 115: register struct pack *pk; 116: { 117: WAKEUP(&pk->p_pr); 118: if (pk->p_state & BADFRAME) 119: return; 120: pk->p_state |= BADFRAME; 121: pk->p_timer = 2; 122: } 123: 124: 125: 126: 127: /* 128: * Look at sequence numbers (mostly). 129: */ 130: pkaccept(pk) 131: register struct pack *pk; 132: { 133: register x, seq; 134: char m, cntl, *p, imask, **bp; 135: int bad, accept, skip, s, t, cc; 136: unsigned short sum; 137: 138: bad = accept = skip = 0; 139: /* 140: * wait for input 141: */ 142: LOCK; 143: x = next[pk->p_pr]; 144: if((imask=pk->p_imap)==0 && pk->p_rcount==0) { 145: UNLOCK; 146: goto out; 147: } 148: pk->p_imap = 0; 149: UNLOCK; 150: 151: 152: /* 153: * determine input window in m. 154: */ 155: t = (~(-1<<pk->p_rwindow)) <<x; 156: m = t; 157: m |= t>>8; 158: 159: 160: /* 161: * mark newly accepted input buffers 162: */ 163: for(x=0; x<8; x++) { 164: 165: if ((imask & mask[x]) == 0) 166: continue; 167: 168: if (((cntl=pk->p_is[x])&0200)==0) { 169: bad++; 170: free: 171: bp = (char **)pk->p_ib[x]; 172: LOCK; 173: *bp = (char *)pk->p_ipool; 174: pk->p_ipool = bp; 175: pk->p_is[x] = 0; 176: UNLOCK; 177: continue; 178: } 179: 180: pk->p_is[x] = ~(B_COPY+B_MARK); 181: sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)cntl; 182: sum += pk->p_isum[x]; 183: if (sum == CHECK) { 184: seq = (cntl>>3) & MOD8; 185: if (m & mask[seq]) { 186: if (pk->p_is[seq] & (B_COPY | B_MARK)) { 187: dup: 188: skip++; 189: goto free; 190: } 191: if (x != seq) { 192: LOCK; 193: p = pk->p_ib[x]; 194: pk->p_ib[x] = pk->p_ib[seq]; 195: pk->p_is[x] = pk->p_is[seq]; 196: pk->p_ib[seq] = p; 197: UNLOCK; 198: } 199: pk->p_is[seq] = B_MARK; 200: accept++; 201: cc = 0; 202: if (cntl&B_SHORT) { 203: pk->p_is[seq] = B_MARK+B_SHORT; 204: p = pk->p_ib[seq]; 205: cc = (unsigned)*p++; 206: if (cc & 0200) { 207: cc &= 0177; 208: cc |= *p << 7; 209: } 210: } 211: pk->p_isum[seq] = pk->p_rsize - cc; 212: } else { 213: goto dup; 214: } 215: } else { 216: bad++; 217: goto free; 218: } 219: } 220: 221: /* 222: * scan window again turning marked buffers into 223: * COPY buffers and looking for missing sequence 224: * numbers. 225: */ 226: accept = 0; 227: for(x=next[pk->p_pr],t= -1; m & mask[x]; x = next[x]) { 228: if (pk->p_is[x] & B_MARK) 229: pk->p_is[x] |= B_COPY; 230: if (pk->p_is[x] & B_COPY) { 231: if (t >= 0) { 232: bp = (char **)pk->p_ib[x]; 233: LOCK; 234: *bp = (char *)pk->p_ipool; 235: pk->p_ipool = bp; 236: pk->p_is[x] = 0; 237: UNLOCK; 238: skip++; 239: } else 240: accept++; 241: } else { 242: if (t<0) 243: t = x; 244: } 245: } 246: 247: if (bad) { 248: pk->p_msg |= M_RJ; 249: } else 250: 251: if (skip) { 252: pk->p_msg |= M_RR; 253: } 254: 255: pk->p_rcount = accept; 256: out: 257: if (pk->p_msg) 258: pkoutput(pk); 259: return(accept); 260: } 261: 262: 263: pkread(S) 264: SDEF; 265: { 266: register struct pack *pk; 267: register x,s; 268: int is,cc,xfr,count; 269: char *cp, **bp; 270: 271: pk = PADDR; 272: xfr = 0; 273: count = -1; 274: while (pkaccept(pk) == 0) { 275: PKGETPKT(pk); 276: if (pk->p_state&DOWN) { 277: SETERROR; 278: goto out; 279: } 280: if (SLEEPNO) { 281: count++; 282: goto out; 283: } 284: SLEEP(&pk->p_pr, PKIPRI); 285: } 286: count = 0; 287: 288: 289: while (UCOUNT) { 290: 291: x = next[pk->p_pr]; 292: is = pk->p_is[x]; 293: 294: if (is & B_COPY) { 295: cc = MIN(pk->p_isum[x], UCOUNT); 296: if (cc==0 && xfr) { 297: break; 298: } 299: if (is & B_RESID) 300: cp = pk->p_rptr; 301: else { 302: cp = pk->p_ib[x]; 303: if (is & B_SHORT) { 304: if (*cp++ & 0200) 305: *cp++; 306: } 307: } 308: IOMOVE(cp,cc,B_READ); 309: count += cc; 310: xfr++; 311: pk->p_isum[x] -= cc; 312: if (pk->p_isum[x] == 0) { 313: LOCK; 314: pk->p_pr = x; 315: bp = (char **)pk->p_ib[x]; 316: *bp = (char *)pk->p_ipool; 317: pk->p_ipool = bp; 318: pk->p_is[x] = 0; 319: pk->p_rcount--; 320: UNLOCK; 321: pk->p_msg |= M_RR; 322: } else { 323: pk->p_rptr = cp+cc; 324: pk->p_is[x] |= B_RESID; 325: } 326: if (cc==0) 327: break; 328: } else 329: break; 330: } 331: pkoutput(pk); 332: if (SLEEPNO) 333: count = pk->p_rcount; 334: out: 335: return(count); 336: } 337: 338: 339: 340: 341: pkwrite(S) 342: SDEF; 343: { 344: register struct pack *pk; 345: register x; 346: int partial; 347: caddr_t cp; 348: int cc, s, fc, count; 349: int pktimeout(); 350: 351: pk = PADDR; 352: if ((pk->p_state&LIVE)==0) { 353: down: 354: SIGNAL; 355: SETERROR; 356: return(-1); 357: } 358: 359: count = UCOUNT; 360: do { 361: LOCK; 362: while (pk->p_xcount>=pk->p_swindow) { 363: pkoutput(pk); 364: PKGETPKT(pk); 365: SLEEP(&pk->p_ps,PKOPRI); 366: if (pk->p_state&DOWN) 367: goto down; 368: } 369: x = next[pk->p_pscopy]; 370: while (pk->p_os[x]!=B_NULL) { 371: goto down; 372: } 373: pk->p_os[x] = B_MARK; 374: pk->p_pscopy = x; 375: pk->p_xcount++; 376: UNLOCK; 377: 378: cp = pk->p_ob[x] = (char *)GETEPACK; 379: partial = 0; 380: if ((int)UCOUNT < pk->p_xsize) { 381: cc = UCOUNT; 382: fc = pk->p_xsize - cc; 383: *cp = fc&0177; 384: if (fc > 127) { 385: *cp++ |= 0200; 386: *cp++ = fc>>7; 387: } else 388: cp++; 389: partial = B_SHORT; 390: } else 391: cc = pk->p_xsize; 392: IOMOVE(cp,cc,B_WRITE); 393: pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize); 394: pk->p_os[x] = B_READY+partial; 395: pkoutput(pk); 396: } while (UCOUNT); 397: 398: return(count-UCOUNT); 399: } 400: 401: pksack(pk) 402: register struct pack *pk; 403: { 404: register x, i; 405: int s; 406: 407: i = 0; 408: LOCK; 409: for(x=pk->p_ps; x!=pk->p_rpr; ) { 410: x = next[x]; 411: if (pk->p_os[x]&B_SENT) { 412: i++; 413: FREEPACK(pk->p_ob[x], pk->p_bits); 414: pk->p_os[x] = B_NULL; 415: pk->p_state &= ~WAITO; 416: pk->p_xcount--; 417: pk->p_ps = x; 418: WAKEUP(&pk->p_ps); 419: } 420: } 421: UNLOCK; 422: return(i); 423: } 424: 425: 426: 427: pkoutput(pk) 428: register struct pack *pk; 429: { 430: register x; 431: int s; 432: char bstate; 433: int i; 434: SDEF; 435: extern pkzot; 436: 437: ISYSTEM; 438: LOCK; 439: if (OBUSY) { 440: UNLOCK; 441: return; 442: } 443: 444: 445: /* 446: * find seq number and buffer state 447: * of next output packet 448: */ 449: if (pk->p_state&RXMIT) { 450: pk->p_nxtps = next[pk->p_rpr]; 451: pk->p_state &= ~RXMIT; 452: } 453: x = pk->p_nxtps; 454: bstate = pk->p_os[x]; 455: 456: 457: /* 458: * Send control packet if indicated 459: */ 460: if (pk->p_msg) { 461: if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) { 462: x = pk->p_msg; 463: for(i=0; i<8; i++) 464: if (x&1) 465: break; else 466: x >>= 1; 467: x = i; 468: x <<= 3; 469: switch(i) { 470: case CLOSE: 471: break; 472: case RJ: 473: case RR: 474: x += pk->p_pr; 475: break; 476: case SRJ: 477: break; 478: case INITB: 479: x += pksize(pk->p_rsize); 480: break; 481: case INITC: 482: x += pk->p_rwindow; 483: break; 484: case INITA: 485: x += pk->p_rwindow; 486: break; 487: } 488: 489: pk->p_msg &= ~mask[i]; 490: pkxstart(pk, x, -1); 491: goto out; 492: } 493: } 494: 495: 496: /* 497: * Don't send data packets if line is marked dead. 498: */ 499: if (pk->p_state&DOWN || (pk->p_state&LIVE)==0) { 500: WAKEUP(&pk->p_ps); 501: goto out; 502: } 503: /* 504: * Start transmission (or retransmission) of data packets. 505: */ 506: if (bstate & (B_READY|B_SENT)) { 507: char seq; 508: 509: bstate |= B_SENT; 510: seq = x; 511: pk->p_nxtps = next[x]; 512: 513: x = 0200+pk->p_pr+(seq<<3); 514: if (bstate & B_SHORT) 515: x |= 0100; 516: pkxstart(pk, x, seq); 517: if (pk->p_os[seq]) 518: pk->p_os[seq] = bstate; 519: pk->p_nout++; 520: goto out; 521: } 522: /* 523: * enable timeout if there's nothing to send 524: * and transmission buffers are languishing 525: */ 526: if (pk->p_xcount) { 527: pk->p_timer = 10+pkzot; 528: pk->p_state |= WAITO; 529: } else 530: pk->p_state &= ~WAITO; 531: WAKEUP(&pk->p_ps); 532: out: 533: pk->p_obusy = 0; 534: UNLOCK; 535: } 536: 537: 538: /* 539: * shut down line by 540: * ignoring new input 541: * letting output drain 542: * releasing space and turning off line discipline 543: */ 544: pkclose(S) 545: SDEF; 546: { 547: register struct pack *pk; 548: register i,s,rbits; 549: char **bp; 550: 551: #define NTRIES 1 552: 553: pk = PADDR; 554: pk->p_state |= DRAINO; 555: 556: 557: /* 558: * try to flush output 559: */ 560: i = 0; 561: LOCK; 562: if (pklive(pk)==0) { 563: pk->p_state = DOWN; 564: UNLOCK; 565: goto final; 566: } 567: pk->p_timer = 2; 568: while (pk->p_xcount && pk->p_state&LIVE) { 569: if (pk->p_state&(RCLOSE+DOWN) || ++i > NTRIES) 570: break; 571: pkoutput(pk); 572: SLEEP(&pk->p_ps,PKOPRI); 573: } 574: pk->p_timer = 0; 575: pk->p_state |= DOWN; 576: UNLOCK; 577: 578: 579: /* 580: * try to exchange CLOSE messages 581: */ 582: i = 0; 583: while ((pk->p_state&RCLOSE)==0 && i<NTRIES) { 584: pk->p_msg = M_CLOSE; 585: pk->p_timer = 2; 586: pkoutput(pk); 587: SLEEP(&pk->p_ps, PKOPRI); 588: i++; 589: } 590: 591: 592: final: 593: TURNOFF; 594: 595: 596: /* 597: * free space 598: */ 599: rbits = DTOM(pk->p_rsize); 600: for (i=0;i<8;i++) { 601: if (pk->p_os[i]!=B_NULL) { 602: FREEPACK(pk->p_ob[i],pk->p_bits); 603: pk->p_xcount--; 604: } 605: if (pk->p_is[i]!=B_NULL) { 606: FREEPACK(pk->p_ib[i],rbits); 607: } 608: } 609: LOCK; 610: while (pk->p_ipool != NULL) { 611: bp = pk->p_ipool; 612: pk->p_ipool = (char **)*bp; 613: FREEPACK((caddr_t)bp, rbits); 614: } 615: UNLOCK; 616: for(i=0;i<NPLINES;i++) 617: if (pklines[i]==pk) { 618: pklines[i] = NULL; 619: } 620: FREEPACK((caddr_t)pk, npbits); 621: } 622: 623: 624: 625: pkreset(pk) 626: register struct pack *pk; 627: { 628: 629: pk->p_ps = pk->p_pr = pk->p_rpr = 0; 630: pk->p_nxtps = 1; 631: } 632: 633: chksum(s,n) 634: register char *s; 635: register n; 636: { 637: register short sum; 638: register unsigned t; 639: register x; 640: 641: sum = -1; 642: x = 0; 643: 644: do { 645: if (sum<0) { 646: sum <<= 1; 647: sum++; 648: } else 649: sum <<= 1; 650: t = sum; 651: sum += (unsigned)*s++; 652: x += sum^n; 653: if ((unsigned)sum <= t) { 654: sum ^= x; 655: } 656: } while (--n > 0); 657: 658: return(sum); 659: } 660: 661: pkline(pk) 662: register struct pack *pk; 663: { 664: register i; 665: for(i=0;i<NPLINES;i++) { 666: if (pklines[i]==pk) 667: return(i); 668: } 669: return(-i); 670: } 671: 672: pkzero(s,n) 673: register char *s; 674: register n; 675: { 676: while (n--) 677: *s++ = 0; 678: } 679: 680: pksize(n) 681: register n; 682: { 683: register k; 684: 685: n >>= 5; 686: for(k=0; n >>= 1; k++); 687: return(k); 688: }