Research V7 development
authorDennis Ritchie <dmr@research.uucp>
Sun, 13 May 1979 22:32:17 +0000 (17:32 -0500)
committerDennis Ritchie <dmr@research.uucp>
Sun, 13 May 1979 22:32:17 +0000 (17:32 -0500)
Work on file usr/sys/dev/pk0.c
Work on file usr/sys/dev/pk2.c
Work on file usr/sys/dev/pk3.c

Synthesized-from: v7

usr/sys/dev/pk0.c [new file with mode: 0644]
usr/sys/dev/pk2.c [new file with mode: 0644]
usr/sys/dev/pk3.c [new file with mode: 0644]

diff --git a/usr/sys/dev/pk0.c b/usr/sys/dev/pk0.c
new file mode 100644 (file)
index 0000000..c9f7fb1
--- /dev/null
@@ -0,0 +1,683 @@
+#define        KERNEL  1
+#include "../h/pk.p"
+
+/*
+ * packet driver
+ */
+
+char next[8]   ={ 1,2,3,4,5,6,7,0};    /* packet sequence numbers */
+char mask[8]   ={ 1,2,4,010,020,040,0100,0200 };
+
+struct pack *pklines[NPLINES];
+
+
+/*
+ * receive control messages
+ */
+
+pkcntl(cntl, pk)
+register cntl;
+register struct pack *pk;
+{
+register val;
+register m;
+
+       val = cntl & MOD8;
+
+       if ( NOTCNTL(cntl) ) {
+               pkbadframe(pk);
+               return;
+       }
+
+       cntl >>= 3;
+       pk->p_state &= ~BADFRAME;
+       m = pk->p_msg;
+
+       switch(cntl) {
+
+       case INITB:
+               val++;
+               pk->p_xsize = pksizes[val];
+               pk->p_lpsize = val;
+               pk->p_bits = DTOM(pk->p_xsize);
+               if (pk->p_state & LIVE) {
+                       pk->p_msg |= M_INITC;
+                       break;
+               }
+               pk->p_state |= INITb;
+               if ((pk->p_state & INITa)==0) {
+                       break;
+               }
+               pk->p_rmsg &= ~M_INITA;
+               pk->p_msg |= M_INITC;
+               break;
+
+       case INITC:
+               if ((pk->p_state&INITab)==INITab) {
+                       pk->p_state = LIVE;
+                       WAKEUP(&pk->p_state);
+                       pk->p_rmsg &= ~(M_INITA|M_INITB);
+               } else
+                       if ((pk->p_state&LIVE)==0)
+                               pk->p_msg |= M_INITB;
+               if (val)
+                       pk->p_swindow = val;
+               break;
+       case INITA:
+               if (val==0 && pk->p_state&LIVE) {
+                       printf("alloc change\n");
+                       break;
+               }
+               if (val) {
+                       pk->p_state |= INITa;
+                       pk->p_msg |= M_INITB;
+                       pk->p_rmsg |= M_INITB;
+                       pk->p_swindow = val;
+               }
+               break;
+       case RJ:
+               pk->p_state |= RXMIT;
+               pk->p_msg |= M_RR;
+       case RR:
+               pk->p_rpr = val;
+               if (pksack(pk)==0) {
+                       WAKEUP(&pk->p_ps);
+               }
+               break;
+       case CLOSE:
+               pk->p_state = DOWN+RCLOSE;
+               pk->p_rmsg = 0;
+               WAKEUP(&pk->p_pr);
+               WAKEUP(&pk->p_ps);
+               WAKEUP(&pk->p_state);
+               return;
+       }
+       if (pk->p_msg==0)
+               pk->p_msg |= pk->p_rmsg;
+
+
+       if (m==0 && pk->p_msg)
+               pkoutput(pk);
+}
+
+
+/*
+ * Send RJ message on first framing error.
+ * Cleared by receiving a good frame 
+ * (pkcntl or pkdata).
+ */
+pkbadframe(pk)
+register struct pack *pk;
+{
+       WAKEUP(&pk->p_pr);
+       if (pk->p_state & BADFRAME)
+               return;
+       pk->p_state |= BADFRAME;
+       pk->p_timer = 2;
+}
+
+
+
+
+/*
+ * Look at sequence numbers (mostly).
+ */
+pkaccept(pk)
+register struct pack *pk;
+{
+register x, seq;
+char m, cntl, *p, imask, **bp;
+int bad, accept, skip, s, t, cc;
+unsigned short sum;
+
+       bad = accept = skip = 0;
+       /*
+        * wait for input
+        */
+       LOCK;
+       x = next[pk->p_pr];
+       if((imask=pk->p_imap)==0 && pk->p_rcount==0) {
+               UNLOCK;
+               goto out;
+       }
+       pk->p_imap = 0;
+       UNLOCK;
+
+
+       /*
+        * determine input window in m.
+        */
+       t = (~(-1<<pk->p_rwindow)) <<x;
+       m = t;
+       m |= t>>8;
+
+
+       /*
+        * mark newly accepted input buffers
+        */
+       for(x=0; x<8; x++) {
+
+               if ((imask & mask[x]) == 0)
+                       continue;
+
+               if (((cntl=pk->p_is[x])&0200)==0) {
+                       bad++;
+free:
+                       bp = (char **)pk->p_ib[x];
+                       LOCK;
+                       *bp = (char *)pk->p_ipool;
+                       pk->p_ipool = bp;
+                       pk->p_is[x] = 0;
+                       UNLOCK;
+                       continue;
+               }
+
+               pk->p_is[x] = ~(B_COPY+B_MARK);
+               sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)cntl;
+               sum += pk->p_isum[x];
+               if (sum == CHECK) {
+                       seq = (cntl>>3) & MOD8;
+                       if (m & mask[seq]) {
+                               if (pk->p_is[seq] & (B_COPY | B_MARK)) {
+                               dup:
+                                       skip++;
+                                       goto free;
+                               }
+                               if (x != seq) {
+                                       LOCK;
+                                       p = pk->p_ib[x];
+                                       pk->p_ib[x] = pk->p_ib[seq];
+                                       pk->p_is[x] = pk->p_is[seq];
+                                       pk->p_ib[seq] = p;
+                                       UNLOCK;
+                               }
+                               pk->p_is[seq] = B_MARK;
+                               accept++;
+                               cc = 0;
+                               if (cntl&B_SHORT) {
+                                       pk->p_is[seq] = B_MARK+B_SHORT;
+                                       p = pk->p_ib[seq];
+                                       cc = (unsigned)*p++;
+                                       if (cc & 0200) {
+                                               cc &= 0177;
+                                               cc |= *p << 7;
+                                       }
+                               }
+                               pk->p_isum[seq] = pk->p_rsize - cc;
+                       } else {
+                               goto dup;
+                       }
+               } else {
+                       bad++;
+                       goto free;
+               }
+       }
+
+       /*
+        * scan window again turning marked buffers into
+        * COPY buffers and looking for missing sequence
+        * numbers.
+        */
+       accept = 0;
+       for(x=next[pk->p_pr],t= -1; m & mask[x]; x = next[x]) {
+               if (pk->p_is[x] & B_MARK)
+                       pk->p_is[x] |= B_COPY;
+               if (pk->p_is[x] & B_COPY) {
+                       if (t >= 0) {
+                               bp = (char **)pk->p_ib[x];
+                               LOCK;
+                               *bp = (char *)pk->p_ipool;
+                               pk->p_ipool = bp;
+                               pk->p_is[x] = 0;
+                               UNLOCK;
+                               skip++;
+                       } else 
+                               accept++;
+               } else {
+                       if (t<0)
+                               t = x;
+               }
+       }
+
+       if (bad) {
+               pk->p_msg |= M_RJ;
+       } else 
+
+       if (skip) {
+               pk->p_msg |= M_RR;
+       }
+
+       pk->p_rcount = accept;
+out:
+       if (pk->p_msg)
+               pkoutput(pk);
+       return(accept);
+}
+
+
+pkread(S)
+SDEF;
+{
+register struct pack *pk;
+register x,s;
+int is,cc,xfr,count;
+char *cp, **bp;
+
+       pk = PADDR;
+       xfr = 0;
+       count = -1;
+       while (pkaccept(pk) == 0) {
+               PKGETPKT(pk);
+               if (pk->p_state&DOWN) {
+                       SETERROR;
+                       goto out;
+               }
+               if (SLEEPNO) {
+                       count++;
+                       goto out;
+               }
+               SLEEP(&pk->p_pr, PKIPRI);
+       }
+       count = 0;
+
+
+       while (UCOUNT) {
+
+               x = next[pk->p_pr];
+               is = pk->p_is[x];
+
+               if (is & B_COPY) {
+                       cc = MIN(pk->p_isum[x], UCOUNT);
+                       if (cc==0 && xfr) {
+                               break;
+                       }
+                       if (is & B_RESID)
+                               cp = pk->p_rptr;
+                       else {
+                               cp = pk->p_ib[x];
+                               if (is & B_SHORT) {
+                                       if (*cp++ & 0200)
+                                               *cp++;
+                               }
+                       }
+                       IOMOVE(cp,cc,B_READ);
+                       count += cc;
+                       xfr++;
+                       pk->p_isum[x] -= cc;
+                       if (pk->p_isum[x] == 0) {
+                               LOCK;
+                               pk->p_pr = x;
+                               bp = (char **)pk->p_ib[x];
+                               *bp = (char *)pk->p_ipool;
+                               pk->p_ipool = bp;
+                               pk->p_is[x] = 0;
+                               pk->p_rcount--;
+                               UNLOCK;
+                               pk->p_msg |= M_RR;
+                       } else {
+                               pk->p_rptr = cp+cc;
+                               pk->p_is[x] |= B_RESID;
+                       }
+                       if (cc==0)
+                               break;
+               } else
+                       break;
+       }
+       pkoutput(pk);
+       if (SLEEPNO)
+               count = pk->p_rcount;
+out:
+       return(count);
+}
+
+
+
+
+pkwrite(S)
+SDEF;
+{
+register struct pack *pk;
+register x;
+int partial;
+caddr_t cp;
+int cc, s, fc, count;
+int pktimeout();
+
+       pk = PADDR;
+       if ((pk->p_state&LIVE)==0) {
+       down:
+               SIGNAL;
+               SETERROR;
+               return(-1);
+       }
+
+       count = UCOUNT;
+       do {
+               LOCK;
+               while (pk->p_xcount>=pk->p_swindow)  {
+                       pkoutput(pk);
+                       PKGETPKT(pk);
+                       SLEEP(&pk->p_ps,PKOPRI);
+                       if (pk->p_state&DOWN)
+                               goto down;
+               }
+               x = next[pk->p_pscopy];
+               while (pk->p_os[x]!=B_NULL)  {
+                       goto down;
+               }
+               pk->p_os[x] = B_MARK;
+               pk->p_pscopy = x;
+               pk->p_xcount++;
+               UNLOCK;
+
+               cp = pk->p_ob[x] = (char *)GETEPACK;
+               partial = 0;
+               if ((int)UCOUNT < pk->p_xsize) {
+                       cc = UCOUNT;
+                       fc = pk->p_xsize - cc;
+                       *cp = fc&0177;
+                       if (fc > 127) {
+                               *cp++ |= 0200;
+                               *cp++ = fc>>7;
+                       } else
+                               cp++;
+                       partial = B_SHORT;
+               } else
+                       cc = pk->p_xsize;
+               IOMOVE(cp,cc,B_WRITE);
+               pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize);
+               pk->p_os[x] = B_READY+partial;
+               pkoutput(pk);
+       } while (UCOUNT);
+
+       return(count-UCOUNT);
+}
+
+pksack(pk)
+register struct pack *pk;
+{
+register x, i;
+int s;
+
+       i = 0;
+       LOCK;
+       for(x=pk->p_ps; x!=pk->p_rpr; ) {
+               x = next[x];
+               if (pk->p_os[x]&B_SENT) {
+                       i++;
+                       FREEPACK(pk->p_ob[x], pk->p_bits);
+                       pk->p_os[x] = B_NULL;
+                       pk->p_state &= ~WAITO;
+                       pk->p_xcount--;
+                       pk->p_ps = x;
+                       WAKEUP(&pk->p_ps);
+               }
+       }
+       UNLOCK;
+       return(i);
+}
+
+
+
+pkoutput(pk)
+register struct pack *pk;
+{
+register x;
+int s;
+char bstate;
+int i;
+SDEF;
+extern pkzot;
+
+       ISYSTEM;
+       LOCK;
+       if (OBUSY) {
+               UNLOCK;
+               return;
+       }
+
+
+       /*
+        * find seq number and buffer state
+        * of next output packet
+        */
+       if (pk->p_state&RXMIT)  {
+               pk->p_nxtps = next[pk->p_rpr];
+               pk->p_state &= ~RXMIT;
+       }
+       x = pk->p_nxtps;
+       bstate = pk->p_os[x];
+
+
+       /*
+        * Send control packet if indicated
+        */
+       if (pk->p_msg) {
+               if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) {
+                       x = pk->p_msg;
+                       for(i=0; i<8; i++) 
+                               if (x&1)
+                                       break; else
+                               x >>= 1;
+                       x = i;
+                       x <<= 3;
+                       switch(i) {
+                       case CLOSE:
+                               break;
+                       case RJ:
+                       case RR:
+                               x += pk->p_pr;
+                               break;
+                       case SRJ:
+                               break;
+                       case INITB:
+                               x += pksize(pk->p_rsize);
+                               break;
+                       case INITC:
+                               x += pk->p_rwindow;
+                               break;
+                       case INITA:
+                               x += pk->p_rwindow;
+                               break;
+                       }
+
+                       pk->p_msg &= ~mask[i];
+                       pkxstart(pk, x, -1);
+                       goto out;
+               }
+       }
+
+
+       /*
+        * Don't send data packets if line is marked dead.
+        */
+       if (pk->p_state&DOWN || (pk->p_state&LIVE)==0) {
+               WAKEUP(&pk->p_ps);
+               goto out;
+       }
+       /*
+        * Start transmission (or retransmission) of data packets.
+        */
+       if (bstate & (B_READY|B_SENT)) {
+               char seq;
+
+               bstate |= B_SENT;
+               seq = x;
+               pk->p_nxtps = next[x];
+
+               x = 0200+pk->p_pr+(seq<<3);
+               if (bstate & B_SHORT)
+                       x |= 0100;
+               pkxstart(pk, x, seq);
+               if (pk->p_os[seq])
+                       pk->p_os[seq] = bstate;
+               pk->p_nout++;
+               goto out;
+       }
+       /*
+        * enable timeout if there's nothing to send
+        * and transmission buffers are languishing
+        */
+       if (pk->p_xcount) {
+               pk->p_timer = 10+pkzot;
+               pk->p_state |= WAITO;
+       } else
+               pk->p_state &= ~WAITO;
+       WAKEUP(&pk->p_ps);
+out:
+       pk->p_obusy = 0;
+       UNLOCK;
+}
+
+
+/*
+ * shut down line by
+ *     ignoring new input
+ *     letting output drain
+ *     releasing space and turning off line discipline
+ */
+pkclose(S)
+SDEF;
+{
+register struct pack *pk;
+register i,s,rbits;
+char **bp;
+
+#define        NTRIES  1
+
+       pk = PADDR;
+       pk->p_state |= DRAINO;
+
+
+       /*
+        * try to flush output
+        */
+       i = 0;
+       LOCK;
+       if (pklive(pk)==0) {
+               pk->p_state = DOWN;
+               UNLOCK;
+               goto final;
+       }
+       pk->p_timer = 2;
+       while (pk->p_xcount && pk->p_state&LIVE) {
+               if (pk->p_state&(RCLOSE+DOWN) || ++i > NTRIES)
+                       break;
+               pkoutput(pk);
+               SLEEP(&pk->p_ps,PKOPRI);
+       }
+       pk->p_timer = 0;
+       pk->p_state |= DOWN;
+       UNLOCK;
+
+
+       /*
+        * try to exchange CLOSE messages
+        */
+       i = 0;
+       while ((pk->p_state&RCLOSE)==0 && i<NTRIES) {
+               pk->p_msg = M_CLOSE;
+               pk->p_timer = 2;
+               pkoutput(pk);
+               SLEEP(&pk->p_ps, PKOPRI);
+               i++;
+       }
+
+
+final:
+       TURNOFF;
+
+
+       /*
+        * free space
+        */
+       rbits = DTOM(pk->p_rsize);
+       for (i=0;i<8;i++) {
+               if (pk->p_os[i]!=B_NULL) {
+                       FREEPACK(pk->p_ob[i],pk->p_bits);
+                       pk->p_xcount--;
+               }
+               if (pk->p_is[i]!=B_NULL)  {
+                       FREEPACK(pk->p_ib[i],rbits);
+               }
+       }
+       LOCK;
+       while (pk->p_ipool != NULL) {
+               bp = pk->p_ipool;
+               pk->p_ipool = (char **)*bp;
+               FREEPACK((caddr_t)bp, rbits);
+       }
+       UNLOCK;
+       for(i=0;i<NPLINES;i++)
+               if (pklines[i]==pk)  {
+                       pklines[i] = NULL;
+               }
+       FREEPACK((caddr_t)pk, npbits);
+}
+
+
+
+pkreset(pk)
+register struct pack *pk;
+{
+
+       pk->p_ps = pk->p_pr =  pk->p_rpr = 0;
+       pk->p_nxtps = 1;
+}
+
+chksum(s,n)
+register char *s;
+register n;
+{
+       register short sum;
+       register unsigned t;
+       register x;
+
+       sum = -1;
+       x = 0;
+
+       do {
+               if (sum<0) {
+                       sum <<= 1;
+                       sum++;
+               } else
+                       sum <<= 1;
+               t = sum;
+               sum += (unsigned)*s++;
+               x += sum^n;
+               if ((unsigned)sum <= t) {
+                       sum ^= x;
+               }
+       } while (--n > 0);
+
+       return(sum);
+}
+
+pkline(pk)
+register struct pack *pk;
+{
+register i;
+       for(i=0;i<NPLINES;i++) {
+               if (pklines[i]==pk)
+                       return(i);
+       }
+       return(-i);
+}
+
+pkzero(s,n)
+register char *s;
+register n;
+{
+       while (n--)
+               *s++ = 0;
+}
+
+pksize(n)
+register n;
+{
+register k;
+
+       n >>= 5;
+       for(k=0; n >>= 1; k++);
+       return(k);
+}
diff --git a/usr/sys/dev/pk2.c b/usr/sys/dev/pk2.c
new file mode 100644 (file)
index 0000000..a8be80c
--- /dev/null
@@ -0,0 +1,265 @@
+#define        KERNEL  1
+#include "../h/pk.p"
+
+/*
+ * input framing and block checking.
+ * frame layout for most devices is:
+ *     
+ *     S|K|X|Y|C|Z|  ... data ... |
+ *
+ *     where   S       == initial synch byte
+ *             K       == encoded frame size (indexes pksizes[])
+ *             X, Y    == block check bytes
+ *             C       == control byte
+ *             Z       == XOR of header (K^X^Y^C)
+ *             data    == 0 or more data bytes
+ *
+ * device driver interfaces on input are:
+ *     pkrint  - byte level
+ *     pkrend  - dma or pseudo-dma transfer level
+ *     pkdata - packet level
+ */
+
+int pksizes[] ={
+       1, 32, 64, 128, 256, 512, 1024, 2048, 4096, 1
+};
+
+/*
+ * Pseudo-dma byte collection.
+ * This code can be put in the device driver
+ * interrupt routine to eliminate the per byte
+ * subroutine call.
+ */
+pkrint(c, tp)
+register c;
+register struct tty *tp;
+{
+
+       if (q1.c_cc<0) {
+               if (q1.c_cf != NULL) {
+                       tp->t_erase = 0;
+                       *q1.c_cf++ = c;
+               }
+               if (++q1.c_cc)
+                       return;
+               pkrend(tp);
+               return;
+       }
+}
+
+
+
+/*
+ * End of input transfer.
+ */
+pkrend(tp)
+register struct tty *tp;
+{
+register char *p;
+struct pack *pk;
+struct header *h;
+register x;
+char   cntl, hdcheck;
+unsigned short sum;
+int i,j,k;
+char **bp;
+
+       p = q1.c_cl;
+       x = (int)q1.c_cf - (int)p;
+       pk = (struct pack *)tp->t_linep;
+       h = (struct header * )&pk->p_ihbuf;
+       if (x == HDRSIZ) {
+               if (*p++ == SYN ) {
+                       hdcheck = k = *p++;
+                       sum = (unsigned)*p;
+                       hdcheck ^= *p++;
+                       sum |= (unsigned)*p << 8;
+                       hdcheck ^= *p++;
+                       hdcheck ^= cntl = *p++;
+                       if (hdcheck != *p) {
+                               goto bad;
+                       }
+                       if (k == 9) {
+                               pkcntl(cntl, pk);
+                               q1.c_cf = q1.c_cl;
+                               q1.c_cc = -HDRSIZ;
+                               goto istart1;
+                       }
+                       if (k && pksizes[k]==pk->p_rsize) {
+                               pk->p_rpr = cntl&MOD8;
+                               pksack(pk);
+                               bp = pk->p_ipool;
+                               if (bp) {
+                                       pk->p_ipool = (char **)*bp;
+                                       pk->p_io = bp;
+                               } else {
+                               }
+                               q1.c_cf = (char *)bp;
+                               q1.c_cc = -pk->p_rsize;
+                               h->sum = sum;
+                               h->cntl = cntl;
+                               goto istart1;
+                       }
+bad:
+                       pkbadframe(pk);
+               }
+scan:
+               x = HDRSIZ;
+               j = 0;
+               p = (caddr_t)h;
+               for (i = 1; i < HDRSIZ; i++)
+                       if (p[i] == SYN)
+                               for(x=i; i<HDRSIZ; i++,j++)
+                                       p[j] = p[i];
+
+               q1.c_cc = -x;
+               q1.c_cf = (caddr_t)((int)p + j);
+               goto istart2;
+       }
+       if (x == pk->p_rsize) {
+               pkdata(h->cntl, h->sum, pk, q1.c_cl);
+               pk->p_io = NULL;
+               q1.c_cf = (char *)h;
+               q1.c_cc = -HDRSIZ;
+               goto istart1;
+       }
+       if (x == 0) {
+               q1.c_cf = (char *)h;
+               q1.c_cc = -HDRSIZ;
+               pkbadframe(pk);
+       } else {
+               pkbadframe(pk);
+               goto scan;
+       }
+istart1:
+       q1.c_cl = q1.c_cf;
+istart2:
+       if (tp->t_iproc != NULL)
+               (*tp->t_iproc)(tp);
+}
+
+
+
+/*
+ * Put packet located at address bp
+ * in an input slot for further processing.
+ */
+pkdata(c, sum, pk, cp)
+char c;
+unsigned short sum;
+register struct pack *pk;
+char *cp;
+{
+register struct tty *tp;
+register x;
+char **bp;
+int t;
+
+       pk->p_state &= ~BADFRAME;
+       bp = (char **)cp;
+       tp = pk->p_ttyp;
+       if (pk->p_state&DRAINO || !(pk->p_state&LIVE)) {
+               pk->p_msg |= pk->p_rmsg;
+               pkoutput(pk);
+               goto drop;
+       }
+       t = next[pk->p_pr];
+       for(x=pk->p_pr; x!=t; x = (x-1)&7) {
+               if (pk->p_is[x] == 0)
+                       goto slot;
+       }
+       /*
+        * this can't happen
+        */
+       printf("no slot\n");
+drop:
+       *bp = (char *)pk->p_ipool;
+       pk->p_ipool = bp;
+       return;
+
+slot:
+       pk->p_imap |= mask[x];
+       pk->p_is[x] = c;
+       pk->p_isum[x] = sum;
+       pk->p_ib[x] = cp;
+       if (tp->t_chan)
+               sdata(tp->t_chan); else
+               wakeup(&pk->p_pr);
+}
+
+
+/*
+ * Start transmission on output device associated with pk.
+ * For asynch devices (t_line==1) framing is
+ * imposed.  For devices with framing and crc
+ * in the driver (t_line==2) the transfer is
+ * passed on to the driver.
+ */
+pkxstart(pk, cntl, x)
+struct pack *pk;
+char cntl;
+register x;
+{
+struct tty *tp;
+register char *p;
+short checkword;
+char hdcheck;
+
+       p = (caddr_t)&pk->p_ohbuf;
+       tp = pk->p_ttyp;
+
+       if (tp->t_line==1) {
+               *p++ = SYN;
+               if (x < 0) {
+                       *p = 9;
+                       checkword = cntl;
+                       q3.c_cl = NULL;
+               } else {
+                       *p = pk->p_lpsize;
+                       checkword = pk->p_osum[x] ^ (unsigned)cntl;
+                       q3.c_cl = pk->p_ob[x];
+               }
+               checkword = CHECK - checkword;
+               hdcheck = *p++;
+               hdcheck ^= *p++ = checkword;
+               hdcheck ^= *p++ = checkword>>8;
+               q3.c_cc = -HDRSIZ;
+       } else {
+               q3.c_cc = -1;
+       }
+
+       hdcheck ^= *p++ = cntl;
+       *p = hdcheck;
+       q3.c_cf = (caddr_t)&pk->p_ohbuf;
+/*
+       pk->p_srxmit++;
+*/
+       (*tp->t_oproc)(tp);
+}
+
+/*
+ * transmitter interrupt.
+ */
+int    pkdelay = 2;
+
+pkxint(tp)
+register struct tty *tp;
+{
+register struct pack *pk;
+register s;
+extern int pkoutput();
+
+       pk = (struct pack *)tp->t_linep;
+       s = spl6();
+       tp->t_state &= ~BUSY;
+       if (q3.c_cl == NULL) {
+                       pkoutput(pk);
+       } else {
+               q3.c_cf = q3.c_cl;
+               q3.c_cl = NULL;
+               q3.c_cc = -pk->p_xsize;
+               (*tp->t_oproc)(tp);
+       }
+       splx(s);
+}
+
diff --git a/usr/sys/dev/pk3.c b/usr/sys/dev/pk3.c
new file mode 100644 (file)
index 0000000..ac42a35
--- /dev/null
@@ -0,0 +1,162 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/conf.h"
+#include "../h/buf.h"
+
+#define        XPRI    30
+#define        NBLOCKS 10
+
+int    bwaiting, wcount;
+struct buf *bufps[NBLOCKS];
+char   *nbase[NBLOCKS];        /* normal allocations */
+short  nmap[NBLOCKS];          /* 1 bit == 32 bytes */
+
+char log[] ={0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4};
+#define        FULL    -1
+#define        LOCK    s = spl6()
+#define        UNLOCK  splx(s)
+
+/*
+ * getepack: get empty packet
+ * with size specified by bitmask.
+ */
+char *
+getepack(bits)
+{
+register i;
+int    s, savbits;
+char   **base;
+short  *map;
+
+       base = nbase; map = nmap;
+       savbits = bits;
+
+       /*
+        * search for space
+        */
+       LOCK;
+       for(;;) {
+
+               if (bits == FULL)
+                       goto force;
+
+               for(i=0; i<NBLOCKS; i++) {
+                       register m;
+                       register unsigned n;
+                       register offset;
+
+                       m = map[i];
+                       if (m==FULL || base[i]==NULL)
+                               continue;
+                       if (bits == 1) {
+                               n = m;
+                               m |= m+1;
+                               n = m-n;
+                               for (offset=0; n > 16; n >>= 4) 
+                                       offset += 4;
+                               offset += log[n];
+                       } else {
+                               bits = savbits;
+                               for(n=17; --n; bits <<= 1)
+                                       if ((m&bits)==0)
+                                               goto found;
+                               continue;
+                       found:
+                               offset = 16-n;
+                               m |= bits;
+                       }
+                       map[i] = m;
+                       UNLOCK;
+                       return(base[i] + 32*offset);
+               }
+               /*
+                * grab another block from the system
+                */
+       force:
+               for(i=0;i<NBLOCKS;i++) {
+                       register struct buf *bp;
+
+                       if (bufps[i]!=NULL)
+                               continue;
+                       bufps[i] = bp = geteblk();
+                       bp->b_flags |= B_PACK;
+                       bp->b_flags |= B_PBUSY;
+                       map[i] = bits;
+                       base[i] = bp->b_un.b_addr;
+                       UNLOCK;
+                       return(bp->b_un.b_addr);
+               }
+               /*
+                * sleep until something is released
+                */
+               bwaiting++;
+               wcount++;
+               sleep((caddr_t)&bwaiting, XPRI);
+               bwaiting--;
+       }
+}
+
+/*
+ * freepack: release space beginning
+ * at address p with length specified
+ * by bits.
+ */
+freepack(p, bits)
+char *p;
+{
+register i, d, s;
+char   **base;
+short  *map;
+
+       if (p==NULL)
+               return;
+       LOCK;
+       base = nbase; map = nmap;
+
+       for(i=0;i<NBLOCKS;i++) {
+               d = p-base[i];
+               if (d>=0 && d<=512) 
+                       goto found;
+       }
+       goto out;
+found:
+       d >>= 5;
+       d = (bits<<d);
+       map[i] &= ~d;
+       if (map[i]==0) {
+               register struct buf *bp;
+
+               bp = bufps[i];
+               bp->b_flags &= ~B_PBUSY;
+               base[i] = NULL;
+               bufps[i] = NULL;
+               brelse(bp);
+       }
+       if (bwaiting)
+               wakeup((caddr_t)&bwaiting);
+out:
+       splx(s);
+}
+
+
+
+/*
+ * integer to bitmap conversion
+ */
+dtom(d)
+register d;
+{
+register m;
+
+       m = 1;
+       while (d>32) {
+               d -= 32;
+               m |= m+1;
+       }
+       return(m);
+}
+
+#define NRECS  160
+int reclist[NRECS];
+int recbits[NRECS];
+