From 244de504da87fbf32ea972b6cffe57e7db8d0904 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Fri, 19 Sep 1997 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1997-09-19 --- pc/devastar.c | 4 +- pc/etherelnk3.c | 324 +++++++++++++++++++++--------------------------- 2 files changed, 141 insertions(+), 187 deletions(-) diff --git a/pc/devastar.c b/pc/devastar.c index dd7c6d257d49a7e0788a6ef0245da0dd18c65843..8a148b1645c429a7ead30d7c27b379c55680d0fe 100644 --- a/pc/devastar.c +++ b/pc/devastar.c @@ -1346,8 +1346,8 @@ astarinput(Astarchan *ac) if(rp > ep) rp = bp; } - if(qproduce(ac->iq, buf, n) < 0) - break; /* flow controlled */ + if(ac->opens == 0 || qproduce(ac->iq, buf, n) < 0) + break; /* flow controlled or not open */ if(a->needpage) setpage(a, 0); ccb->inrp = LEUS(rp - a->addr); diff --git a/pc/etherelnk3.c b/pc/etherelnk3.c index 81edbd63413f047d10fe236210a5e42d4f5b5616..e005ab04f6a5c0ee69eeff81bc21367fbfab4fc8 100644 --- a/pc/etherelnk3.c +++ b/pc/etherelnk3.c @@ -6,7 +6,6 @@ * autoSelect; * PCI latency timer and master enable; * errata list; - * limit 3C90x transmit queue; * rewrite all initialisation. * * Product ID: @@ -365,32 +364,26 @@ enum { /* 3C90x extended register set */ dnIndicate = 0x80000000, /* FrameStartHeader (dpd->control) */ updnLastFrag = 0x80000000, /* (dpd->len) */ + + Nup = 32, + Ndn = 16, }; /* - * Up/Dn Packet Descriptor. - * The hardware info (np, control, addr, len) must be 8-byte aligned. + * Up/Dn Packet Descriptors. + * The hardware info (np, control, addr, len) must be 8-byte aligned + * and this structure size must be a multiple of 8. */ -typedef struct Dpd Dpd; -typedef struct Dpd { +typedef struct Pd Pd; +typedef struct Pd { ulong np; /* next pointer */ ulong control; /* FSH or UpPktStatus */ ulong addr; ulong len; - Dpd* next; + Pd* next; Block* bp; - void* base; /* base of this allocation */ -} Dpd; - -typedef struct Upd { - ulong np; /* next pointer */ - ulong control; /* FSH or UpPktStatus */ - ulong addr; - ulong len; - - uchar data[sizeof(Etherpkt)]; -} Upd; +} Pd; typedef struct { Lock wlock; /* window access */ @@ -403,23 +396,29 @@ typedef struct { int txthreshold; int txbusy; - //Lock upqlock; /* full-busmaster -based reception */ - Block* upqhead; - Block* upqtail; - int upalloc; - int nupd; - - Lock dpdlock; /* pool of free Dpd's */ - Dpd* dpdpool; + int nup; /* full-busmaster -based reception */ + void* upbase; + Pd* upr; + Pd* uphead; - Lock dnqlock; /* full-busmaster -based transmission */ - Dpd* dnqhead; - Dpd* dnqtail; + Lock dnlock; /* full-busmaster -based transmission */ + int ndn; + void* dnbase; + Pd* dnr; + Pd* dnhead; + Pd* dntail; + int dnq; long interrupts; /* statistics */ long timer; long stats[BytesRcvdOk+3]; + int upqmax; + int upstalls; + int dnqmax; + long dninterrupts; + long dnqueued; + int xcvr; /* transceiver type */ int rxstatus9; /* old-style RxStatus register */ int rxearly; /* RxEarlyThreshold */ @@ -428,81 +427,48 @@ typedef struct { int dnenabled; } Ctlr; -static Block* -updalloc(ulong np) +static void +init905(Ctlr* ctlr) { Block *bp; - Upd *upd; + Pd *pd, *prev; /* - * The hardware info (np, control, addr, len) - * must be 8-byte aligned. + * Create rings for the receive and transmit sides. + * Take care with alignment: + * make sure ring base is 8-byte aligned; + * make sure each entry is 8-byte aligned. */ - if(bp = iallocb(sizeof(Upd)+8)){ - bp->rp = (uchar*)ROUNDUP((ulong)bp->rp, 8); - bp->wp = bp->rp; - upd = (Upd*)bp->rp; - upd->np = np; - upd->control = 0; - upd->addr = PADDR(upd->data); - upd->len = updnLastFrag|sizeof(Etherpkt); + ctlr->upbase = malloc((ctlr->nup+1)*sizeof(Pd)); + ctlr->upr = (Pd*)ROUNDUP((ulong)ctlr->upbase, 8); + + prev = ctlr->upr; + for(pd = &ctlr->upr[ctlr->nup-1]; pd >= ctlr->upr; pd--){ + pd->np = PADDR(&prev->np); + pd->control = 0; + bp = allocb(sizeof(Etherpkt)); + pd->addr = PADDR(bp->rp); + pd->len = updnLastFrag|sizeof(Etherpkt); + + pd->next = prev; + prev = pd; + pd->bp = bp; } + ctlr->uphead = ctlr->upr; - return bp; -} - -static void -init905(Ctlr* ctlr) -{ - int i; - ulong np; - Block *bp; - Upd *upd; - - np = 0; - for(i = 0; i < 64; i++){ - bp = updalloc(np); - if(ctlr->upqhead == 0) - ctlr->upqtail = bp; - bp->next = ctlr->upqhead; - ctlr->upqhead = bp; - np = PADDR(bp->rp); - } - ctlr->upqtail->next = ctlr->upqhead; - upd = (Upd*)ctlr->upqtail->rp; - upd->np = PADDR(ctlr->upqhead->rp); -} + ilock(&ctlr->dnlock); + ctlr->dnbase = malloc((ctlr->ndn+1)*sizeof(Pd)); + ctlr->dnr = (Pd*)ROUNDUP((ulong)ctlr->dnbase, 8); -static Dpd* -dpdalloc(Ctlr* ctlr) -{ - Dpd *dpd; - void *base; - - ilock(&ctlr->dpdlock); - if(dpd = ctlr->dpdpool){ - ctlr->dpdpool = dpd->next; - iunlock(&ctlr->dpdlock); - dpd->next = 0; - dpd->bp = 0; - } - else{ - iunlock(&ctlr->dpdlock); - base = smalloc(sizeof(Dpd)+8); - dpd = (Dpd*)ROUNDUP((ulong)base, 8); - dpd->base = base; + prev = ctlr->dnr; + for(pd = &ctlr->dnr[ctlr->ndn-1]; pd >= ctlr->dnr; pd--){ + pd->next = prev; + prev = pd; } - - return dpd; -} - -static void -dpdfree(Ctlr* ctlr, Dpd* dpd) -{ - ilock(&ctlr->dpdlock); - dpd->next = ctlr->dpdpool; - ctlr->dpdpool = dpd; - iunlock(&ctlr->dpdlock); + ctlr->dnhead = ctlr->dnr; + ctlr->dntail = ctlr->dnr; + ctlr->dnq = 0; + iunlock(&ctlr->dnlock); } static Block* @@ -629,7 +595,7 @@ attach(Ether* ether) startdma(ether, PADDR(ctlr->rbp->rp)); else{ if(ctlr->upenabled) - outl(port+UpListPtr, PADDR(ctlr->upqhead->rp)); + outl(port+UpListPtr, PADDR(&ctlr->uphead->np)); } ctlr->attached = 1; @@ -726,16 +692,17 @@ txstart(Ether* ether) } static void -start905(Ether* ether, Dpd* add) +txstart905(Ether* ether) { Ctlr *ctlr; int dnlistptr, port; - Dpd *dpd; + Block *bp; + Pd *pd; ctlr = ether->ctlr; port = ether->port; - ilock(&ctlr->dnqlock); + ilock(&ctlr->dnlock); COMMAND(port, Stall, dnStall); while(STATUS(port) & commandInProgress) ; @@ -744,64 +711,53 @@ start905(Ether* ether, Dpd* add) * Free any completed packets. */ dnlistptr = inl(port+DnListPtr); - while(dpd = ctlr->dnqhead){ - if(PADDR(dpd) == dnlistptr) + pd = ctlr->dntail; + while(ctlr->dnq){ + if(PADDR(&pd->np) == dnlistptr) break; - ctlr->dnqhead = dpd->next; - if(dpd->bp) - freeb(dpd->bp); - dpdfree(ctlr, dpd); + if(pd->bp){ + freeb(pd->bp); + pd->bp = nil; + } + ctlr->dnq--; + pd = pd->next; } + ctlr->dntail = pd; - /* - * Add any new packets to the queue. - */ - if(add){ - if(ctlr->dnqhead){ - dpd = ctlr->dnqtail; - dpd->next = add; - dpd->np = PADDR(&add->np); - dpd->control &= ~dnIndicate; - } - else - ctlr->dnqhead = add; - ctlr->dnqtail = add; + while(ctlr->dnq < (ctlr->ndn-1)){ + bp = qget(ether->oq); + if(bp == nil) + break; + + pd = ctlr->dnhead->next; + pd->np = 0; + pd->control = dnIndicate|BLEN(bp); + pd->addr = PADDR(bp->rp); + pd->len = updnLastFrag|BLEN(bp); + pd->bp = bp; + + if(ctlr->dnq == 0) + ctlr->dntail = pd; + ctlr->dnhead->np = PADDR(&pd->np); + ctlr->dnhead->control &= ~dnIndicate; + ctlr->dnhead = pd; + ctlr->dnq++; + + ctlr->dnqueued++; } + if(ctlr->dnq > ctlr->dnqmax) + ctlr->dnqmax = ctlr->dnq; + /* * If the adapter is not currently processing anything * and there is something on the queue, start it processing. */ - if(dnlistptr == 0 && ctlr->dnqhead) - outl(port+DnListPtr, PADDR(ctlr->dnqhead)); + if(dnlistptr == 0 && ctlr->dnq) + outl(port+DnListPtr, PADDR(&ctlr->dnhead->np)); COMMAND(port, Stall, dnUnStall); - iunlock(&ctlr->dnqlock); -} - -static void -transmit905(Ether* ether) -{ - Ctlr *ctlr; - Block *bp; - Dpd* dpd; - - bp = qget(ether->oq); - if(bp == nil) - return; - - ctlr = ether->ctlr; - - dpd = dpdalloc(ctlr); - dpd->next = 0; - dpd->bp = bp; - - dpd->np = 0; - dpd->control = dnIndicate|BLEN(bp); - dpd->addr = PADDR(bp->rp); - dpd->len = updnLastFrag|BLEN(bp); - - start905(ether, dpd); + iunlock(&ctlr->dnlock); } static void @@ -814,7 +770,7 @@ transmit(Ether* ether) ctlr = ether->ctlr; if(ctlr->dnenabled){ - transmit905(ether); + txstart905(ether); return; } @@ -830,56 +786,44 @@ static void receive905(Ether* ether) { Ctlr *ctlr; - int port; - Block *bp, *xbp; - Upd *upd; + int len, port, q; + Pd *pd; + Block *bp; ctlr = ether->ctlr; port = ether->port; - //ilock(&ctlr->upqlock); - COMMAND(port, Stall, upStall); - while(STATUS(port) & commandInProgress) - ; - - bp = ctlr->upqhead; - upd = (Upd*)bp->rp; - while(upd->control & upPktComplete){ - if(upd->control & upError){ - if(upd->control & upOverrun) + if(inl(port+UpPktStatus) & upStalled) + ctlr->upstalls++; + q = 0; + for(pd = ctlr->uphead; pd->control & upPktComplete; pd = pd->next){ + if(pd->control & upError){ + if(pd->control & upOverrun) ether->overflows++; - if(upd->control & (upOversizedFrame|upRuntFrame)) + if(pd->control & (upOversizedFrame|upRuntFrame)) ether->buffs++; - if(upd->control & upAlignmentError) + if(pd->control & upAlignmentError) ether->frames++; - if(upd->control & upCRCError) + if(pd->control & upCRCError) ether->crcs++; - - upd->control = 0; } - else if(xbp = updalloc(upd->np)){ - bp->rp += sizeof(Upd)-sizeof(Etherpkt); - bp->wp = bp->rp + (upd->control & rxBytes); - - xbp->next = bp->next; - bp->next = 0; - - etheriq(ether, bp, 1); - bp = xbp; + else if(bp = iallocb(sizeof(Etherpkt)+4)){ + len = pd->control & rxBytes; + pd->bp->wp = pd->bp->rp+len; + etheriq(ether, pd->bp, 1); + pd->bp = bp; + pd->addr = PADDR(bp->rp); } - upd = (Upd*)ctlr->upqtail->rp; - upd->np = PADDR(bp->rp); - ctlr->upqtail->next = bp; - ctlr->upqtail = bp; - ctlr->upqhead = bp->next; + pd->control = 0; + COMMAND(port, Stall, upUnStall); - bp = ctlr->upqhead; - upd = (Upd*)bp->rp; + q++; } + ctlr->uphead = pd; - COMMAND(port, Stall, upUnStall); - //iunlock(&ctlr->upqlock); + if(q > ctlr->upqmax) + ctlr->upqmax = q; } static void @@ -1044,8 +988,8 @@ interrupt(Ureg*, void* arg) } if(status & (upComplete)){ - COMMAND(port, AcknowledgeInterrupt, upComplete); receive905(ether); + COMMAND(port, AcknowledgeInterrupt, upComplete); status &= ~upComplete; } @@ -1103,9 +1047,10 @@ interrupt(Ureg*, void* arg) } if(status & dnComplete){ + txstart905(ether); COMMAND(port, AcknowledgeInterrupt, dnComplete); - start905(ether, 0); status &= ~dnComplete; + ctlr->dninterrupts++; } if(status & updateStats){ @@ -1164,6 +1109,12 @@ ifstat(Ether* ether, void* a, long n, ulong offset) len += snprint(p+len, READSTR-len, "framesdeferred: %lud\n", ctlr->stats[FramesDeferred]); len += snprint(p+len, READSTR-len, "bytesrcvdok: %lud\n", ctlr->stats[BytesRcvdOk]); len += snprint(p+len, READSTR-len, "bytesxmittedok: %lud\n", ctlr->stats[BytesRcvdOk+1]); +len += snprint(p+len, READSTR-len, "up: q %lud s %lud\n", + ctlr->upqmax, ctlr->upstalls); +ctlr->upqmax = 0; +len += snprint(p+len, READSTR-len, "dn: q %lud i %lud m %d\n", + ctlr->dnqueued, ctlr->dninterrupts, ctlr->dnqmax); +ctlr->dnqmax = 0; snprint(p+len, READSTR-len, "badssd: %lud\n", ctlr->stats[BytesRcvdOk+2]); n = readstr(offset, a, n, p); @@ -1761,8 +1712,11 @@ etherelnk3reset(Ether* ether) if(!(x & 0x01)) outl(port+PktStatus, upRxEarlyEnable); - if(ctlr->upenabled) + if(ctlr->upenabled || ctlr->dnenabled){ + ctlr->nup = Nup; + ctlr->ndn = Ndn; init905(ctlr); + } else ctlr->rbp = rbpalloc(allocb); outl(port+TxFreeThresh, HOWMANY(ETHERMAXTU, 256));