From f029e17b9e3835e385605837504e51e4f18b428a Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Wed, 30 Sep 1998 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1998-09-30 --- ip/il.c | 159 ++++++++++++++++++++++++++---------------------- ip/ipifc.c | 1 - pc/ether82557.c | 140 ++++++++++++++++++++++++------------------ port/devsd.c | 16 ++++- 4 files changed, 183 insertions(+), 133 deletions(-) diff --git a/ip/il.c b/ip/il.c index 7234d30be593c3b9ae7515d15d2ec419d32cc8c4..43a5bd5629b338ccdeef7a2e762a70f96b0de384 100644 --- a/ip/il.c +++ b/ip/il.c @@ -15,6 +15,7 @@ enum /* Connection state */ Ilestablished, Illistening, Ilclosing, + Ilopening, /* only for file server */ }; char *ilstates[] = @@ -24,7 +25,8 @@ char *ilstates[] = "Syncee", "Established", "Listening", - "Closing" + "Closing", + "Opening", /* only for file server */ }; enum /* Packet types */ @@ -49,7 +51,26 @@ char *iltype[] = "close" }; -static char *etime = "connection timed out"; +enum +{ + Seconds = 1000, + Iltickms = 50, /* time base */ + AckDelay = 2*Iltickms, /* max time twixt message rcvd & ack sent */ + MaxTimeout = 4*Seconds, /* max time between rexmit */ + QueryTime = 5*Seconds, /* time between subsequent queries */ + DeathTime = 5*QueryTime, + + MaxRexmit = 16, /* max retransmissions before hangup */ + Defaultwin = 20, + + LogAGain = 3, + AGain = 1<ptcl); - return snprint(state, n, "%s del %5.5d Br %5.5d md %5.5d una %5.5lud rex %5.5d max %5.5d", + return snprint(state, n, "%s del %5.5d Br %5.5d md %5.5d una %5.5lud rex %5.5d rxq %5.5d max %5.5d", ilstates[ic->state], ic->delay>>LogAGain, ic->rate>>LogAGain, ic->mdev>>LogDGain, - ic->unackeduchars, ic->rxtot, ic->maxrtt); + ic->unackedbytes, ic->rxtot, ic->rxquery, ic->maxrtt); } static int @@ -391,7 +393,7 @@ ilackq(Ilcb *ic, Block *bp) ic->unacked = np; ic->unackedtail = np; np->list = nil; - ic->unackeduchars += n; + ic->unackedbytes += n; } static @@ -399,47 +401,48 @@ void ilrttcalc(Ilcb *ic, Block *bp) { uvlong fastrtt; - int rtt, tt, pt, delay, rate, mrtt; + int rtt, tt, pt, delay, rate; fastrtt = fastticks(nil) - ic->rttstart; - if(microshift >= 0) - rtt = fastrtt >> microshift; - else - rtt = fastrtt << -microshift; - mrtt = rtt >> 10; + if(timeshift >= 0) + rtt = fastrtt >> timeshift; + else { + rtt = fastrtt; + rtt = (rtt<<-timeshift)+timeround; + } delay = ic->delay; rate = ic->rate; /* Guard against zero wrap */ - if(rtt > 120000000) + if(rtt > 120000) return; - /* guess fixed delay as rtt of small packets */ - if(ic->rttlen < 128){ - delay += mrtt - (delay>>LogAGain); - if(delay < AGain) - delay = AGain; - ic->delay = delay; - } - /* this block had to be transmitted after the one acked so count its size */ ic->rttlen += blocklen(bp) + IL_IPSIZE + IL_HDRSIZE; - /* if packet took longer than round trip delay, reset rate */ - tt = mrtt - (delay>>LogAGain); - if(tt > 0){ - rate += ic->rttlen/tt - (rate>>LogAGain); - if(rate < AGain) - rate = AGain; - ic->rate = rate; + if(ic->rttlen < 256){ + /* guess fixed delay as rtt of small packets */ + delay += rtt - (delay>>LogAGain); + if(delay < AGain) + delay = AGain; + ic->delay = delay; + } else { + /* if packet took longer than avg rtt delay, recalc rate */ + tt = rtt - (delay>>LogAGain); + if(tt > 0){ + rate += ic->rttlen/tt - (rate>>LogAGain); + if(rate < AGain) + rate = AGain; + ic->rate = rate; + } } /* mdev */ pt = ic->rttlen/(rate>>LogAGain) + (delay>>LogAGain); - ic->mdev += abs(mrtt-pt) - (ic->mdev>>LogDGain); + ic->mdev += abs(rtt-pt) - (ic->mdev>>LogDGain); - if(mrtt > ic->maxrtt) - ic->maxrtt = mrtt; + if(rtt > ic->maxrtt) + ic->maxrtt = rtt; } void @@ -465,7 +468,7 @@ ilackto(Ilcb *ic, ulong ackto, Block *bp) bp = ic->unacked; ic->unacked = bp->list; bp->list = nil; - ic->unackeduchars -= blocklen(bp); + ic->unackedbytes -= blocklen(bp); freeblist(bp); ic->rexmit = 0; ilsettimeout(ic); @@ -683,6 +686,8 @@ _ilprocess(Conv *s, Ilhdr *h, Block *bp) freeblist(bp); break; case Ilstate: + if(ack >= ic->rttack) + ic->rttack = 0; ilackto(ic, ack, bp); if(h->ilspec > Nqt) h->ilspec = 0; @@ -728,6 +733,7 @@ ilrexmit(Ilcb *ic) Block *nb; Conv *c; ulong id; + Ilpriv *priv; nb = nil; qlock(&ic->ackq); @@ -753,12 +759,14 @@ ilrexmit(Ilcb *ic) ic->rexmit, ic->timeout, c->raddr, c->lport, c->rport); - /* rtt calcs are useless during retransmissions */ - ic->rttack = 0; - ilbackoff(ic); ipoput(c->p->f, nb, 0, ic->conv->ttl); + + /* statistics */ + ic->rxtot++; + priv = c->p->priv; + priv->rexmit++; } /* DEBUG */ @@ -962,8 +970,10 @@ ilsettimeout(Ilcb *ic) { ulong pt; - pt = (ic->delay>>LogAGain) + ic->unackeduchars/(ic->rate>>LogAGain) + ic->mdev; - pt += AckDelay; + pt = (ic->delay>>LogAGain) + + ic->unackedbytes/(ic->rate>>LogAGain) + + (ic->mdev>>(LogDGain-1)) + + AckDelay; if(pt > MaxTimeout) pt = MaxTimeout; ic->timeout = msec + pt; @@ -974,21 +984,18 @@ ilbackoff(Ilcb *ic) { ulong pt; int i; - Ilpriv *priv; - pt = (ic->delay>>LogAGain) + ic->unackeduchars/(ic->rate>>LogAGain) + ic->mdev; - pt += AckDelay; + pt = (ic->delay>>LogAGain) + + ic->unackedbytes/(ic->rate>>LogAGain) + + (ic->mdev>>(LogDGain-1)) + + AckDelay; for(i = 0; i < ic->rexmit; i++) pt = pt + (pt>>1); if(pt > MaxTimeout) pt = MaxTimeout; ic->timeout = msec + pt; - ic->rxtot++; ic->rexmit++; - - priv = ic->conv->p->priv; - priv->rexmit++; } void @@ -1053,7 +1060,9 @@ loop: ilhangup(p, etime); break; } - ilrexmit(ic); + ilsendctl(p, nil, Ilquery, ic->next, ic->recvd, ilnextqt(ic)); + ic->rxquery++; + ilbackoff(ic); } break; } @@ -1068,7 +1077,7 @@ ilcbinit(Ilcb *ic) ic->next = ic->start+1; ic->recvd = 0; ic->window = Defaultwin; - ic->unackeduchars = 0; + ic->unackedbytes = 0; ic->unacked = nil; ic->outoforder = nil; ic->rexmit = 0; @@ -1200,21 +1209,25 @@ ilnextqt(Ilcb *ic) return x; } -/* quick and dirty conversion from fastticks to microseconds */ +/* calculate shift that converts fast ticks to ms (more or less) */ static void -initfast(void) +inittimeshift(void) { int i; uvlong x, hz; fastticks(&hz); x = 3; - for(i = 1; i < 40; i++){ + for(i = 1; i < 45; i++){ if(x >= hz) break; x <<= 1; } - microshift = i - 20; + timeshift = i - 10; + if(i < 0) + timeround = (1<<-i)-1; + else + timeround = 0; } void @@ -1222,7 +1235,7 @@ ilinit(Fs *f) { Proto *il; - initfast(); + inittimeshift(); il = smalloc(sizeof(Proto)); il->priv = smalloc(sizeof(Ilpriv)); diff --git a/ip/ipifc.c b/ip/ipifc.c index 276207e6d85c73e1132e8be31e19431433f10f99..d2aa3d66e74de0b546fc3778134abd874ebad31c 100644 --- a/ip/ipifc.c +++ b/ip/ipifc.c @@ -483,7 +483,6 @@ ipifcrem(Ipifc *ifc, char **argv, int argc, int dolock) free(lifc); -out: if(dolock) wunlock(ifc); return nil; diff --git a/pc/ether82557.c b/pc/ether82557.c index 0afe5d592850fa9ae02c154a925c0d3ace32e4c6..93cd260f6a76d7d80e610afcf263c1158bccffd0 100644 --- a/pc/ether82557.c +++ b/pc/ether82557.c @@ -570,11 +570,90 @@ transmit(Ether* ether) } static void -interrupt(Ureg*, void* arg) +receive(Ether* ether) { Rfd *rfd; + Ctlr *ctlr; + int count; + Block *bp, *pbp, *xbp; + + ctlr = ether->ctlr; + bp = ctlr->rfdhead; + for(rfd = (Rfd*)bp->rp; rfd->field & RfdC; rfd = (Rfd*)bp->rp){ + /* + * If it's an OK receive frame + * 1) save the count + * 2) if it's small, try to allocate a block and copy + * the data, then adjust the necessary fields for reuse; + * 3) if it's big, try to allocate a new Rfd and if + * successful + * adjust the received buffer pointers for the + * actual data received; + * initialise the replacement buffer to point to + * the next in the ring; + * initialise bp to point to the replacement; + * 4) if there's a good packet, pass it on for disposal. + */ + if(rfd->field & RfdOK){ + pbp = nil; + count = rfd->count & 0x3FFF; + if((count < ETHERMAXTU/4) && (pbp = iallocb(count))){ + memmove(pbp->rp, bp->rp+sizeof(Rfd)-sizeof(rfd->data), count); + pbp->wp = pbp->rp + count; + + rfd->count = 0; + rfd->field = 0; + } + else if(xbp = rfdalloc(rfd->link)){ + bp->rp += sizeof(Rfd)-sizeof(rfd->data); + bp->wp = bp->rp + count; + + xbp->next = bp->next; + bp->next = 0; + + pbp = bp; + bp = xbp; + } + if(pbp != nil) + etheriq(ether, pbp, 1); + } + else{ + rfd->count = 0; + rfd->field = 0; + } + + /* + * The ring tail pointer follows the head with with one + * unused buffer in between to defeat hardware prefetch; + * once the tail pointer has been bumped on to the next + * and the new tail has the Suspend bit set, it can be + * removed from the old tail buffer. + * As a replacement for the current head buffer may have + * been allocated above, ensure that the new tail points + * to it (next and link). + */ + rfd = (Rfd*)ctlr->rfdtail->rp; + ctlr->rfdtail = ctlr->rfdtail->next; + ctlr->rfdtail->next = bp; + ((Rfd*)ctlr->rfdtail->rp)->link = PADDR(bp->rp); + ((Rfd*)ctlr->rfdtail->rp)->field |= RfdS; + coherence(); + rfd->field &= ~RfdS; + + /* + * Finally done with the current (possibly replaced) + * head, move on to the next and maintain the sentinel + * between tail and head. + */ + ctlr->rfdhead = bp->next; + bp = ctlr->rfdhead; + } +} + +static void +interrupt(Ureg*, void* arg) +{ Cb* cb; - Block *bp, *xbp; Ctlr *ctlr; Ether *ether; int status; @@ -599,62 +678,7 @@ interrupt(Ureg*, void* arg) ctlr->tick = 0; if(status & StatFR){ - bp = ctlr->rfdhead; - rfd = (Rfd*)bp->rp; - while(rfd->field & RfdC){ - /* - * If it's an OK receive frame and a replacement buffer - * can be allocated then - * adjust the received buffer pointers for the - * actual data received; - * initialise the replacement buffer to point to - * the next in the ring; - * pass the received buffer on for disposal; - * initialise bp to point to the replacement. - * If not, just adjust the necessary fields for reuse. - */ - if((rfd->field & RfdOK) && (xbp = rfdalloc(rfd->link))){ - bp->rp += sizeof(Rfd)-sizeof(rfd->data); - bp->wp = bp->rp + (rfd->count & 0x3FFF); - - xbp->next = bp->next; - bp->next = 0; - - etheriq(ether, bp, 1); - bp = xbp; - } - else{ - rfd->field = 0; - rfd->count = 0; - } - - /* - * The ring tail pointer follows the head with with one - * unused buffer in between to defeat hardware prefetch; - * once the tail pointer has been bumped on to the next - * and the new tail has the Suspend bit set, it can be - * removed from the old tail buffer. - * As a replacement for the current head buffer may have - * been allocated above, ensure that the new tail points - * to it (next and link). - */ - rfd = (Rfd*)ctlr->rfdtail->rp; - ctlr->rfdtail = ctlr->rfdtail->next; - ctlr->rfdtail->next = bp; - ((Rfd*)ctlr->rfdtail->rp)->link = PADDR(bp->rp); - ((Rfd*)ctlr->rfdtail->rp)->field |= RfdS; - coherence(); - rfd->field &= ~RfdS; - - /* - * Finally done with the current (possibly replaced) - * head, move on to the next and maintain the sentinel - * between tail and head. - */ - ctlr->rfdhead = bp->next; - bp = ctlr->rfdhead; - rfd = (Rfd*)bp->rp; - } + receive(ether); status &= ~StatFR; } diff --git a/port/devsd.c b/port/devsd.c index 945208e30da062fc779a08b1bf43fe326ee85c23..84208f6cadba58615cb8e59d2109edbc0cf5b127 100644 --- a/port/devsd.c +++ b/port/devsd.c @@ -122,6 +122,7 @@ sdinit(void) */ nbytes = 0xFF; memset(scratch, 0, nbytes); + if(scsiinquiry(d->t, d->lun, scratch, &nbytes) != STok) continue; if(scratch[0] == 0x7F) @@ -140,8 +141,21 @@ sdinit(void) nbytes = 0xFF; memset(scratch, 0, nbytes); scsireqsense(d->t, 0, scratch, &nbytes, 1); - if((scratch[2] & 0x0F) != 0x02 && (scratch[2] & 0x0F) != 0) + switch(scratch[2] & 0x0F){ + + case 0x00: + case 0x01: + case 0x02: + break; + case 0x06: + if(scratch[12] == 0x28 && scratch[13] == 0) + break; + if(scratch[12] == 0x29 && scratch[13] == 0) + break; + /*FALLTHROUGH*/ + default: continue; + } if(type == TypeDA) scsistart(d->t, d->lun, 0); d->size = d->bsize = 0;