/* etherload.c L. Stewart September 10, 1982 11:12 AM L. Stewart December 3, 1982 2:19 PM, changed to poll style */ /* in cmon.c */ extern char mstate[26]; extern startm(); /* in cmruntimeml.dsm */ extern swab(); extern blt(); /* in cmslcml.dsm */ extern slcinit(); extern waitccb(); extern sltstart(); extern slrstart(); struct ccb { char cmda; char *addra; char counta; char stata; }; struct port { char net, host; int soc1, soc2; }; struct pup { int eaddr; int etype; int len; char tpc, type; int id1, id2; struct port dport, sport; char data[1]; }; struct core { int addrlo, addrhi, count; char data[1]; }; struct ccb minccb, inccb, outccb; /* really want length to be unsigned, but *char is ok too. The problem is to avoid sign extension when assigning from inccb.counta to length */ static char *cdata; static char *caddr; static char *length; static int ccount; static struct pup *rpup; static struct pup *tpup; static struct core *tcore; static int lastid1; static int lastid2; static int tplen; static int rv; static int valid; static int rbuf[130]; static int buf[130]; static int lhost; /* Pup download server */ StartEL() { lhost = GetPIO(1); slcinit(lhost); minccb.cmda = 0x00; minccb.addra = rbuf; minccb.counta = 0; minccb.stata = 0; tpup = (struct pup *) buf; tcore = (struct core *) tpup->data; cdata = tcore->data; rpup = (struct pup *) rbuf; startrx(); }; CheckEL() { if (!(inccb.stata & 0x80)) return; if (inccb.stata != 0x88) StartEL(); if (inccb.counta == 0) length = 256; else length = inccb.counta; echo(length); StartEL(); }; static echo(leng) int leng; { int plen; if ((!(rpup->eaddr & 0xff)) || (leng&01) || (leng<26)) goto quitel; /* unswabbed etype should be 2 */ if (rpup->etype != 2) goto quitel; /* check lengths */ plen = (swab(rpup->len)+5) & 0xfffe; if (plen != leng) goto quitel; /* check pup destintion */ if (rpup->dport.host != lhost) goto quitel; if ((rpup->dport.soc1) || (rpup->dport.soc2 != 0x3000)) goto quitel; if ((rpup->type != 0xc0) && (rpup->type != 0xc2)) { if ((rpup->type != 0xc4) && (rpup->type != 0xc6)) goto quitel; }; if ((rpup->id1 == lastid1) && (rpup->id2 == lastid2)) { if (valid) sendpkt(); goto quitel; }; /* copy packet accross */ blt(rbuf, buf, 260); valid = 0; rv = 0; caddr = swab(tcore->addrlo); ccount = swab(tcore->count); if (tcore->addrhi) goto quitel; /* check puptype */ if (tpup->type == 0xc0) { /* core store */ blt(cdata, caddr, ccount); blt(caddr, cdata, ccount); comtc(); tplen = leng; }; if (tpup->type == 0xc2) { /* core fetch */ mcomc(); }; if (tpup->type == 0xc6) { /* state fetch */ if (((int) caddr != 1) || (ccount != 28)) goto quitel; caddr = mstate; mcomc(); }; if (tpup->type == 0xc4) { /* state store */ if (((int) caddr != 1) || (ccount != 28)) goto quitel; caddr = mstate; blt(cdata, caddr, ccount); mcomc(); setuppkt(); sendpkt(); startm(); }; if (!rv) goto quitel; setuppkt(); sendpkt(); quitel: }; static mcomc() { blt(caddr, cdata, ccount); tplen = (33+ccount) & 0xfffe; tpup->len = swab(tplen - 4); comtc(); }; static sendpkt() { outccb.cmda = 0x50; outccb.addra = buf; outccb.counta = tplen; outccb.stata = 0; sltstart(&outccb); /* wait for transmit done */ waitccb(&outccb); }; static setuppkt() { /* swap src and destination */ ssd(buf); /* fill in no-checksum */ buf[(tplen/2)-1] = 0xffff; /* swap ether source and destination */ tpup->eaddr = swab(tpup->eaddr); /* zero transport control */ tpup->tpc = 0; /* set puptype */ /* tpup->type += 1; doesn't work */ tpup->type = tpup->type+1; }; static comtc() { rv = 1; valid = 1; lastid1 = tpup->id1; lastid2 = tpup->id2; }; static ssd(p) char *p; { char temp[6]; blt(&p[12],temp, 6); blt(&p[18],&p[12], 6); blt(temp,&p[18], 6); }; static startrx() { if (slrstat() & 0x000c) slrinit(); blt(&minccb, &inccb, 5); slrstart(&inccb); };