History

20070407-1350 more updates from plan 9 pc kernel, and a few unreachable fixes(!)

Charles.Forsyth committed 19 years ago

Commit c6d075d1 parent 1f5080232 files · +2847 −256Browse files

Unified · Split

32 files
  1. os/ip/devip.c +0 −2
  2. os/ip/ip.h +0 −1
  3. os/ip/ipifc.c +44 −44
  4. os/ip/iproute.c +1 −1
  5. os/ip/ipv6.h +7 −7
  6. os/ip/tcp.c +44 −28
  7. os/pc/ether2000.c +4 −2
  8. os/pc/ether2114x.c +6 −4
  9. os/pc/ether79c970.c +8 −3
  10. os/pc/ether8139.c +11 −1
  11. os/pc/ether82543gc.c +6 −6
  12. os/pc/ether82557.c +14 −12
  13. os/pc/ether83815.c +147 −22
  14. os/pc/ether8390.c +3 −3
  15. os/pc/etherdp83820.c +1246 −0
  16. os/pc/etherec2t.c +1 −0
  17. os/pc/etherelnk3.c +6 −4
  18. os/pc/etherga620.c +97 −46
  19. os/pc/etherigbe.c +59 −38
  20. os/pc/ethersmc.c +1 −0
  21. os/pc/ethervt6102.c +1025 −0
  22. os/pc/etherwavelan.c +6 −5
  23. os/pc/fns.h +4 −0
  24. os/pc/i8253.c +1 −1
  25. os/pc/io.h +49 −1
  26. os/pc/memory.c +18 −0
  27. os/pc/mmu.c +16 −0
  28. os/pc/pci.c +0 −1
  29. os/port/chan.c +17 −17
  30. os/port/dev.c +0 −2
  31. os/port/ethermii.c +3 −3
  32. os/port/lib.h +3 −2
os/ip/devip.c+0−2
@@ -982,7 +982,6 @@ Fsstdannounce(Conv* c, char* argv[], int argc) · 981 unmodified lines
982982 case 2:
983983 return setladdrport(c, argv[1], 1);
984984 }
985− return nil;
986985 }
987986
988987 /*
@@ -1033,7 +1032,6 @@ Fsstdbind(Conv* c, char* argv[], int argc) · 44 unmodified lines
10331032 case 2:
10341033 return setladdrport(c, argv[1], 0);
10351034 }
1036− return nil;
10371035 }
10381036
10391037 static void
os/ip/ip.h+0−1
@@ -669,5 +669,4 @@ extern Chan* chandial(char*, char*, char*, Chan**); · 668 unmodified lines
669669 /*
670670 * global to all of the stack
671671 */
672−extern int debug;
673672 extern void (*igmpreportfn)(Ipifc*, uchar*);
os/ip/ipifc.c+44−44
@@ -11,11 +11,11 @@ · 10 unmodified lines
1111 #define DPRINT if(0)print
1212
1313 enum {
14− Maxmedia = 32,
15− Nself = Maxmedia*5,
16− NHASH = (1<<6),
17− NCACHE = 256,
18− QMAX = 64*1024-1,
14+ Maxmedia = 32,
15+ Nself = Maxmedia*5,
16+ NHASH = (1<<6),
17+ NCACHE = 256,
18+ QMAX = 64*1024-1,
1919 };
2020
2121 Medium *media[Maxmedia] =
@@ -135,7 +135,7 @@ ipifcbind(Conv *c, char **argv, int argc) · 113 unmodified lines
135135 if(argc > 2)
136136 strncpy(ifc->dev, argv[2], sizeof(ifc->dev));
137137 else
138− sprint(ifc->dev, "%s%d", m->name, c->x);
138+ snprint(ifc->dev, sizeof ifc->dev, "%s%d", m->name, c->x);
139139 ifc->dev[sizeof(ifc->dev)-1] = 0;
140140
141141 /* set up parameters */
@@ -144,15 +144,15 @@ ipifcbind(Conv *c, char **argv, int argc) · 2 unmodified lines
144144 ifc->maxtu = ifc->m->maxtu;
145145 if(ifc->m->unbindonclose == 0)
146146 ifc->conv->inuse++;
147− ifc->rp.mflag = 0; // default not managed
148− ifc->rp.oflag = 0;
149− ifc->rp.maxraint = 600000; // millisecs
150− ifc->rp.minraint = 200000;
151− ifc->rp.linkmtu = 0; // no mtu sent
152− ifc->rp.reachtime = 0;
153− ifc->rp.rxmitra = 0;
154− ifc->rp.ttl = MAXTTL;
155− ifc->rp.routerlt = 3*(ifc->rp.maxraint);
147+ ifc->rp.mflag = 0; // default not managed
148+ ifc->rp.oflag = 0;
149+ ifc->rp.maxraint = 600000; // millisecs
150+ ifc->rp.minraint = 200000;
151+ ifc->rp.linkmtu = 0; // no mtu sent
152+ ifc->rp.reachtime = 0;
153+ ifc->rp.rxmitra = 0;
154+ ifc->rp.ttl = MAXTTL;
155+ ifc->rp.routerlt = 3*(ifc->rp.maxraint);
156156
157157 /* any ancillary structures (like routes) no longer pertain */
158158 ifc->ifcid++;
@@ -229,7 +229,7 @@ ipifcstate(Conv *c, char *state, int n) · 70 unmodified lines
229229
230230 ifc = (Ipifc*)c->ptcl;
231231
232− m = snprint(state, n, sfixedformat,
232+ m = snprint(state, n, sfixedformat,
233233 ifc->dev, ifc->maxtu, ifc->sendra6, ifc->recvra6,
234234 ifc->rp.mflag, ifc->rp.oflag, ifc->rp.maxraint,
235235 ifc->rp.minraint, ifc->rp.linkmtu, ifc->rp.reachtime,
@@ -328,7 +328,7 @@ ipifccreate(Conv *c) · 92 unmodified lines
328328 ifc->reassemble = 0;
329329 }
330330
331−/*
331+/*
332332 * called after last close of ipifc data or ctl
333333 * called with c locked, we must unlock
334334 */
@@ -424,7 +424,7 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp) · 89 unmodified lines
424424 /* ignore if this is already a local address for this ifc */
425425 for(lifc = ifc->lifc; lifc; lifc = lifc->next) {
426426 if(ipcmp(lifc->local, ip) == 0) {
427− if(lifc->tentative != tentative)
427+ if(lifc->tentative != tentative)
428428 lifc->tentative = tentative;
429429 if(lifcp != nil) {
430430 lifc->onlink = lifcp->onlink;
@@ -506,7 +506,7 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp) · 75 unmodified lines
506506 addselfcache(f, ifc, lifc, bcast, Rbcast);
507507
508508 addselfcache(f, ifc, lifc, IPv4bcast, Rbcast);
509− }
509+ }
510510 else {
511511 if(ipcmp(ip, v6loopback) == 0) {
512512 /* add node-local mcast address */
@@ -535,7 +535,7 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp) · 22 unmodified lines
535535
536536 out:
537537 wunlock(ifc);
538− if(tentative && sendnbrdisc)
538+ if(tentative && sendnbrdisc)
539539 icmpns(f, 0, SRC_UNSPEC, ip, TARG_MULTI, ifc->mac);
540540 return nil;
541541 }
@@ -721,29 +721,29 @@ ipifcsetpar6(Ipifc *ifc, char **argv, int argc) · 179 unmodified lines
721721 return Ebadarg;
722722
723723 while (argsleft > 1) {
724− if(strcmp(argv[i],"recvra")==0)
724+ if(strcmp(argv[i],"recvra")==0)
725725 ifc->recvra6 = (atoi(argv[i+1]) != 0);
726− else if(strcmp(argv[i],"sendra")==0)
726+ else if(strcmp(argv[i],"sendra")==0)
727727 ifc->sendra6 = (atoi(argv[i+1]) != 0);
728− else if(strcmp(argv[i],"mflag")==0)
728+ else if(strcmp(argv[i],"mflag")==0)
729729 ifc->rp.mflag = (atoi(argv[i+1]) != 0);
730− else if(strcmp(argv[i],"oflag")==0)
730+ else if(strcmp(argv[i],"oflag")==0)
731731 ifc->rp.oflag = (atoi(argv[i+1]) != 0);
732732 else if(strcmp(argv[i],"maxraint")==0)
733733 ifc->rp.maxraint = atoi(argv[i+1]);
734734 else if(strcmp(argv[i],"minraint")==0)
735735 ifc->rp.minraint = atoi(argv[i+1]);
736− else if(strcmp(argv[i],"linkmtu")==0)
736+ else if(strcmp(argv[i],"linkmtu")==0)
737737 ifc->rp.linkmtu = atoi(argv[i+1]);
738− else if(strcmp(argv[i],"reachtime")==0)
738+ else if(strcmp(argv[i],"reachtime")==0)
739739 ifc->rp.reachtime = atoi(argv[i+1]);
740− else if(strcmp(argv[i],"rxmitra")==0)
740+ else if(strcmp(argv[i],"rxmitra")==0)
741741 ifc->rp.rxmitra = atoi(argv[i+1]);
742− else if(strcmp(argv[i],"ttl")==0)
742+ else if(strcmp(argv[i],"ttl")==0)
743743 ifc->rp.ttl = atoi(argv[i+1]);
744− else if(strcmp(argv[i],"routerlt")==0)
744+ else if(strcmp(argv[i],"routerlt")==0)
745745 ifc->rp.routerlt = atoi(argv[i+1]);
746− else
746+ else
747747 return Ebadarg;
748748
749749 argsleft -= 2;
@@ -778,7 +778,7 @@ ipifcrecvra6(Ipifc *ifc, char **argv, int argc) · 28 unmodified lines
778778 int i;
779779
780780 i = 0;
781− if(argc > 1)
781+ if(argc > 1)
782782 i = atoi(argv[1]);
783783 ifc->recvra6 = (i!=0);
784784 return nil;
@@ -826,7 +826,7 @@ ipifcctl(Conv* c, char**argv, int argc) · 41 unmodified lines
826826 return ipifcaddpref6(ifc, argv, argc);
827827 else if(strcmp(argv[0], "setpar6") == 0)
828828 return ipifcsetpar6(ifc, argv, argc);
829− else if(strcmp(argv[0], "sendra6") == 0)
829+ else if(strcmp(argv[0], "sendra6") == 0)
830830 return ipifcsendra6(ifc, argv, argc);
831831 else if(strcmp(argv[0], "recvra6") == 0)
832832 return ipifcrecvra6(ifc, argv, argc);
@@ -1097,7 +1097,7 @@ ipselftabread(Fs *f, char *cp, ulong offset, int n) · 264 unmodified lines
10971097 }
10981098
10991099 int
1100−iptentative(Fs *f, uchar *addr)
1100+iptentative(Fs *f, uchar *addr)
11011101 {
11021102 Ipself *p;
11031103
@@ -1210,8 +1210,8 @@ v6addrtype(uchar *addr) · 106 unmodified lines
12101210
12111211 #define v6addrcurr(lifc) (( (lifc)->origint + (lifc)->preflt >= (NOW/10^3) ) || ( (lifc)->preflt == 0xffffffff ))
12121212
1213−void
1214−findprimaryip6(Fs *f, uchar *local)
1213+static void
1214+findprimaryipv6(Fs *f, uchar *local)
12151215 {
12161216 Conv **cp, **e;
12171217 Ipifc *ifc;
@@ -1231,7 +1231,7 @@ findprimaryip6(Fs *f, uchar *local) · 13 unmodified lines
12311231 ifc = (Ipifc*)(*cp)->ptcl;
12321232 for(lifc = ifc->lifc; lifc; lifc = lifc->next){
12331233 atypel = v6addrtype(lifc->local);
1234− if(atypel > atype)
1234+ if(atypel > atype)
12351235 if(v6addrcurr(lifc)) {
12361236 ipmove(local, lifc->local);
12371237 atype = atypel;
@@ -1243,10 +1243,10 @@ findprimaryip6(Fs *f, uchar *local) · 5 unmodified lines
12431243 }
12441244
12451245 /*
1246− * returns first ip address configured
1246+ * returns first ip address configured
12471247 */
1248−void
1249−findprimaryip(Fs *f, uchar *local)
1248+static void
1249+findprimaryipv4(Fs *f, uchar *local)
12501250 {
12511251 Conv **cp, **e;
12521252 Ipifc *ifc;
@@ -1258,7 +1258,7 @@ findprimaryip(Fs *f, uchar *local) · 5 unmodified lines
12581258 if(*cp == 0)
12591259 continue;
12601260 ifc = (Ipifc*)(*cp)->ptcl;
1261− for(lifc = ifc->lifc; lifc; lifc = lifc->next){
1261+ if((lifc = ifc->lifc) != nil){
12621262 ipmove(local, lifc->local);
12631263 return;
12641264 }
@@ -1329,10 +1329,10 @@ findlocalip(Fs *f, uchar *local, uchar *remote) · 64 unmodified lines
13291329
13301330 switch(version){
13311331 case V4:
1332− findprimaryip(f, local);
1332+ findprimaryipv4(f, local);
13331333 break;
13341334 case V6:
1335− findprimaryip6(f, local);
1335+ findprimaryipv6(f, local);
13361336 break;
13371337 default:
13381338 panic("findlocalip2: version %d", version);
@@ -1642,7 +1642,7 @@ adddefroute6(Fs *f, uchar *gate, int force) · 303 unmodified lines
16421642 Route *r;
16431643
16441644 r = v6lookup(f, v6Unspecified, nil);
1645− if(r!=nil)
1645+ if(r!=nil)
16461646 if(!(force) && (strcmp(r->tag,"ra")!=0)) // route entries generated
16471647 return; // by all other means take
16481648 // precedence over router annc
@@ -1705,7 +1705,7 @@ ipifcaddpref6(Ipifc *ifc, char**argv, int argc) · 56 unmodified lines
17051705 lifc->preflt = preflt;
17061706 lifc->origint = origint;
17071707
1708− if(ifc->m->pref2addr!=nil)
1708+ if(ifc->m->pref2addr!=nil)
17091709 ifc->m->pref2addr(prefix, ifc->mac);
17101710 else
17111711 return Ebadarg;
os/ip/iproute.c+1−1
@@ -662,7 +662,7 @@ sprintroute(Route *r, Routewalk *rw) · 661 unmodified lines
662662 iname = "-";
663663 if(nifc != -1) {
664664 iname = ifbuf;
665− sprint(ifbuf, "%d", nifc);
665+ snprint(ifbuf, sizeof ifbuf, "%d", nifc);
666666 }
667667 p = seprint(rw->p, rw->e, rformat, addr, mask, gate, t, r->tag, iname);
668668 if(rw->o < 0){
os/ip/ipv6.h+7−7
@@ -61,12 +61,12 @@ enum { /* Header Types */ · 60 unmodified lines
6161 RSVP = 46,
6262 AH = 51,
6363 ESP = 52,
64− ICMPv6 = 58,
64+ ICMPv6 = 58,
6565 NNH = 59,
6666 DOH = 60,
6767 ISO_IP = 80,
6868 IGRP = 88,
69− OSPF = 89,
69+ OSPF = 89,
7070
7171 Maxhdrtype = 256,
7272 };
@@ -98,7 +98,7 @@ enum { · 25 unmodified lines
9898
9999 // various flags & constants
100100
101− v6MINTU = 1280,
101+ v6MINTU = 1280,
102102 HOP_LIMIT = 255,
103103 ETHERHDR_LEN = 14,
104104 IPV6HDR_LEN = 40,
@@ -113,7 +113,7 @@ enum { · 8 unmodified lines
113113 MTU_OPTION = 5,
114114
115115 SRC_UNSPEC = 0,
116− SRC_UNI = 1,
116+ SRC_UNI = 1,
117117 TARG_UNI = 2,
118118 TARG_MULTI = 3,
119119
@@ -124,7 +124,7 @@ enum { · 4 unmodified lines
124124 // Router constants (all times in milliseconds)
125125
126126 MAX_INITIAL_RTR_ADVERT_INTERVAL = 16000,
127− MAX_INITIAL_RTR_ADVERTISEMENTS = 3,
127+ MAX_INITIAL_RTR_ADVERTISEMENTS = 3,
128128 MAX_FINAL_RTR_ADVERTISEMENTS = 3,
129129 MIN_DELAY_BETWEEN_RAS = 3000,
130130 MAX_RA_DELAY_TIME = 500,
@@ -140,9 +140,9 @@ enum { · 9 unmodified lines
140140 MAX_MULTICAST_SOLICIT = 3,
141141 MAX_UNICAST_SOLICIT = 3,
142142 MAX_ANYCAST_DELAY_TIME = 1000,
143− MAX_NEIGHBOR_ADVERTISEMENT = 3,
143+ MAX_NEIGHBOR_ADVERTISEMENT = 3,
144144 REACHABLE_TIME = 30000,
145− RETRANS_TIMER = 1000,
145+ RETRANS_TIMER = 1000,
146146 DELAY_FIRST_PROBE_TIME = 5000,
147147
148148 };
os/ip/tcp.c+44−28
@@ -54,7 +54,7 @@ enum · 53 unmodified lines
5454 TCP_CONNECT = 1, /* Outgoing connection */
5555 SYNACK_RXTIMER = 250, /* ms between SYNACK retransmits */
5656
57− TCPREXMTTHRESH = 3, /* dupack threshhold for rxt */
57+ TCPREXMTTHRESH = 3, /* dupack threshhold for rxt */
5858
5959 FORCE = 1,
6060 CLONE = 2,
@@ -285,7 +285,7 @@ struct Limbo · 224 unmodified lines
285285 };
286286
287287 int tcp_irtt = DEF_RTT; /* Initial guess at round trip time */
288−ushort tcp_mss = DEF_MSS; /* Maximum segment size to be sent */
288+ushort tcp_mss = DEF_MSS; /* Maximum segment size to be sent */
289289
290290 enum {
291291 /* MIB stats */
@@ -350,7 +350,7 @@ struct Tcppriv · 58 unmodified lines
350350 ulong stats[Nstats];
351351 };
352352
353−/*
353+/*
354354 * Setting tcpporthogdefense to non-zero enables Dong Lin's
355355 * solution to hijacked systems staking out port's as a form
356356 * of DoS attack.
@@ -375,7 +375,7 @@ void tcprcvwin(Conv*); · 18 unmodified lines
375375 void tcpacktimer(void*);
376376 void tcpkeepalive(void*);
377377 void tcpsetkacounter(Tcpctl*);
378−void tcprxmit(Conv*);
378+void tcprxmit(Conv*);
379379 void tcpsettimer(Tcpctl*);
380380 void tcpsynackrtt(Conv*);
381381 void tcpsetscale(Conv*, Tcpctl*, ushort, ushort);
@@ -711,7 +711,7 @@ backoff(int n) · 329 unmodified lines
711711 }
712712
713713 void
714−localclose(Conv *s, char *reason) /* called with tcb locked */
714+localclose(Conv *s, char *reason) /* called with tcb locked */
715715 {
716716 Tcpctl *tcb;
717717 Reseq *rp,*rp1;
@@ -1804,8 +1804,8 @@ update(Conv *s, Tcp *seg) · 1086 unmodified lines
18041804 /*
18051805 * update window
18061806 */
1807− if( seq_gt(seg->ack, tcb->snd.wl2)
1808− || (tcb->snd.wl2 == seg->ack && seg->wnd > tcb->snd.wnd)){
1807+ if(seq_gt(seg->ack, tcb->snd.wl2)
1808+ || (tcb->snd.wl2 == seg->ack && seg->wnd > tcb->snd.wnd)){
18091809 tcb->snd.wnd = seg->wnd;
18101810 tcb->snd.wl2 = seg->ack;
18111811 }
@@ -1821,9 +1821,9 @@ update(Conv *s, Tcp *seg) · 9 unmodified lines
18211821 return;
18221822 }
18231823
1824− /*
1824+ /*
18251825 * any positive ack turns off fast rxt,
1826− * (should we do new-reno on partial acks?)
1826+ * (should we do new-reno on partial acks?)
18271827 */
18281828 if(!tcb->snd.recovery || seq_ge(seg->ack, tcb->snd.rxt)) {
18291829 tcb->snd.dupacks = 0;
@@ -1925,7 +1925,7 @@ tcpiput(Proto *tcp, Ipifc*, Block *bp) · 95 unmodified lines
19251925
19261926 f = tcp->f;
19271927 tpriv = tcp->priv;
1928−
1928+
19291929 tpriv->stats[InSegs]++;
19301930
19311931 h4 = (Tcp4hdr*)(bp->rp);
@@ -1939,7 +1939,7 @@ tcpiput(Proto *tcp, Ipifc*, Block *bp) · 7 unmodified lines
19391939
19401940 h4->Unused = 0;
19411941 hnputs(h4->tcplen, length-TCP4_PKT);
1942− if(!(bp->flag & Btcpck) && (h4->tcpcksum[0] || h4->tcpcksum[1]) &&
1942+ if(!(bp->flag & Btcpck) && (h4->tcpcksum[0] || h4->tcpcksum[1]) &&
19431943 ptclcsum(bp, TCP4_IPLEN, length-TCP4_IPLEN)) {
19441944 tpriv->stats[CsumErrs]++;
19451945 tpriv->stats[InErrs]++;
@@ -1978,7 +1978,7 @@ tcpiput(Proto *tcp, Ipifc*, Block *bp) · 32 unmodified lines
19781978 h6->ploadlen[0] = h6->ploadlen[1] = h6->proto = 0;
19791979 h6->ttl = proto;
19801980 hnputl(h6->vcf, length);
1981− if((h6->tcpcksum[0] || h6->tcpcksum[1]) &&
1981+ if((h6->tcpcksum[0] || h6->tcpcksum[1]) &&
19821982 ptclcsum(bp, TCP6_IPLEN, length+TCP6_PHDRSIZE)) {
19831983 tpriv->stats[CsumErrs]++;
19841984 tpriv->stats[InErrs]++;
@@ -2277,7 +2277,7 @@ reset: · 292 unmodified lines
22772277 qpassnolim(s->rq, bp);
22782278 bp = nil;
22792279
2280− /*
2280+ /*
22812281 * Force an ack every 2 data messages. This is
22822282 * a hack for rob to make his home system run
22832283 * faster.
@@ -2412,20 +2412,20 @@ tcpoutput(Conv *s) · 128 unmodified lines
24122412
24132413 for(msgs = 0; msgs < 100; msgs++) {
24142414 tcb = (Tcpctl*)s->ptcl;
2415−
2415+
24162416 switch(tcb->state) {
24172417 case Listen:
24182418 case Closed:
24192419 case Finwait2:
24202420 return;
24212421 }
2422−
2422+
24232423 /* force an ack when a window has opened up */
24242424 if(tcb->rcv.blocked && tcb->rcv.wnd > 0){
24252425 tcb->rcv.blocked = 0;
24262426 tcb->flags |= FORCE;
24272427 }
2428−
2428+
24292429 sndcnt = qlen(s->wq)+tcb->flgcnt;
24302430 sent = tcb->snd.ptr - tcb->snd.una;
24312431
@@ -2841,8 +2841,7 @@ int · 409 unmodified lines
28412841 addreseq(Tcpctl *tcb, Tcppriv *tpriv, Tcp *seg, Block *bp, ushort length)
28422842 {
28432843 Reseq *rp, *rp1;
2844− int i;
2845− static int once;
2844+ int i, rqlen, qmax;
28462845
28472846 rp = malloc(sizeof(Reseq));
28482847 if(rp == nil){
@@ -2864,9 +2863,9 @@ addreseq(Tcpctl *tcb, Tcppriv *tpriv, Tcp *seg, Block *bp, ushort length) · 15 unmodified lines
28642863 return 0;
28652864 }
28662865
2867− length = 0;
2866+ rqlen = 0;
28682867 for(i = 0;; i++) {
2869− length += rp1->length;
2868+ rqlen += rp1->length;
28702869 if(rp1->next == nil || seq_lt(seg->seq, rp1->next->seg.seq)) {
28712870 rp->next = rp1->next;
28722871 rp1->next = rp;
@@ -2876,12 +2875,29 @@ addreseq(Tcpctl *tcb, Tcppriv *tpriv, Tcp *seg, Block *bp, ushort length) · 3 unmodified lines
28762875 }
28772876 rp1 = rp1->next;
28782877 }
2879− if(length > QMAX && once++ == 0){
2880− print("very long tcp resequence queue: %d\n", length);
2881− for(rp1 = tcb->reseq, i = 0; i < 10 && rp1 != nil; rp1 = rp1->next, i++)
2882− print("0x%lux 0x%lux 0x%ux\n", rp1->seg.seq, rp1->seg.ack,
2883− rp1->seg.flags);
2884− return -1;
2878+ qmax = QMAX<<tcb->rcv.scale;
2879+ if(rqlen > qmax){
2880+ print("resequence queue > window: %d > %d\n", rqlen, qmax);
2881+ i = 0;
2882+ for(rp1 = tcb->reseq; rp1 != nil; rp1 = rp1->next){
2883+ print("%#lux %#lux %#ux\n", rp1->seg.seq,
2884+ rp1->seg.ack, rp1->seg.flags);
2885+ if(i++ > 10){
2886+ print("...\n");
2887+ break;
2888+ }
2889+ }
2890+
2891+ // delete entire reassembly queue; wait for retransmit.
2892+ // - should we be smarter and only delete the tail?
2893+ for(rp = tcb->reseq; rp != nil; rp = rp1){
2894+ rp1 = rp->next;
2895+ freeblist(rp->bp);
2896+ free(rp);
2897+ }
2898+ tcb->reseq = nil;
2899+
2900+ return -1;
28852901 }
28862902 return 0;
28872903 }
@@ -2994,7 +3010,7 @@ tcpadvise(Proto *tcp, Block *bp, char *msg) · 106 unmodified lines
29943010 v4tov6(source, h4->tcpsrc);
29953011 psource = nhgets(h4->tcpsport);
29963012 pdest = nhgets(h4->tcpdport);
2997− }
3013+ }
29983014 else {
29993015 ipmove(dest, h6->tcpdst);
30003016 ipmove(source, h6->tcpsrc);
@@ -3122,7 +3138,7 @@ tcpsettimer(Tcpctl *tcb) · 121 unmodified lines
31223138
31233139 /* round trip dependency */
31243140 x = backoff(tcb->backoff) *
3125− (tcb->mdev + (tcb->srtt>>LOGAGAIN) + MSPTICK) / MSPTICK;
3141+ (tcb->mdev + (tcb->srtt>>LOGAGAIN) + MSPTICK) / MSPTICK;
31263142
31273143 /* bounded twixt 1/2 and 64 seconds */
31283144 if(x < 500/MSPTICK)
os/pc/ether2000.c+4−2
@@ -132,7 +132,6 @@ ne2000pnp(Ether* edev) · 131 unmodified lines
132132 static int
133133 ne2000reset(Ether* edev)
134134 {
135− static int first;
136135 ushort buf[16];
137136 ulong port;
138137 Dp8390 *dp8390;
@@ -198,11 +197,14 @@ ne2000reset(Ether* edev) · 59 unmodified lines
198197 * initialisation has been tried, but that wouldn't be
199198 * enough, there are other ethernet boards which could
200199 * match.
200+ * Parallels has buf[0x0E] == 0x00 whereas real hardware
201+ * usually has 0x57.
201202 */
202203 dp8390reset(edev);
203204 memset(buf, 0, sizeof(buf));
204205 dp8390read(dp8390, buf, 0, sizeof(buf));
205− if((buf[0x0E] & 0xFF) != 0x57 || (buf[0x0F] & 0xFF) != 0x57){
206+ i = buf[0x0E] & 0xFF;
207+ if((i != 0x00 && i != 0x57) || (buf[0x0F] & 0xFF) != 0x57){
206208 iofree(edev->port);
207209 free(edev->ctlr);
208210 return -1;
os/pc/ether2114x.c+6−4
@@ -190,6 +190,7 @@ enum { /* Variants */ · 189 unmodified lines
190190 Pnic = (0x0002<<16)|0x11AD,
191191 Pnic2 = (0xC115<<16)|0x11AD,
192192 CentaurP = (0x0985<<16)|0x1317,
193+ CentaurPcb = (0x1985<<16)|0x1317,
193194 };
194195
195196 typedef struct Ctlr Ctlr;
@@ -1515,7 +1516,7 @@ srom(Ctlr* ctlr) · 1319 unmodified lines
15151516 ctlr->srom[20+i+1] = ctlr->srom[i];
15161517 }
15171518 }
1518− if(ctlr->id == CentaurP){
1519+ if(ctlr->id == CentaurP || ctlr->id == CentaurPcb){
15191520 memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic));
15201521 for(i = 0; i < Eaddrlen; i += 2){
15211522 ctlr->srom[20+i] = ctlr->srom[8+i];
@@ -1603,7 +1604,7 @@ srom(Ctlr* ctlr) · 81 unmodified lines
16031604 if(phy){
16041605 x = 0;
16051606 for(k = 0; k < nelem(ctlr->phy); k++){
1606− if(ctlr->id == CentaurP && k != 1)
1607+ if((ctlr->id == CentaurP || ctlr->id == CentaurPcb) && k != 1)
16071608 continue;
16081609 if((oui = miir(ctlr, k, 2)) == -1 || oui == 0)
16091610 continue;
@@ -1655,6 +1656,7 @@ dec2114xpci(void) · 45 unmodified lines
16551656 case Pnic: /* PNIC */
16561657 case Pnic2: /* PNIC-II */
16571658 case CentaurP: /* ADMtek */
1659+ case CentaurPcb: /* ADMtek CardBus */
16581660 break;
16591661 }
16601662
@@ -1690,7 +1692,6 @@ dec2114xpci(void) · 29 unmodified lines
16901692 switch(ctlr->id){
16911693 default:
16921694 break;
1693−
16941695 case Pnic: /* PNIC */
16951696 /*
16961697 * Turn off the jabber timer.
@@ -1698,6 +1699,7 @@ dec2114xpci(void) · 1 unmodified line
16981699 csr32w(ctlr, 15, 0x00000001);
16991700 break;
17001701 case CentaurP:
1702+ case CentaurPcb:
17011703 /*
17021704 * Nice - the register offsets change from *8 to *4
17031705 * for CSR16 and up...
@@ -1823,6 +1825,6 @@ reset(Ether* ether) · 119 unmodified lines
18231825 void
18241826 ether2114xlink(void)
18251827 {
1826− addethercard("21140", reset);
18271828 addethercard("2114x", reset);
1829+ addethercard("21140", reset);
18281830 }
os/pc/ether79c970.c+8−3
@@ -300,6 +300,12 @@ promiscuous(void* arg, int on) · 299 unmodified lines
300300 iunlock(ctlr);
301301 }
302302
303+static void
304+multicast(void* arg, uchar*, int)
305+{
306+ promiscuous(arg, 1);
307+}
308+
303309 static void
304310 txstart(Ether* ether)
305311 {
@@ -522,7 +528,6 @@ reset(Ether* ether) · 216 unmodified lines
522528 ctlr->iow = io32w;
523529 }else{
524530 print("#l%d: card doesn't talk right\n", ether->ctlrno);
525−iprint("#l%d: card doesn't talk right\n", ether->ctlrno);
526531 iunlock(ctlr);
527532 return -1;
528533 }
@@ -539,8 +544,6 @@ iprint("#l%d: card doesn't talk right\n", ether->ctlrno); · 10 unmodified lines
539544 default:
540545 print("#l%d: unknown PCnet card version %.7ux\n",
541546 ether->ctlrno, x&0xFFFFFFF);
542−iprint("#l%d: unknown PCnet card version %.7ux\n",
543− ether->ctlrno, x&0xFFFFFFF);
544547 iunlock(ctlr);
545548 return -1;
546549 }
@@ -629,6 +632,8 @@ iprint("#l%d: unknown PCnet card version %.7ux\n", · 82 unmodified lines
629632
630633 ether->arg = ether;
631634 ether->promiscuous = promiscuous;
635+ ether->multicast = multicast;
636+// ether->shutdown = shutdown;
632637
633638 return 0;
634639 }
os/pc/ether8139.c+11−1
@@ -234,6 +234,12 @@ rtl8139promiscuous(void* arg, int on) · 233 unmodified lines
234234 iunlock(&ctlr->ilock);
235235 }
236236
237+static void
238+rtl8139multicast(void* arg, uchar*, int)
239+{
240+ rtl8139promiscuous(arg, 1);
241+}
242+
237243 static long
238244 rtl8139ifstat(Ether* edev, void* a, long n, ulong offset)
239245 {
@@ -637,8 +643,10 @@ rtl8139match(Ether* edev, int id) · 397 unmodified lines
637643 }
638644
639645 ctlr->port = port;
640− if(rtl8139reset(ctlr))
646+ if(rtl8139reset(ctlr)) {
647+ iofree(port);
641648 continue;
649+ }
642650 pcisetbme(p);
643651
644652 ctlr->active = 1;
@@ -738,6 +746,8 @@ rtl8139pnp(Ether* edev) · 93 unmodified lines
738746
739747 edev->arg = edev;
740748 edev->promiscuous = rtl8139promiscuous;
749+ edev->multicast = rtl8139multicast;
750+// edev->shutdown = rtl8139shutdown;
741751
742752 /*
743753 * This should be much more dynamic but will do for now.
os/pc/ether82543gc.c+6−6
@@ -1243,7 +1243,8 @@ gc82543watchdog(void* arg) · 1242 unmodified lines
12431243 static void
12441244 gc82543pci(void)
12451245 {
1246− int port, cls;
1246+ int cls;
1247+ void *mem;
12471248 Pcidev *p;
12481249 Ctlr *ctlr;
12491250
@@ -1262,8 +1263,8 @@ gc82543pci(void) · 12 unmodified lines
12621263 break;
12631264 }
12641265
1265− port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
1266− if(port == 0){
1266+ mem = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
1267+ if(mem == 0){
12671268 print("gc82543: can't map %8.8luX\n", p->mem[0].bar);
12681269 continue;
12691270 }
@@ -1280,11 +1281,10 @@ gc82543pci(void) · 10 unmodified lines
12801281 cls*4);
12811282 }
12821283 ctlr = malloc(sizeof(Ctlr));
1283− ctlr->port = port;
1284+ ctlr->port = p->mem[0].bar & ~0x0F;
12841285 ctlr->pcidev = p;
12851286 ctlr->id = (p->did<<16)|p->vid;
1286−
1287− ctlr->nic = KADDR(ctlr->port);
1287+ ctlr->nic = mem;
12881288
12891289 if(gc82543reset(ctlr)){
12901290 free(ctlr);
os/pc/ether82557.c+14−12
@@ -290,7 +290,7 @@ command(Ctlr* ctlr, int c, int v) · 289 unmodified lines
290290 if(timeo >= 100){
291291 ctlr->command = -1;
292292 iunlock(&ctlr->rlock);
293− iprint("i82557: command 0x%uX %uX timeout\n", c, v);
293+ iprint("i82557: command %#ux %#ux timeout\n", c, v);
294294 return;
295295 }
296296
@@ -462,7 +462,7 @@ ifstat(Ether* ether, void* a, long n, ulong offset) · 165 unmodified lines
462462 for(i = 0; i < (1<<ctlr->eepromsz); i++){
463463 if(i && ((i & 0x07) == 0))
464464 len += snprint(p+len, READSTR-len, "\n ");
465− len += snprint(p+len, READSTR-len, " %4.4uX", ctlr->eeprom[i]);
465+ len += snprint(p+len, READSTR-len, " %4.4ux", ctlr->eeprom[i]);
466466 }
467467
468468 if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000)){
@@ -471,7 +471,7 @@ ifstat(Ether* ether, void* a, long n, ulong offset) · 2 unmodified lines
471471 for(i = 0; i < 6; i++){
472472 static int miir(Ctlr*, int, int);
473473
474− len += snprint(p+len, READSTR-len, " %4.4uX",
474+ len += snprint(p+len, READSTR-len, " %4.4ux",
475475 miir(ctlr, phyaddr, i));
476476 }
477477 }
@@ -523,7 +523,7 @@ txstart(Ether* ether) · 45 unmodified lines
523523 ctlr->action = 0;
524524 }
525525 else{
526− print("#l%d: action 0x%uX\n", ether->ctlrno, ctlr->action);
526+ print("#l%d: action %#ux\n", ether->ctlrno, ctlr->action);
527527 ctlr->action = 0;
528528 break;
529529 }
@@ -630,14 +630,14 @@ receive(Ether* ether) · 100 unmodified lines
630630 pbp = nil;
631631 count = rfd->count & 0x3FFF;
632632 if((count < ETHERMAXTU/4) && (pbp = iallocb(count))){
633− memmove(pbp->rp, bp->rp+sizeof(Rfd)-sizeof(rfd->data), count);
633+ memmove(pbp->rp, bp->rp+offsetof(Rfd, data[0]), count);
634634 pbp->wp = pbp->rp + count;
635635
636636 rfd->count = 0;
637637 rfd->field = 0;
638638 }
639639 else if(xbp = rfdalloc(rfd->link)){
640− bp->rp += sizeof(Rfd)-sizeof(rfd->data);
640+ bp->rp += offsetof(Rfd, data[0]);
641641 bp->wp = bp->rp + count;
642642
643643 xbp->next = bp->next;
@@ -748,7 +748,7 @@ interrupt(Ureg*, void* arg) · 104 unmodified lines
748748 }
749749
750750 if(status & (StatCX|StatFR|StatCNA|StatRNR|StatMDI|StatSWI))
751− panic("#l%d: status %uX\n", ether->ctlrno, status);
751+ panic("#l%d: status %#ux\n", ether->ctlrno, status);
752752 }
753753 }
754754
@@ -926,14 +926,16 @@ i82557pci(void) · 171 unmodified lines
926926 continue;
927927 case 0x1031: /* Intel 82562EM */
928928 case 0x1050: /* Intel 82562EZ */
929+ case 0x1039: /* Intel 82801BD PRO/100 VE */
930+ case 0x103A: /* Intel 82562 PRO/100 VE */
931+ case 0x103D: /* Intel 82562 PRO/100 VE */
932+ case 0x1064: /* Intel 82562 PRO/100 VE */
929933 case 0x2449: /* Intel 82562ET */
930934 nop = 1;
931935 /*FALLTHROUGH*/
932936 case 0x1209: /* Intel 82559ER */
933937 case 0x1229: /* Intel 8255[789] */
934938 case 0x1030: /* Intel 82559 InBusiness 10/100 */
935− case 0x1039: /* Intel 82801BD PRO/100 VE */
936− case 0x103A: /* Intel 82562 PRO/100 VE */
937939 break;
938940 }
939941
@@ -955,7 +957,7 @@ i82557pci(void) · 15 unmodified lines
955957 */
956958 port = p->mem[1].bar & ~0x01;
957959 if(ioalloc(port, p->mem[1].size, 0, "i82557") < 0){
958− print("i82557: port 0x%uX in use\n", port);
960+ print("i82557: port %#ux in use\n", port);
959961 continue;
960962 }
961963
@@ -997,7 +999,7 @@ scanphy(Ctlr* ctlr) · 35 unmodified lines
997999 oui <<= 6;
9981000 x = miir(ctlr, i, 3);
9991001 oui |= x>>10;
1000− //print("phy%d: oui %uX reg1 %uX\n", i, oui, miir(ctlr, i, 1));
1002+ //print("phy%d: oui %#ux reg1 %#ux\n", i, oui, miir(ctlr, i, 1));
10011003
10021004 ctlr->eeprom[6] = i;
10031005 if(oui == 0xAA00)
@@ -1093,7 +1095,7 @@ reset(Ether* ether) · 89 unmodified lines
10931095 sum += x;
10941096 }
10951097 if(sum != 0xBABA)
1096− print("#l%d: EEPROM checksum - 0x%4.4uX\n", ether->ctlrno, sum);
1098+ print("#l%d: EEPROM checksum - %#4.4ux\n", ether->ctlrno, sum);
10971099
10981100 /*
10991101 * Eeprom[6] indicates whether there is a PHY and whether
os/pc/ether83815.c+147−22
@@ -79,9 +79,22 @@ enum { /* cmdsts */ · 78 unmodified lines
7979 Col = 1<<16, /* collision during receive */
8080 };
8181
82−enum { /* Variants */
82+enum { /* PCI vendor & device IDs */
8383 Nat83815 = (0x0020<<16)|0x100B,
84− Sis900 = (0x0630<<16)|0x1039, /* untested */
84+ SiS = 0x1039,
85+ SiS900 = (0x0900<<16)|SiS,
86+ SiS7016 = (0x7016<<16)|SiS,
87+
88+ SiS630bridge = 0x0008,
89+
90+ /* SiS 900 PCI revision codes */
91+ SiSrev630s = 0x81,
92+ SiSrev630e = 0x82,
93+ SiSrev630ea1 = 0x83,
94+
95+ SiSeenodeaddr = 8, /* short addr of SiS eeprom mac addr */
96+ SiS630eenodeaddr = 9, /* likewise for the 630 */
97+ Nseenodeaddr = 6, /* " for NS eeprom */
8598 };
8699
87100 typedef struct Ctlr Ctlr;
@@ -456,9 +469,9 @@ txrxcfg(Ctlr *ctlr, int txdrth) · 368 unmodified lines
456469 static void
457470 interrupt(Ureg*, void* arg)
458471 {
472+ int len, status, cmdsts, n;
459473 Ctlr *ctlr;
460474 Ether *ether;
461− int len, status, cmdsts;
462475 Des *des;
463476 Block *bp;
464477
@@ -483,6 +496,15 @@ interrupt(Ureg*, void* arg) · 18 unmodified lines
483496 status &= ~(Hiberr|Txrcmp|Rxrcmp|Rxsovr|Dperr|Sserr|Rmabt|Rtabt);
484497 }
485498
499+ /* update link state */
500+ if(status&Phy){
501+ status &= ~Phy;
502+ csr32r(ctlr, Rcfg);
503+ n = csr32r(ctlr, Rcfg);
504+// iprint("83815 phy %x %x\n", n, n&Lnksts);
505+ ether->link = (n&Lnksts) != 0;
506+ }
507+
486508 /*
487509 * Received packets.
488510 */
@@ -511,11 +533,19 @@ interrupt(Ureg*, void* arg) · 22 unmodified lines
511533 }
512534 else if(bp = iallocb(Rbsz)){
513535 len = (cmdsts&Size)-4;
514− des->bp->wp = des->bp->rp+len;
515− etheriq(ether, des->bp, 1);
536+ if(len <= 0){
537+ debug("ns83815: packet len %d <=0\n", len);
538+ freeb(des->bp);
539+ }else{
540+ des->bp->wp = des->bp->rp+len;
541+ etheriq(ether, des->bp, 1);
542+ }
516543 des->bp = bp;
517544 des->addr = PADDR(bp->rp);
518545 coherence();
546+ }else{
547+ debug("ns83815: interrupt: iallocb for input buffer failed\n");
548+ des->bp->next = 0;
519549 }
520550
521551 des->cmdsts = Rbsz;
@@ -607,7 +637,7 @@ ctlrinit(Ether* ether) · 85 unmodified lines
607637 last = nil;
608638 for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
609639 des->bp = iallocb(Rbsz);
610− if (des->bp == nil)
640+ if(des->bp == nil)
611641 error(Enomem);
612642 des->cmdsts = Rbsz;
613643 des->addr = PADDR(des->bp->rp);
@@ -635,8 +665,10 @@ ctlrinit(Ether* ether) · 21 unmodified lines
635665
636666 txrxcfg(ctlr, Drth512);
637667
638− csr32w(ctlr, Rimr, Dperr|Sserr|Rmabt|Rtabt|Rxsovr|Hiberr|Txurn|Txerr|Txdesc|Txok|Rxorn|Rxerr|Rxdesc|Rxok); /* Phy|Pme|Mib */
639− csr32r(ctlr, Risr); /* clear status */
668+ csr32w(ctlr, Rimr, Dperr|Sserr|Rmabt|Rtabt|Rxsovr|Hiberr|Txurn|Txerr|
669+ Txdesc|Txok|Rxorn|Rxerr|Rxdesc|Rxok); /* Phy|Pme|Mib */
670+ csr32w(ctlr, Rmicr, Inten); /* enable phy interrupts */
671+ csr32r(ctlr, Risr); /* clear status */
640672 csr32w(ctlr, Rier, Ie);
641673 }
642674
@@ -762,7 +794,7 @@ softreset(Ctlr* ctlr, int resetphys) · 119 unmodified lines
762794 if(csr16r(ctlr, Ranar) == 0 || (csr32r(ctlr, Rcfg) & Aneg_dn) == 0){
763795 csr16w(ctlr, Rbmcr, Anena|Anrestart);
764796 for(i=0;; i++){
765− if(i > 6000){
797+ if(i > 3000){
766798 print("ns83815: auto neg timed out\n");
767799 break;
768800 }
@@ -791,11 +823,8 @@ media(Ether* ether) · 22 unmodified lines
791823 ctlr = ether->ctlr;
792824 cfg = csr32r(ctlr, Rcfg);
793825 ctlr->fd = (cfg & Fdup) != 0;
794− if(cfg & Speed100)
795− return 100;
796− if((cfg & Lnksts) == 0)
797− return 100; /* no link: use 100 to ensure larger queues */
798− return 10;
826+ ether->link = (cfg&Lnksts) != 0;
827+ return (cfg&(Lnksts|Speed100)) == Lnksts? 10: 100;
799828 }
800829
801830 static char* mediatable[9] = {
@@ -810,8 +839,82 @@ static char* mediatable[9] = { · 8 unmodified lines
810839 "100BASE-FXFD",
811840 };
812841
842+static int
843+is630(ulong id, Pcidev *p)
844+{
845+ if(id == SiS900)
846+ switch (p->rid) {
847+ case SiSrev630s:
848+ case SiSrev630e:
849+ case SiSrev630ea1:
850+ return 1;
851+ }
852+ return 0;
853+}
854+
855+enum {
856+ MagicReg = 0x48,
857+ MagicRegSz = 1,
858+ Magicrden = 0x40, /* read enable, apparently */
859+ Paddr= 0x70, /* address port */
860+ Pdata= 0x71, /* data port */
861+};
862+
863+/* rcmos() originally from LANL's SiS 900 driver's rcmos() */
864+static int
865+sisrdcmos(Ctlr *ctlr)
866+{
867+ int i;
868+ unsigned reg;
869+ ulong port;
870+ Pcidev *p;
871+
872+ debug("ns83815: SiS 630 rev. %ux reading mac address from cmos\n", ctlr->pcidev->rid);
873+ p = pcimatch(nil, SiS, SiS630bridge);
874+ if(p == nil) {
875+ print("ns83815: no SiS 630 rev. %ux bridge for mac addr\n",
876+ ctlr->pcidev->rid);
877+ return 0;
878+ }
879+ port = p->mem[0].bar & ~0x01;
880+ debug("ns83815: SiS 630 rev. %ux reading mac addr from cmos via bridge at port 0x%lux\n", ctlr->pcidev->rid, port);
881+
882+ reg = pcicfgr8(p, MagicReg);
883+ pcicfgw8(p, MagicReg, reg|Magicrden);
884+
885+ for (i = 0; i < Eaddrlen; i++) {
886+ outb(port+Paddr, SiS630eenodeaddr + i);
887+ ctlr->sromea[i] = inb(port+Pdata);
888+ }
889+
890+ pcicfgw8(p, MagicReg, reg & ~Magicrden);
891+ return 1;
892+}
893+
894+/*
895+ * If this is a SiS 630E chipset with an embedded SiS 900 controller,
896+ * we have to read the MAC address from the APC CMOS RAM. - sez freebsd.
897+ * However, CMOS *is* NVRAM normally. See devrtc.c:440, memory.c:88.
898+ */
813899 static void
814−srom(Ctlr* ctlr)
900+sissrom(Ctlr *ctlr)
901+{
902+ union {
903+ uchar eaddr[Eaddrlen];
904+ ushort alignment;
905+ } ee;
906+ int i, off = SiSeenodeaddr, cnt = sizeof ee.eaddr / sizeof(short);
907+ ushort *shp = (ushort *)ee.eaddr;
908+
909+ if(!is630(ctlr->id, ctlr->pcidev) || !sisrdcmos(ctlr)) {
910+ for (i = 0; i < cnt; i++)
911+ *shp++ = eegetw(ctlr, off++);
912+ memmove(ctlr->sromea, ee.eaddr, sizeof ctlr->sromea);
913+ }
914+}
915+
916+static void
917+nssrom(Ctlr* ctlr)
815918 {
816919 int i, j;
817920
@@ -821,30 +924,50 @@ srom(Ctlr* ctlr) · 3 unmodified lines
821924 /*
822925 * the MAC address is reversed, straddling word boundaries
823926 */
824− memset(ctlr->sromea, 0, sizeof(ctlr->sromea));
825− j = 6*16 + 15;
927+ j = Nseenodeaddr*16 + 15;
826928 for(i=0; i<48; i++){
827929 ctlr->sromea[i>>3] |= ((ctlr->srom[j>>4] >> (15-(j&0xF))) & 1) << (i&7);
828930 j++;
829931 }
830932 }
831933
934+static void
935+srom(Ctlr* ctlr)
936+{
937+ memset(ctlr->sromea, 0, sizeof(ctlr->sromea));
938+ switch (ctlr->id) {
939+ case SiS900:
940+ case SiS7016:
941+ sissrom(ctlr);
942+ break;
943+ case Nat83815:
944+ nssrom(ctlr);
945+ break;
946+ default:
947+ print("ns83815: srom: unknown id 0x%ux\n", ctlr->id);
948+ break;
949+ }
950+}
951+
832952 static void
833953 scanpci83815(void)
834954 {
835955 Ctlr *ctlr;
836956 Pcidev *p;
957+ ulong id;
837958
838959 p = nil;
839960 while(p = pcimatch(p, 0, 0)){
840− if(p->ccrb != 0x02 || p->ccru != 0)
961+ if(p->ccrb != Pcibcnet || p->ccru != 0)
841962 continue;
842− switch((p->did<<16)|p->vid){
963+ id = (p->did<<16)|p->vid;
964+ switch(id){
843965 default:
844966 continue;
845967
846968 case Nat83815:
847− case Sis900:
969+ break;
970+ case SiS900:
848971 break;
849972 }
850973
@@ -855,7 +978,7 @@ scanpci83815(void) · 4 unmodified lines
855978 ctlr = malloc(sizeof(Ctlr));
856979 ctlr->port = p->mem[0].bar & ~0x01;
857980 ctlr->pcidev = p;
858− ctlr->id = (p->did<<16)|p->vid;
981+ ctlr->id = id;
859982
860983 if(ioalloc(ctlr->port, p->mem[0].size, 0, "ns83815") < 0){
861984 print("ns83815: port 0x%uX in use\n", ctlr->port);
@@ -885,6 +1008,7 @@ reset(Ether* ether) · 23 unmodified lines
8851008 {
8861009 Ctlr *ctlr;
8871010 int i, x;
1011+ ulong ctladdr;
8881012 uchar ea[Eaddrlen];
8891013 static int scandone;
8901014
@@ -923,7 +1047,8 @@ reset(Ether* ether) · 32 unmodified lines
9231047 memmove(ether->ea, ctlr->sromea, Eaddrlen);
9241048 for(i=0; i<Eaddrlen; i+=2){
9251049 x = ether->ea[i] | (ether->ea[i+1]<<8);
926− csr32w(ctlr, Rrfcr, i);
1050+ ctladdr = (ctlr->id == Nat83815? i: i<<15);
1051+ csr32w(ctlr, Rrfcr, ctladdr);
9271052 csr32w(ctlr, Rrfdr, x);
9281053 }
9291054 csr32w(ctlr, Rrfcr, Rfen|Apm|Aab|Aam);
os/pc/ether8390.c+3−3
@@ -400,7 +400,7 @@ receive(Ether* ether) · 399 unmodified lines
400400 */
401401 if(hdr.next < ctlr->pstart || hdr.next >= ctlr->pstop
402402 || len < 60 || len > sizeof(Etherpkt)){
403− print("dp8390: H#%2.2ux#%2.2ux#%2.2ux#%2.2ux,%lud\n",
403+ print("dp8390: H%2.2ux+%2.2ux+%2.2ux+%2.2ux,%lud\n",
404404 hdr.status, hdr.next, hdr.len0, hdr.len1, len);
405405 regw(ctlr, Cr, Page0|RdABORT|Stp);
406406 ringinit(ctlr);
@@ -588,7 +588,7 @@ interrupt(Ureg*, void* arg) · 181 unmodified lines
588588 if(isr & (Txe|Ptx)){
589589 r = regr(ctlr, Tsr);
590590 if((isr & Txe) && (r & (Cdh|Fu|Crs|Abt))){
591− print("dp8390: Tsr#%2.2ux|", r);
591+ print("dp8390: Tsr %#2.2ux", r);
592592 ether->oerrs++;
593593 }
594594
@@ -686,7 +686,7 @@ multicast(void* arg, uchar *addr, int on) · 91 unmodified lines
686686 if(reverse[1] == 0){
687687 for(i = 0; i < 64; i++)
688688 reverse[i] = ((i&1)<<5) | ((i&2)<<3) | ((i&4)<<1)
689− | ((i&8)>>1) | ((i&16)>>3) | ((i&32)>>5);
689+ | ((i&8)>>1) | ((i&16)>>3) | ((i&32)>>5);
690690 }
691691
692692 /*
os/pc/etherdp83820.c+1246−0
@@ -0,0 +1,1246 @@
1+/*
2+ * National Semiconductor DP83820
3+ * 10/100/1000 Mb/s Ethernet Network Interface Controller
4+ * (Gig-NIC).
5+ * Driver assumes little-endian and 32-bit host throughout.
6+ */
7+#include "u.h"
8+#include "../port/lib.h"
9+#include "mem.h"
10+#include "dat.h"
11+#include "fns.h"
12+#include "io.h"
13+#include "../port/error.h"
14+#include "../port/netif.h"
15+
16+#include "etherif.h"
17+#include "ethermii.h"
18+
19+enum { /* Registers */
20+ Cr = 0x00, /* Command */
21+ Cfg = 0x04, /* Configuration and Media Status */
22+ Mear = 0x08, /* MII/EEPROM Access */
23+ Ptscr = 0x0C, /* PCI Test Control */
24+ Isr = 0x10, /* Interrupt Status */
25+ Imr = 0x14, /* Interrupt Mask */
26+ Ier = 0x18, /* Interrupt Enable */
27+ Ihr = 0x1C, /* Interrupt Holdoff */
28+ Txdp = 0x20, /* Transmit Descriptor Pointer */
29+ Txdphi = 0x24, /* Transmit Descriptor Pointer Hi */
30+ Txcfg = 0x28, /* Transmit Configuration */
31+ Gpior = 0x2C, /* General Purpose I/O Control */
32+ Rxdp = 0x30, /* Receive Descriptor Pointer */
33+ Rxdphi = 0x34, /* Receive Descriptor Pointer Hi */
34+ Rxcfg = 0x38, /* Receive Configuration */
35+ Pqcr = 0x3C, /* Priority Queueing Control */
36+ Wcsr = 0x40, /* Wake on LAN Control/Status */
37+ Pcr = 0x44, /* Pause Control/Status */
38+ Rfcr = 0x48, /* Receive Filter/Match Control */
39+ Rfdr = 0x4C, /* Receive Filter/Match Data */
40+ Brar = 0x50, /* Boot ROM Address */
41+ Brdr = 0x54, /* Boot ROM Data */
42+ Srr = 0x58, /* Silicon Revision */
43+ Mibc = 0x5C, /* MIB Control */
44+ Mibd = 0x60, /* MIB Data */
45+ Txdp1 = 0xA0, /* Txdp Priority 1 */
46+ Txdp2 = 0xA4, /* Txdp Priority 2 */
47+ Txdp3 = 0xA8, /* Txdp Priority 3 */
48+ Rxdp1 = 0xB0, /* Rxdp Priority 1 */
49+ Rxdp2 = 0xB4, /* Rxdp Priority 2 */
50+ Rxdp3 = 0xB8, /* Rxdp Priority 3 */
51+ Vrcr = 0xBC, /* VLAN/IP Receive Control */
52+ Vtcr = 0xC0, /* VLAN/IP Transmit Control */
53+ Vdr = 0xC4, /* VLAN Data */
54+ Ccsr = 0xCC, /* Clockrun Control/Status */
55+ Tbicr = 0xE0, /* TBI Control */
56+ Tbisr = 0xE4, /* TBI Status */
57+ Tanar = 0xE8, /* TBI ANAR */
58+ Tanlpar = 0xEC, /* TBI ANLPAR */
59+ Taner = 0xF0, /* TBI ANER */
60+ Tesr = 0xF4, /* TBI ESR */
61+};
62+
63+enum { /* Cr */
64+ Txe = 0x00000001, /* Transmit Enable */
65+ Txd = 0x00000002, /* Transmit Disable */
66+ Rxe = 0x00000004, /* Receiver Enable */
67+ Rxd = 0x00000008, /* Receiver Disable */
68+ Txr = 0x00000010, /* Transmitter Reset */
69+ Rxr = 0x00000020, /* Receiver Reset */
70+ Swien = 0x00000080, /* Software Interrupt Enable */
71+ Rst = 0x00000100, /* Reset */
72+ TxpriSHFT = 9, /* Tx Priority Queue Select */
73+ TxpriMASK = 0x00001E00,
74+ RxpriSHFT = 13, /* Rx Priority Queue Select */
75+ RxpriMASK = 0x0001E000,
76+};
77+
78+enum { /* Configuration and Media Status */
79+ Bem = 0x00000001, /* Big Endian Mode */
80+ Ext125 = 0x00000002, /* External 125MHz reference Select */
81+ Bromdis = 0x00000004, /* Disable Boot ROM interface */
82+ Pesel = 0x00000008, /* Parity Error Detection Action */
83+ Exd = 0x00000010, /* Excessive Deferral Abort */
84+ Pow = 0x00000020, /* Program Out of Window Timer */
85+ Sb = 0x00000040, /* Single Back-off */
86+ Reqalg = 0x00000080, /* PCI Bus Request Algorithm */
87+ Extstsen = 0x00000100, /* Extended Status Enable */
88+ Phydis = 0x00000200, /* Disable PHY */
89+ Phyrst = 0x00000400, /* Reset PHY */
90+ M64addren = 0x00000800, /* Master 64-bit Addressing Enable */
91+ Data64en = 0x00001000, /* 64-bit Data Enable */
92+ Pci64det = 0x00002000, /* PCI 64-bit Bus Detected */
93+ T64addren = 0x00004000, /* Target 64-bit Addressing Enable */
94+ Mwidis = 0x00008000, /* MWI Disable */
95+ Mrmdis = 0x00010000, /* MRM Disable */
96+ Tmrtest = 0x00020000, /* Timer Test Mode */
97+ Spdstsien = 0x00040000, /* PHY Spdsts Interrupt Enable */
98+ Lnkstsien = 0x00080000, /* PHY Lnksts Interrupt Enable */
99+ Dupstsien = 0x00100000, /* PHY Dupsts Interrupt Enable */
100+ Mode1000 = 0x00400000, /* 1000Mb/s Mode Control */
101+ Tbien = 0x01000000, /* Ten-Bit Interface Enable */
102+ Dupsts = 0x10000000, /* Full Duplex Status */
103+ Spdsts100 = 0x20000000, /* SPEED100 Input Pin Status */
104+ Spdsts1000 = 0x40000000, /* SPEED1000 Input Pin Status */
105+ Lnksts = 0x80000000, /* Link Status */
106+};
107+
108+enum { /* MII/EEPROM Access */
109+ Eedi = 0x00000001, /* EEPROM Data In */
110+ Eedo = 0x00000002, /* EEPROM Data Out */
111+ Eeclk = 0x00000004, /* EEPROM Serial Clock */
112+ Eesel = 0x00000008, /* EEPROM Chip Select */
113+ Mdio = 0x00000010, /* MII Management Data */
114+ Mddir = 0x00000020, /* MII Management Direction */
115+ Mdc = 0x00000040, /* MII Management Clock */
116+};
117+
118+enum { /* Interrupts */
119+ Rxok = 0x00000001, /* Rx OK */
120+ Rxdesc = 0x00000002, /* Rx Descriptor */
121+ Rxerr = 0x00000004, /* Rx Packet Error */
122+ Rxearly = 0x00000008, /* Rx Early Threshold */
123+ Rxidle = 0x00000010, /* Rx Idle */
124+ Rxorn = 0x00000020, /* Rx Overrun */
125+ Txok = 0x00000040, /* Tx Packet OK */
126+ Txdesc = 0x00000080, /* Tx Descriptor */
127+ Txerr = 0x00000100, /* Tx Packet Error */
128+ Txidle = 0x00000200, /* Tx Idle */
129+ Txurn = 0x00000400, /* Tx Underrun */
130+ Mib = 0x00000800, /* MIB Service */
131+ Swi = 0x00001000, /* Software Interrupt */
132+ Pme = 0x00002000, /* Power Management Event */
133+ Phy = 0x00004000, /* PHY Interrupt */
134+ Hibint = 0x00008000, /* High Bits Interrupt Set */
135+ Rxsovr = 0x00010000, /* Rx Status FIFO Overrun */
136+ Rtabt = 0x00020000, /* Received Target Abort */
137+ Rmabt = 0x00040000, /* Received Master Abort */
138+ Sserr = 0x00080000, /* Signalled System Error */
139+ Dperr = 0x00100000, /* Detected Parity Error */
140+ Rxrcmp = 0x00200000, /* Receive Reset Complete */
141+ Txrcmp = 0x00400000, /* Transmit Reset Complete */
142+ Rxdesc0 = 0x00800000, /* Rx Descriptor for Priority Queue 0 */
143+ Rxdesc1 = 0x01000000, /* Rx Descriptor for Priority Queue 1 */
144+ Rxdesc2 = 0x02000000, /* Rx Descriptor for Priority Queue 2 */
145+ Rxdesc3 = 0x04000000, /* Rx Descriptor for Priority Queue 3 */
146+ Txdesc0 = 0x08000000, /* Tx Descriptor for Priority Queue 0 */
147+ Txdesc1 = 0x10000000, /* Tx Descriptor for Priority Queue 1 */
148+ Txdesc2 = 0x20000000, /* Tx Descriptor for Priority Queue 2 */
149+ Txdesc3 = 0x40000000, /* Tx Descriptor for Priority Queue 3 */
150+};
151+
152+enum { /* Interrupt Enable */
153+ Ien = 0x00000001, /* Interrupt Enable */
154+};
155+
156+enum { /* Interrupt Holdoff */
157+ IhSHFT = 0, /* Interrupt Holdoff */
158+ IhMASK = 0x000000FF,
159+ Ihctl = 0x00000100, /* Interrupt Holdoff Control */
160+};
161+
162+enum { /* Transmit Configuration */
163+ TxdrthSHFT = 0, /* Tx Drain Threshold */
164+ TxdrthMASK = 0x000000FF,
165+ FlthSHFT = 16, /* Tx Fill Threshold */
166+ FlthMASK = 0x0000FF00,
167+ Brstdis = 0x00080000, /* 1000Mb/s Burst Disable */
168+ MxdmaSHFT = 20, /* Max Size per Tx DMA Burst */
169+ MxdmaMASK = 0x00700000,
170+ Ecretryen = 0x00800000, /* Excessive Collision Retry Enable */
171+ Atp = 0x10000000, /* Automatic Transmit Padding */
172+ Mlb = 0x20000000, /* MAC Loopback */
173+ Hbi = 0x40000000, /* Heartbeat Ignore */
174+ Csi = 0x80000000, /* Carrier Sense Ignore */
175+};
176+
177+enum { /* Receive Configuration */
178+ RxdrthSHFT = 1, /* Rx Drain Threshold */
179+ RxdrthMASK = 0x0000003E,
180+ Airl = 0x04000000, /* Accept In-Range Length Errored */
181+ Alp = 0x08000000, /* Accept Long Packets */
182+ Rxfd = 0x10000000, /* Receive Full Duplex */
183+ Stripcrc = 0x20000000, /* Strip CRC */
184+ Arp = 0x40000000, /* Accept Runt Packets */
185+ Aep = 0x80000000, /* Accept Errored Packets */
186+};
187+
188+enum { /* Priority Queueing Control */
189+ Txpqen = 0x00000001, /* Transmit Priority Queuing Enable */
190+ Txfairen = 0x00000002, /* Transmit Fairness Enable */
191+ RxpqenSHFT = 2, /* Receive Priority Queue Enable */
192+ RxpqenMASK = 0x0000000C,
193+};
194+
195+enum { /* Pause Control/Status */
196+ PscntSHFT = 0, /* Pause Counter Value */
197+ PscntMASK = 0x0000FFFF,
198+ Pstx = 0x00020000, /* Transmit Pause Frame */
199+ PsffloSHFT = 18, /* Rx Data FIFO Lo Threshold */
200+ PsffloMASK = 0x000C0000,
201+ PsffhiSHFT = 20, /* Rx Data FIFO Hi Threshold */
202+ PsffhiMASK = 0x00300000,
203+ PsstloSHFT = 22, /* Rx Stat FIFO Hi Threshold */
204+ PsstloMASK = 0x00C00000,
205+ PssthiSHFT = 24, /* Rx Stat FIFO Hi Threshold */
206+ PssthiMASK = 0x03000000,
207+ Psrcvd = 0x08000000, /* Pause Frame Received */
208+ Psact = 0x10000000, /* Pause Active */
209+ Psda = 0x20000000, /* Pause on Destination Address */
210+ Psmcast = 0x40000000, /* Pause on Multicast */
211+ Psen = 0x80000000, /* Pause Enable */
212+};
213+
214+enum { /* Receive Filter/Match Control */
215+ RfaddrSHFT = 0, /* Extended Register Address */
216+ RfaddrMASK = 0x000003FF,
217+ Ulm = 0x00080000, /* U/L bit mask */
218+ Uhen = 0x00100000, /* Unicast Hash Enable */
219+ Mhen = 0x00200000, /* Multicast Hash Enable */
220+ Aarp = 0x00400000, /* Accept ARP Packets */
221+ ApatSHFT = 23, /* Accept on Pattern Match */
222+ ApatMASK = 0x07800000,
223+ Apm = 0x08000000, /* Accept on Perfect Match */
224+ Aau = 0x10000000, /* Accept All Unicast */
225+ Aam = 0x20000000, /* Accept All Multicast */
226+ Aab = 0x40000000, /* Accept All Broadcast */
227+ Rfen = 0x80000000, /* Rx Filter Enable */
228+};
229+
230+enum { /* Receive Filter/Match Data */
231+ RfdataSHFT = 0, /* Receive Filter Data */
232+ RfdataMASK = 0x0000FFFF,
233+ BmaskSHFT = 16, /* Byte Mask */
234+ BmaskMASK = 0x00030000,
235+};
236+
237+enum { /* MIB Control */
238+ Wrn = 0x00000001, /* Warning Test Indicator */
239+ Frz = 0x00000002, /* Freeze All Counters */
240+ Aclr = 0x00000004, /* Clear All Counters */
241+ Mibs = 0x00000008, /* MIB Counter Strobe */
242+};
243+
244+enum { /* MIB Data */
245+ Nmibd = 11, /* Number of MIB Data Registers */
246+};
247+
248+enum { /* VLAN/IP Receive Control */
249+ Vtden = 0x00000001, /* VLAN Tag Detection Enable */
250+ Vtren = 0x00000002, /* VLAN Tag Removal Enable */
251+ Dvtf = 0x00000004, /* Discard VLAN Tagged Frames */
252+ Dutf = 0x00000008, /* Discard Untagged Frames */
253+ Ipen = 0x00000010, /* IP Checksum Enable */
254+ Ripe = 0x00000020, /* Reject IP Checksum Errors */
255+ Rtcpe = 0x00000040, /* Reject TCP Checksum Errors */
256+ Rudpe = 0x00000080, /* Reject UDP Checksum Errors */
257+};
258+
259+enum { /* VLAN/IP Transmit Control */
260+ Vgti = 0x00000001, /* VLAN Global Tag Insertion */
261+ Vppti = 0x00000002, /* VLAN Per-Packet Tag Insertion */
262+ Gchk = 0x00000004, /* Global Checksum Generation */
263+ Ppchk = 0x00000008, /* Per-Packet Checksum Generation */
264+};
265+
266+enum { /* VLAN Data */
267+ VtypeSHFT = 0, /* VLAN Type Field */
268+ VtypeMASK = 0x0000FFFF,
269+ VtciSHFT = 16, /* VLAN Tag Control Information */
270+ VtciMASK = 0xFFFF0000,
271+};
272+
273+enum { /* Clockrun Control/Status */
274+ Clkrunen = 0x00000001, /* CLKRUN Enable */
275+ Pmeen = 0x00000100, /* PME Enable */
276+ Pmests = 0x00008000, /* PME Status */
277+};
278+
279+typedef struct {
280+ u32int link; /* Link to the next descriptor */
281+ u32int bufptr; /* pointer to data Buffer */
282+ int cmdsts; /* Command/Status */
283+ int extsts; /* optional Extended Status */
284+
285+ Block* bp; /* Block containing bufptr */
286+ u32int unused; /* pad to 64-bit */
287+} Desc;
288+
289+enum { /* Common cmdsts bits */
290+ SizeMASK = 0x0000FFFF, /* Descriptor Byte Count */
291+ SizeSHFT = 0,
292+ Ok = 0x08000000, /* Packet OK */
293+ Crc = 0x10000000, /* Suppress/Include CRC */
294+ Intr = 0x20000000, /* Interrupt on ownership transfer */
295+ More = 0x40000000, /* not last descriptor in a packet */
296+ Own = 0x80000000, /* Descriptor Ownership */
297+};
298+
299+enum { /* Transmit cmdsts bits */
300+ CcntMASK = 0x000F0000, /* Collision Count */
301+ CcntSHFT = 16,
302+ Ec = 0x00100000, /* Excessive Collisions */
303+ Owc = 0x00200000, /* Out of Window Collision */
304+ Ed = 0x00400000, /* Excessive Deferral */
305+ Td = 0x00800000, /* Transmit Deferred */
306+ Crs = 0x01000000, /* Carrier Sense Lost */
307+ Tfu = 0x02000000, /* Transmit FIFO Underrun */
308+ Txa = 0x04000000, /* Transmit Abort */
309+};
310+
311+enum { /* Receive cmdsts bits */
312+ Irl = 0x00010000, /* In-Range Length Error */
313+ Lbp = 0x00020000, /* Loopback Packet */
314+ Fae = 0x00040000, /* Frame Alignment Error */
315+ Crce = 0x00080000, /* CRC Error */
316+ Ise = 0x00100000, /* Invalid Symbol Error */
317+ Runt = 0x00200000, /* Runt Packet Received */
318+ Long = 0x00400000, /* Too Long Packet Received */
319+ DestMASK = 0x01800000, /* Destination Class */
320+ DestSHFT = 23,
321+ Rxo = 0x02000000, /* Receive Overrun */
322+ Rxa = 0x04000000, /* Receive Aborted */
323+};
324+
325+enum { /* extsts bits */
326+ EvtciMASK = 0x0000FFFF, /* VLAN Tag Control Information */
327+ EvtciSHFT = 0,
328+ Vpkt = 0x00010000, /* VLAN Packet */
329+ Ippkt = 0x00020000, /* IP Packet */
330+ Iperr = 0x00040000, /* IP Checksum Error */
331+ Tcppkt = 0x00080000, /* TCP Packet */
332+ Tcperr = 0x00100000, /* TCP Checksum Error */
333+ Udppkt = 0x00200000, /* UDP Packet */
334+ Udperr = 0x00400000, /* UDP Checksum Error */
335+};
336+
337+enum {
338+ Nrd = 256,
339+ Nrb = 4*Nrd,
340+ Rbsz = ROUNDUP(sizeof(Etherpkt)+8, 8),
341+ Ntd = 128,
342+};
343+
344+typedef struct Ctlr Ctlr;
345+typedef struct Ctlr {
346+ int port;
347+ Pcidev* pcidev;
348+ Ctlr* next;
349+ int active;
350+ int id;
351+
352+ int eepromsz; /* address size in bits */
353+ ushort* eeprom;
354+
355+ int* nic;
356+ int cfg;
357+ int imr;
358+
359+ QLock alock; /* attach */
360+ Lock ilock; /* init */
361+ void* alloc; /* base of per-Ctlr allocated data */
362+
363+ Mii* mii;
364+
365+ Lock rdlock; /* receive */
366+ Desc* rd;
367+ int nrd;
368+ int nrb;
369+ int rdx;
370+ int rxcfg;
371+
372+ Lock tlock; /* transmit */
373+ Desc* td;
374+ int ntd;
375+ int tdh;
376+ int tdt;
377+ int ntq;
378+ int txcfg;
379+
380+ int rxidle;
381+
382+ uint mibd[Nmibd];
383+
384+ int ec;
385+ int owc;
386+ int ed;
387+ int crs;
388+ int tfu;
389+ int txa;
390+} Ctlr;
391+
392+#define csr32r(c, r) (*((c)->nic+((r)/4)))
393+#define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v))
394+
395+static Ctlr* dp83820ctlrhead;
396+static Ctlr* dp83820ctlrtail;
397+
398+static Lock dp83820rblock; /* free receive Blocks */
399+static Block* dp83820rbpool;
400+
401+static char* dp83820mibs[Nmibd] = {
402+ "RXErroredPkts",
403+ "RXFCSErrors",
404+ "RXMsdPktErrors",
405+ "RXFAErrors",
406+ "RXSymbolErrors",
407+ "RXFrameToLong",
408+ "RXIRLErrors",
409+ "RXBadOpcodes",
410+ "RXPauseFrames",
411+ "TXPauseFrames",
412+ "TXSQEErrors",
413+};
414+
415+static int
416+mdior(Ctlr* ctlr, int n)
417+{
418+ int data, i, mear, r;
419+
420+ mear = csr32r(ctlr, Mear);
421+ r = ~(Mdc|Mddir) & mear;
422+ data = 0;
423+ for(i = n-1; i >= 0; i--){
424+ if(csr32r(ctlr, Mear) & Mdio)
425+ data |= (1<<i);
426+ csr32w(ctlr, Mear, Mdc|r);
427+ csr32w(ctlr, Mear, r);
428+ }
429+ csr32w(ctlr, Mear, mear);
430+
431+ return data;
432+}
433+
434+static void
435+mdiow(Ctlr* ctlr, int bits, int n)
436+{
437+ int i, mear, r;
438+
439+ mear = csr32r(ctlr, Mear);
440+ r = Mddir|(~Mdc & mear);
441+ for(i = n-1; i >= 0; i--){
442+ if(bits & (1<<i))
443+ r |= Mdio;
444+ else
445+ r &= ~Mdio;
446+ csr32w(ctlr, Mear, r);
447+ csr32w(ctlr, Mear, Mdc|r);
448+ }
449+ csr32w(ctlr, Mear, mear);
450+}
451+
452+static int
453+dp83820miimir(Mii* mii, int pa, int ra)
454+{
455+ int data;
456+ Ctlr *ctlr;
457+
458+ ctlr = mii->ctlr;
459+
460+ /*
461+ * MII Management Interface Read.
462+ *
463+ * Preamble;
464+ * ST+OP+PA+RA;
465+ * LT + 16 data bits.
466+ */
467+ mdiow(ctlr, 0xFFFFFFFF, 32);
468+ mdiow(ctlr, 0x1800|(pa<<5)|ra, 14);
469+ data = mdior(ctlr, 18);
470+
471+ if(data & 0x10000)
472+ return -1;
473+
474+ return data & 0xFFFF;
475+}
476+
477+static int
478+dp83820miimiw(Mii* mii, int pa, int ra, int data)
479+{
480+ Ctlr *ctlr;
481+
482+ ctlr = mii->ctlr;
483+
484+ /*
485+ * MII Management Interface Write.
486+ *
487+ * Preamble;
488+ * ST+OP+PA+RA+LT + 16 data bits;
489+ * Z.
490+ */
491+ mdiow(ctlr, 0xFFFFFFFF, 32);
492+ data &= 0xFFFF;
493+ data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16);
494+ mdiow(ctlr, data, 32);
495+
496+ return 0;
497+}
498+
499+static Block *
500+dp83820rballoc(Desc* desc)
501+{
502+ Block *bp;
503+
504+ if(desc->bp == nil){
505+ ilock(&dp83820rblock);
506+ if((bp = dp83820rbpool) == nil){
507+ iunlock(&dp83820rblock);
508+ desc->bp = nil;
509+ desc->cmdsts = Own;
510+ return nil;
511+ }
512+ dp83820rbpool = bp->next;
513+ bp->next = nil;
514+ iunlock(&dp83820rblock);
515+
516+ desc->bufptr = PCIWADDR(bp->rp);
517+ desc->bp = bp;
518+ }
519+ else{
520+ bp = desc->bp;
521+ bp->rp = bp->lim - Rbsz;
522+ bp->wp = bp->rp;
523+ }
524+
525+ coherence();
526+ desc->cmdsts = Intr|Rbsz;
527+
528+ return bp;
529+}
530+
531+static void
532+dp83820rbfree(Block *bp)
533+{
534+ bp->rp = bp->lim - Rbsz;
535+ bp->wp = bp->rp;
536+
537+ ilock(&dp83820rblock);
538+ bp->next = dp83820rbpool;
539+ dp83820rbpool = bp;
540+ iunlock(&dp83820rblock);
541+}
542+
543+static void
544+dp83820halt(Ctlr* ctlr)
545+{
546+ int i, timeo;
547+
548+ ilock(&ctlr->ilock);
549+ csr32w(ctlr, Imr, 0);
550+ csr32w(ctlr, Ier, 0);
551+ csr32w(ctlr, Cr, Rxd|Txd);
552+ for(timeo = 0; timeo < 1000; timeo++){
553+ if(!(csr32r(ctlr, Cr) & (Rxe|Txe)))
554+ break;
555+ microdelay(1);
556+ }
557+ csr32w(ctlr, Mibc, Frz);
558+ iunlock(&ctlr->ilock);
559+
560+ if(ctlr->rd != nil){
561+ for(i = 0; i < ctlr->nrd; i++){
562+ if(ctlr->rd[i].bp == nil)
563+ continue;
564+ freeb(ctlr->rd[i].bp);
565+ ctlr->rd[i].bp = nil;
566+ }
567+ }
568+ if(ctlr->td != nil){
569+ for(i = 0; i < ctlr->ntd; i++){
570+ if(ctlr->td[i].bp == nil)
571+ continue;
572+ freeb(ctlr->td[i].bp);
573+ ctlr->td[i].bp = nil;
574+ }
575+ }
576+}
577+
578+static void
579+dp83820cfg(Ctlr* ctlr)
580+{
581+ int cfg;
582+
583+ /*
584+ * Don't know how to deal with a TBI yet.
585+ */
586+ if(ctlr->mii == nil)
587+ return;
588+
589+ /*
590+ * The polarity of these bits is at the mercy
591+ * of the board designer.
592+ * The correct answer for all speed and duplex questions
593+ * should be to query the phy.
594+ */
595+ cfg = csr32r(ctlr, Cfg);
596+ if(!(cfg & Dupsts)){
597+ ctlr->rxcfg |= Rxfd;
598+ ctlr->txcfg |= Csi|Hbi;
599+ iprint("83820: full duplex, ");
600+ }
601+ else{
602+ ctlr->rxcfg &= ~Rxfd;
603+ ctlr->txcfg &= ~(Csi|Hbi);
604+ iprint("83820: half duplex, ");
605+ }
606+ csr32w(ctlr, Rxcfg, ctlr->rxcfg);
607+ csr32w(ctlr, Txcfg, ctlr->txcfg);
608+
609+ switch(cfg & (Spdsts1000|Spdsts100)){
610+ case Spdsts1000: /* 100Mbps */
611+ default: /* 10Mbps */
612+ ctlr->cfg &= ~Mode1000;
613+ if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000)
614+ iprint("100Mb/s\n");
615+ else
616+ iprint("10Mb/s\n");
617+ break;
618+ case Spdsts100: /* 1Gbps */
619+ ctlr->cfg |= Mode1000;
620+ iprint("1Gb/s\n");
621+ break;
622+ }
623+ csr32w(ctlr, Cfg, ctlr->cfg);
624+}
625+
626+static void
627+dp83820init(Ether* edev)
628+{
629+ int i;
630+ Ctlr *ctlr;
631+ Desc *desc;
632+ uchar *alloc;
633+
634+ ctlr = edev->ctlr;
635+
636+ dp83820halt(ctlr);
637+
638+ /*
639+ * Receiver
640+ */
641+ alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8);
642+ ctlr->rd = (Desc*)alloc;
643+ alloc += ctlr->nrd*sizeof(Desc);
644+ memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc));
645+ ctlr->rdx = 0;
646+ for(i = 0; i < ctlr->nrd; i++){
647+ desc = &ctlr->rd[i];
648+ desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]);
649+ if(dp83820rballoc(desc) == nil)
650+ continue;
651+ }
652+ csr32w(ctlr, Rxdphi, 0);
653+ csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd));
654+
655+ for(i = 0; i < Eaddrlen; i += 2){
656+ csr32w(ctlr, Rfcr, i);
657+ csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]);
658+ }
659+ csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm);
660+
661+ ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT);
662+ ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok;
663+
664+ /*
665+ * Transmitter.
666+ */
667+ ctlr->td = (Desc*)alloc;
668+ memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc));
669+ ctlr->tdh = ctlr->tdt = ctlr->ntq = 0;
670+ for(i = 0; i < ctlr->ntd; i++){
671+ desc = &ctlr->td[i];
672+ desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]);
673+ }
674+ csr32w(ctlr, Txdphi, 0);
675+ csr32w(ctlr, Txdp, PCIWADDR(ctlr->td));
676+
677+ ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT);
678+ ctlr->imr |= Txurn|Txidle|Txdesc|Txok;
679+
680+ ilock(&ctlr->ilock);
681+
682+ dp83820cfg(ctlr);
683+
684+ csr32w(ctlr, Mibc, Aclr);
685+ ctlr->imr |= Mib;
686+
687+ csr32w(ctlr, Imr, ctlr->imr);
688+
689+ /* try coalescing adjacent interrupts; use hold-off interval of 100µs */
690+ csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT));
691+
692+ csr32w(ctlr, Ier, Ien);
693+ csr32w(ctlr, Cr, Rxe|Txe);
694+
695+ iunlock(&ctlr->ilock);
696+}
697+
698+static void
699+dp83820attach(Ether* edev)
700+{
701+ Block *bp;
702+ Ctlr *ctlr;
703+
704+ ctlr = edev->ctlr;
705+ qlock(&ctlr->alock);
706+ if(ctlr->alloc != nil){
707+ qunlock(&ctlr->alock);
708+ return;
709+ }
710+
711+ if(waserror()){
712+ if(ctlr->mii != nil){
713+ free(ctlr->mii);
714+ ctlr->mii = nil;
715+ }
716+ if(ctlr->alloc != nil){
717+ free(ctlr->alloc);
718+ ctlr->alloc = nil;
719+ }
720+ qunlock(&ctlr->alock);
721+ nexterror();
722+ }
723+
724+ if(!(ctlr->cfg & Tbien)){
725+ if((ctlr->mii = malloc(sizeof(Mii))) == nil)
726+ error(Enomem);
727+ ctlr->mii->ctlr = ctlr;
728+ ctlr->mii->mir = dp83820miimir;
729+ ctlr->mii->miw = dp83820miimiw;
730+ if(mii(ctlr->mii, ~0) == 0)
731+ error("no PHY");
732+ ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien;
733+ ctlr->imr |= Phy;
734+ }
735+
736+ ctlr->nrd = Nrd;
737+ ctlr->nrb = Nrb;
738+ ctlr->ntd = Ntd;
739+ ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0);
740+ if(ctlr->alloc == nil)
741+ error(Enomem);
742+
743+ for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){
744+ if((bp = allocb(Rbsz)) == nil)
745+ break;
746+ bp->free = dp83820rbfree;
747+ dp83820rbfree(bp);
748+ }
749+
750+ dp83820init(edev);
751+
752+ qunlock(&ctlr->alock);
753+ poperror();
754+}
755+
756+static void
757+dp83820transmit(Ether* edev)
758+{
759+ Block *bp;
760+ Ctlr *ctlr;
761+ Desc *desc;
762+ int cmdsts, r, x;
763+
764+ ctlr = edev->ctlr;
765+
766+ ilock(&ctlr->tlock);
767+
768+ bp = nil;
769+ for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){
770+ desc = &ctlr->td[x];
771+ if((cmdsts = desc->cmdsts) & Own)
772+ break;
773+ if(!(cmdsts & Ok)){
774+ if(cmdsts & Ec)
775+ ctlr->ec++;
776+ if(cmdsts & Owc)
777+ ctlr->owc++;
778+ if(cmdsts & Ed)
779+ ctlr->ed++;
780+ if(cmdsts & Crs)
781+ ctlr->crs++;
782+ if(cmdsts & Tfu)
783+ ctlr->tfu++;
784+ if(cmdsts & Txa)
785+ ctlr->txa++;
786+ edev->oerrs++;
787+ }
788+ desc->bp->next = bp;
789+ bp = desc->bp;
790+ desc->bp = nil;
791+
792+ ctlr->ntq--;
793+ }
794+ ctlr->tdh = x;
795+ if(bp != nil)
796+ freeblist(bp);
797+
798+ x = ctlr->tdt;
799+ while(ctlr->ntq < (ctlr->ntd-1)){
800+ if((bp = qget(edev->oq)) == nil)
801+ break;
802+
803+ desc = &ctlr->td[x];
804+ desc->bufptr = PCIWADDR(bp->rp);
805+ desc->bp = bp;
806+ ctlr->ntq++;
807+ coherence();
808+ desc->cmdsts = Own|Intr|BLEN(bp);
809+
810+ x = NEXT(x, ctlr->ntd);
811+ }
812+ if(x != ctlr->tdt){
813+ ctlr->tdt = x;
814+ r = csr32r(ctlr, Cr);
815+ csr32w(ctlr, Cr, Txe|r);
816+ }
817+
818+ iunlock(&ctlr->tlock);
819+}
820+
821+static void
822+dp83820interrupt(Ureg*, void* arg)
823+{
824+ Block *bp;
825+ Ctlr *ctlr;
826+ Desc *desc;
827+ Ether *edev;
828+ int cmdsts, i, isr, r, x;
829+
830+ edev = arg;
831+ ctlr = edev->ctlr;
832+
833+ for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){
834+ if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){
835+ x = ctlr->rdx;
836+ desc = &ctlr->rd[x];
837+ while((cmdsts = desc->cmdsts) & Own){
838+ if((cmdsts & Ok) && desc->bp != nil){
839+ bp = desc->bp;
840+ desc->bp = nil;
841+ bp->wp += cmdsts & SizeMASK;
842+ etheriq(edev, bp, 1);
843+ }
844+ //else if(!(cmdsts & Ok)){
845+ // iprint("dp83820: rx %8.8uX:", cmdsts);
846+ // bp = desc->bp;
847+ // for(i = 0; i < 20; i++)
848+ // iprint(" %2.2uX", bp->rp[i]);
849+ // iprint("\n");
850+ //}
851+ dp83820rballoc(desc);
852+
853+ x = NEXT(x, ctlr->nrd);
854+ desc = &ctlr->rd[x];
855+ }
856+ ctlr->rdx = x;
857+
858+ if(isr & Rxidle){
859+ r = csr32r(ctlr, Cr);
860+ csr32w(ctlr, Cr, Rxe|r);
861+ ctlr->rxidle++;
862+ }
863+
864+ isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok);
865+ }
866+
867+ if(isr & Txurn){
868+ x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT;
869+ r = (ctlr->txcfg & FlthMASK)>>FlthSHFT;
870+ if(x < ((TxdrthMASK)>>TxdrthSHFT)
871+ && x < (2048/32 - r)){
872+ ctlr->txcfg &= ~TxdrthMASK;
873+ x++;
874+ ctlr->txcfg |= x<<TxdrthSHFT;
875+ csr32w(ctlr, Txcfg, ctlr->txcfg);
876+ }
877+ }
878+
879+ if(isr & (Txurn|Txidle|Txdesc|Txok)){
880+ dp83820transmit(edev);
881+ isr &= ~(Txurn|Txidle|Txdesc|Txok);
882+ }
883+
884+ if(isr & Mib){
885+ for(i = 0; i < Nmibd; i++){
886+ r = csr32r(ctlr, Mibd+(i*sizeof(int)));
887+ ctlr->mibd[i] += r & 0xFFFF;
888+ }
889+ isr &= ~Mib;
890+ }
891+
892+ if((isr & Phy) && ctlr->mii != nil){
893+ ctlr->mii->mir(ctlr->mii, 1, Bmsr);
894+ print("phy: cfg %8.8uX bmsr %4.4uX\n",
895+ csr32r(ctlr, Cfg),
896+ ctlr->mii->mir(ctlr->mii, 1, Bmsr));
897+ dp83820cfg(ctlr);
898+ isr &= ~Phy;
899+ }
900+ if(isr)
901+ iprint("dp83820: isr %8.8uX\n", isr);
902+ }
903+}
904+
905+static long
906+dp83820ifstat(Ether* edev, void* a, long n, ulong offset)
907+{
908+ char *p;
909+ Ctlr *ctlr;
910+ int i, l, r;
911+
912+ ctlr = edev->ctlr;
913+
914+ edev->crcs = ctlr->mibd[Mibd+(1*sizeof(int))];
915+ edev->frames = ctlr->mibd[Mibd+(3*sizeof(int))];
916+ edev->buffs = ctlr->mibd[Mibd+(5*sizeof(int))];
917+ edev->overflows = ctlr->mibd[Mibd+(2*sizeof(int))];
918+
919+ if(n == 0)
920+ return 0;
921+
922+ p = malloc(READSTR);
923+ l = 0;
924+ for(i = 0; i < Nmibd; i++){
925+ r = csr32r(ctlr, Mibd+(i*sizeof(int)));
926+ ctlr->mibd[i] += r & 0xFFFF;
927+ if(ctlr->mibd[i] != 0 && dp83820mibs[i] != nil)
928+ l += snprint(p+l, READSTR-l, "%s: %ud %ud\n",
929+ dp83820mibs[i], ctlr->mibd[i], r);
930+ }
931+ l += snprint(p+l, READSTR-l, "rxidle %d\n", ctlr->rxidle);
932+ l += snprint(p+l, READSTR-l, "ec %d\n", ctlr->ec);
933+ l += snprint(p+l, READSTR-l, "owc %d\n", ctlr->owc);
934+ l += snprint(p+l, READSTR-l, "ed %d\n", ctlr->ed);
935+ l += snprint(p+l, READSTR-l, "crs %d\n", ctlr->crs);
936+ l += snprint(p+l, READSTR-l, "tfu %d\n", ctlr->tfu);
937+ l += snprint(p+l, READSTR-l, "txa %d\n", ctlr->txa);
938+
939+ l += snprint(p+l, READSTR, "rom:");
940+ for(i = 0; i < 0x10; i++){
941+ if(i && ((i & 0x07) == 0))
942+ l += snprint(p+l, READSTR-l, "\n ");
943+ l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]);
944+ }
945+ l += snprint(p+l, READSTR-l, "\n");
946+
947+ if(ctlr->mii != nil && ctlr->mii->curphy != nil){
948+ l += snprint(p+l, READSTR, "phy:");
949+ for(i = 0; i < NMiiPhyr; i++){
950+ if(i && ((i & 0x07) == 0))
951+ l += snprint(p+l, READSTR-l, "\n ");
952+ r = miimir(ctlr->mii, i);
953+ l += snprint(p+l, READSTR-l, " %4.4uX", r);
954+ }
955+ snprint(p+l, READSTR-l, "\n");
956+ }
957+
958+ n = readstr(offset, a, n, p);
959+ free(p);
960+
961+ return n;
962+}
963+
964+static void
965+dp83820promiscuous(void* arg, int on)
966+{
967+ USED(arg, on);
968+}
969+
970+/* multicast already on, don't need to do anything */
971+static void
972+dp83820multicast(void*, uchar*, int)
973+{
974+}
975+
976+static int
977+dp83820detach(Ctlr* ctlr)
978+{
979+ /*
980+ * Soft reset the controller.
981+ */
982+ csr32w(ctlr, Cr, Rst);
983+ delay(1);
984+ while(csr32r(ctlr, Cr) & Rst)
985+ delay(1);
986+ return 0;
987+}
988+
989+static void
990+dp83820shutdown(Ether* ether)
991+{
992+print("dp83820shutdown\n");
993+ dp83820detach(ether->ctlr);
994+}
995+
996+static int
997+atc93c46r(Ctlr* ctlr, int address)
998+{
999+ int data, i, mear, r, size;
1000+
1001+ /*
1002+ * Analog Technology, Inc. ATC93C46
1003+ * or equivalent serial EEPROM.
1004+ */
1005+ mear = csr32r(ctlr, Mear);
1006+ mear &= ~(Eesel|Eeclk|Eedo|Eedi);
1007+ r = Eesel|mear;
1008+
1009+reread:
1010+ csr32w(ctlr, Mear, r);
1011+ data = 0x06;
1012+ for(i = 3-1; i >= 0; i--){
1013+ if(data & (1<<i))
1014+ r |= Eedi;
1015+ else
1016+ r &= ~Eedi;
1017+ csr32w(ctlr, Mear, r);
1018+ csr32w(ctlr, Mear, Eeclk|r);
1019+ microdelay(1);
1020+ csr32w(ctlr, Mear, r);
1021+ microdelay(1);
1022+ }
1023+
1024+ /*
1025+ * First time through must work out the EEPROM size.
1026+ */
1027+ if((size = ctlr->eepromsz) == 0)
1028+ size = 8;
1029+
1030+ for(size = size-1; size >= 0; size--){
1031+ if(address & (1<<size))
1032+ r |= Eedi;
1033+ else
1034+ r &= ~Eedi;
1035+ csr32w(ctlr, Mear, r);
1036+ microdelay(1);
1037+ csr32w(ctlr, Mear, Eeclk|r);
1038+ microdelay(1);
1039+ csr32w(ctlr, Mear, r);
1040+ microdelay(1);
1041+ if(!(csr32r(ctlr, Mear) & Eedo))
1042+ break;
1043+ }
1044+ r &= ~Eedi;
1045+
1046+ data = 0;
1047+ for(i = 16-1; i >= 0; i--){
1048+ csr32w(ctlr, Mear, Eeclk|r);
1049+ microdelay(1);
1050+ if(csr32r(ctlr, Mear) & Eedo)
1051+ data |= (1<<i);
1052+ csr32w(ctlr, Mear, r);
1053+ microdelay(1);
1054+ }
1055+
1056+ csr32w(ctlr, Mear, mear);
1057+
1058+ if(ctlr->eepromsz == 0){
1059+ ctlr->eepromsz = 8-size;
1060+ ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort));
1061+ goto reread;
1062+ }
1063+
1064+ return data;
1065+}
1066+
1067+static int
1068+dp83820reset(Ctlr* ctlr)
1069+{
1070+ int i, r;
1071+ unsigned char sum;
1072+
1073+ /*
1074+ * Soft reset the controller;
1075+ * read the EEPROM to get the initial settings
1076+ * of the Cfg and Gpior bits which should be cleared by
1077+ * the reset.
1078+ */
1079+ dp83820detach(ctlr);
1080+
1081+ atc93c46r(ctlr, 0);
1082+ if(ctlr->eeprom == nil) {
1083+ print("dp83820reset: no eeprom\n");
1084+ return -1;
1085+ }
1086+ sum = 0;
1087+ for(i = 0; i < 0x0E; i++){
1088+ r = atc93c46r(ctlr, i);
1089+ ctlr->eeprom[i] = r;
1090+ sum += r;
1091+ sum += r>>8;
1092+ }
1093+
1094+ if(sum != 0){
1095+ print("dp83820reset: bad EEPROM checksum\n");
1096+ return -1;
1097+ }
1098+
1099+#ifdef notdef
1100+ csr32w(ctlr, Gpior, ctlr->eeprom[4]);
1101+
1102+ cfg = Extstsen|Exd;
1103+ r = csr32r(ctlr, Cfg);
1104+ if(ctlr->eeprom[5] & 0x0001)
1105+ cfg |= Ext125;
1106+ if(ctlr->eeprom[5] & 0x0002)
1107+ cfg |= M64addren;
1108+ if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det))
1109+ cfg |= Data64en;
1110+ if(ctlr->eeprom[5] & 0x0008)
1111+ cfg |= T64addren;
1112+ if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10))
1113+ cfg |= Mwidis;
1114+ if(ctlr->eeprom[5] & 0x0020)
1115+ cfg |= Mrmdis;
1116+ if(ctlr->eeprom[5] & 0x0080)
1117+ cfg |= Mode1000;
1118+ if(ctlr->eeprom[5] & 0x0200)
1119+ cfg |= Tbien|Mode1000;
1120+ /*
1121+ * What about RO bits we might have destroyed with Rst?
1122+ * What about Exd, Tmrtest, Extstsen, Pintctl?
1123+ * Why does it think it has detected a 64-bit bus when
1124+ * it hasn't?
1125+ */
1126+#else
1127+ //r = csr32r(ctlr, Cfg);
1128+ //r &= ~(Mode1000|T64addren|Data64en|M64addren);
1129+ //csr32w(ctlr, Cfg, r);
1130+ //csr32w(ctlr, Cfg, 0x2000);
1131+#endif /* notdef */
1132+ ctlr->cfg = csr32r(ctlr, Cfg);
1133+print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR));
1134+ ctlr->cfg &= ~(T64addren|Data64en|M64addren);
1135+ csr32w(ctlr, Cfg, ctlr->cfg);
1136+ csr32w(ctlr, Mibc, Aclr|Frz);
1137+
1138+ return 0;
1139+}
1140+
1141+static void
1142+dp83820pci(void)
1143+{
1144+ void *mem;
1145+ Pcidev *p;
1146+ Ctlr *ctlr;
1147+
1148+ p = nil;
1149+ while(p = pcimatch(p, 0, 0)){
1150+ if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
1151+ continue;
1152+
1153+ switch((p->did<<16)|p->vid){
1154+ default:
1155+ continue;
1156+ case (0x0022<<16)|0x100B: /* DP83820 (Gig-NIC) */
1157+ break;
1158+ }
1159+
1160+ mem = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
1161+ if(mem == 0){
1162+ print("DP83820: can't map %8.8luX\n", p->mem[1].bar);
1163+ continue;
1164+ }
1165+
1166+ ctlr = malloc(sizeof(Ctlr));
1167+ ctlr->port = p->mem[1].bar & ~0x0F;
1168+ ctlr->pcidev = p;
1169+ ctlr->id = (p->did<<16)|p->vid;
1170+
1171+ ctlr->nic = mem;
1172+ if(dp83820reset(ctlr)){
1173+ free(ctlr);
1174+ continue;
1175+ }
1176+ pcisetbme(p);
1177+
1178+ if(dp83820ctlrhead != nil)
1179+ dp83820ctlrtail->next = ctlr;
1180+ else
1181+ dp83820ctlrhead = ctlr;
1182+ dp83820ctlrtail = ctlr;
1183+ }
1184+}
1185+
1186+static int
1187+dp83820pnp(Ether* edev)
1188+{
1189+ int i;
1190+ Ctlr *ctlr;
1191+ uchar ea[Eaddrlen];
1192+
1193+ if(dp83820ctlrhead == nil)
1194+ dp83820pci();
1195+
1196+ /*
1197+ * Any adapter matches if no edev->port is supplied,
1198+ * otherwise the ports must match.
1199+ */
1200+ for(ctlr = dp83820ctlrhead; ctlr != nil; ctlr = ctlr->next){
1201+ if(ctlr->active)
1202+ continue;
1203+ if(edev->port == 0 || edev->port == ctlr->port){
1204+ ctlr->active = 1;
1205+ break;
1206+ }
1207+ }
1208+ if(ctlr == nil)
1209+ return -1;
1210+
1211+ edev->ctlr = ctlr;
1212+ edev->port = ctlr->port;
1213+ edev->irq = ctlr->pcidev->intl;
1214+ edev->tbdf = ctlr->pcidev->tbdf;
1215+ edev->mbps = 1000;
1216+
1217+ /*
1218+ * Check if the adapter's station address is to be overridden.
1219+ * If not, read it from the EEPROM and set in ether->ea prior to
1220+ * loading the station address in the hardware.
1221+ */
1222+ memset(ea, 0, Eaddrlen);
1223+ if(memcmp(ea, edev->ea, Eaddrlen) == 0)
1224+ for(i = 0; i < Eaddrlen/2; i++){
1225+ edev->ea[2*i] = ctlr->eeprom[0x0C-i];
1226+ edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8;
1227+ }
1228+
1229+ edev->attach = dp83820attach;
1230+ edev->transmit = dp83820transmit;
1231+ edev->interrupt = dp83820interrupt;
1232+ edev->ifstat = dp83820ifstat;
1233+
1234+ edev->arg = edev;
1235+ edev->promiscuous = dp83820promiscuous;
1236+ edev->multicast = dp83820multicast;
1237+ edev->shutdown = dp83820shutdown;
1238+
1239+ return 0;
1240+}
1241+
1242+void
1243+etherdp83820link(void)
1244+{
1245+ addethercard("DP83820", dp83820pnp);
1246+}
os/pc/etherec2t.c+1−0
@@ -31,6 +31,7 @@ static Ec2t ec2tpcmcia[] = { · 30 unmodified lines
3131 { "FA410TX", 1, }, /* Netgear FA410TX */
3232 { "Network Everywhere", 0, }, /* Linksys NP10T 10BaseT Card */
3333 { "10/100 Port Attached", 1, }, /* SMC 8040TX */
34+ { "8041TX-10/100-PC-Card-V2", 0 }, /* SMC 8041TX */
3435 { "FA411", 0 }, /* Netgear FA411 PCMCIA */
3536 { nil, 0, },
3637 };
os/pc/etherelnk3.c+6−4
@@ -1485,15 +1485,15 @@ tcm59Xpci(void) · 1484 unmodified lines
14851485 break;
14861486 case 0x5157:
14871487 ctlr->eepromcmd = EepromRead8bRegister;
1488− ctlr->cbfnpa = upamalloc(p->mem[2].bar, p->mem[2].size, 0);
1488+ ctlr->cbfnpa = p->mem[2].bar&~0x0F;
1489+ ctlr->cbfn = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
14891490 break;
14901491 case 0x6056:
14911492 ctlr->eepromcmd = EepromReadOffRegister;
1492− ctlr->cbfnpa = upamalloc(p->mem[2].bar, p->mem[2].size, 0);
1493+ ctlr->cbfnpa = p->mem[2].bar&~0x0F;
1494+ ctlr->cbfn = vmap(p->mem[2].bar&~0x0F, p->mem[2].size);
14931495 break;
14941496 }
1495− if(ctlr->cbfnpa != 0)
1496− ctlr->cbfn = KADDR(ctlr->cbfnpa);
14971497 pcisetbme(p);
14981498 }
14991499 }
@@ -1834,6 +1834,7 @@ etherelnk3reset(Ether* ether) · 334 unmodified lines
18341834 case 0x9055: /* 3C905B-TX */
18351835 case 0x9200: /* 3C905C-TX */
18361836 case 0x9201: /* 3C920 */
1837+ case 0x9805: /* 3C9805: 3C980-TX Python-T 10/100baseTX */
18371838 /*FALLTHROUGH*/
18381839 case 0x9000: /* 3C900-TPO */
18391840 case 0x9001: /* 3C900-COMBO */
@@ -1927,6 +1928,7 @@ etherelnk3reset(Ether* ether) · 87 unmodified lines
19271928 case 0x9055:
19281929 case 0x9200:
19291930 case 0x9201:
1931+ case 0x9805:
19301932 ctlr->xcvr = xcvrMii;
19311933 resetctlr(ctlr);
19321934 break;
os/pc/etherga620.c+97−46
@@ -124,7 +124,11 @@ enum { /* Om */ · 123 unmodified lines
124124 enum { /* Lmw */
125125 Lmwsz = 2*1024, /* Local Memory Window Size */
126126
127− Sr = 0x3800, /* Send Ring (accessed via Lmw) */
127+ /*
128+ * legal values are 0x3800 iff Nsr is 128, 0x3000 iff Nsr is 256,
129+ * or 0x2000 iff Nsr is 512.
130+ */
131+ Sr = 0x2000, /* Send Ring (accessed via Lmw) */
128132 };
129133
130134 enum { /* Link */
@@ -146,17 +150,17 @@ typedef struct Host64 { · 15 unmodified lines
146150 } Host64;
147151
148152 typedef struct Ere { /* Event Ring Element */
149− int event; /* (event<<24)|(code<<12)|index */
153+ int event; /* event<<24 | code<<12 | index */
150154 int unused;
151155 } Ere;
152156
153−typedef int Cmd; /* (cmd<<24)|(flags<<12)|index */
157+typedef int Cmd; /* cmd<<24 | flags<<12 | index */
154158
155159 typedef struct Rbd { /* Receive Buffer Descriptor */
156160 Host64 addr;
157− int indexlen; /* (ring-index<<16)|buffer-length */
161+ int indexlen; /* ring-index<<16 | buffer-length */
158162 int flags; /* only lower 16-bits */
159− int checksum; /* (ip<<16)|tcp/udp */
163+ int checksum; /* ip<<16 | tcp/udp */
160164 int error; /* only upper 16-bits */
161165 int reserved;
162166 void* opaque; /* passed to receive return ring */
@@ -164,7 +168,7 @@ typedef struct Rbd { /* Receive Buffer Descriptor */ · 1 unmodified line
164168
165169 typedef struct Sbd { /* Send Buffer Descriptor */
166170 Host64 addr;
167− int lenflags; /* (len<<16)|flags */
171+ int lenflags; /* len<<16 | flags */
168172 int reserved;
169173 } Sbd;
170174
@@ -192,7 +196,7 @@ enum { /* Buffer Error Flags */ · 21 unmodified lines
192196
193197 typedef struct Rcb { /* Ring Control Block */
194198 Host64 addr; /* points to the Rbd ring */
195− int control; /* (max_len<<16)|flags */
199+ int control; /* max_len<<16 | flags */
196200 int unused;
197201 } Rcb;
198202
@@ -223,13 +227,17 @@ typedef struct Gib { /* General Information Block */ · 24 unmodified lines
223227 Host64 rsp; /* Refresh Stats */
224228 } Gib;
225229
230+/*
231+ * these sizes are all fixed in the card,
232+ * except for Nsr, which has only 3 valid sizes.
233+ */
226234 enum { /* Host/NIC Interface ring sizes */
227235 Ner = 256, /* event ring */
228236 Ncr = 64, /* command ring */
229− Nsr = 512, /* send ring */
237+ Nsr = 512, /* send ring: 128, 256 or 512 */
230238 Nrsr = 512, /* receive standard ring */
231239 Nrjr = 256, /* receive jumbo ring */
232− Nrmr = 1024, /* receive mini ring */
240+ Nrmr = 1024, /* receive mini ring, optional */
233241 Nrrr = 2048, /* receive return ring */
234242 };
235243
@@ -243,7 +251,7 @@ enum { · 7 unmodified lines
243251 };
244252
245253 typedef struct Ctlr Ctlr;
246−typedef struct Ctlr {
254+struct Ctlr {
247255 int port;
248256 Pcidev* pcidev;
249257 Ctlr* next;
@@ -286,7 +294,7 @@ typedef struct Ctlr { · 36 unmodified lines
286294 int st; /* Stat Ticks */
287295 int smcbd; /* Send Max. Coalesced BDs */
288296 int rmcbd; /* Receive Max. Coalesced BDs */
289−} Ctlr;
297+};
290298
291299 static Ctlr* ctlrhead;
292300 static Ctlr* ctlrtail;
@@ -310,7 +318,7 @@ ga620command(Ctlr* ctlr, int cmd, int flags, int index) · 17 unmodified lines
310318 int cpi;
311319
312320 cpi = csr32r(ctlr, Cpi);
313− csr32w(ctlr, Cr+(cpi*4), (cmd<<24)|(flags<<12)|index);
321+ csr32w(ctlr, Cr+(cpi*4), cmd<<24 | flags<<12 | index);
314322 cpi = NEXT(cpi, Ncr);
315323 csr32w(ctlr, Cpi, cpi);
316324 }
@@ -508,7 +516,7 @@ _ga620transmit(Ether* edev) · 191 unmodified lines
508516
509517 sbd = &ctlr->sr[spi];
510518 sethost64(&sbd->addr, bp->rp);
511− sbd->lenflags = (BLEN(bp)<<16)|Fend;
519+ sbd->lenflags = BLEN(bp)<<16 | Fend;
512520
513521 ctlr->srb[spi] = bp;
514522 work++;
@@ -539,7 +547,7 @@ ga620replenish(Ctlr* ctlr) · 24 unmodified lines
539547 break;
540548 rbd = &ctlr->rsr[rspi];
541549 sethost64(&rbd->addr, bp->rp);
542− rbd->indexlen = (rspi<<16)|(ETHERMAXTU+4);
550+ rbd->indexlen = rspi<<16 | (ETHERMAXTU+4);
543551 rbd->flags = 0;
544552 rbd->opaque = bp;
545553
@@ -550,27 +558,49 @@ ga620replenish(Ctlr* ctlr) · 4 unmodified lines
550558 }
551559
552560 static void
553−ga620event(Ctlr* ctlr, int eci, int epi)
561+ga620event(Ether *edev, int eci, int epi)
554562 {
555− int event;
563+ unsigned event, code;
564+ Ctlr *ctlr;
556565
566+ ctlr = edev->ctlr;
557567 while(eci != epi){
558568 event = ctlr->er[eci].event;
569+ code = (event >> 12) & ((1<<12)-1);
559570 switch(event>>24){
560571 case 0x01: /* firmware operational */
572+ /* host stack (us) is up. 3rd arg of 2 means down. */
561573 ga620command(ctlr, 0x01, 0x01, 0x00);
574+ /*
575+ * link negotiation: any speed is okay.
576+ * 3rd arg of 1 selects gigabit only; 2 10/100 only.
577+ */
562578 ga620command(ctlr, 0x0B, 0x00, 0x00);
563−print("%8.8uX: %8.8uX\n", ctlr->port, event);
579+ print("#l%d: ga620: port %8.8uX: firmware is up\n",
580+ edev->ctlrno, ctlr->port);
564581 break;
565582 case 0x04: /* statistics updated */
566583 break;
567584 case 0x06: /* link state changed */
568−print("%8.8uX: %8.8uX %8.8uX %8.8uX\n",
569− ctlr->port, event, csr32r(ctlr, Gls), csr32r(ctlr, Fls));
585+ switch (code) {
586+ case 1:
587+ edev->mbps = 1000;
588+ break;
589+ case 2:
590+ print("#l%d: link down\n", edev->ctlrno);
591+ break;
592+ case 3:
593+ edev->mbps = 100; /* it's 10 or 100 */
594+ break;
595+ }
596+ if (code != 2)
597+ print("#l%d: %dMbps link up\n",
598+ edev->ctlrno, edev->mbps);
570599 break;
571600 case 0x07: /* event error */
572601 default:
573− print("er[%d] = %8.8uX\n", eci, event);
602+ print("#l%d: ga620: er[%d] = %8.8uX\n", edev->ctlrno,
603+ eci, event);
574604 break;
575605 }
576606 eci = NEXT(eci, Ner);
@@ -645,7 +675,7 @@ ga620interrupt(Ureg*, void* arg) · 68 unmodified lines
645675
646676 csr = csr32r(ctlr, Eci);
647677 if(csr != ctlr->epi[0]){
648− ga620event(ctlr, csr, ctlr->epi[0]);
678+ ga620event(edev, csr, ctlr->epi[0]);
649679 work = 1;
650680 }
651681
@@ -714,9 +744,9 @@ ga620init(Ether* edev) · 62 unmodified lines
714744 /*
715745 * Load the MAC address.
716746 */
717− ea = (edev->ea[0]<<8)|edev->ea[1];
747+ ea = edev->ea[0]<<8 | edev->ea[1];
718748 csr32w(ctlr, Mac, ea);
719− ea = (edev->ea[2]<<24)|(edev->ea[3]<<16)|(edev->ea[4]<<8)|edev->ea[5];
749+ ea = edev->ea[2]<<24 | edev->ea[3]<<16 | edev->ea[4]<<8 | edev->ea[5];
720750 csr32w(ctlr, Mac+4, ea);
721751
722752 /*
@@ -758,7 +788,7 @@ ga620init(Ether* edev) · 35 unmodified lines
758788 * memory it is accessed via the Local Memory Window; with a send
759789 * ring size of 128 the window covers the whole ring and then need
760790 * only be set once:
761− * ctlr->sr = KADDR(ctlr->port+Lmw);
791+ * ctlr->sr = (uchar*)ctlr->nic+Lmw;
762792 * ga620lmw(ctlr, Sr, nil, sizeof(Sbd)*Nsr);
763793 * ctlr->gib->srcb.addr.lo = Sr;
764794 * There is nowhere in the Sbd to hold the Block* associated
@@ -772,7 +802,7 @@ ga620init(Ether* edev) · 7 unmodified lines
772802 flags = HostRing;
773803 if(ctlr->coalupdateonly)
774804 flags |= CoalUpdateOnly;
775− ctlr->gib->srcb.control = (Nsr<<16)|flags;
805+ ctlr->gib->srcb.control = Nsr<<16 | flags;
776806 sethost64(&ctlr->gib->scp, ctlr->sci);
777807 csr32w(ctlr, Spi, 0);
778808 ctlr->srb = malloc(sizeof(Block*)*Nsr);
@@ -786,7 +816,7 @@ ga620init(Ether* edev) · 7 unmodified lines
786816 flags = TcpUdpCksum|NoPseudoHdrCksum;
787817 else
788818 flags = 0;
789− ctlr->gib->rsrcb.control = ((ETHERMAXTU+4)<<16)|flags;
819+ ctlr->gib->rsrcb.control = (ETHERMAXTU+4)<<16 | flags;
790820 csr32w(ctlr, Rspi, 0);
791821
792822 /*
@@ -802,7 +832,7 @@ ga620init(Ether* edev) · 9 unmodified lines
802832 */
803833 ctlr->rrr = malign(sizeof(Rbd)*Nrrr);
804834 sethost64(&ctlr->gib->rrrcb.addr, ctlr->rrr);
805− ctlr->gib->rrrcb.control = (Nrrr<<16)|0;
835+ ctlr->gib->rrrcb.control = Nrrr<<16 | 0;
806836 sethost64(&ctlr->gib->rrrpp, ctlr->rrrpi);
807837 ctlr->rrrci = 0;
808838
@@ -1024,8 +1054,8 @@ ga620detach(Ctlr* ctlr) · 215 unmodified lines
10241054 * wait for code to be loaded from serial EEPROM or flash;
10251055 * make sure CPU A is halted.
10261056 */
1027− csr32w(ctlr, Mhc, (Hr<<24)|Hr);
1028− csr32w(ctlr, Mhc, ((Eews|Ci)<<24)|(Eews|Ci));
1057+ csr32w(ctlr, Mhc, Hr<<24 | Hr);
1058+ csr32w(ctlr, Mhc, (Eews|Ci)<<24 | Eews|Ci);
10291059
10301060 microdelay(1);
10311061 for(timeo = 0; timeo < 500000; timeo++){
@@ -1056,7 +1086,7 @@ print("ga620shutdown\n"); · 24 unmodified lines
10561086 static int
10571087 ga620reset(Ctlr* ctlr)
10581088 {
1059− int cls, csr, i;
1089+ int cls, csr, i, r;
10601090
10611091 if(ga620detach(ctlr) < 0)
10621092 return -1;
@@ -1095,8 +1125,9 @@ ga620reset(Ctlr* ctlr) · 32 unmodified lines
10951125 * Snarf the MAC address from the serial EEPROM.
10961126 */
10971127 for(i = 0; i < Eaddrlen; i++){
1098− if((ctlr->ea[i] = at24c32r(ctlr, 0x8E+i)) == -1)
1128+ if((r = at24c32r(ctlr, 0x8E+i)) == -1)
10991129 return -1;
1130+ ctlr->ea[i] = r;
11001131 }
11011132
11021133 /*
@@ -1114,7 +1145,7 @@ ga620reset(Ctlr* ctlr) · 11 unmodified lines
11141145 static void
11151146 ga620pci(void)
11161147 {
1117− int port;
1148+ void *mem;
11181149 Pcidev *p;
11191150 Ctlr *ctlr;
11201151
@@ -1123,30 +1154,30 @@ ga620pci(void) · 2 unmodified lines
11231154 if(p->ccrb != 0x02 || p->ccru != 0)
11241155 continue;
11251156
1126− switch((p->did<<16)|p->vid){
1157+ switch(p->did<<16 | p->vid){
11271158 default:
11281159 continue;
1129− case (0x620A<<16)|0x1385: /* Netgear GA620 */
1130− case (0x630A<<16)|0x1385: /* Netgear GA620T */
1131− case (0x0001<<16)|0x12AE: /* Alteon Acenic fiber
1160+ case 0x620A<<16 | 0x1385: /* Netgear GA620 fiber */
1161+ case 0x630A<<16 | 0x1385: /* Netgear GA620T copper */
1162+ case 0x0001<<16 | 0x12AE: /* Alteon Acenic fiber
11321163 * and DEC DEGPA-SA */
1133− case (0x0002<<16)|0x12AE: /* Alteon Acenic copper */
1134− case (0x0009<<16)|0x10A9: /* SGI Acenic */
1164+ case 0x0002<<16 | 0x12AE: /* Alteon Acenic copper */
1165+ case 0x0009<<16 | 0x10A9: /* SGI Acenic */
11351166 break;
11361167 }
11371168
1138− port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
1139− if(port == 0){
1169+ mem = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
1170+ if(mem == 0){
11401171 print("ga620: can't map %8.8luX\n", p->mem[0].bar);
11411172 continue;
11421173 }
11431174
11441175 ctlr = malloc(sizeof(Ctlr));
1145− ctlr->port = port;
1176+ ctlr->port = p->mem[0].bar & ~0x0F;
11461177 ctlr->pcidev = p;
1147− ctlr->id = (p->did<<16)|p->vid;
1178+ ctlr->id = p->did<<16 | p->vid;
11481179
1149− ctlr->nic = KADDR(ctlr->port);
1180+ ctlr->nic = mem;
11501181 if(ga620reset(ctlr)){
11511182 free(ctlr);
11521183 continue;
@@ -1160,6 +1191,25 @@ ga620pci(void) · 7 unmodified lines
11601191 }
11611192 }
11621193
1194+static void
1195+ga620promiscuous(void *arg, int on)
1196+{
1197+ Ether *ether = arg;
1198+
1199+ /* 3rd arg: 1 enables, 2 disables */
1200+ ga620command(ether->ctlr, 0xa, (on? 1: 2), 0);
1201+}
1202+
1203+static void
1204+ga620multicast(void *arg, uchar *addr, int on)
1205+{
1206+ Ether *ether = arg;
1207+
1208+ USED(addr);
1209+ /* 3rd arg: 1 enables, 2 disables */
1210+ ga620command(ether->ctlr, 0xe, (on? 1: 2), 0);
1211+}
1212+
11631213 static int
11641214 ga620pnp(Ether* edev)
11651215 {
@@ -1188,7 +1238,7 @@ ga620pnp(Ether* edev) · 22 unmodified lines
11881238 edev->port = ctlr->port;
11891239 edev->irq = ctlr->pcidev->intl;
11901240 edev->tbdf = ctlr->pcidev->tbdf;
1191− edev->mbps = 1000;
1241+ edev->mbps = 1000; /* placeholder */
11921242
11931243 /*
11941244 * Check if the adapter's station address is to be overridden.
@@ -1209,10 +1259,11 @@ ga620pnp(Ether* edev) · 14 unmodified lines
12091259 edev->interrupt = ga620interrupt;
12101260 edev->ifstat = ga620ifstat;
12111261 edev->ctl = ga620ctl;
1212− edev->shutdown = ga620shutdown;
12131262
12141263 edev->arg = edev;
1215− edev->promiscuous = nil;
1264+ edev->promiscuous = ga620promiscuous;
1265+ edev->multicast = ga620multicast;
1266+ edev->shutdown = ga620shutdown;
12161267
12171268 return 0;
12181269 }
os/pc/etherigbe.c+59−38
@@ -29,16 +29,17 @@ · 28 unmodified lines
2929 #include "ethermii.h"
3030
3131 enum {
32− i82542 = (0x1000<<16)|0x8086,
33− i82543gc = (0x1004<<16)|0x8086,
34− i82544ei = (0x1008<<16)|0x8086,
35− i82547ei = (0x1019<<16)|0x8086,
36− i82540em = (0x100E<<16)|0x8086,
37− i82540eplp = (0x101E<<16)|0x8086,
32+ i82542 = (0x1000<<16)|0x8086,
33+ i82543gc = (0x1004<<16)|0x8086,
34+ i82544ei = (0x1008<<16)|0x8086,
35+ i82547ei = (0x1019<<16)|0x8086,
36+ i82540em = (0x100E<<16)|0x8086,
37+ i82540eplp = (0x101E<<16)|0x8086,
3838 i82545gmc = (0x1026<<16)|0x8086,
39− i82547gi = (0x1075<<16)|0x8086,
40− i82541gi = (0x1076<<16)|0x8086,
41− i82546gb = (0x1079<<16)|0x8086,
39+ i82547gi = (0x1075<<16)|0x8086,
40+ i82541gi = (0x1076<<16)|0x8086,
41+ i82541gi2 = (0x1077<<16)|0x8086,
42+ i82546gb = (0x1079<<16)|0x8086,
4243 i82541pi = (0x107c<<16)|0x8086,
4344 i82546eb = (0x1010<<16)|0x8086,
4445 };
@@ -172,7 +173,9 @@ enum { /* Eecd */ · 127 unmodified lines
172173 Do = 0x00000008, /* Data Output from the EEPROM */
173174 Areq = 0x00000040, /* EEPROM Access Request */
174175 Agnt = 0x00000080, /* EEPROM Access Grant */
176+ Eepresent = 0x00000100, /* EEPROM Present */
175177 Eesz256 = 0x00000200, /* EEPROM is 256 words not 64 */
178+ Eeszaddr = 0x00000400, /* EEPROM size for 8254[17] */
176179 Spi = 0x00002000, /* EEPROM is SPI not Microwire */
177180 };
178181
@@ -442,6 +445,7 @@ typedef struct Ctlr { · 263 unmodified lines
442445 int port;
443446 Pcidev* pcidev;
444447 Ctlr* next;
448+ Ether* edev;
445449 int active;
446450 int started;
447451 int id;
@@ -508,7 +512,7 @@ static Ctlr* igbectlrhead; · 60 unmodified lines
508512 static Ctlr* igbectlrtail;
509513
510514 static Lock igberblock; /* free receive Blocks */
511−static Block* igberbpool;
515+static Block* igberbpool; /* receive Blocks for all igbe controllers */
512516
513517 static char* statistics[Nstatistics] = {
514518 "CRC Error",
@@ -671,13 +675,13 @@ igbectl(Ether* edev, void* buf, long n) · 156 unmodified lines
671675 {
672676 int v;
673677 char *p;
674− Ctlr *ctlr;
678+ Ctlr *ctlr;
675679 Cmdbuf *cb;
676680 Cmdtab *ct;
677681
678682 if((ctlr = edev->ctlr) == nil)
679683 error(Enonexist);
680−
684+
681685 cb = parsecmd(buf, n);
682686 if(waserror()){
683687 free(cb);
@@ -736,7 +740,7 @@ igbemulticast(void* arg, uchar* addr, int on) · 52 unmodified lines
736740 ctlr->mta[x] |= 1<<bit;
737741 else
738742 ctlr->mta[x] &= ~(1<<bit);
739−
743+
740744 csr32w(ctlr, Mta+x*4, ctlr->mta[x]);
741745 }
742746
@@ -831,6 +835,7 @@ igbelproc(void* arg) · 88 unmodified lines
831835 case i82540eplp:
832836 case i82547gi:
833837 case i82541gi:
838+ case i82541gi2:
834839 case i82541pi:
835840 break;
836841 }
@@ -881,6 +886,7 @@ igbetxinit(Ctlr* ctlr) · 44 unmodified lines
881886 case i82540em:
882887 case i82540eplp:
883888 case i82541gi:
889+ case i82541gi2:
884890 case i82541pi:
885891 case i82545gmc:
886892 case i82546gb:
@@ -923,6 +929,7 @@ igbetxinit(Ctlr* ctlr) · 36 unmodified lines
923929 case i82546gb:
924930 case i82546eb:
925931 case i82541gi:
932+ case i82541gi2:
926933 case i82541pi:
927934 r = csr32r(ctlr, Txdctl);
928935 r &= ~WthreshMASK;
@@ -1006,7 +1013,8 @@ igbereplenish(Ctlr* ctlr) · 77 unmodified lines
10061013 if(ctlr->rb[rdt] == nil){
10071014 bp = igberballoc();
10081015 if(bp == nil){
1009− iprint("no available buffers\n");
1016+ iprint("#l%d: igbereplenish: no available buffers\n",
1017+ ctlr->edev->ctlrno);
10101018 break;
10111019 }
10121020 ctlr->rb[rdt] = bp;
@@ -1052,6 +1060,7 @@ igberxinit(Ctlr* ctlr) · 39 unmodified lines
10521060 case i82540em:
10531061 case i82540eplp:
10541062 case i82541gi:
1063+ case i82541gi2:
10551064 case i82541pi:
10561065 case i82545gmc:
10571066 case i82546gb:
@@ -1100,10 +1109,10 @@ igberproc(void* arg) · 42 unmodified lines
11001109 rdh = ctlr->rdh;
11011110 for(;;){
11021111 rd = &ctlr->rdba[rdh];
1103−
1112+
11041113 if(!(rd->status & Rdd))
11051114 break;
1106−
1115+
11071116 /*
11081117 * Accept eop packets with no errors.
11091118 * With no errors and the Ixsm bit set,
@@ -1150,7 +1159,7 @@ igberproc(void* arg) · 40 unmodified lines
11501159 rdh = NEXT(rdh, ctlr->nrd);
11511160 }
11521161 ctlr->rdh = rdh;
1153−
1162+
11541163 if(ctlr->rdfree < ctlr->nrd/2 || (ctlr->rim & Rxdmt0))
11551164 igbereplenish(ctlr);
11561165 }
@@ -1164,6 +1173,7 @@ igbeattach(Ether* edev) · 7 unmodified lines
11641173 char name[KNAMELEN];
11651174
11661175 ctlr = edev->ctlr;
1176+ ctlr->edev = edev; /* point back to Ether* */
11671177 qlock(&ctlr->alock);
11681178 if(ctlr->alloc != nil){
11691179 qunlock(&ctlr->alock);
@@ -1177,7 +1187,7 @@ igbeattach(Ether* edev) · 7 unmodified lines
11771187 qunlock(&ctlr->alock);
11781188 return;
11791189 }
1180− ctlr->rdba = (Rd*)ROUNDUP((ulong)ctlr->alloc, 128);
1190+ ctlr->rdba = (Rd*)ROUNDUP((uintptr)ctlr->alloc, 128);
11811191 ctlr->tdba = (Td*)(ctlr->rdba+ctlr->nrd);
11821192
11831193 ctlr->rb = malloc(ctlr->nrd*sizeof(Block*));
@@ -1448,6 +1458,7 @@ igbemii(Ctlr* ctlr) · 264 unmodified lines
14481458 case i82540eplp:
14491459 case i82547gi:
14501460 case i82541gi:
1461+ case i82541gi2:
14511462 case i82541pi:
14521463 case i82545gmc:
14531464 case i82546gb:
@@ -1468,7 +1479,8 @@ igbemii(Ctlr* ctlr) · 14 unmodified lines
14681479 ctlr->mii = nil;
14691480 return -1;
14701481 }
1471− print("oui %X phyno %d\n", phy->oui, phy->phyno);
1482+ USED(phy);
1483+ // print("oui %X phyno %d\n", phy->oui, phy->phyno);
14721484
14731485 /*
14741486 * 8254X-specific PHY registers not in 802.3:
@@ -1480,6 +1492,7 @@ igbemii(Ctlr* ctlr) · 5 unmodified lines
14801492 switch(ctlr->id){
14811493 case i82547gi:
14821494 case i82541gi:
1495+ case i82541gi2:
14831496 case i82541pi:
14841497 case i82545gmc:
14851498 case i82546gb:
@@ -1491,13 +1504,13 @@ igbemii(Ctlr* ctlr) · 5 unmodified lines
14911504 r |= 0x0060; /* auto-crossover all speeds */
14921505 r |= 0x0002; /* polarity reversal enabled */
14931506 miimiw(ctlr->mii, 16, r);
1494−
1507+
14951508 r = miimir(ctlr->mii, 20);
14961509 r |= 0x0070; /* +25MHz clock */
14971510 r &= ~0x0F00;
14981511 r |= 0x0100; /* 1x downshift */
14991512 miimiw(ctlr->mii, 20, r);
1500−
1513+
15011514 miireset(ctlr->mii);
15021515 p = 0;
15031516 if(ctlr->txcw & TxcwPs)
@@ -1578,7 +1591,7 @@ at93c46io(Ctlr* ctlr, char* op, int data) · 74 unmodified lines
15781591 break;
15791592 }
15801593 csr32w(ctlr, Eecd, eecd);
1581− microdelay(1);
1594+ microdelay(50);
15821595 }
15831596 if(loop >= 0)
15841597 return -1;
@@ -1597,11 +1610,10 @@ at93c46r(Ctlr* ctlr) · 12 unmodified lines
15971610 print("igbe: SPI EEPROM access not implemented\n");
15981611 return 0;
15991612 }
1600− if(eecd & Eesz256)
1613+ if(eecd & (Eeszaddr|Eesz256))
16011614 bits = 8;
16021615 else
16031616 bits = 6;
1604− snprint(rop, sizeof(rop), "S :%dDCc;", bits+3);
16051617
16061618 sum = 0;
16071619
@@ -1609,11 +1621,12 @@ at93c46r(Ctlr* ctlr) · 1 unmodified line
16091621 default:
16101622 areq = 0;
16111623 break;
1624+ case i82541gi:
1625+ case i82547gi:
16121626 case i82540em:
16131627 case i82540eplp:
1614− case i82541gi:
16151628 case i82541pi:
1616− case i82547gi:
1629+ case i82541gi2:
16171630 case i82545gmc:
16181631 case i82546gb:
16191632 case i82546eb:
@@ -1630,6 +1643,7 @@ at93c46r(Ctlr* ctlr) · 10 unmodified lines
16301643 }
16311644 break;
16321645 }
1646+ snprint(rop, sizeof(rop), "S :%dDCc;", bits+3);
16331647
16341648 for(addr = 0; addr < 0x40; addr++){
16351649 /*
@@ -1698,6 +1712,7 @@ igbedetach(Ctlr* ctlr) · 62 unmodified lines
16981712 case i82541gi:
16991713 case i82541pi:
17001714 case i82547gi:
1715+ case i82541gi2:
17011716 case i82545gmc:
17021717 case i82546gb:
17031718 case i82546eb:
@@ -1751,6 +1766,8 @@ igbereset(Ctlr* ctlr) · 47 unmodified lines
17511766 if ((ctlr->id == i82546gb || ctlr->id == i82546eb) && BUSFNO(ctlr->pcidev->tbdf) == 1)
17521767 ctlr->eeprom[Ea+2] += 0x100; // second interface
17531768 for(i = Ea; i < Eaddrlen/2; i++){
1769+if(i == Ea && ctlr->id == i82541gi && ctlr->eeprom[i] == 0xFFFF)
1770+ ctlr->eeprom[i] = 0xD000;
17541771 ctlr->ra[2*i] = ctlr->eeprom[i];
17551772 ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
17561773 }
@@ -1773,14 +1790,14 @@ igbereset(Ctlr* ctlr) · 16 unmodified lines
17731790
17741791 /*
17751792 * Just in case the Eerst didn't load the defaults
1776− * (doesn't appear to fully on the 8243GC), do it manually.
1793+ * (doesn't appear to fully on the 82543GC), do it manually.
17771794 */
1778− if (ctlr->id == i82543gc) { // 82543
1795+ if (ctlr->id == i82543gc) {
17791796 txcw = csr32r(ctlr, Txcw);
17801797 txcw &= ~(TxcwAne|TxcwPauseMASK|TxcwFd);
17811798 ctrl = csr32r(ctlr, Ctrl);
17821799 ctrl &= ~(SwdpioloMASK|Frcspd|Ilos|Lrst|Fd);
1783−
1800+
17841801 if(ctlr->eeprom[Icw1] & 0x0400){
17851802 ctrl |= Fd;
17861803 txcw |= TxcwFd;
@@ -1794,7 +1811,7 @@ igbereset(Ctlr* ctlr) · 7 unmodified lines
17941811 swdpio = (ctlr->eeprom[Icw1] & 0x01E0)>>5;
17951812 ctrl |= swdpio<<SwdpioloSHIFT;
17961813 csr32w(ctlr, Ctrl, ctrl);
1797−
1814+
17981815 ctrl = csr32r(ctlr, Ctrlext);
17991816 ctrl &= ~(Ips|SwdpiohiMASK);
18001817 swdpio = (ctlr->eeprom[Icw2] & 0x00F0)>>4;
@@ -1802,7 +1819,7 @@ igbereset(Ctlr* ctlr) · 1 unmodified line
18021819 ctrl |= Ips;
18031820 ctrl |= swdpio<<SwdpiohiSHIFT;
18041821 csr32w(ctlr, Ctrlext, ctrl);
1805−
1822+
18061823 if(ctlr->eeprom[Icw2] & 0x0800)
18071824 txcw |= TxcwAne;
18081825 pause = (ctlr->eeprom[Icw2] & 0x3000)>>12;
@@ -1827,7 +1844,7 @@ igbereset(Ctlr* ctlr) · 18 unmodified lines
18271844 csr32w(ctlr, Txcw, txcw);
18281845 }
18291846
1830−
1847+
18311848 /*
18321849 * Flow control - values from the datasheet.
18331850 */
@@ -1848,9 +1865,10 @@ igbereset(Ctlr* ctlr) · 14 unmodified lines
18481865 static void
18491866 igbepci(void)
18501867 {
1851− int port, cls;
1868+ int cls;
18521869 Pcidev *p;
18531870 Ctlr *ctlr;
1871+ void *mem;
18541872
18551873 p = nil;
18561874 while(p = pcimatch(p, 0, 0)){
@@ -1865,8 +1883,9 @@ igbepci(void) · 8 unmodified lines
18651883 case i82547ei:
18661884 case i82540em:
18671885 case i82540eplp:
1868− case i82547gi:
18691886 case i82541gi:
1887+ case i82547gi:
1888+ case i82541gi2:
18701889 case i82541pi:
18711890 case i82545gmc:
18721891 case i82546gb:
@@ -1874,8 +1893,8 @@ igbepci(void) · 1 unmodified line
18741893 break;
18751894 }
18761895
1877− port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
1878− if(port == 0){
1896+ mem = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
1897+ if(mem == nil){
18791898 print("igbe: can't map %8.8luX\n", p->mem[0].bar);
18801899 continue;
18811900 }
@@ -1893,14 +1912,15 @@ igbepci(void) · 11 unmodified lines
18931912 break;
18941913 }
18951914 ctlr = malloc(sizeof(Ctlr));
1896− ctlr->port = port;
1915+ ctlr->port = p->mem[0].bar & ~0x0F;
18971916 ctlr->pcidev = p;
18981917 ctlr->id = (p->did<<16)|p->vid;
18991918 ctlr->cls = cls*4;
1900− ctlr->nic = KADDR(ctlr->port);
1919+ ctlr->nic = mem;
19011920
19021921 if(igbereset(ctlr)){
19031922 free(ctlr);
1923+ vunmap(mem, p->mem[0].size);
19041924 continue;
19051925 }
19061926 pcisetbme(p);
@@ -1966,3 +1986,4 @@ etherigbelink(void) · 59 unmodified lines
19661986 addethercard("i82543", igbepnp);
19671987 addethercard("igbe", igbepnp);
19681988 }
1989+
os/pc/ethersmc.c+1−0
@@ -713,6 +713,7 @@ reset(Ether* ether) · 712 unmodified lines
713713 if (ctlr == 0) {
714714 iofree(ether->port);
715715 pcmspecialclose(slot);
716+ return -1;
716717 }
717718
718719 ilock(ctlr);
os/pc/ethervt6102.c+1025−0
@@ -0,0 +1,1025 @@
1+/*
2+ * VIA VT6102 Fast Ethernet Controller (Rhine II).
3+ * To do:
4+ * cache-line size alignments - done
5+ * reduce tx interrupts
6+ * use 2 descriptors on tx for alignment - done
7+ * reorganise initialisation/shutdown/reset
8+ * adjust Tx FIFO threshold on underflow - untested
9+ * why does the link status never cause an interrupt?
10+ * use the lproc as a periodic timer for stalls, etc.
11+ */
12+#include "u.h"
13+#include "../port/lib.h"
14+#include "mem.h"
15+#include "dat.h"
16+#include "fns.h"
17+#include "io.h"
18+#include "../port/error.h"
19+#include "../port/netif.h"
20+
21+#include "etherif.h"
22+#include "ethermii.h"
23+
24+enum {
25+ Par0 = 0x00, /* Ethernet Address */
26+ Rcr = 0x06, /* Receive Configuration */
27+ Tcr = 0x07, /* Transmit Configuration */
28+ Cr = 0x08, /* Control */
29+ Isr = 0x0C, /* Interrupt Status */
30+ Imr = 0x0E, /* Interrupt Mask */
31+ Rxdaddr = 0x18, /* Current Rx Descriptor Address */
32+ Txdaddr = 0x1C, /* Current Tx Descriptor Address */
33+ Phyadr = 0x6C, /* Phy Address */
34+ Miisr = 0x6D, /* MII Status */
35+ Bcr0 = 0x6E, /* Bus Control */
36+ Bcr1 = 0x6F,
37+ Miicr = 0x70, /* MII Control */
38+ Miiadr = 0x71, /* MII Address */
39+ Miidata = 0x72, /* MII Data */
40+ Eecsr = 0x74, /* EEPROM Control and Status */
41+};
42+
43+enum { /* Rcr */
44+ Sep = 0x01, /* Accept Error Packets */
45+ Ar = 0x02, /* Accept Small Packets */
46+ Am = 0x04, /* Accept Multicast */
47+ Ab = 0x08, /* Accept Broadcast */
48+ Prom = 0x10, /* Accept Physical Address Packets */
49+ RrftMASK = 0xE0, /* Receive FIFO Threshold */
50+ RrftSHIFT = 5,
51+ Rrft64 = 0<<RrftSHIFT,
52+ Rrft32 = 1<<RrftSHIFT,
53+ Rrft128 = 2<<RrftSHIFT,
54+ Rrft256 = 3<<RrftSHIFT,
55+ Rrft512 = 4<<RrftSHIFT,
56+ Rrft768 = 5<<RrftSHIFT,
57+ Rrft1024 = 6<<RrftSHIFT,
58+ RrftSAF = 7<<RrftSHIFT,
59+};
60+
61+enum { /* Tcr */
62+ Lb0 = 0x02, /* Loopback Mode */
63+ Lb1 = 0x04,
64+ Ofset = 0x08, /* Back-off Priority Selection */
65+ RtsfMASK = 0xE0, /* Transmit FIFO Threshold */
66+ RtsfSHIFT = 5,
67+ Rtsf128 = 0<<RtsfSHIFT,
68+ Rtsf256 = 1<<RtsfSHIFT,
69+ Rtsf512 = 2<<RtsfSHIFT,
70+ Rtsf1024 = 3<<RtsfSHIFT,
71+ RtsfSAF = 7<<RtsfSHIFT,
72+};
73+
74+enum { /* Cr */
75+ Init = 0x0001, /* INIT Process Begin */
76+ Strt = 0x0002, /* Start NIC */
77+ Stop = 0x0004, /* Stop NIC */
78+ Rxon = 0x0008, /* Turn on Receive Process */
79+ Txon = 0x0010, /* Turn on Transmit Process */
80+ Tdmd = 0x0020, /* Transmit Poll Demand */
81+ Rdmd = 0x0040, /* Receive Poll Demand */
82+ Eren = 0x0100, /* Early Receive Enable */
83+ Fdx = 0x0400, /* Set MAC to Full Duplex Mode */
84+ Dpoll = 0x0800, /* Disable Td/Rd Auto Polling */
85+ Tdmd1 = 0x2000, /* Transmit Poll Demand 1 */
86+ Rdmd1 = 0x4000, /* Receive Poll Demand 1 */
87+ Sfrst = 0x8000, /* Software Reset */
88+};
89+
90+enum { /* Isr/Imr */
91+ Prx = 0x0001, /* Received Packet Successfully */
92+ Ptx = 0x0002, /* Transmitted Packet Successfully */
93+ Rxe = 0x0004, /* Receive Error */
94+ Txe = 0x0008, /* Transmit Error */
95+ Tu = 0x0010, /* Transmit Buffer Underflow */
96+ Ru = 0x0020, /* Receive Buffer Link Error */
97+ Be = 0x0040, /* PCI Bus Error */
98+ Cnt = 0x0080, /* Counter Overflow */
99+ Eri = 0x0100, /* Early Receive Interrupt */
100+ Udfi = 0x0200, /* Tx FIFO Underflow */
101+ Ovfi = 0x0400, /* Receive FIFO Overflow */
102+ Pktrace = 0x0800, /* Hmmm... */
103+ Norbf = 0x1000, /* No Receive Buffers */
104+ Abti = 0x2000, /* Transmission Abort */
105+ Srci = 0x4000, /* Port State Change */
106+ Geni = 0x8000, /* General Purpose Interrupt */
107+};
108+
109+enum { /* Phyadr */
110+ PhyadMASK = 0x1F, /* PHY Address */
111+ PhyadSHIFT = 0,
112+ Mfdc = 0x20, /* Accelerate MDC Speed */
113+ Mpo0 = 0x40, /* MII Polling Timer Interval */
114+ Mpo1 = 0x80,
115+};
116+
117+enum { /* Bcr0 */
118+ DmaMASK = 0x07, /* DMA Length */
119+ DmaSHIFT = 0,
120+ Dma32 = 0<<DmaSHIFT,
121+ Dma64 = 1<<DmaSHIFT,
122+ Dma128 = 2<<DmaSHIFT,
123+ Dma256 = 3<<DmaSHIFT,
124+ Dma512 = 4<<DmaSHIFT,
125+ Dma1024 = 5<<DmaSHIFT,
126+ DmaSAF = 7<<DmaSHIFT,
127+ CrftMASK = 0x38, /* Rx FIFO Threshold */
128+ CrftSHIFT = 3,
129+ Crft64 = 1<<CrftSHIFT,
130+ Crft128 = 2<<CrftSHIFT,
131+ Crft256 = 3<<CrftSHIFT,
132+ Crft512 = 4<<CrftSHIFT,
133+ Crft1024 = 5<<CrftSHIFT,
134+ CrftSAF = 7<<CrftSHIFT,
135+ Extled = 0x40, /* Extra LED Support Control */
136+ Med2 = 0x80, /* Medium Select Control */
137+};
138+
139+enum { /* Bcr1 */
140+ PotMASK = 0x07, /* Polling Timer Interval */
141+ PotSHIFT = 0,
142+ CtftMASK = 0x38, /* Tx FIFO Threshold */
143+ CtftSHIFT = 3,
144+ Ctft64 = 1<<CtftSHIFT,
145+ Ctft128 = 2<<CtftSHIFT,
146+ Ctft256 = 3<<CtftSHIFT,
147+ Ctft512 = 4<<CtftSHIFT,
148+ Ctft1024 = 5<<CtftSHIFT,
149+ CtftSAF = 7<<CtftSHIFT,
150+};
151+
152+enum { /* Miicr */
153+ Mdc = 0x01, /* Clock */
154+ Mdi = 0x02, /* Data In */
155+ Mdo = 0x04, /* Data Out */
156+ Mout = 0x08, /* Output Enable */
157+ Mdpm = 0x10, /* Direct Program Mode Enable */
158+ Wcmd = 0x20, /* Write Enable */
159+ Rcmd = 0x40, /* Read Enable */
160+ Mauto = 0x80, /* Auto Polling Enable */
161+};
162+
163+enum { /* Miiadr */
164+ MadMASK = 0x1F, /* MII Port Address */
165+ MadSHIFT = 0,
166+ Mdone = 0x20, /* Accelerate MDC Speed */
167+ Msrcen = 0x40, /* MII Polling Timer Interval */
168+ Midle = 0x80,
169+};
170+
171+enum { /* Eecsr */
172+ Edo = 0x01, /* Data Out */
173+ Edi = 0x02, /* Data In */
174+ Eck = 0x04, /* Clock */
175+ Ecs = 0x08, /* Chip Select */
176+ Dpm = 0x10, /* Direct Program Mode Enable */
177+ Autold = 0x20, /* Dynamic Reload */
178+ Embp = 0x40, /* Embedded Program Enable */
179+ Eepr = 0x80, /* Programmed */
180+};
181+
182+/*
183+ * Ring descriptor. The space allocated for each
184+ * of these will be rounded up to a cache-line boundary.
185+ * The first 4 elements are known to the hardware.
186+ */
187+typedef struct Ds Ds;
188+typedef struct Ds {
189+ uint status;
190+ uint control;
191+ uint addr;
192+ uint branch;
193+
194+ Block* bp;
195+ void* bounce;
196+ Ds* next;
197+ Ds* prev;
198+} Ds;
199+
200+enum { /* Rx Ds status */
201+ Rerr = 0x00000001, /* Receiver Error */
202+ Crc = 0x00000002, /* CRC Error */
203+ Fae = 0x00000004, /* Frame Alignment Error */
204+ Fov = 0x00000008, /* FIFO Overflow */
205+ Long = 0x00000010, /* A Long Packet */
206+ Runt = 0x00000020, /* A Runt Packet */
207+ Rxserr = 0x00000040, /* System Error */
208+ Buff = 0x00000080, /* Buffer Underflow Error */
209+ Rxedp = 0x00000100, /* End of Packet Buffer */
210+ Rxstp = 0x00000200, /* Packet Start */
211+ Chn = 0x00000400, /* Chain Buffer */
212+ Phy = 0x00000800, /* Physical Address Packet */
213+ Bar = 0x00001000, /* Broadcast Packet */
214+ Mar = 0x00002000, /* Multicast Packet */
215+ Rxok = 0x00008000, /* Packet Received Successfully */
216+ LengthMASK = 0x07FF0000, /* Received Packet Length */
217+ LengthSHIFT = 16,
218+
219+ Own = 0x80000000, /* Descriptor Owned by NIC */
220+};
221+
222+enum { /* Tx Ds status */
223+ NcrMASK = 0x0000000F, /* Collision Retry Count */
224+ NcrSHIFT = 0,
225+ Cols = 0x00000010, /* Experienced Collisions */
226+ Cdh = 0x00000080, /* CD Heartbeat */
227+ Abt = 0x00000100, /* Aborted after Excessive Collisions */
228+ Owc = 0x00000200, /* Out of Window Collision Seen */
229+ Crs = 0x00000400, /* Carrier Sense Lost */
230+ Udf = 0x00000800, /* FIFO Underflow */
231+ Tbuff = 0x00001000, /* Invalid Td */
232+ Txserr = 0x00002000, /* System Error */
233+ Terr = 0x00008000, /* Excessive Collisions */
234+};
235+
236+enum { /* Tx Ds control */
237+ TbsMASK = 0x000007FF, /* Tx Buffer Size */
238+ TbsSHIFT = 0,
239+ Chain = 0x00008000, /* Chain Buffer */
240+ Crcdisable = 0x00010000, /* Disable CRC generation */
241+ Stp = 0x00200000, /* Start of Packet */
242+ Edp = 0x00400000, /* End of Packet */
243+ Ic = 0x00800000, /* Assert Interrupt Immediately */
244+};
245+
246+enum {
247+ Nrd = 64,
248+ Ntd = 64,
249+ Rdbsz = ROUNDUP(ETHERMAXTU+4, 4),
250+
251+ Nrxstats = 8,
252+ Ntxstats = 9,
253+
254+ Txcopy = 128,
255+};
256+
257+typedef struct Ctlr Ctlr;
258+typedef struct Ctlr {
259+ int port;
260+ Pcidev* pcidev;
261+ Ctlr* next;
262+ int active;
263+ int id;
264+ uchar par[Eaddrlen];
265+
266+ QLock alock; /* attach */
267+ void* alloc; /* receive/transmit descriptors */
268+ int cls; /* alignment */
269+ int nrd;
270+ int ntd;
271+
272+ Ds* rd;
273+ Ds* rdh;
274+
275+ Lock tlock;
276+ Ds* td;
277+ Ds* tdh;
278+ Ds* tdt;
279+ int tdused;
280+
281+ Lock clock; /* */
282+ int cr;
283+ int imr;
284+ int tft; /* Tx threshold */
285+
286+ Mii* mii;
287+ Rendez lrendez;
288+ int lwakeup;
289+
290+ uint rxstats[Nrxstats]; /* statistics */
291+ uint txstats[Ntxstats];
292+ uint intr;
293+ uint lintr;
294+ uint lsleep;
295+ uint rintr;
296+ uint tintr;
297+ uint taligned;
298+ uint tsplit;
299+ uint tcopied;
300+ uint txdw;
301+} Ctlr;
302+
303+static Ctlr* vt6102ctlrhead;
304+static Ctlr* vt6102ctlrtail;
305+
306+#define csr8r(c, r) (inb((c)->port+(r)))
307+#define csr16r(c, r) (ins((c)->port+(r)))
308+#define csr32r(c, r) (inl((c)->port+(r)))
309+#define csr8w(c, r, b) (outb((c)->port+(r), (int)(b)))
310+#define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w)))
311+#define csr32w(c, r, w) (outl((c)->port+(r), (ulong)(w)))
312+
313+static char* rxstats[Nrxstats] = {
314+ "Receiver Error",
315+ "CRC Error",
316+ "Frame Alignment Error",
317+ "FIFO Overflow",
318+ "Long Packet",
319+ "Runt Packet",
320+ "System Error",
321+ "Buffer Underflow Error",
322+};
323+static char* txstats[Ntxstats] = {
324+ "Aborted after Excessive Collisions",
325+ "Out of Window Collision Seen",
326+ "Carrier Sense Lost",
327+ "FIFO Underflow",
328+ "Invalid Td",
329+ "System Error",
330+ nil,
331+ "Excessive Collisions",
332+};
333+
334+static long
335+vt6102ifstat(Ether* edev, void* a, long n, ulong offset)
336+{
337+ char *p;
338+ Ctlr *ctlr;
339+ int i, l, r;
340+
341+ ctlr = edev->ctlr;
342+
343+ p = malloc(2*READSTR);
344+ l = 0;
345+ for(i = 0; i < Nrxstats; i++){
346+ l += snprint(p+l, 2*READSTR-l, "%s: %ud\n",
347+ rxstats[i], ctlr->rxstats[i]);
348+ }
349+ for(i = 0; i < Ntxstats; i++){
350+ if(txstats[i] == nil)
351+ continue;
352+ l += snprint(p+l, 2*READSTR-l, "%s: %ud\n",
353+ txstats[i], ctlr->txstats[i]);
354+ }
355+ l += snprint(p+l, 2*READSTR-l, "cls: %ud\n", ctlr->cls);
356+ l += snprint(p+l, 2*READSTR-l, "intr: %ud\n", ctlr->intr);
357+ l += snprint(p+l, 2*READSTR-l, "lintr: %ud\n", ctlr->lintr);
358+ l += snprint(p+l, 2*READSTR-l, "lsleep: %ud\n", ctlr->lsleep);
359+ l += snprint(p+l, 2*READSTR-l, "rintr: %ud\n", ctlr->rintr);
360+ l += snprint(p+l, 2*READSTR-l, "tintr: %ud\n", ctlr->tintr);
361+ l += snprint(p+l, 2*READSTR-l, "taligned: %ud\n", ctlr->taligned);
362+ l += snprint(p+l, 2*READSTR-l, "tsplit: %ud\n", ctlr->tsplit);
363+ l += snprint(p+l, 2*READSTR-l, "tcopied: %ud\n", ctlr->tcopied);
364+ l += snprint(p+l, 2*READSTR-l, "txdw: %ud\n", ctlr->txdw);
365+ l += snprint(p+l, 2*READSTR-l, "tft: %ud\n", ctlr->tft);
366+
367+ if(ctlr->mii != nil && ctlr->mii->curphy != nil){
368+ l += snprint(p+l, 2*READSTR, "phy: ");
369+ for(i = 0; i < NMiiPhyr; i++){
370+ if(i && ((i & 0x07) == 0))
371+ l += snprint(p+l, 2*READSTR-l, "\n ");
372+ r = miimir(ctlr->mii, i);
373+ l += snprint(p+l, 2*READSTR-l, " %4.4uX", r);
374+ }
375+ snprint(p+l, 2*READSTR-l, "\n");
376+ }
377+ snprint(p+l, 2*READSTR-l, "\n");
378+
379+ n = readstr(offset, a, n, p);
380+ free(p);
381+
382+ return n;
383+}
384+
385+static void
386+vt6102promiscuous(void* arg, int on)
387+{
388+ int rcr;
389+ Ctlr *ctlr;
390+ Ether *edev;
391+
392+ edev = arg;
393+ ctlr = edev->ctlr;
394+ rcr = csr8r(ctlr, Rcr);
395+ if(on)
396+ rcr |= Prom;
397+ else
398+ rcr &= ~Prom;
399+ csr8w(ctlr, Rcr, rcr);
400+}
401+
402+static void
403+vt6102multicast(void* arg, uchar* addr, int on)
404+{
405+ /*
406+ * For now Am is set in Rcr.
407+ * Will need to interlock with promiscuous
408+ * when this gets filled in.
409+ */
410+ USED(arg, addr, on);
411+}
412+
413+static int
414+vt6102wakeup(void* v)
415+{
416+ return *((int*)v) != 0;
417+}
418+
419+static void
420+vt6102imr(Ctlr* ctlr, int imr)
421+{
422+ ilock(&ctlr->clock);
423+ ctlr->imr |= imr;
424+ csr16w(ctlr, Imr, ctlr->imr);
425+ iunlock(&ctlr->clock);
426+}
427+
428+static void
429+vt6102lproc(void* arg)
430+{
431+ Ctlr *ctlr;
432+ Ether *edev;
433+ MiiPhy *phy;
434+
435+ edev = arg;
436+ ctlr = edev->ctlr;
437+ for(;;){
438+ if(ctlr->mii == nil || ctlr->mii->curphy == nil)
439+ break;
440+ if(miistatus(ctlr->mii) < 0)
441+ goto enable;
442+
443+ phy = ctlr->mii->curphy;
444+ ilock(&ctlr->clock);
445+ if(phy->fd)
446+ ctlr->cr |= Fdx;
447+ else
448+ ctlr->cr &= ~Fdx;
449+ csr16w(ctlr, Cr, ctlr->cr);
450+ iunlock(&ctlr->clock);
451+enable:
452+ ctlr->lwakeup = 0;
453+ vt6102imr(ctlr, Srci);
454+
455+ ctlr->lsleep++;
456+ sleep(&ctlr->lrendez, vt6102wakeup, &ctlr->lwakeup);
457+
458+ }
459+ pexit("vt6102lproc: done", 1);
460+}
461+
462+static void
463+vt6102attach(Ether* edev)
464+{
465+ int i;
466+ Ctlr *ctlr;
467+ Ds *ds, *prev;
468+ uchar *alloc, *bounce;
469+ char name[KNAMELEN];
470+
471+ ctlr = edev->ctlr;
472+ qlock(&ctlr->alock);
473+ if(ctlr->alloc != nil){
474+ qunlock(&ctlr->alock);
475+ return;
476+ }
477+
478+ /*
479+ * Descriptor and bounce-buffer space.
480+ * Must all be aligned on a 4-byte boundary,
481+ * but try to align on cache-lines.
482+ */
483+ ctlr->nrd = Nrd;
484+ ctlr->ntd = Ntd;
485+ alloc = malloc((ctlr->nrd+ctlr->ntd)*ctlr->cls + ctlr->ntd*Txcopy + ctlr->cls-1);
486+ if(alloc == nil){
487+ qunlock(&ctlr->alock);
488+ return;
489+ }
490+ ctlr->alloc = alloc;
491+ alloc = (uchar*)ROUNDUP((ulong)alloc, ctlr->cls);
492+
493+ ctlr->rd = (Ds*)alloc;
494+
495+ if(waserror()){
496+ ds = ctlr->rd;
497+ for(i = 0; i < ctlr->nrd; i++){
498+ if(ds->bp != nil){
499+ freeb(ds->bp);
500+ ds->bp = nil;
501+ }
502+ if((ds = ds->next) == nil)
503+ break;
504+ }
505+ free(ctlr->alloc);
506+ ctlr->alloc = nil;
507+ qunlock(&ctlr->alock);
508+ nexterror();
509+ }
510+
511+ prev = ctlr->rd + ctlr->nrd-1;
512+ for(i = 0; i < ctlr->nrd; i++){
513+ ds = (Ds*)alloc;
514+ alloc += ctlr->cls;
515+
516+ ds->control = Rdbsz;
517+ ds->branch = PCIWADDR(alloc);
518+
519+ ds->bp = iallocb(Rdbsz+3);
520+ if(ds->bp == nil)
521+ error("vt6102: can't allocate receive ring\n");
522+ ds->bp->rp = (uchar*)ROUNDUP((ulong)ds->bp->rp, 4);
523+ ds->addr = PCIWADDR(ds->bp->rp);
524+
525+ ds->next = (Ds*)alloc;
526+ ds->prev = prev;
527+ prev = ds;
528+
529+ ds->status = Own;
530+ }
531+ prev->branch = 0;
532+ prev->next = ctlr->rd;
533+ prev->status = 0;
534+ ctlr->rdh = ctlr->rd;
535+
536+ ctlr->td = (Ds*)alloc;
537+ prev = ctlr->td + ctlr->ntd-1;
538+ bounce = alloc + ctlr->ntd*ctlr->cls;
539+ for(i = 0; i < ctlr->ntd; i++){
540+ ds = (Ds*)alloc;
541+ alloc += ctlr->cls;
542+
543+ ds->bounce = bounce;
544+ bounce += Txcopy;
545+ ds->next = (Ds*)alloc;
546+ ds->prev = prev;
547+ prev = ds;
548+ }
549+ prev->next = ctlr->td;
550+ ctlr->tdh = ctlr->tdt = ctlr->td;
551+ ctlr->tdused = 0;
552+
553+ ctlr->cr = Dpoll|Rdmd|Txon|Rxon|Strt;
554+ /*Srci|Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx*/
555+ ctlr->imr = Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx;
556+
557+ ilock(&ctlr->clock);
558+ csr32w(ctlr, Rxdaddr, PCIWADDR(ctlr->rd));
559+ csr32w(ctlr, Txdaddr, PCIWADDR(ctlr->td));
560+ csr16w(ctlr, Isr, ~0);
561+ csr16w(ctlr, Imr, ctlr->imr);
562+ csr16w(ctlr, Cr, ctlr->cr);
563+ iunlock(&ctlr->clock);
564+
565+ snprint(name, KNAMELEN, "#l%dlproc", edev->ctlrno);
566+ kproc(name, vt6102lproc, edev, 0);
567+
568+ qunlock(&ctlr->alock);
569+ poperror();
570+}
571+
572+static void
573+vt6102transmit(Ether* edev)
574+{
575+ Block *bp;
576+ Ctlr *ctlr;
577+ Ds *ds, *next;
578+ int control, i, o, prefix, size, tdused, timeo;
579+
580+ ctlr = edev->ctlr;
581+
582+ ilock(&ctlr->tlock);
583+
584+ /*
585+ * Free any completed packets
586+ */
587+ ds = ctlr->tdh;
588+ for(tdused = ctlr->tdused; tdused > 0; tdused--){
589+ /*
590+ * For some errors the chip will turn the Tx engine
591+ * off. Wait for that to happen.
592+ * Could reset and re-init the chip here if it doesn't
593+ * play fair.
594+ * To do: adjust Tx FIFO threshold on underflow.
595+ */
596+ if(ds->status & (Abt|Tbuff|Udf)){
597+ for(timeo = 0; timeo < 1000; timeo++){
598+ if(!(csr16r(ctlr, Cr) & Txon))
599+ break;
600+ microdelay(1);
601+ }
602+ ds->status = Own;
603+ csr32w(ctlr, Txdaddr, PCIWADDR(ds));
604+ }
605+
606+ if(ds->status & Own)
607+ break;
608+ ds->addr = 0;
609+ ds->branch = 0;
610+
611+ if(ds->bp != nil){
612+ freeb(ds->bp);
613+ ds->bp = nil;
614+ }
615+ for(i = 0; i < Ntxstats-1; i++){
616+ if(ds->status & (1<<i))
617+ ctlr->txstats[i]++;
618+ }
619+ ctlr->txstats[i] += (ds->status & NcrMASK)>>NcrSHIFT;
620+
621+ ds = ds->next;
622+ }
623+ ctlr->tdh = ds;
624+
625+ /*
626+ * Try to fill the ring back up.
627+ */
628+ ds = ctlr->tdt;
629+ while(tdused < ctlr->ntd-2){
630+ if((bp = qget(edev->oq)) == nil)
631+ break;
632+ tdused++;
633+
634+ size = BLEN(bp);
635+ prefix = 0;
636+
637+ if(o = (((int)bp->rp) & 0x03)){
638+ prefix = Txcopy-o;
639+ if(prefix > size)
640+ prefix = size;
641+ memmove(ds->bounce, bp->rp, prefix);
642+ ds->addr = PCIWADDR(ds->bounce);
643+ bp->rp += prefix;
644+ size -= prefix;
645+ }
646+
647+ next = ds->next;
648+ ds->branch = PCIWADDR(ds->next);
649+
650+ if(size){
651+ if(prefix){
652+ next->bp = bp;
653+ next->addr = PCIWADDR(bp->rp);
654+ next->branch = PCIWADDR(next->next);
655+ next->control = Edp|Chain|((size<<TbsSHIFT) & TbsMASK);
656+
657+ control = Stp|Chain|((prefix<<TbsSHIFT) & TbsMASK);
658+
659+ next = next->next;
660+ tdused++;
661+ ctlr->tsplit++;
662+ }
663+ else{
664+ ds->bp = bp;
665+ ds->addr = PCIWADDR(bp->rp);
666+ control = Edp|Stp|((size<<TbsSHIFT) & TbsMASK);
667+ ctlr->taligned++;
668+ }
669+ }
670+ else{
671+ freeb(bp);
672+ control = Edp|Stp|((prefix<<TbsSHIFT) & TbsMASK);
673+ ctlr->tcopied++;
674+ }
675+
676+ ds->control = control;
677+ if(tdused >= ctlr->ntd-2){
678+ ds->control |= Ic;
679+ ctlr->txdw++;
680+ }
681+ coherence();
682+ ds->status = Own;
683+
684+ ds = next;
685+ }
686+ ctlr->tdt = ds;
687+ ctlr->tdused = tdused;
688+ if(ctlr->tdused)
689+ csr16w(ctlr, Cr, Tdmd|ctlr->cr);
690+
691+ iunlock(&ctlr->tlock);
692+}
693+
694+static void
695+vt6102receive(Ether* edev)
696+{
697+ Ds *ds;
698+ Block *bp;
699+ Ctlr *ctlr;
700+ int i, len;
701+
702+ ctlr = edev->ctlr;
703+
704+ ds = ctlr->rdh;
705+ while(!(ds->status & Own) && ds->status != 0){
706+ if(ds->status & Rerr){
707+ for(i = 0; i < Nrxstats; i++){
708+ if(ds->status & (1<<i))
709+ ctlr->rxstats[i]++;
710+ }
711+ }
712+ else if(bp = iallocb(Rdbsz+3)){
713+ len = ((ds->status & LengthMASK)>>LengthSHIFT)-4;
714+ ds->bp->wp = ds->bp->rp+len;
715+ etheriq(edev, ds->bp, 1);
716+ bp->rp = (uchar*)ROUNDUP((ulong)bp->rp, 4);
717+ ds->addr = PCIWADDR(bp->rp);
718+ ds->bp = bp;
719+ }
720+ ds->control = Rdbsz;
721+ ds->branch = 0;
722+ ds->status = 0;
723+
724+ ds->prev->branch = PCIWADDR(ds);
725+ coherence();
726+ ds->prev->status = Own;
727+
728+ ds = ds->next;
729+ }
730+ ctlr->rdh = ds;
731+
732+ csr16w(ctlr, Cr, ctlr->cr);
733+}
734+
735+static void
736+vt6102interrupt(Ureg*, void* arg)
737+{
738+ Ctlr *ctlr;
739+ Ether *edev;
740+ int imr, isr, r, timeo;
741+
742+ edev = arg;
743+ ctlr = edev->ctlr;
744+
745+ ilock(&ctlr->clock);
746+ csr16w(ctlr, Imr, 0);
747+ imr = ctlr->imr;
748+ ctlr->intr++;
749+ for(;;){
750+ if((isr = csr16r(ctlr, Isr)) != 0)
751+ csr16w(ctlr, Isr, isr);
752+ if((isr & ctlr->imr) == 0)
753+ break;
754+
755+ if(isr & Srci){
756+ imr &= ~Srci;
757+ ctlr->lwakeup = isr & Srci;
758+ wakeup(&ctlr->lrendez);
759+ isr &= ~Srci;
760+ ctlr->lintr++;
761+ }
762+ if(isr & (Norbf|Pktrace|Ovfi|Ru|Rxe|Prx)){
763+ vt6102receive(edev);
764+ isr &= ~(Norbf|Pktrace|Ovfi|Ru|Rxe|Prx);
765+ ctlr->rintr++;
766+ }
767+ if(isr & (Abti|Udfi|Tu|Txe|Ptx)){
768+ if(isr & (Abti|Udfi|Tu)){
769+ for(timeo = 0; timeo < 1000; timeo++){
770+ if(!(csr16r(ctlr, Cr) & Txon))
771+ break;
772+ microdelay(1);
773+ }
774+
775+ if((isr & Udfi) && ctlr->tft < CtftSAF){
776+ ctlr->tft += 1<<CtftSHIFT;
777+ r = csr8r(ctlr, Bcr1) & ~CtftMASK;
778+ csr8w(ctlr, Bcr1, r|ctlr->tft);
779+ }
780+ }
781+ vt6102transmit(edev);
782+ isr &= ~(Abti|Udfi|Tu|Txe|Ptx);
783+ ctlr->tintr++;
784+ }
785+ if(isr)
786+ panic("vt6102: isr %4.4uX\n", isr);
787+ }
788+ ctlr->imr = imr;
789+ csr16w(ctlr, Imr, ctlr->imr);
790+ iunlock(&ctlr->clock);
791+}
792+
793+static int
794+vt6102miimicmd(Mii* mii, int pa, int ra, int cmd, int data)
795+{
796+ Ctlr *ctlr;
797+ int r, timeo;
798+
799+ ctlr = mii->ctlr;
800+
801+ csr8w(ctlr, Miicr, 0);
802+ r = csr8r(ctlr, Phyadr);
803+ csr8w(ctlr, Phyadr, (r & ~PhyadMASK)|pa);
804+ csr8w(ctlr, Phyadr, pa);
805+ csr8w(ctlr, Miiadr, ra);
806+ if(cmd == Wcmd)
807+ csr16w(ctlr, Miidata, data);
808+ csr8w(ctlr, Miicr, cmd);
809+
810+ for(timeo = 0; timeo < 10000; timeo++){
811+ if(!(csr8r(ctlr, Miicr) & cmd))
812+ break;
813+ microdelay(1);
814+ }
815+ if(timeo >= 10000)
816+ return -1;
817+
818+ if(cmd == Wcmd)
819+ return 0;
820+ return csr16r(ctlr, Miidata);
821+}
822+
823+static int
824+vt6102miimir(Mii* mii, int pa, int ra)
825+{
826+ return vt6102miimicmd(mii, pa, ra, Rcmd, 0);
827+}
828+
829+static int
830+vt6102miimiw(Mii* mii, int pa, int ra, int data)
831+{
832+ return vt6102miimicmd(mii, pa, ra, Wcmd, data);
833+}
834+
835+static int
836+vt6102detach(Ctlr* ctlr)
837+{
838+ int timeo;
839+
840+ /*
841+ * Soft reset the controller.
842+ */
843+ csr16w(ctlr, Cr, Sfrst);
844+ for(timeo = 0; timeo < 10000; timeo++){
845+ if(!(csr16r(ctlr, Cr) & Sfrst))
846+ break;
847+ microdelay(1);
848+ }
849+ if(timeo >= 1000)
850+ return -1;
851+
852+ return 0;
853+}
854+
855+static int
856+vt6102reset(Ctlr* ctlr)
857+{
858+ MiiPhy *phy;
859+ int i, r, timeo;
860+
861+ if(vt6102detach(ctlr) < 0)
862+ return -1;
863+
864+ /*
865+ * Load the MAC address into the PAR[01]
866+ * registers.
867+ */
868+ r = csr8r(ctlr, Eecsr);
869+ csr8w(ctlr, Eecsr, Autold|r);
870+ for(timeo = 0; timeo < 100; timeo++){
871+ if(!(csr8r(ctlr, Cr) & Autold))
872+ break;
873+ microdelay(1);
874+ }
875+ if(timeo >= 100)
876+ return -1;
877+
878+ for(i = 0; i < Eaddrlen; i++)
879+ ctlr->par[i] = csr8r(ctlr, Par0+i);
880+
881+ /*
882+ * Configure DMA and Rx/Tx thresholds.
883+ * If the Rx/Tx threshold bits in Bcr[01] are 0 then
884+ * the thresholds are determined by Rcr/Tcr.
885+ */
886+ r = csr8r(ctlr, Bcr0) & ~(CrftMASK|DmaMASK);
887+ csr8w(ctlr, Bcr0, r|Crft64|Dma64);
888+ r = csr8r(ctlr, Bcr1) & ~CtftMASK;
889+ csr8w(ctlr, Bcr1, r|ctlr->tft);
890+
891+ r = csr8r(ctlr, Rcr) & ~(RrftMASK|Prom|Ar|Sep);
892+ csr8w(ctlr, Rcr, r|Ab|Am);
893+
894+ r = csr8r(ctlr, Tcr) & ~(RtsfMASK|Ofset|Lb1|Lb0);
895+ csr8w(ctlr, Tcr, r);
896+
897+ /*
898+ * Link management.
899+ */
900+ if((ctlr->mii = malloc(sizeof(Mii))) == nil)
901+ return -1;
902+ ctlr->mii->mir = vt6102miimir;
903+ ctlr->mii->miw = vt6102miimiw;
904+ ctlr->mii->ctlr = ctlr;
905+
906+ if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){
907+ free(ctlr->mii);
908+ ctlr->mii = nil;
909+ return -1;
910+ }
911+ // print("oui %X phyno %d\n", phy->oui, phy->phyno);
912+ USED(phy);
913+
914+ //miiane(ctlr->mii, ~0, ~0, ~0);
915+
916+ return 0;
917+}
918+
919+static void
920+vt6102pci(void)
921+{
922+ Pcidev *p;
923+ Ctlr *ctlr;
924+ int cls, port;
925+
926+ p = nil;
927+ while(p = pcimatch(p, 0, 0)){
928+ if(p->ccrb != Pcibcnet || p->ccru != Pciscether)
929+ continue;
930+
931+ switch((p->did<<16)|p->vid){
932+ default:
933+ continue;
934+ case (0x3065<<16)|0x1106: /* Rhine II */
935+ case (0x3106<<16)|0x1106: /* Rhine III */
936+ break;
937+ }
938+
939+ port = p->mem[0].bar & ~0x01;
940+ if(ioalloc(port, p->mem[0].size, 0, "vt6102") < 0){
941+ print("vt6102: port 0x%uX in use\n", port);
942+ continue;
943+ }
944+ ctlr = malloc(sizeof(Ctlr));
945+ ctlr->port = port;
946+ ctlr->pcidev = p;
947+ ctlr->id = (p->did<<16)|p->vid;
948+ if((cls = pcicfgr8(p, PciCLS)) == 0 || cls == 0xFF)
949+ cls = 0x10;
950+ ctlr->cls = cls*4;
951+ if(ctlr->cls < sizeof(Ds)){
952+ print("vt6102: cls %d < sizeof(Ds)\n", ctlr->cls);
953+ iofree(port);
954+ free(ctlr);
955+ continue;
956+ }
957+ ctlr->tft = Ctft64;
958+
959+ if(vt6102reset(ctlr)){
960+ iofree(port);
961+ free(ctlr);
962+ continue;
963+ }
964+ pcisetbme(p);
965+
966+ if(vt6102ctlrhead != nil)
967+ vt6102ctlrtail->next = ctlr;
968+ else
969+ vt6102ctlrhead = ctlr;
970+ vt6102ctlrtail = ctlr;
971+ }
972+}
973+
974+static int
975+vt6102pnp(Ether* edev)
976+{
977+ Ctlr *ctlr;
978+
979+ if(vt6102ctlrhead == nil)
980+ vt6102pci();
981+
982+ /*
983+ * Any adapter matches if no edev->port is supplied,
984+ * otherwise the ports must match.
985+ */
986+ for(ctlr = vt6102ctlrhead; ctlr != nil; ctlr = ctlr->next){
987+ if(ctlr->active)
988+ continue;
989+ if(edev->port == 0 || edev->port == ctlr->port){
990+ ctlr->active = 1;
991+ break;
992+ }
993+ }
994+ if(ctlr == nil)
995+ return -1;
996+
997+ edev->ctlr = ctlr;
998+ edev->port = ctlr->port;
999+ edev->irq = ctlr->pcidev->intl;
1000+ edev->tbdf = ctlr->pcidev->tbdf;
1001+ edev->mbps = 100;
1002+ memmove(edev->ea, ctlr->par, Eaddrlen);
1003+
1004+ /*
1005+ * Linkage to the generic ethernet driver.
1006+ */
1007+ edev->attach = vt6102attach;
1008+ edev->transmit = vt6102transmit;
1009+ edev->interrupt = vt6102interrupt;
1010+ edev->ifstat = vt6102ifstat;
1011+ edev->ctl = nil;
1012+
1013+ edev->arg = edev;
1014+ edev->promiscuous = vt6102promiscuous;
1015+ edev->multicast = vt6102multicast;
1016+
1017+ return 0;
1018+}
1019+
1020+void
1021+ethervt6102link(void)
1022+{
1023+ addethercard("vt6102", vt6102pnp);
1024+ addethercard("rhine", vt6102pnp);
1025+}
os/pc/etherwavelan.c+6−5
@@ -87,6 +87,7 @@ static struct { · 86 unmodified lines
8787 int did;
8888 } wavelanpci[] = {
8989 0x1260, 0x3873, /* Intersil Prism2.5 */
90+ 0x1737, 0x0019, /* Linksys WPC-11 untested */
9091 };
9192
9293 static Ctlr *ctlrhead, *ctlrtail;
@@ -95,7 +96,7 @@ static void · 2 unmodified lines
9596 wavelanpciscan(void)
9697 {
9798 int i;
98− ulong pa;
99+ void *mem;
99100 Pcidev *p;
100101 Ctlr *ctlr;
101102
@@ -117,13 +118,13 @@ wavelanpciscan(void) · 15 unmodified lines
117118
118119 ctlr = malloc(sizeof(Ctlr));
119120 ctlr->pcidev = p;
120− pa = upamalloc(p->mem[0].bar&~0xF, p->mem[0].size, 0);
121− if(pa == 0){
122− print("wavelanpci: %.4ux %.4ux: upamalloc 0x%.8lux %d failed\n", p->vid, p->did, p->mem[0].bar&~0xF, p->mem[0].size);
121+ mem = vmap(p->mem[0].bar&~0xF, p->mem[0].size);
122+ if(mem == nil){
123+ print("wavelanpci: %.4ux %.4ux: vmap 0x%.8lux %d failed\n", p->vid, p->did, p->mem[0].bar&~0xF, p->mem[0].size);
123124 free(ctlr);
124125 continue;
125126 }
126− ctlr->mmb = (ushort*)KADDR(pa);
127+ ctlr->mmb = mem;
127128 if(ctlrhead != nil)
128129 ctlrtail->next = ctlr;
129130 else
os/pc/fns.h+4−0
@@ -104,6 +104,7 @@ void pcicfgw16(Pcidev*, int, int); · 103 unmodified lines
104104 void pcicfgw32(Pcidev*, int, int);
105105 void pciclrbme(Pcidev*);
106106 void pciclrioe(Pcidev*);
107+void pciclrmwi(Pcidev*);
107108 int pcigetpms(Pcidev*);
108109 void pcihinv(Pcidev*);
109110 uchar pciipin(Pcidev*, uchar);
@@ -144,7 +145,10 @@ ulong umbrwmalloc(ulong, int, int); · 34 unmodified lines
144145 void umbrwfree(ulong, int);
145146 ulong upamalloc(ulong, int, int);
146147 void upafree(ulong, int);
148+void upareserve(ulong, int);
147149 void vectortable(void);
150+void* vmap(ulong, int);
151+void vunmap(void*, int);
148152 void wrmsr(ulong, ulong);
149153 int xchgw(ushort*, int);
150154 ulong kzeromap(ulong, ulong, int);
os/pc/i8253.c+1−1
@@ -201,7 +201,7 @@ i8253timerset(uvlong next) · 200 unmodified lines
201201 period = want - now;
202202 if(period < MinPeriod)
203203 period = MinPeriod;
204− else if(period > (4*MaxPeriod)/5) /* strong attraction to MaxPeriod */
204+ else if(period > MaxPeriod)
205205 period = MaxPeriod;
206206 }
207207
os/pc/io.h+49−1
@@ -95,7 +95,7 @@ enum { · 94 unmodified lines
9595 /*
9696 * PCI support code.
9797 */
98−enum { /* type 0 and type 1 pre-defined header */
98+enum { /* type 0 & type 1 pre-defined header */
9999 PciVID = 0x00, /* vendor ID */
100100 PciDID = 0x02, /* device ID */
101101 PciPCR = 0x04, /* command */
@@ -116,6 +116,54 @@ enum { /* type 0 and type 1 pre-defined header */ · 14 unmodified lines
116116 PciINTP = 0x3D, /* interrupt pin */
117117 };
118118
119+/* ccrb (base class code) values; controller types */
120+enum {
121+ Pcibcpci1 = 0, /* pci 1.0; no class codes defined */
122+ Pcibcstore = 1, /* mass storage */
123+ Pcibcnet = 2, /* network */
124+ Pcibcdisp = 3, /* display */
125+ Pcibcmmedia = 4, /* multimedia */
126+ Pcibcmem = 5, /* memory */
127+ Pcibcbridge = 6, /* bridge */
128+ Pcibccomm = 7, /* simple comms (e.g., serial) */
129+ Pcibcbasesys = 8, /* base system */
130+ Pcibcinput = 9, /* input */
131+ Pcibcdock = 0xa, /* docking stations */
132+ Pcibcproc = 0xb, /* processors */
133+ Pcibcserial = 0xc, /* serial bus (e.g., USB) */
134+ Pcibcwireless = 0xd, /* wireless */
135+ Pcibcintell = 0xe, /* intelligent i/o */
136+ Pcibcsatcom = 0xf, /* satellite comms */
137+ Pcibccrypto = 0x10, /* encryption/decryption */
138+ Pcibcdacq = 0x11, /* data acquisition & signal proc. */
139+};
140+
141+/* ccru (sub-class code) values; common cases only */
142+enum {
143+ /* mass storage */
144+ Pciscscsi = 0, /* SCSI */
145+ Pciscide = 1, /* IDE (ATA) */
146+
147+ /* network */
148+ Pciscether = 0, /* Ethernet */
149+
150+ /* display */
151+ Pciscvga = 0, /* VGA */
152+ Pciscxga = 1, /* XGA */
153+ Pcisc3d = 2, /* 3D */
154+
155+ /* bridges */
156+ Pcischostpci = 0, /* host/pci */
157+ Pciscpcicpci = 1, /* pci/pci */
158+
159+ /* simple comms */
160+ Pciscserial = 0, /* 16450, etc. */
161+ Pciscmultiser = 1, /* multiport serial */
162+
163+ /* serial bus */
164+ Pciscusb = 3, /* USB */
165+};
166+
119167 enum { /* type 0 pre-defined header */
120168 PciCIS = 0x28, /* cardbus CIS pointer */
121169 PciSVID = 0x2C, /* subsystem vendor ID */
os/pc/memory.c+18−0
@@ -568,3 +568,21 @@ upafree(ulong pa, int size) · 567 unmodified lines
568568 {
569569 mapfree(&xrmapupa, pa, size);
570570 }
571+
572+void
573+upareserve(ulong pa, int size)
574+{
575+ ulong a;
576+
577+ a = mapalloc(&rmapupa, pa, size, 0);
578+ if(a != pa){
579+ /*
580+ * This can happen when we're using the E820
581+ * map, which might have already reserved some
582+ * of the regions claimed by the pci devices.
583+ */
584+ // print("upareserve: cannot reserve pa=%#.8lux size=%d\n", pa, size);
585+ if(a != 0)
586+ mapfree(&rmapupa, a, size);
587+ }
588+}
os/pc/mmu.c+16−0
@@ -319,3 +319,19 @@ mmukmap(ulong pa, ulong va, int size) · 318 unmodified lines
319319
320320 return pa;
321321 }
322+
323+void*
324+vmap(ulong pa, int size)
325+{
326+ pa = upamalloc(pa, size, 0);
327+ if(pa == 0)
328+ return nil;
329+ return KADDR(pa);
330+}
331+
332+void
333+vunmap(void *va, int size)
334+{
335+ if(va != nil)
336+ upafree(PADDR(va), size);
337+}
os/pc/pci.c+0−1
@@ -176,7 +176,6 @@ pcibusmap(Pcidev *root, ulong *pmema, ulong *pioa, int wrreg) · 175 unmodified lines
176176 int ntb, i, size, rno, hole;
177177 ulong v, mema, ioa, sioa, smema, base, limit;
178178 Pcisiz *table, *tptr, *mtb, *itb;
179− extern void qsort(void*, long, long, int (*)(void*, void*));
180179
181180 if(!nobios)
182181 return;
os/port/chan.c+17−17
@@ -1297,25 +1297,25 @@ if(c->umh != nil){ · 1296 unmodified lines
12971297 c = cnew;
12981298 c->name = addelem(c->name, e.elems[e.nelems-1]);
12991299 break;
1300− }else{ /* create failed */
1301− cclose(cnew);
1302− if(m)
1303− putmhead(m);
1304− if(omode & OEXCL)
1305− nexterror();
1306− /* save error */
1307− createerr = up->env->errstr;
1308− up->env->errstr = tmperrbuf;
1309− /* note: we depend that walk does not error */
1310− if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) < 0){
1311− up->env->errstr = createerr;
1312− error(createerr); /* report true error */
1313− }
1300+ }
1301+
1302+ /* create failed */
1303+ cclose(cnew);
1304+ if(m)
1305+ putmhead(m);
1306+ if(omode & OEXCL)
1307+ nexterror();
1308+ /* save error */
1309+ createerr = up->env->errstr;
1310+ up->env->errstr = tmperrbuf;
1311+ /* note: we depend that walk does not error */
1312+ if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) < 0){
13141313 up->env->errstr = createerr;
1315− omode |= OTRUNC;
1316− goto Open;
1314+ error(createerr); /* report true error */
13171315 }
1318− panic("namec: not reached");
1316+ up->env->errstr = createerr;
1317+ omode |= OTRUNC;
1318+ goto Open;
13191319
13201320 default:
13211321 panic("unknown namec access %d\n", amode);
os/port/dev.c+0−2
@@ -258,8 +258,6 @@ devstat(Chan *c, uchar *db, int n, Dirtab *tab, int ntab, Devgen *gen) · 257 unmodified lines
258258 }
259259 break;
260260 }
261− error(Egreg); /* not reached? */
262− return -1;
263261 }
264262
265263 long
os/port/ethermii.c+3−3
@@ -177,13 +177,13 @@ miistatus(Mii* mii) · 176 unmodified lines
177177 bmsr = mii->mir(mii, phyno, Bmsr);
178178 if(!(bmsr & (BmsrAnc|BmsrAna)))
179179 {
180−print("miistatus 1\n");
180+print("miistatus: auto-neg incomplete\n");
181181 return -1;
182182 }
183183
184184 bmsr = mii->mir(mii, phyno, Bmsr);
185185 if(!(bmsr & BmsrLs)){
186−print("miistatus 2\n");
186+print("miistatus: link down\n");
187187 phy->link = 0;
188188 return -1;
189189 }
@@ -217,7 +217,7 @@ print("miistatus 2\n"); · 27 unmodified lines
217217 }
218218 if(phy->speed == 0)
219219 {
220−print("miistatus 3\n");
220+print("miistatus: phy speed 0\n");
221221 return -1;
222222 }
223223
os/port/lib.h+3−2
@@ -2,9 +2,9 @@ · 1 unmodified line
22 /*
33 * functions (possibly) linked in, complete, from libc.
44 */
5−#define nelem(n) (sizeof(n)/sizeof(n[0]))
5+#define nelem(x) (sizeof(x)/sizeof((x)[0]))
66 #define offsetof(s, m) (ulong)(&(((s*)0)->m))
7−#define assert(x) if(x){}else _assert("x")
7+#define assert(x) if(x){}else _assert("x")
88
99 /*
1010 * mem routines
@@ -123,6 +123,7 @@ extern char end[]; · 112 unmodified lines
123123 extern int getfields(char*, char**, int, int, char*);
124124 extern int tokenize(char*, char**, int);
125125 extern int dec64(uchar*, int, char*, int);
126+extern void qsort(void*, long, long, int (*)(void*, void*));
126127
127128 extern int toupper(int);
128129 extern char* netmkaddr(char*, char*, char*);