|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 4977 (0x1371)
Types: TextFile
Notes: UNIX file
Names: »cudld.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦f4b8d8c84⟧ UNIX Filesystem
└─⟦this⟧ »cmd/cu/cudld.c«
/*
* Downloading routines for use by
* the CU terminal emulator.
* A packet consists of an STX, packet type and sequence, information,
* an ETX and then a two character CRC character.
*/
#include <stdio.h>
#include <signal.h>
#include "cu.h"
PKT rpkt; /* Received data (no windowing yet) */
PKT xpkt; /* Transmitted data */
static unsigned accrc; /* For incremental C▶12◀C-16 computation */
int nretry; /* Number of retries */
int timeout();
/*
* Encode characters that need escaping on the line
* Any entry that is zero need not be touched.
*/
static char encode[256] = {
0100, 0101, 0102, 0103, 0104, 0105, 0106, 0107, /*000-007*/
0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, /*010-017*/
0120, 0121, 0122, 0123, 0000, 0000, 0000, 0000, /*010-017*/
0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, /*030-037*/
0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, /*040-047*/
0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, /*050-057*/
0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, /*060-067*/
0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, /*070-077*/
0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, /*100-107*/
0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, /*110-117*/
0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, /*120-127*/
0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, /*130-137*/
0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, /*140-147*/
0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, /*150-157*/
0000, 0000, 0000, 0000, 0000, 0000, 0000, 0000, /*160-167*/
0000, 0000, 0000, 0000, 0000, 0000, 0000, 0077, /*170-177*/
};
/*
* Callled to initialise everything
* for the packet routines.
*/
pktinit()
{
signal(SIGALRM, timeout);
}
PKT *
getpkt()
{
register unsigned char c;
register char *cp;
register PKT *pp;
alarm(TLEN);
pp = &rpkt;
cp = &pp->p_type;
pp->p_flags = 0;
accrc = 0;
while ((c = sget()) != STX)
if (pp->p_flags != 0)
goto bad;
while ((c = sget()) != ETX) {
if (pp->p_flags != 0)
goto bad;
if (c == DLE) {
if ((c = sget()) == EOF)
break;
c ^= 0100;
}
crcchar(c);
*cp++ = c;
}
checkcrc(pp);
bad:
pp->p_len = cp - (char *)(&pp->p_type);
alarm(0);
return (pp);
}
/*
* Put out a packet of length `nb'
* bytes. This also sends the
* proper CRC-16 check character.
*/
putpkt(pp)
PKT *pp;
{
register unsigned char *cp;
register unsigned nb;
register unsigned c;
sput(STX);
accrc = 0;
cp = &pp->p_type;
nb = pp->p_len;
do {
mput(*cp++);
} while (--nb);
sput(ETX);
c = accrc;
mput(c&0xFF);
mput(c>>8);
}
/*
* Mapped putting of a character.
*/
mput(c)
register int c;
{
register int c1;
if ((c1 = encode[c]) != 0) {
sput(DLE);
sput(c1);
} else
sput(c);
crcchar(c);
}
/*
* Send the packet using the lower-level routines to do
* retransmission on the line.
*/
sendpkt(xpp)
register PKT *xpp;
{
register PKT *rpp;
for (;;) {
putpkt(xpp);
rpp = getpkt();
if (rpp->p_type == 'E')
doend(rpp);
if (rpp->p_flags==0 && rpp->p_type=='A')
break;
/* Error */
nretry++;
}
}
/*
* Receive a packet.
* Manage the sequence numbers.
*/
PKT *
rcvpkt(seqno)
unsigned seqno;
{
register PKT *rpp;
register unsigned rseq;
for (;;) {
rpp = getpkt();
if (rpp->p_flags != 0) {
nretry++;
nakpkt();
continue;
}
if (rpp->p_type == 'E')
doend(rpp);
rseq = (rpp->p_seq[1] << 8) + rpp->p_seq[0];
if (rpp->p_type=='I' && rseq!=seqno)
nakpkt();
else
break;
}
return (rpp);
}
/*
* Generate a Nak packet
*/
nakpkt()
{
xpkt.p_type = 'N';
xpkt.p_len = 1;
putpkt(&xpkt);
}
/*
* Generate an acknowledgement
*/
ackpkt()
{
xpkt.p_type = 'A';
xpkt.p_len = 1;
putpkt(&xpkt);
}
/*
* Generate an end packet.
*/
endpkt(s, f)
register char *s;
int f;
{
register unsigned n;
xpkt.p_type = 'E';
n = strlen(s)+1;
xpkt.p_len = n + 3;
strncpy(&xpkt.p_data[0], s, n);
putpkt(&xpkt);
if (f)
getpkt();
}
/*
* Read in a CRC from the line
* and compare it to the expected one.
*/
checkcrc(pp)
PKT *pp;
{
register int c;
register int i;
register unsigned crc;
static unsigned char x[2];
for (i=0; i<2; i++) {
if ((c = sget()) == EOF)
break;
if (c == DLE) {
if ((c = sget()) == EOF)
break;
c ^= 0100;
}
x[i] = c;
}
crc = x[0] | (x[1]<<8);
if (crc != accrc)
pp->p_flags |= PCRC; else
pp->p_flags &= ~PCRC;
}
/*
* Called on line timeout.
*/
timeout()
{
signal(SIGALRM, timeout);
rpkt.p_flags |= PTOUT;
}
/*
* CRC Calculation using the BNR fast Matrix Multiply
* and Table Lookup Algorithm
*/
static int ytab[] = {
0, 0146001, 0154001, 012000, 0170001, 036000,
024000, 0162001, 0120001, 066000, 074000,
0132001, 050000, 0116001, 0104001, 042000
};
static int ztab[] = {
0, 0140301, 0140601, 0500, 0141401, 01700,
01200, 0141101, 0143001, 03300, 03600, 0143501,
02400, 0142701, 0142201, 02100
};
crcchar(c)
register c;
{
accrc ^= c;
accrc = (accrc>>8) ^ ztab[accrc&0xF] ^ ytab[(accrc>>4)&0xF];
}