date and time created 83/07/02 17:57:22 by sam
authorSam Leffler <sam@ucbvax.Berkeley.EDU>
Sun, 3 Jul 1983 08:57:22 +0000 (00:57 -0800)
committerSam Leffler <sam@ucbvax.Berkeley.EDU>
Sun, 3 Jul 1983 08:57:22 +0000 (00:57 -0800)
SCCS-vsn: usr.bin/uucp/uucico/pk1.c 5.1

usr/src/usr.bin/uucp/uucico/pk1.c [new file with mode: 0644]

diff --git a/usr/src/usr.bin/uucp/uucico/pk1.c b/usr/src/usr.bin/uucp/uucico/pk1.c
new file mode 100644 (file)
index 0000000..841a160
--- /dev/null
@@ -0,0 +1,396 @@
+#ifndef lint
+static char sccsid[] = "@(#)pk1.c      5.1 (Berkeley) %G%";
+#endif
+
+extern char    *malloc();
+
+#define USER   1
+#include <stdio.h>
+#ifdef SYSIII
+#include <sys/types.h>
+#endif
+#include "pk.p"
+#include <sys/param.h>
+#include "pk.h"
+#include <sys/buf.h>
+#include <setjmp.h>
+#include <signal.h>
+
+
+#define PKMAXSTMSG 40
+#define        PKTIME  25
+extern int Errorrate;
+int Connodata = 0;
+int Ntimeout = 0;
+#define CONNODATA 10
+#define NTIMEOUT 50
+/*
+ * packet driver support routines
+ *
+ */
+
+struct pack *pklines[NPLINES];
+
+/*
+ * start initial synchronization.
+ */
+
+struct pack *
+pkopen(ifn, ofn)
+int ifn, ofn;
+{
+       register struct pack *pk;
+       register char **bp;
+       register int i;
+
+       if (++pkactive >= NPLINES)
+               return(NULL);
+       if ((pk = (struct pack *) malloc(sizeof (struct pack))) == NULL)
+               return(NULL);
+       pkzero((caddr_t) pk, sizeof (struct pack));
+       pk->p_ifn = ifn;
+       pk->p_ofn = ofn;
+       pk->p_xsize = pk->p_rsize = PACKSIZE;
+       pk->p_rwindow = pk->p_swindow = WINDOWS;
+       /*  allocate input windows */
+       for (i = 0; i < pk->p_rwindow; i++) {
+               if ((bp = (char **) GETEPACK) == NULL)
+                       break;
+               *bp = (char *) pk->p_ipool;
+               pk->p_ipool = bp;
+       }
+       if (i == 0)
+               return(NULL);
+       pk->p_rwindow = i;
+
+       /* start synchronization */
+       pk->p_msg = pk->p_rmsg = M_INITA;
+       for (i = 0; i < NPLINES; i++) {
+               if (pklines[i] == NULL) {
+                       pklines[i] = pk;
+                       break;
+               }
+       }
+       if (i >= NPLINES)
+               return(NULL);
+       pkoutput(pk);
+
+       for (i = 0; i < PKMAXSTMSG; i++) {
+               PKGETPKT(pk);
+               if ((pk->p_state & LIVE) != 0)
+                       break;
+       }
+       if (i >= PKMAXSTMSG)
+               return(NULL);
+
+       pkreset(pk);
+       return(pk);
+}
+
+
+/*
+ * 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
+ *
+ */
+
+int pksizes[] = {
+       1, 32, 64, 128, 256, 512, 1024, 2048, 4096, 1
+};
+
+#define GETRIES 5
+/*
+ * Pseudo-dma byte collection.
+ */
+
+pkgetpack(ipk)
+struct pack *ipk;
+{
+       int ret, k, tries;
+       register char *p;
+       register struct pack *pk;
+       register struct header *h;
+       unsigned short sum;
+       int ifn;
+       char **bp;
+       char hdchk;
+
+       pk = PADDR;
+       if ((pk->p_state & DOWN) ||
+         Connodata > CONNODATA /* || Ntimeout > NTIMEOUT */)
+               pkfail();
+       ifn = pk->p_ifn;
+
+       /* find HEADER */
+       for (tries = 0; tries < GETRIES; ) {
+               p = (caddr_t) &pk->p_ihbuf;
+               if ((ret = pkcget(ifn, p, 1)) < 0) {
+                       /* set up retransmit or REJ */
+                       tries++;
+                       pk->p_msg |= pk->p_rmsg;
+                       if (pk->p_msg == 0)
+                               pk->p_msg |= M_RR;
+                       if ((pk->p_state & LIVE) == LIVE)
+                               pk->p_state |= RXMIT;
+                       pkoutput(pk);
+                       continue;
+               }
+               if (*p != SYN)
+                       continue;
+               p++;
+               ret = pkcget(ifn, p, HDRSIZ - 1);
+               if (ret == -1)
+                       continue;
+               break;
+       }
+       if (tries >= GETRIES) {
+               PKDEBUG(4, "tries = %d\n", tries);
+               pkfail();
+       }
+
+       Connodata++;
+       h = (struct header * ) &pk->p_ihbuf;
+       p = (caddr_t) h;
+       hdchk = p[1] ^ p[2] ^ p[3] ^ p[4];
+       p += 2;
+       sum = (unsigned) *p++ & 0377;
+       sum |= (unsigned) *p << 8;
+       h->sum = sum;
+       PKDEBUG(7, "rec h->cntl %o\n", (unsigned) h->cntl);
+       k = h->ksize;
+       if (hdchk != h->ccntl) {
+               /* bad header */
+               PKDEBUG(7, "bad header %o,", hdchk);
+               PKDEBUG(7, "h->ccntl %o\n", h->ccntl);
+               return;
+       }
+       if (k == 9) {
+               if (((h->sum + h->cntl) & 0xffff) == CHECK) {
+                       pkcntl(h->cntl, pk);
+                       PKDEBUG(7, "state - %o\n", pk->p_state);
+               }
+               else {
+                       /*  bad header */
+                       PKDEBUG(7, "bad header (k==9) %o\n", h->cntl);
+                       pk->p_state |= BADFRAME;
+               }
+               return;
+       }
+       if (k && pksizes[k] == pk->p_rsize) {
+               pk->p_rpr = h->cntl & MOD8;
+               pksack(pk);
+               Connodata = 0;
+               bp = pk->p_ipool;
+               pk->p_ipool = (char **) *bp;
+               if (bp == NULL) {
+                       PKDEBUG(7, "bp NULL %s\n", "");
+               return;
+               }
+       }
+       else {
+               return;
+       }
+       ret = pkcget(pk->p_ifn, (char *) bp, pk->p_rsize);
+       if (ret == 0)
+               pkdata(h->cntl, h->sum, pk, (char **) bp);
+       return;
+}
+
+
+pkdata(c, sum, pk, bp)
+char c;
+unsigned short sum;
+register struct pack *pk;
+char **bp;
+{
+register x;
+int t;
+char m;
+
+       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;
+       }
+drop:
+       *bp = (char *)pk->p_ipool;
+       pk->p_ipool = bp;
+       return;
+
+slot:
+       m = mask[x];
+       pk->p_imap |= m;
+       pk->p_is[x] = c;
+       pk->p_isum[x] = sum;
+       pk->p_ib[x] = (char *)bp;
+       return;
+}
+
+
+
+/*
+ * setup input transfers
+ */
+pkrstart(pk)
+{}
+
+#define PKMAXBUF 128
+/*
+ * 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)
+register struct pack *pk;
+char cntl;
+register x;
+{
+       register char *p;
+       int ret;
+       short checkword;
+       char hdchk;
+
+       p = (caddr_t) &pk->p_ohbuf;
+       *p++ = SYN;
+       if (x < 0) {
+               *p++ = hdchk = 9;
+               checkword = cntl;
+       }
+       else {
+               *p++ = hdchk = pk->p_lpsize;
+               checkword = pk->p_osum[x] ^ (unsigned)(cntl & 0377);
+       }
+       checkword = CHECK - checkword;
+       *p = checkword;
+       hdchk ^= *p++;
+       *p = checkword>>8;
+       hdchk ^= *p++;
+       *p = cntl;
+       hdchk ^= *p++;
+       *p = hdchk;
+ /*  writes  */
+PKDEBUG(7, "send %o\n", (unsigned) cntl);
+       p = (caddr_t) & pk->p_ohbuf;
+       if (x < 0) {
+#ifdef PROTODEBUG
+               GENERROR(p, HDRSIZ);
+#endif
+               ret = write(pk->p_ofn, p, HDRSIZ);
+               PKASSERT(ret == HDRSIZ, "PKXSTART ret", "", ret);
+       }
+       else {
+               char buf[PKMAXBUF + HDRSIZ], *b;
+               int i;
+               for (i = 0, b = buf; i < HDRSIZ; i++) 
+                       *b++ = *p++;
+               for (i = 0, p = pk->p_ob[x]; i < pk->p_xsize; i++)
+                       *b++ = *p++;
+#ifdef PROTODEBUG
+               GENERROR(buf, pk->p_xsize + HDRSIZ);
+#endif
+               ret = write(pk->p_ofn, buf, pk->p_xsize + HDRSIZ);
+               PKASSERT(ret == pk->p_xsize + HDRSIZ,
+                 "PKXSTART ret", "", ret);
+               Connodata = 0;
+       }
+       if (pk->p_msg)
+               pkoutput(pk);
+       return;
+}
+
+
+pkmove(p1, p2, count, flag)
+char *p1, *p2;
+int count, flag;
+{
+       register char *s, *d;
+       register int i;
+
+       if (flag == B_WRITE) {
+               s = p2;
+               d = p1;
+       }
+       else {
+               s = p1;
+               d = p2;
+       }
+       for (i = 0; i < count; i++)
+               *d++ = *s++;
+       return;
+}
+
+
+/***
+ *     pkcget(fn, b, n)        get n characters from input
+ *     char *b;                - buffer for characters
+ *     int fn;                 - file descriptor
+ *     int n;                  - requested number of characters
+ *
+ *     return codes:
+ *             n - number of characters returned
+ *             0 - end of file
+ */
+
+jmp_buf Getjbuf;
+cgalarm() { longjmp(Getjbuf, 1); }
+
+pkcget(fn, b, n)
+int fn, n;
+register char *b;
+{
+       register int nchars, ret;
+
+       if (setjmp(Getjbuf)) {
+               Ntimeout++;
+               PKDEBUG(4, "alarm %d\n", Ntimeout);
+               return(-1);
+       }
+       signal(SIGALRM, cgalarm);
+
+       alarm(PKTIME);
+       for (nchars = 0; nchars < n; nchars += ret) {
+               ret = read(fn, b, n - nchars);
+               if (ret == 0) {
+                       alarm(0);
+                       return(-1);
+               }
+               PKASSERT(ret > 0, "PKCGET READ", "", ret);
+               b += ret;
+       }
+       alarm(0);
+       return(0);
+}
+
+
+#ifdef PROTODEBUG
+generror(p, s)
+char *p;
+int s;
+{
+       int r;
+       if (Errorrate != 0 && (rand() % Errorrate) == 0) {
+               r = rand() % s;
+fprintf(stderr, "gen err at %o, (%o), ", r, (unsigned) *(p + r));
+               *(p + r) += 1;
+       }
+       return;
+}
+
+
+#endif