From c3b211cd7e429704dabee105b6a1c3963cf94da1 Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 29 Sep 1998 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1998-09-29 --- ip/il.c | 443 +++++++++++++++++++++++++----------------------- pc/ether82557.c | 94 ++++++++-- port/qio.c | 1 + 3 files changed, 305 insertions(+), 233 deletions(-) diff --git a/ip/il.c b/ip/il.c index ca81e5065a50c3858c0a21f08a55e5185a327008..7234d30be593c3b9ae7515d15d2ec419d32cc8c4 100644 --- a/ip/il.c +++ b/ip/il.c @@ -7,6 +7,16 @@ #include "ip.h" +enum /* Connection state */ +{ + Ilclosed, + Ilsyncer, + Ilsyncee, + Ilestablished, + Illistening, + Ilclosing, +}; + char *ilstates[] = { "Closed", @@ -17,18 +27,6 @@ char *ilstates[] = "Closing" }; -char *iltype[] = -{ - "sync", - "data", - "dataquery", - "ack", - "query", - "state", - "close" -}; -static char *etime = "connection timed out"; - enum /* Packet types */ { Ilsync, @@ -40,16 +38,19 @@ enum /* Packet types */ Ilclose, }; -enum /* Connection state */ -{ - Ilclosed, - Ilsyncer, - Ilsyncee, - Ilestablished, - Illistening, - Ilclosing, +char *iltype[] = +{ + "sync", + "data", + "dataquery", + "ack", + "query", + "state", + "close" }; +static char *etime = "connection timed out"; + enum { Nqt= 8, @@ -68,25 +69,30 @@ struct Ilcb /* Control block */ Block *outoforder; ulong next; /* Id of next to send */ ulong recvd; /* Last packet received */ + ulong acksent; /* Last packet acked */ ulong start; /* Local start id */ ulong rstart; /* Remote start id */ - int timeout; /* Time out counter */ - int slowtime; /* Slow time counter */ - int fasttime; /* Retransmission timer */ - int acktime; /* Acknowledge timer */ - int querytime; /* Query timer */ - int deathtime; /* Time to kill connection */ + int window; /* Maximum receive window */ + int rxtot; /* number of retransmits on this connection */ + int rexmit; /* number of retransmits of *unacked */ + ulong qt[Nqt+1]; /* state table for query messages */ + int qtx; /* ... index into qt */ + + /* timers */ + ulong lastxmit; /* time of last xmit */ + ulong lastrecv; /* time of last recv */ + ulong timeout; /* retransmission time for *unacked */ + ulong acktime; /* time to send next ack */ + ulong querytime; /* time to send next query */ + + /* adaptive measurements */ int delay; /* Average of the fixed rtt delay */ int rate; /* Average uchar rate */ int mdev; /* Mean deviation of rtt */ int maxrtt; /* largest rtt seen */ ulong rttack; /* The ack we are waiting for */ int rttlen; /* Length of rttack packet */ - ulong rttms; /* Time we issued rttack packet */ - int window; /* Maximum receive window */ - int rexmit; /* number of retransmits */ - ulong qt[Nqt+1]; /* state table for query messages */ - int qtx; /* ... index into qt */ + uvlong rttstart; /* Time we issued rttack packet */ }; enum @@ -142,20 +148,16 @@ struct Ilpriv QLock apl; }; -/* Always Acktime < Fasttime < Slowtime << Ackkeepalive */ enum { Seconds = 1000, - Iltickms = 100, /* time base */ - - Ackkeepalive = 600*Seconds, - Acktime = 2*Iltickms, /* max time twixt message rcvd & ack sent */ + 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, - Slowtime = 90*Seconds, /* max time waiting for an ack before hangup */ - Fasttime = 4*Seconds, /* max time between rexmit */ - Querytime = 5*Seconds, /* time between subsequent queries */ - Keepalivetime = 60*Seconds, /* time before first query */ - Deathtime = 120*Seconds, /* time between first query and hangup */ + MaxRexmit = 10, /* max retransmissions before hangup */ Defaultwin = 20, LogAGain = 3, @@ -163,6 +165,7 @@ enum LogDGain = 2, DGain = 1<state], ic->delay>>LogAGain, ic->rate>>LogAGain, ic->mdev>>LogDGain, - ic->unackeduchars, ic->rexmit, ic->maxrtt); + ic->unackeduchars, ic->rxtot, ic->maxrtt); } static int @@ -230,7 +236,7 @@ ilannounce(Conv *c, char **argv, int argc) e = Fsstdannounce(c, argv, argc); if(e != nil) return e; - e = ilstart(c, IL_LISTEN, 20); + e = ilstart(c, IL_LISTEN); if(e != nil) return e; Fsconnected(c, nil); @@ -275,7 +281,7 @@ ilkick(Conv *c, int l) Ilhdr *ih; Ilcb *ic; int dlen; - ulong id; + ulong id, ack; Block *bp; Fs *f; @@ -318,8 +324,10 @@ ilkick(Conv *c, int l) qlock(&ic->ackq); id = ic->next++; hnputl(ih->ilid, id); - - hnputl(ih->ilack, ic->recvd); + ack = ic->recvd; + hnputl(ih->ilack, ack); + ic->acksent = ack; + ic->acktime = msec + AckDelay; ih->iltype = Ildata; ih->ilspec = 0; ih->ilsum[0] = 0; @@ -335,11 +343,12 @@ ilkick(Conv *c, int l) /* Start the round trip timer for this packet if the timer is free */ if(ic->rttack == 0) { ic->rttack = id; - ic->rttms = msec; + ic->rttstart = fastticks(nil); ic->rttlen = dlen + IL_IPSIZE + IL_HDRSIZE; } - ic->acktime = Ackkeepalive; + if(ic->timeout <= msec) + ilsettimeout(ic); ipoput(f, bp, 0, c->ttl); } @@ -366,31 +375,6 @@ ilxstats(Proto *il, char *buf, int len) return n; } -void -ilinit(Fs *f) -{ - Proto *il; - - il = smalloc(sizeof(Proto)); - il->priv = smalloc(sizeof(Ilpriv)); - il->name = "il"; - il->kick = ilkick; - il->connect = ilconnect; - il->announce = ilannounce; - il->state = ilstate; - il->create = ilcreate; - il->close = ilclose; - il->rcv = iliput; - il->ctl = nil; - il->advise = iladvise; - il->stats = ilxstats; - il->inuse = ilinuse; - il->ipproto = IP_ILPROTO; - il->nc = Nchans; - il->ptclsize = sizeof(Ilcb); - Fsproto(f, il); -} - void ilackq(Ilcb *ic, Block *bp) { @@ -403,11 +387,8 @@ ilackq(Ilcb *ic, Block *bp) np = copyblock(bp, n); if(ic->unacked) ic->unackedtail->list = np; - else { - /* Start timer since we may have been idle for some time */ - iltimers(ic); + else ic->unacked = np; - } ic->unackedtail = np; np->list = nil; ic->unackeduchars += n; @@ -415,29 +396,37 @@ ilackq(Ilcb *ic, Block *bp) static void -ilrttcalc(Ilcb *ic) +ilrttcalc(Ilcb *ic, Block *bp) { - int rtt, tt, pt, delay, rate; + uvlong fastrtt; + int rtt, tt, pt, delay, rate, mrtt; - /* add in clock resolution hack */ - rtt = (msec + TK2MS(1) - 1) - ic->rttms; + fastrtt = fastticks(nil) - ic->rttstart; + if(microshift >= 0) + rtt = fastrtt >> microshift; + else + rtt = fastrtt << -microshift; + mrtt = rtt >> 10; delay = ic->delay; rate = ic->rate; - /* Guard against the ulong zero wrap of MACHP(0)->ticks */ - if(rtt > 120000) + /* Guard against zero wrap */ + if(rtt > 120000000) return; /* guess fixed delay as rtt of small packets */ if(ic->rttlen < 128){ - delay += rtt - (delay>>LogAGain); + delay += mrtt - (delay>>LogAGain); if(delay < AGain) delay = AGain; ic->delay = delay; } - /* rate */ - tt = rtt - (delay>>LogAGain); + /* 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) @@ -447,21 +436,20 @@ ilrttcalc(Ilcb *ic) /* mdev */ pt = ic->rttlen/(rate>>LogAGain) + (delay>>LogAGain); - ic->mdev += abs(rtt-pt) - (ic->mdev>>LogDGain); + ic->mdev += abs(mrtt-pt) - (ic->mdev>>LogDGain); - if(rtt > ic->maxrtt) - ic->maxrtt = rtt; + if(mrtt > ic->maxrtt) + ic->maxrtt = mrtt; } void -ilackto(Ilcb *ic, ulong ackto) +ilackto(Ilcb *ic, ulong ackto, Block *bp) { Ilhdr *h; - Block *bp; ulong id; if(ic->rttack == ackto) - ilrttcalc(ic); + ilrttcalc(ic, bp); /* Cancel if we've passed the packet we were interested in */ if(ic->rttack <= ackto) @@ -479,6 +467,8 @@ ilackto(Ilcb *ic, ulong ackto) bp->list = nil; ic->unackeduchars -= blocklen(bp); freeblist(bp); + ic->rexmit = 0; + ilsettimeout(ic); } qunlock(&ic->ackq); } @@ -585,19 +575,8 @@ iliput(Proto *il, uchar*, Block *bp) ic = (Ilcb*)new->ptcl; ic->conv = new; ic->state = Ilsyncee; - initseq += msec; - ic->start = initseq & 0xffffff; - ic->next = ic->start+1; - ic->recvd = 0; + ilcbinit(ic); ic->rstart = nhgetl(ih->ilid); - ic->slowtime = Slowtime; - ic->delay = Iltickms<mdev = Iltickms<rate = DefByteRate<querytime = Keepalivetime; - ic->deathtime = Deathtime; - ic->window = Defaultwin; - ic->unackeduchars = 0; ilprocess(new, ih, bp); return; @@ -618,8 +597,7 @@ _ilprocess(Conv *s, Ilhdr *h, Block *bp) ic = (Ilcb*)s->ptcl; - ic->querytime = Keepalivetime; - ic->deathtime = Deathtime; + ic->lastrecv = msec; switch(ic->state) { default: @@ -641,7 +619,6 @@ _ilprocess(Conv *s, Ilhdr *h, Block *bp) ic->state = Ilestablished; Fsconnected(s, nil); ilpullup(s); - iltimers(ic); } break; case Ilclose: @@ -661,14 +638,12 @@ _ilprocess(Conv *s, Ilhdr *h, Block *bp) else { ic->recvd = id; ilsendctl(s, nil, Ilsync, ic->start, ic->recvd, 0); - iltimers(ic); } break; case Ilack: if(ack == ic->start) { ic->state = Ilestablished; ilpullup(s); - iltimers(ic); } break; case Ilclose: @@ -683,45 +658,38 @@ _ilprocess(Conv *s, Ilhdr *h, Block *bp) case Ilsync: if(id != ic->rstart) ilhangup(s, "remote close"); - else { + else ilsendctl(s, nil, Ilack, ic->next, ic->rstart, 0); - iltimers(ic); - } freeblist(bp); break; case Ildata: - iltimers(ic); - ilackto(ic, ack); - ic->acktime = Acktime; + ilackto(ic, ack, bp); iloutoforder(s, h, bp); ilpullup(s); break; case Ildataquery: - iltimers(ic); - ilackto(ic, ack); - ic->acktime = Acktime; + ilackto(ic, ack, bp); iloutoforder(s, h, bp); ilpullup(s); ilsendctl(s, nil, Ilstate, ic->next, ic->recvd, h->ilspec); break; case Ilack: - ilackto(ic, ack); - iltimers(ic); + ilackto(ic, ack, bp); freeblist(bp); break; case Ilquery: - ilackto(ic, ack); + ilackto(ic, ack, bp); ilsendctl(s, nil, Ilstate, ic->next, ic->recvd, h->ilspec); - iltimers(ic); freeblist(bp); break; case Ilstate: - ilackto(ic, ack); + ilackto(ic, ack, bp); if(h->ilspec > Nqt) h->ilspec = 0; - if(ic->qt[h->ilspec] > ack) + if(ic->qt[h->ilspec] > ack){ ilrexmit(ic); - iltimers(ic); + ilsettimeout(ic); + } freeblist(bp); break; case Ilclose: @@ -731,7 +699,6 @@ _ilprocess(Conv *s, Ilhdr *h, Block *bp) ilsendctl(s, nil, Ilclose, ic->next, ic->recvd, 0); ic->state = Ilclosing; ilfreeq(ic); - iltimers(ic); break; } break; @@ -745,7 +712,6 @@ _ilprocess(Conv *s, Ilhdr *h, Block *bp) ilsendctl(s, nil, Ilclose, ic->next, ic->recvd, 0); if(ack == ic->next) ilhangup(s, nil); - iltimers(ic); break; default: break; @@ -762,8 +728,6 @@ ilrexmit(Ilcb *ic) Block *nb; Conv *c; ulong id; - int x; - Ilpriv *ipriv; nb = nil; qlock(&ic->ackq); @@ -784,25 +748,15 @@ ilrexmit(Ilcb *ic) hnputs(h->ilsum, ptclcsum(nb, IL_IPSIZE, nhgets(h->illen))); c = ic->conv; - ipriv = c->p->priv; id = nhgetl(h->ilid); - netlog(c->p->f, Logil, "il: rexmit %ud %ud: %d %d: %i %d/%d\n", id, ic->recvd, - ic->fasttime, ic->timeout, + netlog(c->p->f, Logil, "il: rexmit %d %ud: %d %d: %i %d/%d\n", id, ic->recvd, + ic->rexmit, ic->timeout, c->raddr, c->lport, c->rport); - ipriv->rexmit++; - ic->rexmit++; - - /* - * Double delay estimate and half bandwidth estimate. This is - * in keeping with van jacobson's tcp alg. - */ + /* rtt calcs are useless during retransmissions */ ic->rttack = 0; - if((ic->delay>>LogAGain) < 2*Seconds) - ic->delay *= 2; - x = ic->rate>>1; - if(x >= (1<rate = x; + + ilbackoff(ic); ipoput(c->p->f, nb, 0, ic->conv->ttl); } @@ -832,7 +786,8 @@ ilhangup(Conv *s, char *msg) Ilcb *ic; int callout; - netlog(s->p->f, Logil, "il: hangup! %I %d/%d: %s\n", s->raddr, s->lport, s->rport, msg?msg:"no reason"); + netlog(s->p->f, Logil, "il: hangup! %I %d/%d: %s\n", s->raddr, + s->lport, s->rport, msg?msg:"no reason"); ic = (Ilcb*)s->ptcl; callout = ic->state == Ilsyncer; @@ -981,7 +936,8 @@ ilsendctl(Conv *ipc, Ilhdr *inih, int type, ulong id, ulong ack, int ilspec) hnputl(ih->ilid, id); hnputl(ih->ilack, ack); ic = (Ilcb*)ipc->ptcl; - ic->acktime = Ackkeepalive; + ic->acksent = ack; + ic->acktime = msec; ttl = ipc->ttl; } ih->iltype = type; @@ -1001,6 +957,40 @@ ilsendctl(Conv *ipc, Ilhdr *inih, int type, ulong id, ulong ack, int ilspec) ipoput(ipc->p->f, bp, 0, ttl); } +void +ilsettimeout(Ilcb *ic) +{ + ulong pt; + + pt = (ic->delay>>LogAGain) + ic->unackeduchars/(ic->rate>>LogAGain) + ic->mdev; + pt += AckDelay; + if(pt > MaxTimeout) + pt = MaxTimeout; + ic->timeout = msec + pt; +} + +void +ilbackoff(Ilcb *ic) +{ + ulong pt; + int i; + Ilpriv *priv; + + pt = (ic->delay>>LogAGain) + ic->unackeduchars/(ic->rate>>LogAGain) + ic->mdev; + pt += 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 ilackproc(void *x) { @@ -1018,56 +1008,52 @@ loop: p = *s; ic = (Ilcb*)p->ptcl; - ic->timeout += Iltickms; switch(ic->state) { case Ilclosed: case Illistening: break; case Ilclosing: - if(ic->timeout >= ic->fasttime) { + if(ic->timeout <= msec) { + if(ic->rexmit > MaxRexmit){ + ilhangup(p, nil); + break; + } ilsendctl(p, nil, Ilclose, ic->next, ic->recvd, 0); ilbackoff(ic); } - if(ic->timeout >= ic->slowtime) - ilhangup(p, nil); break; case Ilsyncee: case Ilsyncer: - if(ic->timeout >= ic->fasttime) { + if(ic->timeout <= msec) { + if(ic->rexmit > MaxRexmit){ + ilhangup(p, etime); + break; + } ilsendctl(p, nil, Ilsync, ic->start, ic->recvd, 0); ilbackoff(ic); } - if(ic->timeout >= ic->slowtime) - ilhangup(p, etime); break; case Ilestablished: - ic->acktime -= Iltickms; - if(ic->acktime <= 0) + if(ic->recvd != ic->acksent && ic->acktime <= msec) ilsendctl(p, nil, Ilack, ic->next, ic->recvd, 0); - ic->querytime -= Iltickms; - if(ic->querytime <= 0){ - ic->deathtime -= Querytime; - if(ic->deathtime < 0){ - netlog(il->f, Logil, "il: hangup due to deathtime (%d) < 0 \n", ic->deathtime); + if(ic->querytime <= msec){ + if(msec - ic->lastrecv > DeathTime){ + netlog(il->f, Logil, "il: hangup: deathtime\n"); ilhangup(p, etime); break; } ilsendctl(p, nil, Ilquery, ic->next, ic->recvd, ilnextqt(ic)); - ic->querytime = Querytime; - } - if(ic->unacked == nil) { - ic->timeout = 0; - break; + ic->querytime = msec + QueryTime; } - if(ic->timeout >= ic->fasttime) { + + if(ic->unacked != nil && ic->timeout <= msec) { + if(ic->rexmit > MaxRexmit){ + netlog(il->f, Logil, "il: hangup: too many rexmits\n"); + ilhangup(p, etime); + break; + } ilrexmit(ic); - ilbackoff(ic); - } - if(ic->timeout >= ic->slowtime) { - netlog(il->f, Logil, "il: hangup due to timeout (%d) >= slowtime (%d)\n", ic->timeout, ic->slowtime); - ilhangup(p, etime); - break; } break; } @@ -1076,17 +1062,31 @@ loop: } void -ilbackoff(Ilcb *ic) +ilcbinit(Ilcb *ic) { - ic->fasttime += ic->fasttime>>1; - if(ic->fasttime > Fasttime) - ic->fasttime = Fasttime; + ic->start = nrand(0x1000000); + ic->next = ic->start+1; + ic->recvd = 0; + ic->window = Defaultwin; + ic->unackeduchars = 0; + ic->unacked = nil; + ic->outoforder = nil; + ic->rexmit = 0; + ic->rxtot = 0; + ic->qtx = 1; + + /* timers */ + ic->delay = DefRtt<mdev = DefRtt<rate = DefByteRate<querytime = msec + QueryTime; + ic->lastrecv = msec; /* or we'll timeout right away */ + ilsettimeout(ic); } char* -ilstart(Conv *c, int type, int window) +ilstart(Conv *c, int type) { - char *e; Ilcb *ic; Ilpriv *ipriv; char kpname[NAMELEN]; @@ -1106,26 +1106,10 @@ ilstart(Conv *c, int type, int window) ic = (Ilcb*)c->ptcl; ic->conv = c; - e = nil; - if(ic->state != Ilclosed) - return e; + return nil; - ic->unacked = nil; - ic->outoforder = nil; - ic->unackeduchars = 0; - ic->delay = Iltickms<mdev = Iltickms<rate = DefByteRate<start = initseq & 0xffffff; - ic->next = ic->start+1; - ic->recvd = 0; - ic->window = window; - ic->rexmit = 0; - ic->qtx = 1; + ilcbinit(ic); switch(type) { default: @@ -1140,7 +1124,7 @@ ilstart(Conv *c, int type, int window) break; } - return e; + return nil; } void @@ -1165,21 +1149,6 @@ ilfreeq(Ilcb *ic) qunlock(&ic->outo); } -void -iltimers(Ilcb *ic) -{ - int pt; - - ic->timeout = 0; - pt = (ic->delay>>LogAGain) + ic->unackeduchars/(ic->rate>>LogAGain) + ic->mdev; - ic->fasttime = Acktime + pt + Iltickms - 1; - if(ic->fasttime > Fasttime) - ic->fasttime = Fasttime; - ic->slowtime = (Slowtime/Seconds)*pt; - if(ic->slowtime < Slowtime) - ic->slowtime = Slowtime; -} - void iladvise(Proto *il, Block *bp, char *msg) { @@ -1230,3 +1199,47 @@ ilnextqt(Ilcb *ic) return x; } + +/* quick and dirty conversion from fastticks to microseconds */ +static void +initfast(void) +{ + int i; + uvlong x, hz; + + fastticks(&hz); + x = 3; + for(i = 1; i < 40; i++){ + if(x >= hz) + break; + x <<= 1; + } + microshift = i - 20; +} + +void +ilinit(Fs *f) +{ + Proto *il; + + initfast(); + + il = smalloc(sizeof(Proto)); + il->priv = smalloc(sizeof(Ilpriv)); + il->name = "il"; + il->kick = ilkick; + il->connect = ilconnect; + il->announce = ilannounce; + il->state = ilstate; + il->create = ilcreate; + il->close = ilclose; + il->rcv = iliput; + il->ctl = nil; + il->advise = iladvise; + il->stats = ilxstats; + il->inuse = ilinuse; + il->ipproto = IP_ILPROTO; + il->nc = Nchans; + il->ptclsize = sizeof(Ilcb); + Fsproto(f, il); +} diff --git a/pc/ether82557.c b/pc/ether82557.c index 083f31f43b26c3b223800ce4e807e144476674a7..0afe5d592850fa9ae02c154a925c0d3ace32e4c6 100644 --- a/pc/ether82557.c +++ b/pc/ether82557.c @@ -192,6 +192,8 @@ typedef struct Ctlr { int port; ushort eeprom[0x40]; + Lock miilock; + Rendez timer; /* watchdog timer for receive lockup errata */ int tick; @@ -379,7 +381,7 @@ static long ifstat(Ether* ether, void* a, long n, ulong offset) { char *p; - int len; + int i, len, phyaddr; Ctlr *ctlr; ulong dump[17]; @@ -431,8 +433,27 @@ ifstat(Ether* ether, void* a, long n, ulong offset) ctlr->cbqmaxhw = ctlr->cbqmax; len += snprint(p+len, READSTR-len, "cbqmax: %d\n", ctlr->cbqmax); ctlr->cbqmax = 0; - snprint(p+len, READSTR-len, "threshold: %d\n", ctlr->threshold); + len += snprint(p+len, READSTR-len, "threshold: %d\n", ctlr->threshold); + + len += snprint(p+len, READSTR-len, "eeprom:"); + for(i = 0; i < 0x40; i++){ + if(i && ((i & 0x07) == 0)) + len += snprint(p+len, READSTR-len, "\n "); + len += snprint(p+len, READSTR-len, " %4.4uX", ctlr->eeprom[i]); + } + + if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000)){ + phyaddr = ctlr->eeprom[6] & 0x00FF; + len += snprint(p+len, READSTR-len, "\nphy %2d:", phyaddr); + for(i = 0; i < 6; i++){ + static int miir(Ctlr*, int, int); + len += snprint(p+len, READSTR-len, " %4.4uX", + miir(ctlr, phyaddr, i)); + } + } + + snprint(p+len, READSTR-len, "\n"); n = readstr(offset, a, n, p); free(p); @@ -731,6 +752,7 @@ miir(Ctlr* ctlr, int phyadd, int regadd) { int mcr, timo; + lock(&ctlr->miilock); csr32w(ctlr, Mcr, MDIread|(phyadd<<21)|(regadd<<16)); mcr = 0; for(timo = 64; timo; timo--){ @@ -739,6 +761,7 @@ miir(Ctlr* ctlr, int phyadd, int regadd) break; microdelay(1); } + unlock(&ctlr->miilock); if(mcr & MDIready) return mcr & 0xFFFF; @@ -751,6 +774,7 @@ miiw(Ctlr* ctlr, int phyadd, int regadd, int data) { int mcr, timo; + lock(&ctlr->miilock); csr32w(ctlr, Mcr, MDIwrite|(phyadd<<21)|(regadd<<16)|(data & 0xFFFF)); mcr = 0; for(timo = 64; timo; timo--){ @@ -759,6 +783,7 @@ miiw(Ctlr* ctlr, int phyadd, int regadd, int data) break; microdelay(1); } + unlock(&ctlr->miilock); if(mcr & MDIready) return 0; @@ -853,10 +878,22 @@ i82557pci(void) } } +static char* mediatable[9] = { + "10BASE-T", /* TP */ + "10BASE-2", /* BNC */ + "10BASE-5", /* AUI */ + "100BASE-TX", + "10BASE-TFD", + "100BASE-TXFD", + "100BASE-T4", + "100BASE-FX", + "100BASE-FXFD", +}; + static int reset(Ether* ether) { - int anar, anlpar, bmcr, bmsr, force, i, phyaddr, port, x; + int anar, anlpar, bmcr, bmsr, i, k, medium, phyaddr, port, x; unsigned short sum; Block *bp, **bpp; Adapter *ap; @@ -1024,25 +1061,46 @@ reset(Ether* ether) * Force speed and duplex if no auto-negotiation. */ if(anlpar == 0){ - force = 0; + medium = -1; for(i = 0; i < ether->nopt; i++){ - if(cistrcmp(ether->opt[i], "fullduplex") == 0){ - force = 1; - bmcr |= 0x0100; - ctlr->configdata[19] |= 0x40; + for(k = 0; k < nelem(mediatable); k++){ + if(cistrcmp(mediatable[k], ether->opt[i])) + continue; + medium = k; + break; } - else if(cistrcmp(ether->opt[i], "speed") == 0){ - force = 1; - x = strtol(ðer->opt[i][6], 0, 0); - if(x == 10) - bmcr &= ~0x2000; - else if(x == 100) - bmcr |= 0x2000; - else - force = 0; + + switch(medium){ + default: + break; + + case 0x00: /* 10BASE-T */ + case 0x01: /* 10BASE-2 */ + case 0x02: /* 10BASE-5 */ + bmcr &= ~(0x2000|0x0100); + ctlr->configdata[19] &= ~0x40; + break; + + case 0x03: /* 100BASE-TX */ + case 0x06: /* 100BASE-T4 */ + case 0x07: /* 100BASE-FX */ + ctlr->configdata[19] &= ~0x40; + bmcr |= 0x2000; + break; + + case 0x04: /* 10BASE-TFD */ + bmcr = (bmcr & ~0x2000)|0x0100; + ctlr->configdata[19] |= 0x40; + break; + + case 0x05: /* 100BASE-TXFD */ + case 0x08: /* 100BASE-FXFD */ + bmcr |= 0x2000|0x0100; + ctlr->configdata[19] |= 0x40; + break; } } - if(force) + if(medium != -1) miiw(ctlr, phyaddr, 0x00, bmcr); } diff --git a/port/qio.c b/port/qio.c index 43770a896addf3aec8b7dcd40934c94c2bb9ed07..c31a049d378b1063d01675629cc4170a282afeb6 100644 --- a/port/qio.c +++ b/port/qio.c @@ -1196,6 +1196,7 @@ qclose(Queue *q) bfirst = q->bfirst; q->bfirst = 0; q->len = 0; + q->dlen = 0; q->noblock = 0; iunlock(q);