home *** CD-ROM | disk | FTP | other *** search
- /*
- * GIO.C WINDOWED G PROTOCOL
- *
- * written from scratch, except the checksum routine which was
- * rewritten but based on the old one.
- *
- * WINDOW SIZE: When changing the window size be sure there
- * are enough buffers available for pending txs.
- *
- * GIO.C (c)Copyright 1989, Matthew Dillon, All Rights Reserved
- * extended to window size of 7 by Jack J. Rouse
- *
- * Added variable packetsize (SegSize, TxSegSize). <CB>
- *
- */
-
- #include "includes.h"
-
- typedef unsigned char ubyte;
- typedef unsigned short uword;
-
- typedef struct {
- ubyte Dle; /* Literal ASCII DLE */
- ubyte K; /* data size 2^(K+4) except K=0 means no data */
- ubyte CL,CH; /* MAGIC - chksum(data) ^ C */
- ubyte C;
- ubyte X; /* K ^ C0 ^ C1 ^ C */
- } Frame;
-
- typedef struct {
- ubyte CType; /* bits 7-6 of C */
- ubyte CCmd; /* bits 5-3 of C */
- ubyte CSeq; /* bits 2-0 of C */
- ubyte PLen; /* pre-data (2 bytes) for SHORTDATA type */
- ubyte *Data; /* implies CType=LONGDATA or SHORTDATA */
- uword DLen; /* length of data */
- } Packet;
-
- Prototype int gwrdata (FILE *);
- Prototype int gwrmsg (char *);
- Prototype int grddata (FILE *);
- Prototype int grdmsg (char *, int);
- Prototype int gturnon (int);
- Prototype int gturnoff (void);
- Prototype void ResetGIO (void);
-
- Prototype int ReducedTimeout;
-
- int ReducedTimeout;
-
- Local char *GetTxBuf (void);
- Local int SendDataPacket (unsigned char *, int);
- Local int RecvDataPacket (char **);
- Local int GetData (int, Packet *);
- Local int RecvdAck (char);
- Local int WriteCtlPacket (int);
- Local int WritePacket (Packet *, int);
- Local int ReadPacket (Packet *, int, int);
- Local int CheckSum (unsigned char *, int);
- Local void FrameToPacket (Frame *, Packet *, unsigned char *);
- Local int LenToK (unsigned short);
-
- #define SUCCESS 0
- #define FAIL 1
-
- #define MAGIC 0125252
- #define DLE 0x10
- #define WINDOWSIZE 7
- #define SEGSIZEK 2 /* 64 bytes ?? */
- #define SEGSIZEMAX 9 /* 4096 bytes max <CB> */
-
- #define SUB1(var) (((var)-1)&7)
-
- #define CT_CONTROL (0 << 6)
- #define CT_ALTCHN (1 << 6)
- #define CT_LONGDATA (2 << 6)
- #define CT_SHORTDATA (3 << 6)
- #define CT_MASK (3 << 6)
-
- #define CC_CLOSE (1 << 3)
- #define CC_RJ (2 << 3)
- #define CC_SRJ (3 << 3)
- #define CC_RR (4 << 3)
- #define CC_INITC (5 << 3)
- #define CC_INITB (6 << 3)
- #define CC_INITA (7 << 3)
- #define CC_MASK (7 << 3)
-
- #define SEQ_MASK 7
-
- #define WAIT_ACK 1
- #define WAIT_DATA 2
- #define WAIT_CONTROL 3
-
- #define MaxPktSize 4096
-
- char RxBuf [MaxPktSize + 4];
- char *TxBuf [8];
-
- /* TRANSMIT STAGE */
- char TxSeq = 0; /* Last send packet */
- char TxPend= 0; /* hasn't been acked yet */
- uword TxWinSize; /* 1 or 2 (max 7) */
- uword TxSegSize; /* maximum segment size */
- char TxSegK; /* K for TxSegSize */
- Packet TxPacket[8]; /* contents of last packet */
-
- /* RECEIVE STAGE */
- char RxSeq = 0; /* Last valid recv pkt */
- char RxRdy = 0; /* Has come in.. */
- char RxRetry = 8;
- char RxNotAcked = 0; /* We have yet to ack it */
- Packet RxPacket; /* The packet that has come in */
-
- Prototype int Tot_Retries;
- Prototype int Tot_Packets;
-
- int
- Tot_Retries,
- Tot_Packets;
-
- void
- ResetGIO (void)
- {
- TxSeq = 0;
- TxPend= 0;
- TxWinSize = 0;
- TxSegSize = 0;
- TxSegK = 0;
- RxSeq = 0;
- RxRdy = 0;
- RxRetry = 8;
- RxNotAcked = 0;
-
- return;
- }
-
- /*
- * Get Transmit Buffer. Note that some space to the left is available
- */
-
- Local
- char *
- GetTxBuf (void)
- {
- static int
- index = 0;
-
- if (++index > TxWinSize)
- index = 0;
-
- if (TxBuf [index] == NULL &&
- (TxBuf [index] = (char *) malloc (MaxPktSize + 4)) == NULL) {
- printf("Out of memory in GetTxBuf.");
- /* could handle this case better, but it should be rare */
- xexit (1);
- }
- return (TxBuf [index] + 2);
- }
-
- int
- gwrdata (FILE *fi)
- {
- if (debug > 7)
- printf ("GWRDATA: ");
-
- for (;;) {
- int
- bytes;
- char
- *buf = GetTxBuf ();
-
- if ((bytes = fread (buf, 1, TxSegSize, fi)) <= 0)
- break;
-
- BytesOut += bytes;
-
- if (SendDataPacket (buf, bytes) != SUCCESS) {
- if (debug > 7)
- printf ("GWR Failed\n");
- return FAIL;
- }
- if (debug > 7)
- printf("\nGWROK ");
- }
-
- {
- char
- *buf = GetTxBuf ();
-
- if (SendDataPacket (buf, 0) != SUCCESS) {
- if (debug > 7)
- printf ("GWR Failed (last)\n");
- return FAIL;
- }
- }
-
- if (debug > 7)
- printf ("\nGWFile Last Ack\n");
-
- while (TxPend) {
- if (GetData (WAIT_ACK, NULL) == FAIL)
- return FAIL;
- }
-
- if (debug > 7)
- printf ("success\n");
-
- return SUCCESS;
- }
-
- /*
- * Write message to the other guy.
- *
- * NOTE: LONGDATA packets used exclusively and \0 fill to end.
- */
-
- int
- gwrmsg (char *str)
- {
- int
- len = strlen (str) + 1; /* type + str + \0 */
-
- if (debug > 7)
- printf ("GWRMSG: %s\n", str);
-
- while (len > TxSegSize) {
- char
- *buf = GetTxBuf ();
-
- movmem (str, buf, TxSegSize);
- if (debug > 7)
- printf ("GWR-SEND %d\n", TxSegSize);
-
- if (SendDataPacket (buf, TxSegSize) != SUCCESS)
- return FAIL;
-
- len -= TxSegSize;
- str += TxSegSize;
- }
-
- /*
- * Find optimal packet size (remember, we must force LONGDATA
- *
- * Apparently packet sizes less than the agreed upon size are
- * not allowed ???
- */
-
- {
- int
- siz = TxSegSize;
- char
- *buf = GetTxBuf ();
-
- if (VarPackets) {
- int
- k = TxSegK;
-
- while (k > 1 && (siz >> 1) >= len) {
- --k;
- siz >>= 1;
- }
- }
-
- if (debug > 7)
- printf ("GWR-FNL %d %d\n", len, siz);
-
- movmem (str, buf, len);
- setmem (buf + len, siz - len, 0);
- if (SendDataPacket (buf, siz) != SUCCESS) {
- if (debug > 7)
- printf ("GWR-FAIL\n");
- return FAIL;
- }
- }
-
- if (debug > 7)
- printf ("GWR Last Ack\n");
-
- while (TxPend) {
- if (GetData (WAIT_ACK, NULL) == FAIL)
- return(FAIL);
- }
-
- if (debug > 7)
- printf ("success\n");
-
- return SUCCESS;
- }
-
- int
- grddata (FILE *fi)
- {
- int
- bytes;
- char
- *buf;
-
- if (debug > 7)
- printf ("GRDDATA\n");
-
- while ((bytes = RecvDataPacket (&buf)) > 0) {
- if (debug > 7)
- printf ("GRDDATA blk %d\n", bytes);
-
- fwrite (buf, 1, bytes, fi); /* FIXME - check result */
- BytesIn += bytes;
- }
-
- if (debug > 7)
- printf ("GRDDATA end %d\n", bytes);
-
- if (bytes < 0)
- return FAIL;
-
- return SUCCESS;
- }
-
- int
- grdmsg (char *buf, int maxlen)
- {
- int
- i,
- n,
- slen;
- char
- *ptr;
-
- i = 0;
- if (debug > 7)
- printf ("GRDMSG\n");
-
- while ((n = RecvDataPacket (&ptr)) > 0) {
- ptr [n] = 0;
- slen = strlen (ptr);
- if (slen > maxlen - 1) {
- printf ("GRDMSG: Buffer overflow!\n");
- return FAIL;
- }
- movmem (ptr, buf + i, slen);
- buf [i + slen] = 0;
- if (slen != n)
- break;
- i += slen;
- maxlen -= slen;
- }
-
- if (debug > 7)
- printf ("GRDMSGEND %d (%d) %s\n", n, i, buf);
-
- if (n < 0) {
- buf [0] = 0;
- return FAIL;
- }
-
- return SUCCESS;
- }
-
- Local
- int
- SendDataPacket (ubyte *buf, int bytes)
- {
- Packet
- P;
-
- /*
- * If window exhausted we must wait for at least one ack.
- */
-
- while (TxPend == TxWinSize) {
- if (GetData (WAIT_ACK, NULL) == FAIL)
- return FAIL;
- }
-
- TxSeq = (TxSeq + 1) & 7; /* next Tx packet */
-
- /*
- * Figure out best fit packet size. Apparently packets smaller
- * than the agreed upon size are not allowed ???
- */
-
- if (VarPackets) {
- int
- k = TxSegK;
-
- P.DLen = TxSegSize;
- while (k > 1 && P.DLen && (P.DLen >> 1) >= bytes) {
- --k;
- P.DLen >>= 1;
- }
- }
- else
- P.DLen = TxSegSize;
-
- if (bytes < P.DLen) {
- uword
- extra = P.DLen - bytes;
-
- setmem (buf + bytes, extra, 0);
- if (extra <= 127) {
- P.PLen = 1;
- buf [-1] = extra;
- }
- else {
- P.PLen = 2;
- buf [-2] = 0x80 | extra;
- buf [-1] = (extra >> 7);
- }
- P.CType = CT_SHORTDATA;
- }
- else {
- P.PLen = 0;
- P.CType = CT_LONGDATA;
- }
-
- P.CCmd = TxSeq << 3; /* transmit sequence number */
- P.CSeq = RxSeq; /* last valid received pkt */
- P.Data = buf;
-
- if (debug > 7)
- printf ("WRITE DATA PACKET txseq=%d rxack=%d\n", TxSeq, P.CSeq);
-
- #ifdef NOTDEF
- RxNotAcked = 0; /* We've acked the rx packet */
- #else
- if (RxNotAcked) { /* always send CC_RR packets */
- WriteCtlPacket (CC_RR | RxSeq);
- RxNotAcked = 0;
- }
- #endif
-
- TxPacket [TxSeq] = P;
- ++TxPend;
-
- WritePacket (&TxPacket [TxSeq], 1);
- ++Tot_Packets;
-
- return SUCCESS;
- }
-
- Local
- int
- RecvDataPacket (char **pbuf)
- {
- if (RxRdy == 0) {
- if (GetData (WAIT_DATA, NULL) != SUCCESS)
- return -1;
- }
- *pbuf = RxPacket.Data;
- RxRdy = 0;
-
- return (int) RxPacket.DLen;
- }
-
- int
- gturnon (int master)
- {
- Packet
- P;
- int
- retry = 5,
- windowsize = WINDOWSIZE, /* our prefered window size */
- segsize = SEGSIZEK; /* our prefered segment size */
-
- if (WindowSize < windowsize) /* command line override */
- windowsize = WindowSize;
-
- if (SegSize > segsize && SegSize < SEGSIZEMAX)
- segsize = SegSize; /* added by <CB> */
-
- if (debug > 0)
- printf ("Proposed SegSize is %d\n", segsize);
-
- if (master) {
- while (retry > 0) {
- WriteCtlPacket (CC_INITA | windowsize);
- if (GetData (WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
- if (P.CSeq && P.CSeq < windowsize)
- windowsize = P.CSeq;
- break;
- }
- --retry;
- }
- while (retry > 0) {
- WriteCtlPacket (CC_INITB | (segsize - 1));
- if (GetData (WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
- if (P.CSeq < segsize - 1)
- segsize = P.CSeq + 1;
- break;
- }
- --retry;
- }
- while (retry > 0) {
- WriteCtlPacket (CC_INITC | windowsize);
- if (GetData (WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
- if (P.CSeq && P.CSeq < windowsize)
- windowsize = P.CSeq;
- break;
- }
- --retry;
- }
- }
- else {
- while (retry > 0) {
- if (GetData (WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) {
- WriteCtlPacket (CC_INITA | windowsize);
- if (P.CSeq && windowsize > P.CSeq)
- windowsize = P.CSeq;
- break;
- }
- --retry;
- }
- while (retry > 0) {
- if (GetData (WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) {
- WriteCtlPacket (CC_INITB | (segsize - 1));
- if (P.CSeq < segsize - 1)
- segsize = P.CSeq + 1;
- break;
- }
- --retry;
- }
- while (retry > 0) {
- if (GetData (WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) {
- WriteCtlPacket (CC_INITC | windowsize);
- if (P.CSeq && windowsize > P.CSeq)
- windowsize = P.CSeq;
- break;
- }
- --retry;
- }
- }
-
- TxSegK = segsize;
- TxSegSize = 1 << (TxSegK + 4);
- TxWinSize = windowsize;
-
- xfer.proto [0] = 'g';
- xfer.proto [1] = TxWinSize;
- xfer.proto [2] = TxSegK;
-
- if (debug > 0) {
- printf ("Window Size is %d\n", TxWinSize);
- printf ("Segment Size is %d (%d bytes)\n", TxSegK, TxSegSize);
- }
-
- if (retry == 0)
- return FAIL;
-
- return SUCCESS;
- }
-
- int
- gturnoff (void)
- {
- Packet
- P;
- int
- retry = 5;
-
- if (RxNotAcked) { /* ack last data packet sent (presumably master's HY) */
- WriteCtlPacket (CC_RR | RxSeq);
- RxNotAcked = 0;
- }
-
- while (retry > 0) {
- WriteCtlPacket (CC_CLOSE);
- if (GetData (WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_CLOSE)
- return SUCCESS;
- --retry;
- }
-
- return FAIL;
- }
-
- /*
- * GetData()
- *
- * This is the core of the packet protocol. As soon as we get a satisfactory
- * terminating condition we return. However, on unsatisfactory conditions
- * such as having to send a reject, we attempt to drain any pending data
- * (i.e. multiple returned rejects) so we do not do multiple resends.
- *
- * The resend flag only applies on a failure return.
- */
-
- Local
- int
- GetData (int waitfor, Packet *p)
- {
- Packet
- P;
- int
- timeout,
- drainmode = 0;
-
- /*
- * If we haven't acked the last packet we received we must do
- * so now before we can expect to receive another one!
- */
-
- if (debug > 7)
- printf ("Get-Data waitfor %s\n", (waitfor == WAIT_ACK) ? "WAIT_ACK" : "WAIT_DATA");
-
- if (waitfor == WAIT_ACK)
- timeout = (PacketTimeout) ? PacketTimeout : 5;
- else
- if (waitfor == WAIT_DATA)
- timeout = (PacketTimeout) ? PacketTimeout * 4 : 20;
- else
- timeout = (PacketTimeout) ? PacketTimeout * 4 : 20;
-
- for (;;) {
- /*
- * due to confusion on connection termination, we do not wait
- * around trying to retry the final termination acknowlege.
- */
-
- if (ReducedTimeout) {
- if (RxRetry > 2)
- RxRetry = 2;
- if (timeout > 5)
- timeout = 5;
- }
- if (RxNotAcked) { /* good, send ack for rx'd pkt */
- WriteCtlPacket (CC_RR | RxSeq);
- RxNotAcked = 0;
- } /* bad, timeout on read */
- if (ReadPacket (&P, (drainmode) ? 0 : timeout, (waitfor == WAIT_DATA)) == FAIL) {
- drainmode = 0;
-
- /*
- * fail if greater than 20% of packets received are retries.
- */
- #define ERROR_THRESHOLD (Tot_Packets < 50 || (Tot_Packets/(Tot_Retries+1)) > 4)
-
- /*
- * If we have timed out waiting for data then send a reject
- */
-
- if (waitfor == WAIT_DATA && RxRetry && ERROR_THRESHOLD) {
- --RxRetry;
- /*
- * sd: To properly drain on errors I found a small
- * delay was needed here.
- */
- if (NoDelay == 0)
- Delay (15);
- ++Tot_Retries;
-
- if (debug > 7)
- printf ("\nWAIT-DATA, TIMEOUT, SEND RJ\n");
-
- WriteCtlPacket (CC_RJ | RxSeq);
- continue;
- }
-
- /*
- * If we have timed out waiting for an ack send the entire
- * window. We must send the window sometime and it might as
- * well be now.
- */
-
- if (waitfor == WAIT_ACK && RxRetry && ERROR_THRESHOLD) {
- int
- i;
-
- if (debug > 7)
- printf ("RESEND %d packets\n", TxPend);
- for (i = 1; i <= TxPend; ++i) {
- Packet
- *pkt = &TxPacket [(TxSeq - TxPend + i) & 7];
-
- pkt->CSeq = RxSeq;
- WritePacket (pkt, 1);
- }
- --RxRetry;
- ++Tot_Retries;
- continue;
- }
-
- if (debug > 7)
- printf ("COMPLETE FAILURE RxRetry = %d\n", RxRetry);
-
- return FAIL;
- }
-
- /*
- * valid packet, terminating condition?
- */
-
- RxRetry = 8;
- switch (P.CType) {
- case CT_CONTROL:
- switch (P.CCmd) {
- case CC_CLOSE: /* End of communication ... not an ACK! */
- if (waitfor == WAIT_CONTROL) {
- *p = P;
- return SUCCESS;
- }
- return FAIL;
- case CC_RJ: /* Reject packet (P.CSeq == last good packet) */
- RecvdAck (P.CSeq);
- drainmode = 1;
- break;
- case CC_SRJ: /* Selective Reject (P.CSeq == bad packet # ) */
- return FAIL;
- case CC_RR: /* Ack to packet (P.CSeq == packet # acked) */
- #ifdef NOTDEF
- if (P.CSeq == ((TxSeq - TxPend) & 7)) {
- /*
- * The CSeq packet was previously acknowledged
- * The receiver apparently has not seen anything since.
- * This is the same as a rejection.
- */
- goto resend;
- }
- #endif
- if (RecvdAck (P.CSeq) == SUCCESS && waitfor == WAIT_ACK)
- return SUCCESS;
- else
- drainmode = 1; /* .19 */
- break;
- case CC_INITC:
- case CC_INITB:
- case CC_INITA:
- if (waitfor == WAIT_CONTROL) {
- *p = P;
- return SUCCESS;
- }
- return FAIL;
- }
- break;
- case CT_ALTCHN:
- printf ("ALTCHN packet ??\n");
- break;
- case CT_LONGDATA:
- case CT_SHORTDATA:
- {
- char
- rxseq = P.CCmd >> 3;
- char
- txack = P.CSeq;
-
- if (RxRdy == 1) {
- printf ("Got two receive packets without me acking!\n");
- }
-
- if (rxseq == RxSeq) { /* already got this packet */
- RxNotAcked = 1;
- continue;
- /* expected packet? */
- }
- else
- if (rxseq != ((RxSeq + 1) & 7)) {
- drainmode = 1;
- printf ("Received sequence %d, expected %d\n", rxseq, (RxSeq + 1) & 7);
- break;
- }
-
- if (debug > 6)
- printf ("RECV SEQUENCE %d\n", rxseq);
-
- RecvdAck (txack); /* woa */
-
- /*
- * Delay sending the ACK back in case we can combine
- * it with the next transmitted packet.
- */
-
- RxNotAcked = 1; /* we haven't ack'd the rx packet */
-
- ++Tot_Packets;
-
- RxSeq = (RxSeq + 1) & 7;
- RxRdy = 1;
- RxPacket = P;
- if (waitfor == WAIT_DATA)
- return SUCCESS;
- if (TxPend == 0 && waitfor == WAIT_ACK)
- return SUCCESS;
- }
- break;
- }
- }
-
- return;
- }
-
- Local
- int
- RecvdAck (char seq)
- {
- int
- i;
-
- /*
- * which packet was acked?
- */
-
- for (i = 0; i < TxPend; ++i) {
- if (seq == ((TxSeq - i) & 7))
- break;
- }
-
- if (i && i == TxPend) {
- if (seq != ((TxSeq - TxPend) & 7))
- printf ("He acked the wrong packet! %d expected %d\n", seq, TxSeq);
- return FAIL;
- }
-
- if (debug > 7)
- printf ("TxPend %d -> %d\n", TxPend, i);
-
- TxPend = i;
-
- return SUCCESS;
- }
-
- Local
- int
- WriteCtlPacket (int cc)
- {
- Packet
- pk;
-
- pk.CType = CT_CONTROL;
- pk.CCmd = cc & CC_MASK;
- pk.CSeq = cc & SEQ_MASK;
- pk.PLen = 0;
- pk.DLen = 0;
- WritePacket (&pk, 0);
-
- return SUCCESS;
- }
-
- Local
- int
- WritePacket (Packet *pk, int async)
- {
- Frame
- F;
- uword
- sum;
-
- F.Dle = DLE;
- F.C = pk->CType | pk->CCmd | pk->CSeq;
- F.K = 9;
-
- if (pk->CType == CT_SHORTDATA || pk->CType == CT_LONGDATA)
- F.K = LenToK (pk->DLen);
- else
- pk->DLen = 0;
-
- sum = MAGIC - (CheckSum (pk->Data - pk->PLen, pk->DLen) ^ F.C);
-
- F.CH = sum >> 8;
- F.CL = sum;
- F.X = F.K ^ F.CH ^ F.CL ^ F.C;
-
- if (debug > 7)
- printf ("WritePacket: F.K = %d F.C = %d.%d.%d\n", F.K, F.C >> 6, (F.C >> 3) & 7, F.C & 7);
-
- if (async)
- xwritea (&F, sizeof (F));
- else
- xwrite (&F, sizeof (F)); /* write header */
-
- if (pk->DLen) { /* write data */
- if (async)
- xwritea (pk->Data - pk->PLen, pk->DLen);
- else
- xwrite (pk->Data - pk->PLen, pk->DLen);
- }
-
- return SUCCESS;
- }
-
- Local
- int
- ReadPacket (Packet *pk, int timeout, int delay_flg)
- {
- Frame
- F;
- int
- c,
- i = 0;
-
- pk->Data = RxBuf;
- pk->CType = 0xFF;
- pk->CCmd = 0;
- pk->CSeq = 0;
-
- if (debug > 7)
- printf ("ReadPacket\n");
-
- while ((c = xgetc (timeout, delay_flg)) != EOF) {
- if (debug > 8)
- printf ("RP %d %02x\n", i, c);
-
- switch(i) {
- case 0:
- if (c == DLE) {
- F.Dle = c;
- ++i;
- if (timeout == 0)
- timeout = 1;
- }
- break;
- case 1:
- F.K = c;
- ++i;
- if (c == DLE) { /* K only valid 1-9 */
- F.Dle = c;
- i = 1;
- }
- else
- if (c == 0 || c > 9)
- i = 0;
- break;
- case 2:
- F.CL = c;
- ++i;
- break;
- case 3:
- F.CH = c;
- ++i;
- break;
- case 4:
- F.C = c;
- ++i;
- break;
- case 5:
- F.X = c;
- if (F.X != (F.K ^ F.CH ^ F.CL ^ F.C)) {
- printf ("F.X failed: %02x %02x\n", F.X, (F.K ^ F.CH ^ F.CL ^ F.C));
- i = 0;
- }
- else { /* get data segment if any */
- ++i;
- }
- break;
- }
- if (i == 6)
- break;
- }
-
- if (debug > 7) {
- if (i)
- printf ("RP Hdr i = %d, F.K = %d F.C = %d.%d.%d\n", i, F.K, F.C >> 6, (F.C >> 3) & 7, F.C & 7);
- else
- printf ("RP Hdr <rx timeout>\n");
- }
-
- if (i == 6) { /* Receive Data Portion */
- uword
- n,
- pktsize = 1 << (F.K + 4);
-
- if (F.K == 9)
- pktsize = 0;
-
- if (pktsize > MaxPktSize) {
- printf ("Protocol failure pktsize %d/%d/%d\n", pktsize, TxSegSize, MaxPktSize);
- return FAIL;
- }
- for (n = 0; n < pktsize; ++n) {
- if ((c = xgetc (4, delay_flg)) == EOF)
- break;
- pk->Data [n] = c;
- }
- if (c != EOF) {
- uword
- hissum,
- oursum;
-
- hissum = (F.CH << 8) | F.CL;
- oursum = MAGIC - (CheckSum (pk->Data, pktsize) ^ F.C);
-
- if (debug > 7)
- printf ("Got Data, checking: %04x %04x\n", hissum, oursum);
-
- if (hissum == oursum) {
- FrameToPacket (&F, pk, pk->Data);
- return SUCCESS;
- }
- }
- else {
- FrameToPacket (&F, pk, pk->Data); /* mainly for pk->CType */
- return FAIL;
- }
- }
- /*
- * Timeout, retry?
- */
- return FAIL;
- }
-
- Local
- int
- CheckSum (ubyte *s, int n)
- {
- uword
- sum,
- x,
- t;
-
- if (n == 0)
- return 0;
- sum = -1;
- x = 0;
-
- while (n) {
- if (sum & 0x8000)
- sum = (sum << 1) | 1;
- else
- sum = (sum << 1);
-
- t = sum;
- sum += *s++;
- x += sum ^ n;
-
- if (sum <= t)
- sum ^= x;
-
- --n;
- }
- return (int) sum;
- }
-
- Local
- void
- FrameToPacket (Frame *fr, Packet *pk, ubyte *data)
- {
- pk->CType = fr->C & CT_MASK;
- pk->CCmd = fr->C & CC_MASK;
- pk->CSeq = fr->C & SEQ_MASK;
-
- switch (pk->CType) {
- case CT_LONGDATA:
- pk->DLen = 1 << (fr->K + 4);
- break;
- case CT_SHORTDATA:
- pk->DLen = 1 << (fr->K + 4);
- if (pk->Data [0] & 0x80) {
- pk->DLen -= (pk->Data[0] & 0x7F) | (pk->Data[1] << 7);
- pk->Data += 2;
- }
- else {
- pk->DLen -= *pk->Data;
- ++pk->Data;
- }
- break;
- default:
- pk->DLen = 0;
- break;
- }
-
- return;
- }
-
- Local
- int
- LenToK (uword bytes)
- {
- uword
- n = 32,
- k = 1;
-
- while (n < bytes) {
- n <<= 1;
- ++k;
- }
-
- if (k > 8) {
- printf ("Soft error, LenToK: %d %d %d\n", bytes, n, k);
- k = 8;
- }
-
- return (int) k;
- }
-