From c37268ee3be0685df1e704722dd947cdcc81332c Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 28 Dec 1990 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1990-12-28 --- port/devlance.c | 119 +++++++++++++++++------------------------ power/dat.h | 13 +++++ power/fns.h | 1 + power/main.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 198 insertions(+), 72 deletions(-) diff --git a/port/devlance.c b/port/devlance.c index 0c33a3db36f33a1b6d28c89840f7cb8281aefa00..ad75e097c16c19679f32399498497f9b09954260 100644 --- a/port/devlance.c +++ b/port/devlance.c @@ -23,17 +23,6 @@ enum { #define NOW (MACHP(0)->ticks*MS2HZ) -/* - * Ethernet packet buffers. These must also be in lance addressible RAM. - */ -typedef struct { - uchar d[6]; - uchar s[6]; - uchar type[2]; - uchar data[1500]; - uchar crc[4]; -} Pkt; - /* * Communication with the lance is via a transmit and receive ring of * message descriptors. The Initblock contains pointers to and sizes of @@ -70,12 +59,11 @@ typedef struct Lancemem Msg tmr[Ntrb]; /* transmit message ring */ /* - * packet buffers (for IO2 version) + * packet buffers (for SGI IO2 version only) */ - Pkt rp[Nrrb]; - Pkt tp[Ntrb]; + Etherpkt rp[Nrrb]; + Etherpkt tp[Ntrb]; } Lancemem; -#define LANCEMEM ((Lancemem*)0) /* * Some macros for dealing with lance memory addresses. The lance splits @@ -83,6 +71,16 @@ typedef struct Lancemem */ #define HADDR(a) ((((ulong)(a))>>16)&0xFF) #define LADDR(a) (((ulong)a)&0xFFFF) + +/* + * The following functions exist to sidestep a quirk in the SGI IO3 lance + * interface. In all other processors, the lance's initialization block and + * descriptor rings look like normal memory. In the SGI IO3, the CPU sees a + * 6 byte pad twixt all lance memory shorts. Therefore, we use the following + * macros to compute the address whenever accessing the lance memory to make + * the code portable. Sic transit gloria. + */ +#define LANCEMEM ((Lancemem*)0) #define MPs(a) (*(short *)(l.lanceram + l.sep*((ushort*)&a - (ushort*)0))) #define MPus(a) (*(ushort *)(l.lanceram + l.sep*((ushort*)&a - (ushort*)0))) @@ -147,8 +145,8 @@ typedef struct { int kstarted; Debqueue dq; - Pkt *rp; /* receive buffers */ - Pkt *tp; /* transmit buffers */ + Etherpkt *rp; /* receive buffers */ + Etherpkt *tp; /* transmit buffers */ uchar *rpa[Nrrb]; /* receive buffer address in lance space */ uchar *tpa[Ntrb]; /* transmit buffer address in lance space */ @@ -256,7 +254,7 @@ sprintpacket(char *buf, Trace *t) * save a message in a circular queue for later debugging */ void -lancedebq(char tag, Pkt *p, int len) +lancedebq(char tag, Etherpkt *p, int len) { Trace *t; @@ -338,7 +336,7 @@ static void lanceoput(Queue *q, Block *bp ) { int n, len; - Pkt *p; + Etherpkt *p; Msg *m; if(bp->type == M_CTL){ @@ -375,7 +373,7 @@ lanceoput(Queue *q, Block *bp ) */ len = 0; while(bp = getq(q)){ - if(sizeof(Pkt) - len >= (n = BLEN(bp))){ + if(sizeof(Etherpkt) - len >= (n = BLEN(bp))){ memcpy(((uchar *)p)+len, bp->rptr, n); len += n; } else @@ -424,6 +422,22 @@ enum { }; Dirtab lancedir[Ndir]; +/* + * configure the lance + */ +void +lanceconfig(void *ramstart, void *ramend, void *rap, void *rdp, int sep, + void *lancemem, uchar* ea) +{ + l.lanceram = ramstart; + l.lanceend = ramend; + l.rap = rap; + l.rdp = rdp; + l.sep = sep; + l.lm = lancemem; /* where lance sees its memory start */ + memcpy(l.ea, ea, 6); +} + /* * stop the lance, disable all ring buffers, and free all staged rcv buffers */ @@ -431,35 +445,19 @@ void lancereset(void) { int i; - ushort *sp; ulong x; int index; static int already; /* - * so that we don't have to indirect through constants + * stop the lance */ - l.rap = LANCERAP; - l.rdp = LANCERDP; + *l.rap = 0; + *l.rdp = STOP; - /* - * allocate the send and receive buffers and map them into - * the lance's address space. - */ if(already == 0){ already = 1; if(ioid < IO3R1){ - /* - * toggle lance's reset line - */ - MODEREG->promenet &= ~1; - MODEREG->promenet |= 1; - - l.lanceram = LANCERAM; - l.lanceend = LANCEEND; - l.lm = (Lancemem *)0; - l.sep = 1; - /* * allocate packet buffers in lance memory */ @@ -468,25 +466,14 @@ lancereset(void) for(i = 0; i < Ntrb; i++) l.tpa[i] = (uchar *)&l.lm->tp[i]; - l.rp = ((Lancemem *)LANCERAM)->rp; - l.tp = ((Lancemem *)LANCERAM)->tp; + l.rp = ((Lancemem *)l.lanceram)->rp; + l.tp = ((Lancemem *)l.lanceram)->tp; } else { - /* - * toggle lance's reset line - */ - MODEREG->promenet |= 1; - MODEREG->promenet &= ~1; - - l.lanceram = LANCE3RAM; - l.lanceend = LANCE3END; - l.lm = (Lancemem *)0x800000; - l.sep = 4; - /* * allocate packet buffers in MP bus memory * and map it into lance space */ - l.rp = (Pkt *)ialloc((Nrrb + Ntrb)*sizeof(Pkt), 1); + l.rp = (Etherpkt *)ialloc((Nrrb + Ntrb)*sizeof(Etherpkt), 1); l.tp = l.rp + Nrrb; index = 0x1E00; for(i = 0; i < Nrrb; i++){ @@ -504,12 +491,6 @@ lancereset(void) } } - /* - * run through all lance memory to set parity - */ - for(sp = l.lanceram; sp < l.lanceend; sp += l.sep) - *sp = 0; - } /* @@ -520,7 +501,7 @@ static void lancestart(void) { int i; - Pkt *p; + Etherpkt *p; Lancemem *lm = LANCEMEM; Msg *m; @@ -536,15 +517,9 @@ lancestart(void) * the id prom has them in reverse order, the init * structure wants them in byte swapped order */ - MPus(lm->etheraddr[0]) = (LANCEID[16]&0xff00)|((LANCEID[20]>>8)&0xff); - MPus(lm->etheraddr[1]) = (LANCEID[8]&0xff00)|((LANCEID[12]>>8)&0xff); - MPus(lm->etheraddr[2]) = (LANCEID[0]&0xff00)|((LANCEID[4]>>8)&0xff); - l.ea[0] = LANCEID[20]>>8; - l.ea[1] = LANCEID[16]>>8; - l.ea[2] = LANCEID[12]>>8; - l.ea[3] = LANCEID[8]>>8; - l.ea[4] = LANCEID[4]>>8; - l.ea[5] = LANCEID[0]>>8; + MPus(lm->etheraddr[0]) = (l.ea[1]<<8) | l.ea[0]; + MPus(lm->etheraddr[1]) = (l.ea[3]<<8) | l.ea[2]; + MPus(lm->etheraddr[2]) = (l.ea[5]<<8) | l.ea[4]; /* * ignore multicast addresses @@ -559,7 +534,7 @@ lancestart(void) */ m = lm->rmr; for(i = 0; i < Nrrb; i++, m++){ - MPs(m->size) = -sizeof(Pkt); + MPs(m->size) = -sizeof(Etherpkt); MPus(m->cntflags) = 0; MPus(m->laddr) = LADDR(l.rpa[i]); MPus(m->flags) = HADDR(l.rpa[i]); @@ -860,7 +835,7 @@ void lancekproc(void *arg) { Block *bp; - Pkt *p; + Etherpkt *p; Ethertype *e; int t; int len; @@ -930,7 +905,7 @@ stage: * stage the next input buffer */ m = &(lm->rmr[l.rc]); - MPs(m->size) = -sizeof(Pkt); + MPs(m->size) = -sizeof(Etherpkt); MPus(m->cntflags) = 0; MPus(m->laddr) = LADDR(l.rpa[l.rc]); MPus(m->flags) = OWN|HADDR(l.rpa[l.rc]); diff --git a/power/dat.h b/power/dat.h index 6f54c60ecc9d4cdb4b02ac0a982fd7251de6806f..a3e4d70fa256f644c502ee048c6bad176a5282e7 100644 --- a/power/dat.h +++ b/power/dat.h @@ -9,6 +9,7 @@ typedef struct Dirtab Dirtab; typedef struct Env Env; typedef struct Envp Envp; typedef struct Envval Envval; +typedef struct Etherpkt Etherpkt; typedef struct FPsave FPsave; typedef struct Label Label; typedef struct List List; @@ -408,6 +409,7 @@ struct Block uchar *base; /* start of the buffer */ uchar flags; uchar type; + ulong va; /* virtual address if mapped for a dev */ }; /* flag bits */ @@ -488,6 +490,17 @@ enum { Streambhi= 32, /* block count high water mark */ }; +/* + * Ethernet packet buffers. + */ +struct Etherpkt { + uchar d[6]; + uchar s[6]; + uchar type[2]; + uchar data[1500]; + uchar crc[4]; +}; + /* * nonet constants */ diff --git a/power/fns.h b/power/fns.h index 92e5ad4447782af9ca1ea5e809ee7ae16cc196c5..39076d4ca9c6f159873a4bc9cc20f5cfd8c443ed 100644 --- a/power/fns.h +++ b/power/fns.h @@ -91,6 +91,7 @@ void isdir(Chan*); void kbdchar(int); void kproc(char*, void(*)(void*), void*); void launchinit(void); +void lanceconfig(void*, void*, void*, void*, int, void*, uchar*); void lancereset(void); void lanceinit(void); void lanceintr(void); diff --git a/power/main.c b/power/main.c index 9adf67fe974a6bcafe2d1372814eea9d3fa5856e..21124944a1f0ccbd4d66132202ea34ed3cf28017 100644 --- a/power/main.c +++ b/power/main.c @@ -39,6 +39,25 @@ char sysname[64]; */ int ioid; +/* + * lance memory mapping + */ +typedef struct Lancemap Lancemap; +struct Lancemap +{ + int rused; /* first used receive map */ + int rnext; /* next receive map to use */ + int rtot; + + int tused; /* first used transmit map */ + int tnext; /* next transmit map to use */ + int ttot; + Rendez tr; /* where to wait for a transmit map */ +}; +Lancemap lm; + +extern int ioid; + char user[NAMELEN] = "bootes"; void @@ -132,6 +151,8 @@ ioboardinit(void) { long i; int maxlevel; + ushort *sp; + uchar ea[6]; ioid = *IOID; if(ioid >= IO3R1) @@ -178,6 +199,122 @@ ioboardinit(void) * enable all interrupts on the IO2 */ *IO2SETMASK = 0xff; + + /* + * get our ether addr out of the non-volatile ram + */ + ea[0] = LANCEID[20]>>8; + ea[1] = LANCEID[16]>>8; + ea[2] = LANCEID[12]>>8; + ea[3] = LANCEID[8]>>8; + ea[4] = LANCEID[4]>>8; + ea[5] = LANCEID[0]>>8; + + /* + * reset the lance. + * configure the lance software parameters. + * run through all lance memory to set parity. + */ + if(ioid >= IO3R1){ + MODEREG->promenet |= 1; + MODEREG->promenet &= ~1; + lanceconfig(LANCE3RAM, LANCE3END, LANCERAP, LANCERDP, 4, + (void*)0x800000, ea); + for(sp = LANCE3RAM; sp < LANCE3END; sp += 2) + *sp = 0; + } else { + MODEREG->promenet &= ~1; + MODEREG->promenet |= 1; + lanceconfig(LANCERAM, LANCEEND, LANCERAP, LANCERDP, 1, + (void*)0x0, ea); + for(sp = LANCERAM; sp < LANCEEND; sp += 1) + *sp = 0; + } + + /* + * initialize the map/buffer use + */ + lm.ttot = 128; + lm.rtot = 128; + lm.rnext = lm.rused = lm.tnext = lm.tused = 0; +} + +/* + * map/copy a list of blocks to somewhere the lance can access + * + * if bp==0, just create a block and map it in + */ +static int +isomap(void *x) +{ + int next; + + next = (int)x; + return x != lm.tused; +} +Block * +lancemap(Block *bp, int len) +{ + Block *nbp, *tbp; + int next; + ulong x; + + if(bp == 0){ + next = lm.rnext+1 % lm.rtot; + if(ioid >= IO3R1){ + bp = allocb(sizeof(Etherpkt)); + x = (ulong)(bp->wptr); + *WRITEMAP = (next<<16) | ((x>>12)&0xFFFF); + bp->va = (next<<12) | (x & 0xFFF)); + } else { + bp = allocb(0); + x = (ulong)(LANCEMEM+4*1024+next*sizeof(Etherpkt)); + bp->va = x; + bp->rptr = (uchar *)x; + bp->wptr = (uchar *)x; + } + lm.rnext = next; + return bp; + } + + if(ioid >= IO3R1){ + for(nbp = bp; nbp; nbp = nbp->next){ + next = lm.tnext+1 % lm.ttot; + if(next == lm.tused) + sleep(&lm.tr, isomap, (void *)next); + x = (ulong)(nbp->rptr); + *WRITEMAP = ((lm.rtot + next)<<16) | ((x>>12)&0xFFFF); + nbp->va = ((lm.rtot + next)<<12) | (x & 0xFFF)); + lm.tnext = next; + } + } else { + tbp = bp; + bp = allocb(0); + next = lm.tnext+1 % lm.ttot; + if(next == lm.tused) + sleep(&lm.tr, isomap, (void *)next); + x = (ulong)(LANCEMEM+4*1024+(next+lm.rtot)*sizeof(Etherpkt)); + bp->va = x; + bp->rptr = (uchar *)x; + bp->wptr = (uchar *)x; + for(nbp = tbp; nbp; nbp = nbp->next){ + n = BLEN(nbp); + if(BLEN(bp) + n < sizeof(Etherpkt)) + n = sizeof(Etherpkt) - BLEN(bp); + memcpy(bp->wptr, nbp->rptr, n); + bp->wptr += n; + } + freeb(tbp); + lm.tnext = next; + } +} + +/* + * get a block back from the lance + */ +Block * +lanceunmap(Block *bp) +{ } void