/* dslc.c L. Stewart January 21, 1983 5:10 PM D. Swinehart July 12, 1982 8:45 AM L. Stewart January 21, 1983 7:38 PM, new EtherHost L. Stewart January 22, 1983 3:35 PM, new statistics L. Stewart January 23, 1983 5:44 PM, Fix StartRx call */ #include <Lark.h> #include <Ec.h> #include <Env.h> #include <Alloc.h> #include <Queue.h> #include <Pup.h> struct ccb { char cmda; char *addra; char counta; char stata; }; /* Runtime */ extern InByte(); extern Swab(); extern CallSwat(); /* Context package */ extern InitNContext(); extern Block(); /* Queue package */ extern Enqueue(); extern Dequeue(); extern InitQueue(); /* Runtime */ extern int DoubleEq(); /* Timer package */ extern SetTmr(); extern TmrExp(); /* Ethernet machine language */ extern SLCInit(); extern SLTStart(); extern SLRStart(); /* Pup level 1 */ extern GetPBI(); extern MaybeGetPBI(); extern SetLocalNet(); extern int currentHost; extern int localHost; extern int localNet; extern int lenPup; extern struct SocketEntry pupSockets[1 /*maxPupSockets*/]; /* transmit and receive SLC control blocks */ static struct ccb rxccb; static struct PBI *rxPBI; static struct ccb txccb; static struct PBI *txPBI; /* if txPBI is non-zero, then a transmission is in progress */ static int rBufCount; /* transmit and receive timeout timers */ static int txtmr[1]; static int rxtmr[1]; /* ether output queue */ static struct Queue outQ[1]; /* stack space */ static int etherStack[200]; /* statistics */ static int slcrp; /* packet counters */ static int slctp; static int slrsmash; /* SLC resets due to timeout */ static int sltsmash; static int noBuffer; /* lost packets due to buffer shortage */ static EtherPr() { struct EtherEncapsulation *ee; int temp; for (;;) { Block(); /* test for reception or hung receiver */ if (rxccb.stata & 0x80) { if (rxccb.stata == 0x88) { temp = (int) rxPBI->pup; temp = temp - 4; ee = (struct EtherEncapsulation *) temp; if (ee->type == 2) { /* Swabbed typePup */ rxPBI = IntLev1(rxPBI); }; }; StartRx(); }; if (TmrExp(rxtmr)) { SLCReset(); /* violent ! */ slrsmash += 1; }; if (txPBI && TmrExp(txtmr)) { SLCReset(); /* violent ! */ sltsmash += 1; }; /* test for completion of transmit or hung transmitter */ if (txPBI) { if (txccb.stata & 0x80) { Enqueue(txPBI->queue, txPBI); txPBI = Dequeue(outQ); if (txPBI) Txpkt(txPBI); }; }; }; }; /* The socket dispatch runs at interrupt level, but the associcated procedure is called by pup level 1 process */ struct PBI *IntLev1(pbi) struct PBI *pbi; { struct Pup *pup; struct PBI *npbi; int dNet, dHost, i, temp; slcrp += 1; pup = pbi->pup; if (pup->sPort.host == 0) goto BcastSource; /* If the destination is not us, discard packet. */ if ((dNet = pup->dPort.net) == 0) goto ZeroDNet; if (dNet != localNet) { if (!localNet) SetLocalNet(dNet); else goto Misaddressed; }; /* If checksum exists and is to be checked, here's the place to do it. */ /* This line is a simulation of a successful checksum checking activity. */ /* TEMP? Pups not addressed to our multicast or specific address cannot be supported. Not sure they could be received, anyhow. */ if (((dHost = pup->dPort.host) != 0) && (dHost != currentHost) && (dHost != localHost)) goto BadHost; /* Dispatch Other designated packets (e.g., voice data) */ for (i = 1; i <= maxPupSockets; ++i) { if (DoubleEq(&pupSockets[i].port.socket, &pup->dPort.socket)) { temp = (int) pupSockets[i].PortProc; pbi->clientWord = temp; if ((npbi = MaybeGetPBI(0)) != 0) { Enqueue(pupSockets[i].q, pbi) pbi = npbi; }; else noBuffer += 1; goto FoundIt; }; }; Misaddressed: BcastSource: ZeroDNet: BadHost: FoundIt: return(pbi); }; InitEther(zone, ctxQ, x) struct ZN *zone; struct Queue *ctxQ; int x; { int myc; txPBI = rxPBI = 0; noBuffer = slrsmash = sltsmash = 0; rBufCount = (lenPup + lenEtherEncapsulation) << 1; if (rBufCount > 256) CallSwat(ecPup1 + 19); rBufCount = (-rBufCount) & 0x00ff; myc = InitNContext("EtherPr", etherStack, 200, &EtherPr); Enqueue(ctxQ, myc); InitQueue(outQ); SLCReset(); }; static SLCReset() { SLCInit(EtherHost()); if (txPBI) { Enqueue(txPBI->queue, txPBI); if (txPBI = Dequeue(outQ)) Txpkt(txPBI); }; StartRx(); }; static StartRx() { if (rxPBI == 0) rxPBI = GetPBI(0); rxccb.cmda = 0x00; rxccb.addra = rxPBI->pup; rxccb.addra = rxccb.addra - 4; rxccb.counta = rBufCount; rxccb.stata = 0; SetTmr(10000, rxtmr); SLRStart(&rxccb); }; int EtherHost() { return ((InByte(piob) & 0x003f) + 0x0040); }; TransmitPacket(pbi) struct PBI *pbi; { if (txPBI) Enqueue(outQ, pbi); else Txpkt(pbi); }; static Txpkt(pbi) struct PBI *pbi; { int len; txPBI = pbi; len = Swab(txPBI->pup->length); len = (len + 5) & 0x0fffe; if (len > 256) CallSwat(ecPup1+20); txccb.cmda = 0x50; txccb.addra = txPBI->pup; txccb.addra = txccb.addra - 4; txccb.counta = len & 0x00ff; txccb.stata = 0; SLTStart(&txccb); SetTmr(2000, txtmr); slctp += 1; };