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
982 case 2:982 case 2:
983 return setladdrport(c, argv[1], 1);983 return setladdrport(c, argv[1], 1);
984 }984 }
985 return nil;
986}985}
987 986
988/*987/*
@@ -1033,7 +1032,6 @@ Fsstdbind(Conv* c, char* argv[], int argc) · 44 unmodified lines
1033 case 2:1032 case 2:
1034 return setladdrport(c, argv[1], 0);1033 return setladdrport(c, argv[1], 0);
1035 }1034 }
1036 return nil;
1037}1035}
1038 1036
1039static void1037static void
os/ip/ip.h+0−1
@@ -669,5 +669,4 @@ extern Chan* chandial(char*, char*, char*, Chan**); · 668 unmodified lines
669/*669/*
670 * global to all of the stack670 * global to all of the stack
671 */671 */
672extern int debug;
673extern void (*igmpreportfn)(Ipifc*, uchar*);672extern void (*igmpreportfn)(Ipifc*, uchar*);
os/ip/ipifc.c+44−44
@@ -11,11 +11,11 @@ · 10 unmodified lines
11#define DPRINT if(0)print11#define DPRINT if(0)print
12 12
13enum {13enum {
14 Maxmedia = 32,14 Maxmedia = 32,
15 Nself = Maxmedia*5,15 Nself = Maxmedia*5,
16 NHASH = (1<<6),16 NHASH = (1<<6),
17 NCACHE = 256,17 NCACHE = 256,
18 QMAX = 64*1024-1,18 QMAX = 64*1024-1,
19};19};
20 20
21Medium *media[Maxmedia] =21Medium *media[Maxmedia] =
@@ -135,7 +135,7 @@ ipifcbind(Conv *c, char **argv, int argc) · 113 unmodified lines
135 if(argc > 2)135 if(argc > 2)
136 strncpy(ifc->dev, argv[2], sizeof(ifc->dev));136 strncpy(ifc->dev, argv[2], sizeof(ifc->dev));
137 else137 else
138 sprint(ifc->dev, "%s%d", m->name, c->x);138 snprint(ifc->dev, sizeof ifc->dev, "%s%d", m->name, c->x);
139 ifc->dev[sizeof(ifc->dev)-1] = 0;139 ifc->dev[sizeof(ifc->dev)-1] = 0;
140 140
141 /* set up parameters */141 /* set up parameters */
@@ -144,15 +144,15 @@ ipifcbind(Conv *c, char **argv, int argc) · 2 unmodified lines
144 ifc->maxtu = ifc->m->maxtu;144 ifc->maxtu = ifc->m->maxtu;
145 if(ifc->m->unbindonclose == 0)145 if(ifc->m->unbindonclose == 0)
146 ifc->conv->inuse++;146 ifc->conv->inuse++;
147 ifc->rp.mflag = 0; // default not managed147 ifc->rp.mflag = 0; // default not managed
148 ifc->rp.oflag = 0;148 ifc->rp.oflag = 0;
149 ifc->rp.maxraint = 600000; // millisecs149 ifc->rp.maxraint = 600000; // millisecs
150 ifc->rp.minraint = 200000;150 ifc->rp.minraint = 200000;
151 ifc->rp.linkmtu = 0; // no mtu sent151 ifc->rp.linkmtu = 0; // no mtu sent
152 ifc->rp.reachtime = 0;152 ifc->rp.reachtime = 0;
153 ifc->rp.rxmitra = 0;153 ifc->rp.rxmitra = 0;
154 ifc->rp.ttl = MAXTTL;154 ifc->rp.ttl = MAXTTL;
155 ifc->rp.routerlt = 3*(ifc->rp.maxraint);155 ifc->rp.routerlt = 3*(ifc->rp.maxraint);
156 156
157 /* any ancillary structures (like routes) no longer pertain */157 /* any ancillary structures (like routes) no longer pertain */
158 ifc->ifcid++;158 ifc->ifcid++;
@@ -229,7 +229,7 @@ ipifcstate(Conv *c, char *state, int n) · 70 unmodified lines
229 229
230 ifc = (Ipifc*)c->ptcl;230 ifc = (Ipifc*)c->ptcl;
231 231
232 m = snprint(state, n, sfixedformat, 232 m = snprint(state, n, sfixedformat,
233 ifc->dev, ifc->maxtu, ifc->sendra6, ifc->recvra6,233 ifc->dev, ifc->maxtu, ifc->sendra6, ifc->recvra6,
234 ifc->rp.mflag, ifc->rp.oflag, ifc->rp.maxraint,234 ifc->rp.mflag, ifc->rp.oflag, ifc->rp.maxraint,
235 ifc->rp.minraint, ifc->rp.linkmtu, ifc->rp.reachtime,235 ifc->rp.minraint, ifc->rp.linkmtu, ifc->rp.reachtime,
@@ -328,7 +328,7 @@ ipifccreate(Conv *c) · 92 unmodified lines
328 ifc->reassemble = 0;328 ifc->reassemble = 0;
329}329}
330 330
331/* 331/*
332 * called after last close of ipifc data or ctl332 * called after last close of ipifc data or ctl
333 * called with c locked, we must unlock333 * called with c locked, we must unlock
334 */334 */
@@ -424,7 +424,7 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp) · 89 unmodified lines
424 /* ignore if this is already a local address for this ifc */424 /* ignore if this is already a local address for this ifc */
425 for(lifc = ifc->lifc; lifc; lifc = lifc->next) {425 for(lifc = ifc->lifc; lifc; lifc = lifc->next) {
426 if(ipcmp(lifc->local, ip) == 0) {426 if(ipcmp(lifc->local, ip) == 0) {
427 if(lifc->tentative != tentative) 427 if(lifc->tentative != tentative)
428 lifc->tentative = tentative;428 lifc->tentative = tentative;
429 if(lifcp != nil) {429 if(lifcp != nil) {
430 lifc->onlink = lifcp->onlink;430 lifc->onlink = lifcp->onlink;
@@ -506,7 +506,7 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp) · 75 unmodified lines
506 addselfcache(f, ifc, lifc, bcast, Rbcast);506 addselfcache(f, ifc, lifc, bcast, Rbcast);
507 507
508 addselfcache(f, ifc, lifc, IPv4bcast, Rbcast);508 addselfcache(f, ifc, lifc, IPv4bcast, Rbcast);
509 } 509 }
510 else {510 else {
511 if(ipcmp(ip, v6loopback) == 0) {511 if(ipcmp(ip, v6loopback) == 0) {
512 /* add node-local mcast address */512 /* add node-local mcast address */
@@ -535,7 +535,7 @@ ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp) · 22 unmodified lines
535 535
536out:536out:
537 wunlock(ifc);537 wunlock(ifc);
538 if(tentative && sendnbrdisc) 538 if(tentative && sendnbrdisc)
539 icmpns(f, 0, SRC_UNSPEC, ip, TARG_MULTI, ifc->mac);539 icmpns(f, 0, SRC_UNSPEC, ip, TARG_MULTI, ifc->mac);
540 return nil;540 return nil;
541}541}
@@ -721,29 +721,29 @@ ipifcsetpar6(Ipifc *ifc, char **argv, int argc) · 179 unmodified lines
721 return Ebadarg;721 return Ebadarg;
722 722
723 while (argsleft > 1) {723 while (argsleft > 1) {
724 if(strcmp(argv[i],"recvra")==0) 724 if(strcmp(argv[i],"recvra")==0)
725 ifc->recvra6 = (atoi(argv[i+1]) != 0);725 ifc->recvra6 = (atoi(argv[i+1]) != 0);
726 else if(strcmp(argv[i],"sendra")==0) 726 else if(strcmp(argv[i],"sendra")==0)
727 ifc->sendra6 = (atoi(argv[i+1]) != 0);727 ifc->sendra6 = (atoi(argv[i+1]) != 0);
728 else if(strcmp(argv[i],"mflag")==0) 728 else if(strcmp(argv[i],"mflag")==0)
729 ifc->rp.mflag = (atoi(argv[i+1]) != 0);729 ifc->rp.mflag = (atoi(argv[i+1]) != 0);
730 else if(strcmp(argv[i],"oflag")==0) 730 else if(strcmp(argv[i],"oflag")==0)
731 ifc->rp.oflag = (atoi(argv[i+1]) != 0);731 ifc->rp.oflag = (atoi(argv[i+1]) != 0);
732 else if(strcmp(argv[i],"maxraint")==0)732 else if(strcmp(argv[i],"maxraint")==0)
733 ifc->rp.maxraint = atoi(argv[i+1]);733 ifc->rp.maxraint = atoi(argv[i+1]);
734 else if(strcmp(argv[i],"minraint")==0)734 else if(strcmp(argv[i],"minraint")==0)
735 ifc->rp.minraint = atoi(argv[i+1]);735 ifc->rp.minraint = atoi(argv[i+1]);
736 else if(strcmp(argv[i],"linkmtu")==0) 736 else if(strcmp(argv[i],"linkmtu")==0)
737 ifc->rp.linkmtu = atoi(argv[i+1]);737 ifc->rp.linkmtu = atoi(argv[i+1]);
738 else if(strcmp(argv[i],"reachtime")==0) 738 else if(strcmp(argv[i],"reachtime")==0)
739 ifc->rp.reachtime = atoi(argv[i+1]);739 ifc->rp.reachtime = atoi(argv[i+1]);
740 else if(strcmp(argv[i],"rxmitra")==0) 740 else if(strcmp(argv[i],"rxmitra")==0)
741 ifc->rp.rxmitra = atoi(argv[i+1]);741 ifc->rp.rxmitra = atoi(argv[i+1]);
742 else if(strcmp(argv[i],"ttl")==0) 742 else if(strcmp(argv[i],"ttl")==0)
743 ifc->rp.ttl = atoi(argv[i+1]);743 ifc->rp.ttl = atoi(argv[i+1]);
744 else if(strcmp(argv[i],"routerlt")==0) 744 else if(strcmp(argv[i],"routerlt")==0)
745 ifc->rp.routerlt = atoi(argv[i+1]);745 ifc->rp.routerlt = atoi(argv[i+1]);
746 else 746 else
747 return Ebadarg; 747 return Ebadarg;
748 748
749 argsleft -= 2;749 argsleft -= 2;
@@ -778,7 +778,7 @@ ipifcrecvra6(Ipifc *ifc, char **argv, int argc) · 28 unmodified lines
778 int i;778 int i;
779 779
780 i = 0;780 i = 0;
781 if(argc > 1) 781 if(argc > 1)
782 i = atoi(argv[1]);782 i = atoi(argv[1]);
783 ifc->recvra6 = (i!=0); 783 ifc->recvra6 = (i!=0);
784 return nil;784 return nil;
@@ -826,7 +826,7 @@ ipifcctl(Conv* c, char**argv, int argc) · 41 unmodified lines
826 return ipifcaddpref6(ifc, argv, argc);826 return ipifcaddpref6(ifc, argv, argc);
827 else if(strcmp(argv[0], "setpar6") == 0)827 else if(strcmp(argv[0], "setpar6") == 0)
828 return ipifcsetpar6(ifc, argv, argc);828 return ipifcsetpar6(ifc, argv, argc);
829 else if(strcmp(argv[0], "sendra6") == 0) 829 else if(strcmp(argv[0], "sendra6") == 0)
830 return ipifcsendra6(ifc, argv, argc);830 return ipifcsendra6(ifc, argv, argc);
831 else if(strcmp(argv[0], "recvra6") == 0)831 else if(strcmp(argv[0], "recvra6") == 0)
832 return ipifcrecvra6(ifc, argv, argc);832 return ipifcrecvra6(ifc, argv, argc);
@@ -1097,7 +1097,7 @@ ipselftabread(Fs *f, char *cp, ulong offset, int n) · 264 unmodified lines
1097}1097}
1098 1098
1099int1099int
1100iptentative(Fs *f, uchar *addr) 1100iptentative(Fs *f, uchar *addr)
1101{1101{
1102 Ipself *p;1102 Ipself *p;
1103 1103
@@ -1210,8 +1210,8 @@ v6addrtype(uchar *addr) · 106 unmodified lines
1210 1210
1211#define v6addrcurr(lifc) (( (lifc)->origint + (lifc)->preflt >= (NOW/10^3) ) || ( (lifc)->preflt == 0xffffffff ))1211#define v6addrcurr(lifc) (( (lifc)->origint + (lifc)->preflt >= (NOW/10^3) ) || ( (lifc)->preflt == 0xffffffff ))
1212 1212
1213void1213static void
1214findprimaryip6(Fs *f, uchar *local)1214findprimaryipv6(Fs *f, uchar *local)
1215{1215{
1216 Conv **cp, **e;1216 Conv **cp, **e;
1217 Ipifc *ifc;1217 Ipifc *ifc;
@@ -1231,7 +1231,7 @@ findprimaryip6(Fs *f, uchar *local) · 13 unmodified lines
1231 ifc = (Ipifc*)(*cp)->ptcl;1231 ifc = (Ipifc*)(*cp)->ptcl;
1232 for(lifc = ifc->lifc; lifc; lifc = lifc->next){1232 for(lifc = ifc->lifc; lifc; lifc = lifc->next){
1233 atypel = v6addrtype(lifc->local);1233 atypel = v6addrtype(lifc->local);
1234 if(atypel > atype) 1234 if(atypel > atype)
1235 if(v6addrcurr(lifc)) {1235 if(v6addrcurr(lifc)) {
1236 ipmove(local, lifc->local);1236 ipmove(local, lifc->local);
1237 atype = atypel;1237 atype = atypel;
@@ -1243,10 +1243,10 @@ findprimaryip6(Fs *f, uchar *local) · 5 unmodified lines
1243}1243}
1244 1244
1245/*1245/*
1246 * returns first ip address configured 1246 * returns first ip address configured
1247 */1247 */
1248void1248static void
1249findprimaryip(Fs *f, uchar *local)1249findprimaryipv4(Fs *f, uchar *local)
1250{1250{
1251 Conv **cp, **e;1251 Conv **cp, **e;
1252 Ipifc *ifc;1252 Ipifc *ifc;
@@ -1258,7 +1258,7 @@ findprimaryip(Fs *f, uchar *local) · 5 unmodified lines
1258 if(*cp == 0)1258 if(*cp == 0)
1259 continue;1259 continue;
1260 ifc = (Ipifc*)(*cp)->ptcl;1260 ifc = (Ipifc*)(*cp)->ptcl;
1261 for(lifc = ifc->lifc; lifc; lifc = lifc->next){1261 if((lifc = ifc->lifc) != nil){
1262 ipmove(local, lifc->local);1262 ipmove(local, lifc->local);
1263 return;1263 return;
1264 }1264 }
@@ -1329,10 +1329,10 @@ findlocalip(Fs *f, uchar *local, uchar *remote) · 64 unmodified lines
1329 1329
1330 switch(version){1330 switch(version){
1331 case V4:1331 case V4:
1332 findprimaryip(f, local);1332 findprimaryipv4(f, local);
1333 break;1333 break;
1334 case V6:1334 case V6:
1335 findprimaryip6(f, local);1335 findprimaryipv6(f, local);
1336 break;1336 break;
1337 default:1337 default:
1338 panic("findlocalip2: version %d", version);1338 panic("findlocalip2: version %d", version);
@@ -1642,7 +1642,7 @@ adddefroute6(Fs *f, uchar *gate, int force) · 303 unmodified lines
1642 Route *r;1642 Route *r;
1643 1643
1644 r = v6lookup(f, v6Unspecified, nil);1644 r = v6lookup(f, v6Unspecified, nil);
1645 if(r!=nil) 1645 if(r!=nil)
1646 if(!(force) && (strcmp(r->tag,"ra")!=0)) // route entries generated1646 if(!(force) && (strcmp(r->tag,"ra")!=0)) // route entries generated
1647 return; // by all other means take1647 return; // by all other means take
1648 // precedence over router annc1648 // precedence over router annc
@@ -1705,7 +1705,7 @@ ipifcaddpref6(Ipifc *ifc, char**argv, int argc) · 56 unmodified lines
1705 lifc->preflt = preflt;1705 lifc->preflt = preflt;
1706 lifc->origint = origint;1706 lifc->origint = origint;
1707 1707
1708 if(ifc->m->pref2addr!=nil) 1708 if(ifc->m->pref2addr!=nil)
1709 ifc->m->pref2addr(prefix, ifc->mac);1709 ifc->m->pref2addr(prefix, ifc->mac);
1710 else1710 else
1711 return Ebadarg;1711 return Ebadarg;
os/ip/iproute.c+1−1
@@ -662,7 +662,7 @@ sprintroute(Route *r, Routewalk *rw) · 661 unmodified lines
662 iname = "-";662 iname = "-";
663 if(nifc != -1) {663 if(nifc != -1) {
664 iname = ifbuf;664 iname = ifbuf;
665 sprint(ifbuf, "%d", nifc);665 snprint(ifbuf, sizeof ifbuf, "%d", nifc);
666 }666 }
667 p = seprint(rw->p, rw->e, rformat, addr, mask, gate, t, r->tag, iname);667 p = seprint(rw->p, rw->e, rformat, addr, mask, gate, t, r->tag, iname);
668 if(rw->o < 0){668 if(rw->o < 0){
os/ip/ipv6.h+7−7
@@ -61,12 +61,12 @@ enum { /* Header Types */ · 60 unmodified lines
61 RSVP = 46,61 RSVP = 46,
62 AH = 51,62 AH = 51,
63 ESP = 52,63 ESP = 52,
64 ICMPv6 = 58, 64 ICMPv6 = 58,
65 NNH = 59,65 NNH = 59,
66 DOH = 60,66 DOH = 60,
67 ISO_IP = 80,67 ISO_IP = 80,
68 IGRP = 88,68 IGRP = 88,
69 OSPF = 89, 69 OSPF = 89,
70 70
71 Maxhdrtype = 256,71 Maxhdrtype = 256,
72};72};
@@ -98,7 +98,7 @@ enum { · 25 unmodified lines
98 98
99 // various flags & constants99 // various flags & constants
100 100
101 v6MINTU = 1280, 101 v6MINTU = 1280,
102 HOP_LIMIT = 255,102 HOP_LIMIT = 255,
103 ETHERHDR_LEN = 14,103 ETHERHDR_LEN = 14,
104 IPV6HDR_LEN = 40,104 IPV6HDR_LEN = 40,
@@ -113,7 +113,7 @@ enum { · 8 unmodified lines
113 MTU_OPTION = 5,113 MTU_OPTION = 5,
114 114
115 SRC_UNSPEC = 0,115 SRC_UNSPEC = 0,
116 SRC_UNI = 1, 116 SRC_UNI = 1,
117 TARG_UNI = 2,117 TARG_UNI = 2,
118 TARG_MULTI = 3,118 TARG_MULTI = 3,
119 119
@@ -124,7 +124,7 @@ enum { · 4 unmodified lines
124 // Router constants (all times in milliseconds)124 // Router constants (all times in milliseconds)
125 125
126 MAX_INITIAL_RTR_ADVERT_INTERVAL = 16000,126 MAX_INITIAL_RTR_ADVERT_INTERVAL = 16000,
127 MAX_INITIAL_RTR_ADVERTISEMENTS = 3, 127 MAX_INITIAL_RTR_ADVERTISEMENTS = 3,
128 MAX_FINAL_RTR_ADVERTISEMENTS = 3,128 MAX_FINAL_RTR_ADVERTISEMENTS = 3,
129 MIN_DELAY_BETWEEN_RAS = 3000,129 MIN_DELAY_BETWEEN_RAS = 3000,
130 MAX_RA_DELAY_TIME = 500,130 MAX_RA_DELAY_TIME = 500,
@@ -140,9 +140,9 @@ enum { · 9 unmodified lines
140 MAX_MULTICAST_SOLICIT = 3,140 MAX_MULTICAST_SOLICIT = 3,
141 MAX_UNICAST_SOLICIT = 3,141 MAX_UNICAST_SOLICIT = 3,
142 MAX_ANYCAST_DELAY_TIME = 1000,142 MAX_ANYCAST_DELAY_TIME = 1000,
143 MAX_NEIGHBOR_ADVERTISEMENT = 3, 143 MAX_NEIGHBOR_ADVERTISEMENT = 3,
144 REACHABLE_TIME = 30000,144 REACHABLE_TIME = 30000,
145 RETRANS_TIMER = 1000, 145 RETRANS_TIMER = 1000,
146 DELAY_FIRST_PROBE_TIME = 5000,146 DELAY_FIRST_PROBE_TIME = 5000,
147 147
148};148};
os/ip/tcp.c+44−28
@@ -54,7 +54,7 @@ enum · 53 unmodified lines
54 TCP_CONNECT = 1, /* Outgoing connection */54 TCP_CONNECT = 1, /* Outgoing connection */
55 SYNACK_RXTIMER = 250, /* ms between SYNACK retransmits */55 SYNACK_RXTIMER = 250, /* ms between SYNACK retransmits */
56 56
57 TCPREXMTTHRESH = 3, /* dupack threshhold for rxt */57 TCPREXMTTHRESH = 3, /* dupack threshhold for rxt */
58 58
59 FORCE = 1,59 FORCE = 1,
60 CLONE = 2,60 CLONE = 2,
@@ -285,7 +285,7 @@ struct Limbo · 224 unmodified lines
285};285};
286 286
287int tcp_irtt = DEF_RTT; /* Initial guess at round trip time */287int tcp_irtt = DEF_RTT; /* Initial guess at round trip time */
288ushort tcp_mss = DEF_MSS; /* Maximum segment size to be sent */288ushort tcp_mss = DEF_MSS; /* Maximum segment size to be sent */
289 289
290enum {290enum {
291 /* MIB stats */291 /* MIB stats */
@@ -350,7 +350,7 @@ struct Tcppriv · 58 unmodified lines
350 ulong stats[Nstats];350 ulong stats[Nstats];
351};351};
352 352
353/* 353/*
354 * Setting tcpporthogdefense to non-zero enables Dong Lin's354 * Setting tcpporthogdefense to non-zero enables Dong Lin's
355 * solution to hijacked systems staking out port's as a form355 * solution to hijacked systems staking out port's as a form
356 * of DoS attack.356 * of DoS attack.
@@ -375,7 +375,7 @@ void tcprcvwin(Conv*); · 18 unmodified lines
375void tcpacktimer(void*);375void tcpacktimer(void*);
376void tcpkeepalive(void*);376void tcpkeepalive(void*);
377void tcpsetkacounter(Tcpctl*);377void tcpsetkacounter(Tcpctl*);
378void tcprxmit(Conv*);378void tcprxmit(Conv*);
379void tcpsettimer(Tcpctl*);379void tcpsettimer(Tcpctl*);
380void tcpsynackrtt(Conv*);380void tcpsynackrtt(Conv*);
381void tcpsetscale(Conv*, Tcpctl*, ushort, ushort);381void tcpsetscale(Conv*, Tcpctl*, ushort, ushort);
@@ -711,7 +711,7 @@ backoff(int n) · 329 unmodified lines
711}711}
712 712
713void713void
714localclose(Conv *s, char *reason) /* called with tcb locked */714localclose(Conv *s, char *reason) /* called with tcb locked */
715{715{
716 Tcpctl *tcb;716 Tcpctl *tcb;
717 Reseq *rp,*rp1;717 Reseq *rp,*rp1;
@@ -1804,8 +1804,8 @@ update(Conv *s, Tcp *seg) · 1086 unmodified lines
1804 /*1804 /*
1805 * update window1805 * update window
1806 */1806 */
1807 if( seq_gt(seg->ack, tcb->snd.wl2)1807 if(seq_gt(seg->ack, tcb->snd.wl2)
1808 || (tcb->snd.wl2 == seg->ack && seg->wnd > tcb->snd.wnd)){1808 || (tcb->snd.wl2 == seg->ack && seg->wnd > tcb->snd.wnd)){
1809 tcb->snd.wnd = seg->wnd;1809 tcb->snd.wnd = seg->wnd;
1810 tcb->snd.wl2 = seg->ack;1810 tcb->snd.wl2 = seg->ack;
1811 }1811 }
@@ -1821,9 +1821,9 @@ update(Conv *s, Tcp *seg) · 9 unmodified lines
1821 return;1821 return;
1822 }1822 }
1823 1823
1824 /*1824 /*
1825 * any positive ack turns off fast rxt,1825 * 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?)
1827 */1827 */
1828 if(!tcb->snd.recovery || seq_ge(seg->ack, tcb->snd.rxt)) {1828 if(!tcb->snd.recovery || seq_ge(seg->ack, tcb->snd.rxt)) {
1829 tcb->snd.dupacks = 0;1829 tcb->snd.dupacks = 0;
@@ -1925,7 +1925,7 @@ tcpiput(Proto *tcp, Ipifc*, Block *bp) · 95 unmodified lines
1925 1925
1926 f = tcp->f;1926 f = tcp->f;
1927 tpriv = tcp->priv;1927 tpriv = tcp->priv;
1928 1928
1929 tpriv->stats[InSegs]++;1929 tpriv->stats[InSegs]++;
1930 1930
1931 h4 = (Tcp4hdr*)(bp->rp);1931 h4 = (Tcp4hdr*)(bp->rp);
@@ -1939,7 +1939,7 @@ tcpiput(Proto *tcp, Ipifc*, Block *bp) · 7 unmodified lines
1939 1939
1940 h4->Unused = 0;1940 h4->Unused = 0;
1941 hnputs(h4->tcplen, length-TCP4_PKT);1941 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]) &&
1943 ptclcsum(bp, TCP4_IPLEN, length-TCP4_IPLEN)) {1943 ptclcsum(bp, TCP4_IPLEN, length-TCP4_IPLEN)) {
1944 tpriv->stats[CsumErrs]++;1944 tpriv->stats[CsumErrs]++;
1945 tpriv->stats[InErrs]++;1945 tpriv->stats[InErrs]++;
@@ -1978,7 +1978,7 @@ tcpiput(Proto *tcp, Ipifc*, Block *bp) · 32 unmodified lines
1978 h6->ploadlen[0] = h6->ploadlen[1] = h6->proto = 0;1978 h6->ploadlen[0] = h6->ploadlen[1] = h6->proto = 0;
1979 h6->ttl = proto;1979 h6->ttl = proto;
1980 hnputl(h6->vcf, length);1980 hnputl(h6->vcf, length);
1981 if((h6->tcpcksum[0] || h6->tcpcksum[1]) && 1981 if((h6->tcpcksum[0] || h6->tcpcksum[1]) &&
1982 ptclcsum(bp, TCP6_IPLEN, length+TCP6_PHDRSIZE)) {1982 ptclcsum(bp, TCP6_IPLEN, length+TCP6_PHDRSIZE)) {
1983 tpriv->stats[CsumErrs]++;1983 tpriv->stats[CsumErrs]++;
1984 tpriv->stats[InErrs]++;1984 tpriv->stats[InErrs]++;
@@ -2277,7 +2277,7 @@ reset: · 292 unmodified lines
2277 qpassnolim(s->rq, bp);2277 qpassnolim(s->rq, bp);
2278 bp = nil;2278 bp = nil;
2279 2279
2280 /* 2280 /*
2281 * Force an ack every 2 data messages. This is2281 * Force an ack every 2 data messages. This is
2282 * a hack for rob to make his home system run2282 * a hack for rob to make his home system run
2283 * faster.2283 * faster.
@@ -2412,20 +2412,20 @@ tcpoutput(Conv *s) · 128 unmodified lines
2412 2412
2413 for(msgs = 0; msgs < 100; msgs++) {2413 for(msgs = 0; msgs < 100; msgs++) {
2414 tcb = (Tcpctl*)s->ptcl;2414 tcb = (Tcpctl*)s->ptcl;
2415 2415
2416 switch(tcb->state) {2416 switch(tcb->state) {
2417 case Listen:2417 case Listen:
2418 case Closed:2418 case Closed:
2419 case Finwait2:2419 case Finwait2:
2420 return;2420 return;
2421 }2421 }
2422 2422
2423 /* force an ack when a window has opened up */2423 /* force an ack when a window has opened up */
2424 if(tcb->rcv.blocked && tcb->rcv.wnd > 0){2424 if(tcb->rcv.blocked && tcb->rcv.wnd > 0){
2425 tcb->rcv.blocked = 0;2425 tcb->rcv.blocked = 0;
2426 tcb->flags |= FORCE;2426 tcb->flags |= FORCE;
2427 }2427 }
2428 2428
2429 sndcnt = qlen(s->wq)+tcb->flgcnt;2429 sndcnt = qlen(s->wq)+tcb->flgcnt;
2430 sent = tcb->snd.ptr - tcb->snd.una;2430 sent = tcb->snd.ptr - tcb->snd.una;
2431 2431
@@ -2841,8 +2841,7 @@ int · 409 unmodified lines
2841addreseq(Tcpctl *tcb, Tcppriv *tpriv, Tcp *seg, Block *bp, ushort length)2841addreseq(Tcpctl *tcb, Tcppriv *tpriv, Tcp *seg, Block *bp, ushort length)
2842{2842{
2843 Reseq *rp, *rp1;2843 Reseq *rp, *rp1;
2844 int i;2844 int i, rqlen, qmax;
2845 static int once;
2846 2845
2847 rp = malloc(sizeof(Reseq));2846 rp = malloc(sizeof(Reseq));
2848 if(rp == nil){2847 if(rp == nil){
@@ -2864,9 +2863,9 @@ addreseq(Tcpctl *tcb, Tcppriv *tpriv, Tcp *seg, Block *bp, ushort length) · 15 unmodified lines
2864 return 0;2863 return 0;
2865 }2864 }
2866 2865
2867 length = 0;2866 rqlen = 0;
2868 for(i = 0;; i++) {2867 for(i = 0;; i++) {
2869 length += rp1->length;2868 rqlen += rp1->length;
2870 if(rp1->next == nil || seq_lt(seg->seq, rp1->next->seg.seq)) {2869 if(rp1->next == nil || seq_lt(seg->seq, rp1->next->seg.seq)) {
2871 rp->next = rp1->next;2870 rp->next = rp1->next;
2872 rp1->next = rp;2871 rp1->next = rp;
@@ -2876,12 +2875,29 @@ addreseq(Tcpctl *tcb, Tcppriv *tpriv, Tcp *seg, Block *bp, ushort length) · 3 unmodified lines
2876 }2875 }
2877 rp1 = rp1->next;2876 rp1 = rp1->next;
2878 }2877 }
2879 if(length > QMAX && once++ == 0){2878 qmax = QMAX<<tcb->rcv.scale;
2880 print("very long tcp resequence queue: %d\n", length);2879 if(rqlen > qmax){
2881 for(rp1 = tcb->reseq, i = 0; i < 10 && rp1 != nil; rp1 = rp1->next, i++)2880 print("resequence queue > window: %d > %d\n", rqlen, qmax);
2882 print("0x%lux 0x%lux 0x%ux\n", rp1->seg.seq, rp1->seg.ack,2881 i = 0;
2883 rp1->seg.flags);2882 for(rp1 = tcb->reseq; rp1 != nil; rp1 = rp1->next){
2884 return -1;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;
2885 }2901 }
2886 return 0;2902 return 0;
2887}2903}
@@ -2994,7 +3010,7 @@ tcpadvise(Proto *tcp, Block *bp, char *msg) · 106 unmodified lines
2994 v4tov6(source, h4->tcpsrc);3010 v4tov6(source, h4->tcpsrc);
2995 psource = nhgets(h4->tcpsport);3011 psource = nhgets(h4->tcpsport);
2996 pdest = nhgets(h4->tcpdport);3012 pdest = nhgets(h4->tcpdport);
2997 } 3013 }
2998 else {3014 else {
2999 ipmove(dest, h6->tcpdst);3015 ipmove(dest, h6->tcpdst);
3000 ipmove(source, h6->tcpsrc);3016 ipmove(source, h6->tcpsrc);
@@ -3122,7 +3138,7 @@ tcpsettimer(Tcpctl *tcb) · 121 unmodified lines
3122 3138
3123 /* round trip dependency */3139 /* round trip dependency */
3124 x = backoff(tcb->backoff) *3140 x = backoff(tcb->backoff) *
3125 (tcb->mdev + (tcb->srtt>>LOGAGAIN) + MSPTICK) / MSPTICK;3141 (tcb->mdev + (tcb->srtt>>LOGAGAIN) + MSPTICK) / MSPTICK;
3126 3142
3127 /* bounded twixt 1/2 and 64 seconds */3143 /* bounded twixt 1/2 and 64 seconds */
3128 if(x < 500/MSPTICK)3144 if(x < 500/MSPTICK)
os/pc/ether2000.c+4−2
@@ -132,7 +132,6 @@ ne2000pnp(Ether* edev) · 131 unmodified lines
132static int132static int
133ne2000reset(Ether* edev)133ne2000reset(Ether* edev)
134{134{
135 static int first;
136 ushort buf[16];135 ushort buf[16];
137 ulong port;136 ulong port;
138 Dp8390 *dp8390;137 Dp8390 *dp8390;
@@ -198,11 +197,14 @@ ne2000reset(Ether* edev) · 59 unmodified lines
198 * initialisation has been tried, but that wouldn't be197 * initialisation has been tried, but that wouldn't be
199 * enough, there are other ethernet boards which could198 * enough, there are other ethernet boards which could
200 * match.199 * match.
200 * Parallels has buf[0x0E] == 0x00 whereas real hardware
201 * usually has 0x57.
201 */202 */
202 dp8390reset(edev);203 dp8390reset(edev);
203 memset(buf, 0, sizeof(buf));204 memset(buf, 0, sizeof(buf));
204 dp8390read(dp8390, buf, 0, sizeof(buf));205 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){
206 iofree(edev->port);208 iofree(edev->port);
207 free(edev->ctlr);209 free(edev->ctlr);
208 return -1;210 return -1;
os/pc/ether2114x.c+6−4
@@ -190,6 +190,7 @@ enum { /* Variants */ · 189 unmodified lines
190 Pnic = (0x0002<<16)|0x11AD,190 Pnic = (0x0002<<16)|0x11AD,
191 Pnic2 = (0xC115<<16)|0x11AD,191 Pnic2 = (0xC115<<16)|0x11AD,
192 CentaurP = (0x0985<<16)|0x1317,192 CentaurP = (0x0985<<16)|0x1317,
193 CentaurPcb = (0x1985<<16)|0x1317,
193};194};
194 195
195typedef struct Ctlr Ctlr;196typedef struct Ctlr Ctlr;
@@ -1515,7 +1516,7 @@ srom(Ctlr* ctlr) · 1319 unmodified lines
1515 ctlr->srom[20+i+1] = ctlr->srom[i];1516 ctlr->srom[20+i+1] = ctlr->srom[i];
1516 }1517 }
1517 }1518 }
1518 if(ctlr->id == CentaurP){1519 if(ctlr->id == CentaurP || ctlr->id == CentaurPcb){
1519 memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic));1520 memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic));
1520 for(i = 0; i < Eaddrlen; i += 2){1521 for(i = 0; i < Eaddrlen; i += 2){
1521 ctlr->srom[20+i] = ctlr->srom[8+i];1522 ctlr->srom[20+i] = ctlr->srom[8+i];
@@ -1603,7 +1604,7 @@ srom(Ctlr* ctlr) · 81 unmodified lines
1603 if(phy){1604 if(phy){
1604 x = 0;1605 x = 0;
1605 for(k = 0; k < nelem(ctlr->phy); k++){1606 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)
1607 continue;1608 continue;
1608 if((oui = miir(ctlr, k, 2)) == -1 || oui == 0)1609 if((oui = miir(ctlr, k, 2)) == -1 || oui == 0)
1609 continue;1610 continue;
@@ -1655,6 +1656,7 @@ dec2114xpci(void) · 45 unmodified lines
1655 case Pnic: /* PNIC */1656 case Pnic: /* PNIC */
1656 case Pnic2: /* PNIC-II */1657 case Pnic2: /* PNIC-II */
1657 case CentaurP: /* ADMtek */1658 case CentaurP: /* ADMtek */
1659 case CentaurPcb: /* ADMtek CardBus */
1658 break;1660 break;
1659 }1661 }
1660 1662
@@ -1690,7 +1692,6 @@ dec2114xpci(void) · 29 unmodified lines
1690 switch(ctlr->id){1692 switch(ctlr->id){
1691 default:1693 default:
1692 break;1694 break;
1693
1694 case Pnic: /* PNIC */1695 case Pnic: /* PNIC */
1695 /*1696 /*
1696 * Turn off the jabber timer.1697 * Turn off the jabber timer.
@@ -1698,6 +1699,7 @@ dec2114xpci(void) · 1 unmodified line
1698 csr32w(ctlr, 15, 0x00000001);1699 csr32w(ctlr, 15, 0x00000001);
1699 break;1700 break;
1700 case CentaurP:1701 case CentaurP:
1702 case CentaurPcb:
1701 /*1703 /*
1702 * Nice - the register offsets change from *8 to *41704 * Nice - the register offsets change from *8 to *4
1703 * for CSR16 and up...1705 * for CSR16 and up...
@@ -1823,6 +1825,6 @@ reset(Ether* ether) · 119 unmodified lines
1823void1825void
1824ether2114xlink(void)1826ether2114xlink(void)
1825{1827{
1826 addethercard("21140", reset);
1827 addethercard("2114x", reset);1828 addethercard("2114x", reset);
1829 addethercard("21140", reset);
1828}1830}
os/pc/ether79c970.c+8−3
@@ -300,6 +300,12 @@ promiscuous(void* arg, int on) · 299 unmodified lines
300 iunlock(ctlr);300 iunlock(ctlr);
301}301}
302 302
303static void
304multicast(void* arg, uchar*, int)
305{
306 promiscuous(arg, 1);
307}
308
303static void309static void
304txstart(Ether* ether)310txstart(Ether* ether)
305{311{
@@ -522,7 +528,6 @@ reset(Ether* ether) · 216 unmodified lines
522 ctlr->iow = io32w;528 ctlr->iow = io32w;
523 }else{529 }else{
524 print("#l%d: card doesn't talk right\n", ether->ctlrno);530 print("#l%d: card doesn't talk right\n", ether->ctlrno);
525iprint("#l%d: card doesn't talk right\n", ether->ctlrno);
526 iunlock(ctlr);531 iunlock(ctlr);
527 return -1;532 return -1;
528 }533 }
@@ -539,8 +544,6 @@ iprint("#l%d: card doesn't talk right\n", ether->ctlrno); · 10 unmodified lines
539 default:544 default:
540 print("#l%d: unknown PCnet card version %.7ux\n",545 print("#l%d: unknown PCnet card version %.7ux\n",
541 ether->ctlrno, x&0xFFFFFFF);546 ether->ctlrno, x&0xFFFFFFF);
542iprint("#l%d: unknown PCnet card version %.7ux\n",
543 ether->ctlrno, x&0xFFFFFFF);
544 iunlock(ctlr);547 iunlock(ctlr);
545 return -1;548 return -1;
546 }549 }
@@ -629,6 +632,8 @@ iprint("#l%d: unknown PCnet card version %.7ux\n", · 82 unmodified lines
629 632
630 ether->arg = ether;633 ether->arg = ether;
631 ether->promiscuous = promiscuous;634 ether->promiscuous = promiscuous;
635 ether->multicast = multicast;
636// ether->shutdown = shutdown;
632 637
633 return 0;638 return 0;
634}639}
os/pc/ether8139.c+11−1
@@ -234,6 +234,12 @@ rtl8139promiscuous(void* arg, int on) · 233 unmodified lines
234 iunlock(&ctlr->ilock);234 iunlock(&ctlr->ilock);
235}235}
236 236
237static void
238rtl8139multicast(void* arg, uchar*, int)
239{
240 rtl8139promiscuous(arg, 1);
241}
242
237static long243static long
238rtl8139ifstat(Ether* edev, void* a, long n, ulong offset)244rtl8139ifstat(Ether* edev, void* a, long n, ulong offset)
239{245{
@@ -637,8 +643,10 @@ rtl8139match(Ether* edev, int id) · 397 unmodified lines
637 }643 }
638 644
639 ctlr->port = port;645 ctlr->port = port;
640 if(rtl8139reset(ctlr))646 if(rtl8139reset(ctlr)) {
647 iofree(port);
641 continue;648 continue;
649 }
642 pcisetbme(p);650 pcisetbme(p);
643 651
644 ctlr->active = 1;652 ctlr->active = 1;
@@ -738,6 +746,8 @@ rtl8139pnp(Ether* edev) · 93 unmodified lines
738 746
739 edev->arg = edev;747 edev->arg = edev;
740 edev->promiscuous = rtl8139promiscuous;748 edev->promiscuous = rtl8139promiscuous;
749 edev->multicast = rtl8139multicast;
750// edev->shutdown = rtl8139shutdown;
741 751
742 /*752 /*
743 * This should be much more dynamic but will do for now.753 * 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
1243static void1243static void
1244gc82543pci(void)1244gc82543pci(void)
1245{1245{
1246 int port, cls;1246 int cls;
1247 void *mem;
1247 Pcidev *p;1248 Pcidev *p;
1248 Ctlr *ctlr;1249 Ctlr *ctlr;
1249 1250
@@ -1262,8 +1263,8 @@ gc82543pci(void) · 12 unmodified lines
1262 break;1263 break;
1263 }1264 }
1264 1265
1265 port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);1266 mem = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
1266 if(port == 0){1267 if(mem == 0){
1267 print("gc82543: can't map %8.8luX\n", p->mem[0].bar);1268 print("gc82543: can't map %8.8luX\n", p->mem[0].bar);
1268 continue;1269 continue;
1269 }1270 }
@@ -1280,11 +1281,10 @@ gc82543pci(void) · 10 unmodified lines
1280 cls*4);1281 cls*4);
1281 }1282 }
1282 ctlr = malloc(sizeof(Ctlr));1283 ctlr = malloc(sizeof(Ctlr));
1283 ctlr->port = port;1284 ctlr->port = p->mem[0].bar & ~0x0F;
1284 ctlr->pcidev = p;1285 ctlr->pcidev = p;
1285 ctlr->id = (p->did<<16)|p->vid;1286 ctlr->id = (p->did<<16)|p->vid;
1286 1287 ctlr->nic = mem;
1287 ctlr->nic = KADDR(ctlr->port);
1288 1288
1289 if(gc82543reset(ctlr)){1289 if(gc82543reset(ctlr)){
1290 free(ctlr);1290 free(ctlr);
os/pc/ether82557.c+14−12
@@ -290,7 +290,7 @@ command(Ctlr* ctlr, int c, int v) · 289 unmodified lines
290 if(timeo >= 100){290 if(timeo >= 100){
291 ctlr->command = -1;291 ctlr->command = -1;
292 iunlock(&ctlr->rlock);292 iunlock(&ctlr->rlock);
293 iprint("i82557: command 0x%uX %uX timeout\n", c, v);293 iprint("i82557: command %#ux %#ux timeout\n", c, v);
294 return;294 return;
295 }295 }
296 296
@@ -462,7 +462,7 @@ ifstat(Ether* ether, void* a, long n, ulong offset) · 165 unmodified lines
462 for(i = 0; i < (1<<ctlr->eepromsz); i++){462 for(i = 0; i < (1<<ctlr->eepromsz); i++){
463 if(i && ((i & 0x07) == 0))463 if(i && ((i & 0x07) == 0))
464 len += snprint(p+len, READSTR-len, "\n ");464 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]);
466 }466 }
467 467
468 if((ctlr->eeprom[6] & 0x1F00) && !(ctlr->eeprom[6] & 0x8000)){468 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
471 for(i = 0; i < 6; i++){471 for(i = 0; i < 6; i++){
472 static int miir(Ctlr*, int, int);472 static int miir(Ctlr*, int, int);
473 473
474 len += snprint(p+len, READSTR-len, " %4.4uX",474 len += snprint(p+len, READSTR-len, " %4.4ux",
475 miir(ctlr, phyaddr, i));475 miir(ctlr, phyaddr, i));
476 }476 }
477 }477 }
@@ -523,7 +523,7 @@ txstart(Ether* ether) · 45 unmodified lines
523 ctlr->action = 0;523 ctlr->action = 0;
524 }524 }
525 else{525 else{
526 print("#l%d: action 0x%uX\n", ether->ctlrno, ctlr->action);526 print("#l%d: action %#ux\n", ether->ctlrno, ctlr->action);
527 ctlr->action = 0;527 ctlr->action = 0;
528 break;528 break;
529 }529 }
@@ -630,14 +630,14 @@ receive(Ether* ether) · 100 unmodified lines
630 pbp = nil;630 pbp = nil;
631 count = rfd->count & 0x3FFF;631 count = rfd->count & 0x3FFF;
632 if((count < ETHERMAXTU/4) && (pbp = iallocb(count))){632 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);
634 pbp->wp = pbp->rp + count;634 pbp->wp = pbp->rp + count;
635 635
636 rfd->count = 0;636 rfd->count = 0;
637 rfd->field = 0;637 rfd->field = 0;
638 }638 }
639 else if(xbp = rfdalloc(rfd->link)){639 else if(xbp = rfdalloc(rfd->link)){
640 bp->rp += sizeof(Rfd)-sizeof(rfd->data);640 bp->rp += offsetof(Rfd, data[0]);
641 bp->wp = bp->rp + count;641 bp->wp = bp->rp + count;
642 642
643 xbp->next = bp->next;643 xbp->next = bp->next;
@@ -748,7 +748,7 @@ interrupt(Ureg*, void* arg) · 104 unmodified lines
748 }748 }
749 749
750 if(status & (StatCX|StatFR|StatCNA|StatRNR|StatMDI|StatSWI))750 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);
752 }752 }
753}753}
754 754
@@ -926,14 +926,16 @@ i82557pci(void) · 171 unmodified lines
926 continue;926 continue;
927 case 0x1031: /* Intel 82562EM */927 case 0x1031: /* Intel 82562EM */
928 case 0x1050: /* Intel 82562EZ */928 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 */
929 case 0x2449: /* Intel 82562ET */933 case 0x2449: /* Intel 82562ET */
930 nop = 1;934 nop = 1;
931 /*FALLTHROUGH*/935 /*FALLTHROUGH*/
932 case 0x1209: /* Intel 82559ER */936 case 0x1209: /* Intel 82559ER */
933 case 0x1229: /* Intel 8255[789] */937 case 0x1229: /* Intel 8255[789] */
934 case 0x1030: /* Intel 82559 InBusiness 10/100 */938 case 0x1030: /* Intel 82559 InBusiness 10/100 */
935 case 0x1039: /* Intel 82801BD PRO/100 VE */
936 case 0x103A: /* Intel 82562 PRO/100 VE */
937 break;939 break;
938 }940 }
939 941
@@ -955,7 +957,7 @@ i82557pci(void) · 15 unmodified lines
955 */957 */
956 port = p->mem[1].bar & ~0x01;958 port = p->mem[1].bar & ~0x01;
957 if(ioalloc(port, p->mem[1].size, 0, "i82557") < 0){959 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);
959 continue;961 continue;
960 }962 }
961 963
@@ -997,7 +999,7 @@ scanphy(Ctlr* ctlr) · 35 unmodified lines
997 oui <<= 6;999 oui <<= 6;
998 x = miir(ctlr, i, 3);1000 x = miir(ctlr, i, 3);
999 oui |= x>>10;1001 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));
1001 1003
1002 ctlr->eeprom[6] = i;1004 ctlr->eeprom[6] = i;
1003 if(oui == 0xAA00)1005 if(oui == 0xAA00)
@@ -1093,7 +1095,7 @@ reset(Ether* ether) · 89 unmodified lines
1093 sum += x;1095 sum += x;
1094 }1096 }
1095 if(sum != 0xBABA)1097 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);
1097 1099
1098 /*1100 /*
1099 * Eeprom[6] indicates whether there is a PHY and whether1101 * 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
79 Col = 1<<16, /* collision during receive */79 Col = 1<<16, /* collision during receive */
80};80};
81 81
82enum { /* Variants */82enum { /* PCI vendor & device IDs */
83 Nat83815 = (0x0020<<16)|0x100B,83 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 */
85};98};
86 99
87typedef struct Ctlr Ctlr;100typedef struct Ctlr Ctlr;
@@ -456,9 +469,9 @@ txrxcfg(Ctlr *ctlr, int txdrth) · 368 unmodified lines
456static void469static void
457interrupt(Ureg*, void* arg)470interrupt(Ureg*, void* arg)
458{471{
472 int len, status, cmdsts, n;
459 Ctlr *ctlr;473 Ctlr *ctlr;
460 Ether *ether;474 Ether *ether;
461 int len, status, cmdsts;
462 Des *des;475 Des *des;
463 Block *bp;476 Block *bp;
464 477
@@ -483,6 +496,15 @@ interrupt(Ureg*, void* arg) · 18 unmodified lines
483 status &= ~(Hiberr|Txrcmp|Rxrcmp|Rxsovr|Dperr|Sserr|Rmabt|Rtabt);496 status &= ~(Hiberr|Txrcmp|Rxrcmp|Rxsovr|Dperr|Sserr|Rmabt|Rtabt);
484 }497 }
485 498
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
486 /*508 /*
487 * Received packets.509 * Received packets.
488 */510 */
@@ -511,11 +533,19 @@ interrupt(Ureg*, void* arg) · 22 unmodified lines
511 }533 }
512 else if(bp = iallocb(Rbsz)){534 else if(bp = iallocb(Rbsz)){
513 len = (cmdsts&Size)-4;535 len = (cmdsts&Size)-4;
514 des->bp->wp = des->bp->rp+len;536 if(len <= 0){
515 etheriq(ether, des->bp, 1);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 }
516 des->bp = bp;543 des->bp = bp;
517 des->addr = PADDR(bp->rp);544 des->addr = PADDR(bp->rp);
518 coherence();545 coherence();
546 }else{
547 debug("ns83815: interrupt: iallocb for input buffer failed\n");
548 des->bp->next = 0;
519 }549 }
520 550
521 des->cmdsts = Rbsz;551 des->cmdsts = Rbsz;
@@ -607,7 +637,7 @@ ctlrinit(Ether* ether) · 85 unmodified lines
607 last = nil;637 last = nil;
608 for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){638 for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){
609 des->bp = iallocb(Rbsz);639 des->bp = iallocb(Rbsz);
610 if (des->bp == nil)640 if(des->bp == nil)
611 error(Enomem);641 error(Enomem);
612 des->cmdsts = Rbsz;642 des->cmdsts = Rbsz;
613 des->addr = PADDR(des->bp->rp);643 des->addr = PADDR(des->bp->rp);
@@ -635,8 +665,10 @@ ctlrinit(Ether* ether) · 21 unmodified lines
635 665
636 txrxcfg(ctlr, Drth512);666 txrxcfg(ctlr, Drth512);
637 667
638 csr32w(ctlr, Rimr, Dperr|Sserr|Rmabt|Rtabt|Rxsovr|Hiberr|Txurn|Txerr|Txdesc|Txok|Rxorn|Rxerr|Rxdesc|Rxok); /* Phy|Pme|Mib */668 csr32w(ctlr, Rimr, Dperr|Sserr|Rmabt|Rtabt|Rxsovr|Hiberr|Txurn|Txerr|
639 csr32r(ctlr, Risr); /* clear status */669 Txdesc|Txok|Rxorn|Rxerr|Rxdesc|Rxok); /* Phy|Pme|Mib */
670 csr32w(ctlr, Rmicr, Inten); /* enable phy interrupts */
671 csr32r(ctlr, Risr); /* clear status */
640 csr32w(ctlr, Rier, Ie);672 csr32w(ctlr, Rier, Ie);
641}673}
642 674
@@ -762,7 +794,7 @@ softreset(Ctlr* ctlr, int resetphys) · 119 unmodified lines
762 if(csr16r(ctlr, Ranar) == 0 || (csr32r(ctlr, Rcfg) & Aneg_dn) == 0){794 if(csr16r(ctlr, Ranar) == 0 || (csr32r(ctlr, Rcfg) & Aneg_dn) == 0){
763 csr16w(ctlr, Rbmcr, Anena|Anrestart);795 csr16w(ctlr, Rbmcr, Anena|Anrestart);
764 for(i=0;; i++){796 for(i=0;; i++){
765 if(i > 6000){797 if(i > 3000){
766 print("ns83815: auto neg timed out\n");798 print("ns83815: auto neg timed out\n");
767 break;799 break;
768 }800 }
@@ -791,11 +823,8 @@ media(Ether* ether) · 22 unmodified lines
791 ctlr = ether->ctlr;823 ctlr = ether->ctlr;
792 cfg = csr32r(ctlr, Rcfg);824 cfg = csr32r(ctlr, Rcfg);
793 ctlr->fd = (cfg & Fdup) != 0;825 ctlr->fd = (cfg & Fdup) != 0;
794 if(cfg & Speed100)826 ether->link = (cfg&Lnksts) != 0;
795 return 100;827 return (cfg&(Lnksts|Speed100)) == Lnksts? 10: 100;
796 if((cfg & Lnksts) == 0)
797 return 100; /* no link: use 100 to ensure larger queues */
798 return 10;
799}828}
800 829
801static char* mediatable[9] = {830static char* mediatable[9] = {
@@ -810,8 +839,82 @@ static char* mediatable[9] = { · 8 unmodified lines
810 "100BASE-FXFD",839 "100BASE-FXFD",
811};840};
812 841
842static int
843is630(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
855enum {
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() */
864static int
865sisrdcmos(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 */
813static void899static void
814srom(Ctlr* ctlr)900sissrom(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
916static void
917nssrom(Ctlr* ctlr)
815{918{
816 int i, j;919 int i, j;
817 920
@@ -821,30 +924,50 @@ srom(Ctlr* ctlr) · 3 unmodified lines
821 /*924 /*
822 * the MAC address is reversed, straddling word boundaries925 * the MAC address is reversed, straddling word boundaries
823 */926 */
824 memset(ctlr->sromea, 0, sizeof(ctlr->sromea));927 j = Nseenodeaddr*16 + 15;
825 j = 6*16 + 15;
826 for(i=0; i<48; i++){928 for(i=0; i<48; i++){
827 ctlr->sromea[i>>3] |= ((ctlr->srom[j>>4] >> (15-(j&0xF))) & 1) << (i&7);929 ctlr->sromea[i>>3] |= ((ctlr->srom[j>>4] >> (15-(j&0xF))) & 1) << (i&7);
828 j++;930 j++;
829 }931 }
830}932}
831 933
934static void
935srom(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
832static void952static void
833scanpci83815(void)953scanpci83815(void)
834{954{
835 Ctlr *ctlr;955 Ctlr *ctlr;
836 Pcidev *p;956 Pcidev *p;
957 ulong id;
837 958
838 p = nil;959 p = nil;
839 while(p = pcimatch(p, 0, 0)){960 while(p = pcimatch(p, 0, 0)){
840 if(p->ccrb != 0x02 || p->ccru != 0)961 if(p->ccrb != Pcibcnet || p->ccru != 0)
841 continue;962 continue;
842 switch((p->did<<16)|p->vid){963 id = (p->did<<16)|p->vid;
964 switch(id){
843 default:965 default:
844 continue;966 continue;
845 967
846 case Nat83815:968 case Nat83815:
847 case Sis900:969 break;
970 case SiS900:
848 break;971 break;
849 }972 }
850 973
@@ -855,7 +978,7 @@ scanpci83815(void) · 4 unmodified lines
855 ctlr = malloc(sizeof(Ctlr));978 ctlr = malloc(sizeof(Ctlr));
856 ctlr->port = p->mem[0].bar & ~0x01;979 ctlr->port = p->mem[0].bar & ~0x01;
857 ctlr->pcidev = p;980 ctlr->pcidev = p;
858 ctlr->id = (p->did<<16)|p->vid;981 ctlr->id = id;
859 982
860 if(ioalloc(ctlr->port, p->mem[0].size, 0, "ns83815") < 0){983 if(ioalloc(ctlr->port, p->mem[0].size, 0, "ns83815") < 0){
861 print("ns83815: port 0x%uX in use\n", ctlr->port);984 print("ns83815: port 0x%uX in use\n", ctlr->port);
@@ -885,6 +1008,7 @@ reset(Ether* ether) · 23 unmodified lines
885{1008{
886 Ctlr *ctlr;1009 Ctlr *ctlr;
887 int i, x;1010 int i, x;
1011 ulong ctladdr;
888 uchar ea[Eaddrlen];1012 uchar ea[Eaddrlen];
889 static int scandone;1013 static int scandone;
890 1014
@@ -923,7 +1047,8 @@ reset(Ether* ether) · 32 unmodified lines
923 memmove(ether->ea, ctlr->sromea, Eaddrlen);1047 memmove(ether->ea, ctlr->sromea, Eaddrlen);
924 for(i=0; i<Eaddrlen; i+=2){1048 for(i=0; i<Eaddrlen; i+=2){
925 x = ether->ea[i] | (ether->ea[i+1]<<8);1049 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);
927 csr32w(ctlr, Rrfdr, x);1052 csr32w(ctlr, Rrfdr, x);
928 }1053 }
929 csr32w(ctlr, Rrfcr, Rfen|Apm|Aab|Aam);1054 csr32w(ctlr, Rrfcr, Rfen|Apm|Aab|Aam);
os/pc/ether8390.c+3−3
@@ -400,7 +400,7 @@ receive(Ether* ether) · 399 unmodified lines
400 */400 */
401 if(hdr.next < ctlr->pstart || hdr.next >= ctlr->pstop401 if(hdr.next < ctlr->pstart || hdr.next >= ctlr->pstop
402 || len < 60 || len > sizeof(Etherpkt)){402 || 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",
404 hdr.status, hdr.next, hdr.len0, hdr.len1, len);404 hdr.status, hdr.next, hdr.len0, hdr.len1, len);
405 regw(ctlr, Cr, Page0|RdABORT|Stp);405 regw(ctlr, Cr, Page0|RdABORT|Stp);
406 ringinit(ctlr);406 ringinit(ctlr);
@@ -588,7 +588,7 @@ interrupt(Ureg*, void* arg) · 181 unmodified lines
588 if(isr & (Txe|Ptx)){588 if(isr & (Txe|Ptx)){
589 r = regr(ctlr, Tsr);589 r = regr(ctlr, Tsr);
590 if((isr & Txe) && (r & (Cdh|Fu|Crs|Abt))){590 if((isr & Txe) && (r & (Cdh|Fu|Crs|Abt))){
591 print("dp8390: Tsr#%2.2ux|", r);591 print("dp8390: Tsr %#2.2ux", r);
592 ether->oerrs++;592 ether->oerrs++;
593 }593 }
594 594
@@ -686,7 +686,7 @@ multicast(void* arg, uchar *addr, int on) · 91 unmodified lines
686 if(reverse[1] == 0){686 if(reverse[1] == 0){
687 for(i = 0; i < 64; i++)687 for(i = 0; i < 64; i++)
688 reverse[i] = ((i&1)<<5) | ((i&2)<<3) | ((i&4)<<1)688 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);
690 }690 }
691 691
692 /*692 /*
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
19enum { /* 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
63enum { /* 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
78enum { /* 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
108enum { /* 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
118enum { /* 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
152enum { /* Interrupt Enable */
153 Ien = 0x00000001, /* Interrupt Enable */
154};
155
156enum { /* Interrupt Holdoff */
157 IhSHFT = 0, /* Interrupt Holdoff */
158 IhMASK = 0x000000FF,
159 Ihctl = 0x00000100, /* Interrupt Holdoff Control */
160};
161
162enum { /* 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
177enum { /* 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
188enum { /* 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
195enum { /* 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
214enum { /* 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
230enum { /* Receive Filter/Match Data */
231 RfdataSHFT = 0, /* Receive Filter Data */
232 RfdataMASK = 0x0000FFFF,
233 BmaskSHFT = 16, /* Byte Mask */
234 BmaskMASK = 0x00030000,
235};
236
237enum { /* 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
244enum { /* MIB Data */
245 Nmibd = 11, /* Number of MIB Data Registers */
246};
247
248enum { /* 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
259enum { /* 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
266enum { /* VLAN Data */
267 VtypeSHFT = 0, /* VLAN Type Field */
268 VtypeMASK = 0x0000FFFF,
269 VtciSHFT = 16, /* VLAN Tag Control Information */
270 VtciMASK = 0xFFFF0000,
271};
272
273enum { /* Clockrun Control/Status */
274 Clkrunen = 0x00000001, /* CLKRUN Enable */
275 Pmeen = 0x00000100, /* PME Enable */
276 Pmests = 0x00008000, /* PME Status */
277};
278
279typedef 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
289enum { /* 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
299enum { /* 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
311enum { /* 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
325enum { /* 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
337enum {
338 Nrd = 256,
339 Nrb = 4*Nrd,
340 Rbsz = ROUNDUP(sizeof(Etherpkt)+8, 8),
341 Ntd = 128,
342};
343
344typedef struct Ctlr Ctlr;
345typedef 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
395static Ctlr* dp83820ctlrhead;
396static Ctlr* dp83820ctlrtail;
397
398static Lock dp83820rblock; /* free receive Blocks */
399static Block* dp83820rbpool;
400
401static 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
415static int
416mdior(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
434static void
435mdiow(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
452static int
453dp83820miimir(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
477static int
478dp83820miimiw(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
499static Block *
500dp83820rballoc(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
531static void
532dp83820rbfree(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
543static void
544dp83820halt(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
578static void
579dp83820cfg(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
626static void
627dp83820init(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
698static void
699dp83820attach(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
756static void
757dp83820transmit(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
821static void
822dp83820interrupt(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
905static long
906dp83820ifstat(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
964static void
965dp83820promiscuous(void* arg, int on)
966{
967 USED(arg, on);
968}
969
970/* multicast already on, don't need to do anything */
971static void
972dp83820multicast(void*, uchar*, int)
973{
974}
975
976static int
977dp83820detach(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
989static void
990dp83820shutdown(Ether* ether)
991{
992print("dp83820shutdown\n");
993 dp83820detach(ether->ctlr);
994}
995
996static int
997atc93c46r(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
1009reread:
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
1067static int
1068dp83820reset(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);
1133print("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
1141static void
1142dp83820pci(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
1186static int
1187dp83820pnp(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
1242void
1243etherdp83820link(void)
1244{
1245 addethercard("DP83820", dp83820pnp);
1246}
os/pc/etherec2t.c+1−0
@@ -31,6 +31,7 @@ static Ec2t ec2tpcmcia[] = { · 30 unmodified lines
31 { "FA410TX", 1, }, /* Netgear FA410TX */31 { "FA410TX", 1, }, /* Netgear FA410TX */
32 { "Network Everywhere", 0, }, /* Linksys NP10T 10BaseT Card */32 { "Network Everywhere", 0, }, /* Linksys NP10T 10BaseT Card */
33 { "10/100 Port Attached", 1, }, /* SMC 8040TX */33 { "10/100 Port Attached", 1, }, /* SMC 8040TX */
34 { "8041TX-10/100-PC-Card-V2", 0 }, /* SMC 8041TX */
34 { "FA411", 0 }, /* Netgear FA411 PCMCIA */35 { "FA411", 0 }, /* Netgear FA411 PCMCIA */
35 { nil, 0, },36 { nil, 0, },
36};37};
os/pc/etherelnk3.c+6−4
@@ -1485,15 +1485,15 @@ tcm59Xpci(void) · 1484 unmodified lines
1485 break;1485 break;
1486 case 0x5157:1486 case 0x5157:
1487 ctlr->eepromcmd = EepromRead8bRegister;1487 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);
1489 break;1490 break;
1490 case 0x6056:1491 case 0x6056:
1491 ctlr->eepromcmd = EepromReadOffRegister;1492 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);
1493 break;1495 break;
1494 }1496 }
1495 if(ctlr->cbfnpa != 0)
1496 ctlr->cbfn = KADDR(ctlr->cbfnpa);
1497 pcisetbme(p);1497 pcisetbme(p);
1498 }1498 }
1499}1499}
@@ -1834,6 +1834,7 @@ etherelnk3reset(Ether* ether) · 334 unmodified lines
1834 case 0x9055: /* 3C905B-TX */1834 case 0x9055: /* 3C905B-TX */
1835 case 0x9200: /* 3C905C-TX */1835 case 0x9200: /* 3C905C-TX */
1836 case 0x9201: /* 3C920 */1836 case 0x9201: /* 3C920 */
1837 case 0x9805: /* 3C9805: 3C980-TX Python-T 10/100baseTX */
1837 /*FALLTHROUGH*/1838 /*FALLTHROUGH*/
1838 case 0x9000: /* 3C900-TPO */1839 case 0x9000: /* 3C900-TPO */
1839 case 0x9001: /* 3C900-COMBO */1840 case 0x9001: /* 3C900-COMBO */
@@ -1927,6 +1928,7 @@ etherelnk3reset(Ether* ether) · 87 unmodified lines
1927 case 0x9055:1928 case 0x9055:
1928 case 0x9200:1929 case 0x9200:
1929 case 0x9201:1930 case 0x9201:
1931 case 0x9805:
1930 ctlr->xcvr = xcvrMii;1932 ctlr->xcvr = xcvrMii;
1931 resetctlr(ctlr);1933 resetctlr(ctlr);
1932 break;1934 break;
os/pc/etherga620.c+97−46
@@ -124,7 +124,11 @@ enum { /* Om */ · 123 unmodified lines
124enum { /* Lmw */124enum { /* Lmw */
125 Lmwsz = 2*1024, /* Local Memory Window Size */125 Lmwsz = 2*1024, /* Local Memory Window Size */
126 126
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) */
128};132};
129 133
130enum { /* Link */134enum { /* Link */
@@ -146,17 +150,17 @@ typedef struct Host64 { · 15 unmodified lines
146} Host64;150} Host64;
147 151
148typedef struct Ere { /* Event Ring Element */152typedef struct Ere { /* Event Ring Element */
149 int event; /* (event<<24)|(code<<12)|index */153 int event; /* event<<24 | code<<12 | index */
150 int unused;154 int unused;
151} Ere;155} Ere;
152 156
153typedef int Cmd; /* (cmd<<24)|(flags<<12)|index */157typedef int Cmd; /* cmd<<24 | flags<<12 | index */
154 158
155typedef struct Rbd { /* Receive Buffer Descriptor */159typedef struct Rbd { /* Receive Buffer Descriptor */
156 Host64 addr;160 Host64 addr;
157 int indexlen; /* (ring-index<<16)|buffer-length */161 int indexlen; /* ring-index<<16 | buffer-length */
158 int flags; /* only lower 16-bits */162 int flags; /* only lower 16-bits */
159 int checksum; /* (ip<<16)|tcp/udp */163 int checksum; /* ip<<16 | tcp/udp */
160 int error; /* only upper 16-bits */164 int error; /* only upper 16-bits */
161 int reserved;165 int reserved;
162 void* opaque; /* passed to receive return ring */166 void* opaque; /* passed to receive return ring */
@@ -164,7 +168,7 @@ typedef struct Rbd { /* Receive Buffer Descriptor */ · 1 unmodified line
164 168
165typedef struct Sbd { /* Send Buffer Descriptor */169typedef struct Sbd { /* Send Buffer Descriptor */
166 Host64 addr;170 Host64 addr;
167 int lenflags; /* (len<<16)|flags */171 int lenflags; /* len<<16 | flags */
168 int reserved;172 int reserved;
169} Sbd;173} Sbd;
170 174
@@ -192,7 +196,7 @@ enum { /* Buffer Error Flags */ · 21 unmodified lines
192 196
193typedef struct Rcb { /* Ring Control Block */197typedef struct Rcb { /* Ring Control Block */
194 Host64 addr; /* points to the Rbd ring */198 Host64 addr; /* points to the Rbd ring */
195 int control; /* (max_len<<16)|flags */199 int control; /* max_len<<16 | flags */
196 int unused;200 int unused;
197} Rcb;201} Rcb;
198 202
@@ -223,13 +227,17 @@ typedef struct Gib { /* General Information Block */ · 24 unmodified lines
223 Host64 rsp; /* Refresh Stats */227 Host64 rsp; /* Refresh Stats */
224} Gib;228} Gib;
225 229
230/*
231 * these sizes are all fixed in the card,
232 * except for Nsr, which has only 3 valid sizes.
233 */
226enum { /* Host/NIC Interface ring sizes */234enum { /* Host/NIC Interface ring sizes */
227 Ner = 256, /* event ring */235 Ner = 256, /* event ring */
228 Ncr = 64, /* command ring */236 Ncr = 64, /* command ring */
229 Nsr = 512, /* send ring */237 Nsr = 512, /* send ring: 128, 256 or 512 */
230 Nrsr = 512, /* receive standard ring */238 Nrsr = 512, /* receive standard ring */
231 Nrjr = 256, /* receive jumbo ring */239 Nrjr = 256, /* receive jumbo ring */
232 Nrmr = 1024, /* receive mini ring */240 Nrmr = 1024, /* receive mini ring, optional */
233 Nrrr = 2048, /* receive return ring */241 Nrrr = 2048, /* receive return ring */
234};242};
235 243
@@ -243,7 +251,7 @@ enum { · 7 unmodified lines
243};251};
244 252
245typedef struct Ctlr Ctlr;253typedef struct Ctlr Ctlr;
246typedef struct Ctlr {254struct Ctlr {
247 int port;255 int port;
248 Pcidev* pcidev;256 Pcidev* pcidev;
249 Ctlr* next;257 Ctlr* next;
@@ -286,7 +294,7 @@ typedef struct Ctlr { · 36 unmodified lines
286 int st; /* Stat Ticks */294 int st; /* Stat Ticks */
287 int smcbd; /* Send Max. Coalesced BDs */295 int smcbd; /* Send Max. Coalesced BDs */
288 int rmcbd; /* Receive Max. Coalesced BDs */296 int rmcbd; /* Receive Max. Coalesced BDs */
289} Ctlr;297};
290 298
291static Ctlr* ctlrhead;299static Ctlr* ctlrhead;
292static Ctlr* ctlrtail;300static Ctlr* ctlrtail;
@@ -310,7 +318,7 @@ ga620command(Ctlr* ctlr, int cmd, int flags, int index) · 17 unmodified lines
310 int cpi;318 int cpi;
311 319
312 cpi = csr32r(ctlr, Cpi);320 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);
314 cpi = NEXT(cpi, Ncr);322 cpi = NEXT(cpi, Ncr);
315 csr32w(ctlr, Cpi, cpi);323 csr32w(ctlr, Cpi, cpi);
316}324}
@@ -508,7 +516,7 @@ _ga620transmit(Ether* edev) · 191 unmodified lines
508 516
509 sbd = &ctlr->sr[spi];517 sbd = &ctlr->sr[spi];
510 sethost64(&sbd->addr, bp->rp);518 sethost64(&sbd->addr, bp->rp);
511 sbd->lenflags = (BLEN(bp)<<16)|Fend;519 sbd->lenflags = BLEN(bp)<<16 | Fend;
512 520
513 ctlr->srb[spi] = bp;521 ctlr->srb[spi] = bp;
514 work++;522 work++;
@@ -539,7 +547,7 @@ ga620replenish(Ctlr* ctlr) · 24 unmodified lines
539 break;547 break;
540 rbd = &ctlr->rsr[rspi];548 rbd = &ctlr->rsr[rspi];
541 sethost64(&rbd->addr, bp->rp);549 sethost64(&rbd->addr, bp->rp);
542 rbd->indexlen = (rspi<<16)|(ETHERMAXTU+4);550 rbd->indexlen = rspi<<16 | (ETHERMAXTU+4);
543 rbd->flags = 0;551 rbd->flags = 0;
544 rbd->opaque = bp;552 rbd->opaque = bp;
545 553
@@ -550,27 +558,49 @@ ga620replenish(Ctlr* ctlr) · 4 unmodified lines
550}558}
551 559
552static void560static void
553ga620event(Ctlr* ctlr, int eci, int epi)561ga620event(Ether *edev, int eci, int epi)
554{562{
555 int event;563 unsigned event, code;
564 Ctlr *ctlr;
556 565
566 ctlr = edev->ctlr;
557 while(eci != epi){567 while(eci != epi){
558 event = ctlr->er[eci].event;568 event = ctlr->er[eci].event;
569 code = (event >> 12) & ((1<<12)-1);
559 switch(event>>24){570 switch(event>>24){
560 case 0x01: /* firmware operational */571 case 0x01: /* firmware operational */
572 /* host stack (us) is up. 3rd arg of 2 means down. */
561 ga620command(ctlr, 0x01, 0x01, 0x00);573 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 */
562 ga620command(ctlr, 0x0B, 0x00, 0x00);578 ga620command(ctlr, 0x0B, 0x00, 0x00);
563print("%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);
564 break;581 break;
565 case 0x04: /* statistics updated */582 case 0x04: /* statistics updated */
566 break;583 break;
567 case 0x06: /* link state changed */584 case 0x06: /* link state changed */
568print("%8.8uX: %8.8uX %8.8uX %8.8uX\n",585 switch (code) {
569 ctlr->port, event, csr32r(ctlr, Gls), csr32r(ctlr, Fls));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);
570 break;599 break;
571 case 0x07: /* event error */600 case 0x07: /* event error */
572 default:601 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);
574 break;604 break;
575 }605 }
576 eci = NEXT(eci, Ner);606 eci = NEXT(eci, Ner);
@@ -645,7 +675,7 @@ ga620interrupt(Ureg*, void* arg) · 68 unmodified lines
645 675
646 csr = csr32r(ctlr, Eci);676 csr = csr32r(ctlr, Eci);
647 if(csr != ctlr->epi[0]){677 if(csr != ctlr->epi[0]){
648 ga620event(ctlr, csr, ctlr->epi[0]);678 ga620event(edev, csr, ctlr->epi[0]);
649 work = 1;679 work = 1;
650 }680 }
651 681
@@ -714,9 +744,9 @@ ga620init(Ether* edev) · 62 unmodified lines
714 /*744 /*
715 * Load the MAC address.745 * Load the MAC address.
716 */746 */
717 ea = (edev->ea[0]<<8)|edev->ea[1];747 ea = edev->ea[0]<<8 | edev->ea[1];
718 csr32w(ctlr, Mac, ea);748 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];
720 csr32w(ctlr, Mac+4, ea);750 csr32w(ctlr, Mac+4, ea);
721 751
722 /*752 /*
@@ -758,7 +788,7 @@ ga620init(Ether* edev) · 35 unmodified lines
758 * memory it is accessed via the Local Memory Window; with a send788 * memory it is accessed via the Local Memory Window; with a send
759 * ring size of 128 the window covers the whole ring and then need789 * ring size of 128 the window covers the whole ring and then need
760 * only be set once:790 * only be set once:
761 * ctlr->sr = KADDR(ctlr->port+Lmw);791 * ctlr->sr = (uchar*)ctlr->nic+Lmw;
762 * ga620lmw(ctlr, Sr, nil, sizeof(Sbd)*Nsr);792 * ga620lmw(ctlr, Sr, nil, sizeof(Sbd)*Nsr);
763 * ctlr->gib->srcb.addr.lo = Sr;793 * ctlr->gib->srcb.addr.lo = Sr;
764 * There is nowhere in the Sbd to hold the Block* associated794 * There is nowhere in the Sbd to hold the Block* associated
@@ -772,7 +802,7 @@ ga620init(Ether* edev) · 7 unmodified lines
772 flags = HostRing;802 flags = HostRing;
773 if(ctlr->coalupdateonly) 803 if(ctlr->coalupdateonly)
774 flags |= CoalUpdateOnly;804 flags |= CoalUpdateOnly;
775 ctlr->gib->srcb.control = (Nsr<<16)|flags;805 ctlr->gib->srcb.control = Nsr<<16 | flags;
776 sethost64(&ctlr->gib->scp, ctlr->sci);806 sethost64(&ctlr->gib->scp, ctlr->sci);
777 csr32w(ctlr, Spi, 0);807 csr32w(ctlr, Spi, 0);
778 ctlr->srb = malloc(sizeof(Block*)*Nsr);808 ctlr->srb = malloc(sizeof(Block*)*Nsr);
@@ -786,7 +816,7 @@ ga620init(Ether* edev) · 7 unmodified lines
786 flags = TcpUdpCksum|NoPseudoHdrCksum;816 flags = TcpUdpCksum|NoPseudoHdrCksum;
787 else817 else
788 flags = 0;818 flags = 0;
789 ctlr->gib->rsrcb.control = ((ETHERMAXTU+4)<<16)|flags;819 ctlr->gib->rsrcb.control = (ETHERMAXTU+4)<<16 | flags;
790 csr32w(ctlr, Rspi, 0);820 csr32w(ctlr, Rspi, 0);
791 821
792 /*822 /*
@@ -802,7 +832,7 @@ ga620init(Ether* edev) · 9 unmodified lines
802 */832 */
803 ctlr->rrr = malign(sizeof(Rbd)*Nrrr);833 ctlr->rrr = malign(sizeof(Rbd)*Nrrr);
804 sethost64(&ctlr->gib->rrrcb.addr, ctlr->rrr);834 sethost64(&ctlr->gib->rrrcb.addr, ctlr->rrr);
805 ctlr->gib->rrrcb.control = (Nrrr<<16)|0;835 ctlr->gib->rrrcb.control = Nrrr<<16 | 0;
806 sethost64(&ctlr->gib->rrrpp, ctlr->rrrpi);836 sethost64(&ctlr->gib->rrrpp, ctlr->rrrpi);
807 ctlr->rrrci = 0;837 ctlr->rrrci = 0;
808 838
@@ -1024,8 +1054,8 @@ ga620detach(Ctlr* ctlr) · 215 unmodified lines
1024 * wait for code to be loaded from serial EEPROM or flash;1054 * wait for code to be loaded from serial EEPROM or flash;
1025 * make sure CPU A is halted.1055 * make sure CPU A is halted.
1026 */1056 */
1027 csr32w(ctlr, Mhc, (Hr<<24)|Hr);1057 csr32w(ctlr, Mhc, Hr<<24 | Hr);
1028 csr32w(ctlr, Mhc, ((Eews|Ci)<<24)|(Eews|Ci));1058 csr32w(ctlr, Mhc, (Eews|Ci)<<24 | Eews|Ci);
1029 1059
1030 microdelay(1);1060 microdelay(1);
1031 for(timeo = 0; timeo < 500000; timeo++){1061 for(timeo = 0; timeo < 500000; timeo++){
@@ -1056,7 +1086,7 @@ print("ga620shutdown\n"); · 24 unmodified lines
1056static int1086static int
1057ga620reset(Ctlr* ctlr)1087ga620reset(Ctlr* ctlr)
1058{1088{
1059 int cls, csr, i;1089 int cls, csr, i, r;
1060 1090
1061 if(ga620detach(ctlr) < 0)1091 if(ga620detach(ctlr) < 0)
1062 return -1;1092 return -1;
@@ -1095,8 +1125,9 @@ ga620reset(Ctlr* ctlr) · 32 unmodified lines
1095 * Snarf the MAC address from the serial EEPROM.1125 * Snarf the MAC address from the serial EEPROM.
1096 */1126 */
1097 for(i = 0; i < Eaddrlen; i++){1127 for(i = 0; i < Eaddrlen; i++){
1098 if((ctlr->ea[i] = at24c32r(ctlr, 0x8E+i)) == -1)1128 if((r = at24c32r(ctlr, 0x8E+i)) == -1)
1099 return -1;1129 return -1;
1130 ctlr->ea[i] = r;
1100 }1131 }
1101 1132
1102 /*1133 /*
@@ -1114,7 +1145,7 @@ ga620reset(Ctlr* ctlr) · 11 unmodified lines
1114static void1145static void
1115ga620pci(void)1146ga620pci(void)
1116{1147{
1117 int port;1148 void *mem;
1118 Pcidev *p;1149 Pcidev *p;
1119 Ctlr *ctlr;1150 Ctlr *ctlr;
1120 1151
@@ -1123,30 +1154,30 @@ ga620pci(void) · 2 unmodified lines
1123 if(p->ccrb != 0x02 || p->ccru != 0)1154 if(p->ccrb != 0x02 || p->ccru != 0)
1124 continue;1155 continue;
1125 1156
1126 switch((p->did<<16)|p->vid){1157 switch(p->did<<16 | p->vid){
1127 default:1158 default:
1128 continue;1159 continue;
1129 case (0x620A<<16)|0x1385: /* Netgear GA620 */1160 case 0x620A<<16 | 0x1385: /* Netgear GA620 fiber */
1130 case (0x630A<<16)|0x1385: /* Netgear GA620T */1161 case 0x630A<<16 | 0x1385: /* Netgear GA620T copper */
1131 case (0x0001<<16)|0x12AE: /* Alteon Acenic fiber1162 case 0x0001<<16 | 0x12AE: /* Alteon Acenic fiber
1132 * and DEC DEGPA-SA */1163 * and DEC DEGPA-SA */
1133 case (0x0002<<16)|0x12AE: /* Alteon Acenic copper */1164 case 0x0002<<16 | 0x12AE: /* Alteon Acenic copper */
1134 case (0x0009<<16)|0x10A9: /* SGI Acenic */1165 case 0x0009<<16 | 0x10A9: /* SGI Acenic */
1135 break;1166 break;
1136 }1167 }
1137 1168
1138 port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);1169 mem = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
1139 if(port == 0){1170 if(mem == 0){
1140 print("ga620: can't map %8.8luX\n", p->mem[0].bar);1171 print("ga620: can't map %8.8luX\n", p->mem[0].bar);
1141 continue;1172 continue;
1142 }1173 }
1143 1174
1144 ctlr = malloc(sizeof(Ctlr));1175 ctlr = malloc(sizeof(Ctlr));
1145 ctlr->port = port;1176 ctlr->port = p->mem[0].bar & ~0x0F;
1146 ctlr->pcidev = p;1177 ctlr->pcidev = p;
1147 ctlr->id = (p->did<<16)|p->vid;1178 ctlr->id = p->did<<16 | p->vid;
1148 1179
1149 ctlr->nic = KADDR(ctlr->port);1180 ctlr->nic = mem;
1150 if(ga620reset(ctlr)){1181 if(ga620reset(ctlr)){
1151 free(ctlr);1182 free(ctlr);
1152 continue;1183 continue;
@@ -1160,6 +1191,25 @@ ga620pci(void) · 7 unmodified lines
1160 }1191 }
1161}1192}
1162 1193
1194static void
1195ga620promiscuous(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
1203static void
1204ga620multicast(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
1163static int1213static int
1164ga620pnp(Ether* edev)1214ga620pnp(Ether* edev)
1165{1215{
@@ -1188,7 +1238,7 @@ ga620pnp(Ether* edev) · 22 unmodified lines
1188 edev->port = ctlr->port;1238 edev->port = ctlr->port;
1189 edev->irq = ctlr->pcidev->intl;1239 edev->irq = ctlr->pcidev->intl;
1190 edev->tbdf = ctlr->pcidev->tbdf;1240 edev->tbdf = ctlr->pcidev->tbdf;
1191 edev->mbps = 1000;1241 edev->mbps = 1000; /* placeholder */
1192 1242
1193 /*1243 /*
1194 * Check if the adapter's station address is to be overridden.1244 * Check if the adapter's station address is to be overridden.
@@ -1209,10 +1259,11 @@ ga620pnp(Ether* edev) · 14 unmodified lines
1209 edev->interrupt = ga620interrupt;1259 edev->interrupt = ga620interrupt;
1210 edev->ifstat = ga620ifstat;1260 edev->ifstat = ga620ifstat;
1211 edev->ctl = ga620ctl;1261 edev->ctl = ga620ctl;
1212 edev->shutdown = ga620shutdown;
1213 1262
1214 edev->arg = edev;1263 edev->arg = edev;
1215 edev->promiscuous = nil;1264 edev->promiscuous = ga620promiscuous;
1265 edev->multicast = ga620multicast;
1266 edev->shutdown = ga620shutdown;
1216 1267
1217 return 0;1268 return 0;
1218}1269}
os/pc/etherigbe.c+59−38
@@ -29,16 +29,17 @@ · 28 unmodified lines
29#include "ethermii.h"29#include "ethermii.h"
30 30
31enum {31enum {
32 i82542 = (0x1000<<16)|0x8086,32 i82542 = (0x1000<<16)|0x8086,
33 i82543gc = (0x1004<<16)|0x8086,33 i82543gc = (0x1004<<16)|0x8086,
34 i82544ei = (0x1008<<16)|0x8086,34 i82544ei = (0x1008<<16)|0x8086,
35 i82547ei = (0x1019<<16)|0x8086,35 i82547ei = (0x1019<<16)|0x8086,
36 i82540em = (0x100E<<16)|0x8086,36 i82540em = (0x100E<<16)|0x8086,
37 i82540eplp = (0x101E<<16)|0x8086,37 i82540eplp = (0x101E<<16)|0x8086,
38 i82545gmc = (0x1026<<16)|0x8086,38 i82545gmc = (0x1026<<16)|0x8086,
39 i82547gi = (0x1075<<16)|0x8086,39 i82547gi = (0x1075<<16)|0x8086,
40 i82541gi = (0x1076<<16)|0x8086,40 i82541gi = (0x1076<<16)|0x8086,
41 i82546gb = (0x1079<<16)|0x8086,41 i82541gi2 = (0x1077<<16)|0x8086,
42 i82546gb = (0x1079<<16)|0x8086,
42 i82541pi = (0x107c<<16)|0x8086,43 i82541pi = (0x107c<<16)|0x8086,
43 i82546eb = (0x1010<<16)|0x8086,44 i82546eb = (0x1010<<16)|0x8086,
44};45};
@@ -172,7 +173,9 @@ enum { /* Eecd */ · 127 unmodified lines
172 Do = 0x00000008, /* Data Output from the EEPROM */173 Do = 0x00000008, /* Data Output from the EEPROM */
173 Areq = 0x00000040, /* EEPROM Access Request */174 Areq = 0x00000040, /* EEPROM Access Request */
174 Agnt = 0x00000080, /* EEPROM Access Grant */175 Agnt = 0x00000080, /* EEPROM Access Grant */
176 Eepresent = 0x00000100, /* EEPROM Present */
175 Eesz256 = 0x00000200, /* EEPROM is 256 words not 64 */177 Eesz256 = 0x00000200, /* EEPROM is 256 words not 64 */
178 Eeszaddr = 0x00000400, /* EEPROM size for 8254[17] */
176 Spi = 0x00002000, /* EEPROM is SPI not Microwire */179 Spi = 0x00002000, /* EEPROM is SPI not Microwire */
177};180};
178 181
@@ -442,6 +445,7 @@ typedef struct Ctlr { · 263 unmodified lines
442 int port;445 int port;
443 Pcidev* pcidev;446 Pcidev* pcidev;
444 Ctlr* next;447 Ctlr* next;
448 Ether* edev;
445 int active;449 int active;
446 int started;450 int started;
447 int id;451 int id;
@@ -508,7 +512,7 @@ static Ctlr* igbectlrhead; · 60 unmodified lines
508static Ctlr* igbectlrtail;512static Ctlr* igbectlrtail;
509 513
510static Lock igberblock; /* free receive Blocks */514static Lock igberblock; /* free receive Blocks */
511static Block* igberbpool;515static Block* igberbpool; /* receive Blocks for all igbe controllers */
512 516
513static char* statistics[Nstatistics] = {517static char* statistics[Nstatistics] = {
514 "CRC Error",518 "CRC Error",
@@ -671,13 +675,13 @@ igbectl(Ether* edev, void* buf, long n) · 156 unmodified lines
671{675{
672 int v;676 int v;
673 char *p;677 char *p;
674 Ctlr *ctlr; 678 Ctlr *ctlr;
675 Cmdbuf *cb;679 Cmdbuf *cb;
676 Cmdtab *ct;680 Cmdtab *ct;
677 681
678 if((ctlr = edev->ctlr) == nil)682 if((ctlr = edev->ctlr) == nil)
679 error(Enonexist);683 error(Enonexist);
680 684
681 cb = parsecmd(buf, n);685 cb = parsecmd(buf, n);
682 if(waserror()){686 if(waserror()){
683 free(cb);687 free(cb);
@@ -736,7 +740,7 @@ igbemulticast(void* arg, uchar* addr, int on) · 52 unmodified lines
736 ctlr->mta[x] |= 1<<bit;740 ctlr->mta[x] |= 1<<bit;
737 else741 else
738 ctlr->mta[x] &= ~(1<<bit);742 ctlr->mta[x] &= ~(1<<bit);
739 743
740 csr32w(ctlr, Mta+x*4, ctlr->mta[x]);744 csr32w(ctlr, Mta+x*4, ctlr->mta[x]);
741}745}
742 746
@@ -831,6 +835,7 @@ igbelproc(void* arg) · 88 unmodified lines
831 case i82540eplp:835 case i82540eplp:
832 case i82547gi:836 case i82547gi:
833 case i82541gi:837 case i82541gi:
838 case i82541gi2:
834 case i82541pi:839 case i82541pi:
835 break;840 break;
836 }841 }
@@ -881,6 +886,7 @@ igbetxinit(Ctlr* ctlr) · 44 unmodified lines
881 case i82540em:886 case i82540em:
882 case i82540eplp:887 case i82540eplp:
883 case i82541gi:888 case i82541gi:
889 case i82541gi2:
884 case i82541pi:890 case i82541pi:
885 case i82545gmc:891 case i82545gmc:
886 case i82546gb:892 case i82546gb:
@@ -923,6 +929,7 @@ igbetxinit(Ctlr* ctlr) · 36 unmodified lines
923 case i82546gb:929 case i82546gb:
924 case i82546eb:930 case i82546eb:
925 case i82541gi:931 case i82541gi:
932 case i82541gi2:
926 case i82541pi:933 case i82541pi:
927 r = csr32r(ctlr, Txdctl);934 r = csr32r(ctlr, Txdctl);
928 r &= ~WthreshMASK;935 r &= ~WthreshMASK;
@@ -1006,7 +1013,8 @@ igbereplenish(Ctlr* ctlr) · 77 unmodified lines
1006 if(ctlr->rb[rdt] == nil){1013 if(ctlr->rb[rdt] == nil){
1007 bp = igberballoc();1014 bp = igberballoc();
1008 if(bp == nil){1015 if(bp == nil){
1009 iprint("no available buffers\n");1016 iprint("#l%d: igbereplenish: no available buffers\n",
1017 ctlr->edev->ctlrno);
1010 break;1018 break;
1011 }1019 }
1012 ctlr->rb[rdt] = bp;1020 ctlr->rb[rdt] = bp;
@@ -1052,6 +1060,7 @@ igberxinit(Ctlr* ctlr) · 39 unmodified lines
1052 case i82540em:1060 case i82540em:
1053 case i82540eplp:1061 case i82540eplp:
1054 case i82541gi:1062 case i82541gi:
1063 case i82541gi2:
1055 case i82541pi:1064 case i82541pi:
1056 case i82545gmc:1065 case i82545gmc:
1057 case i82546gb:1066 case i82546gb:
@@ -1100,10 +1109,10 @@ igberproc(void* arg) · 42 unmodified lines
1100 rdh = ctlr->rdh;1109 rdh = ctlr->rdh;
1101 for(;;){1110 for(;;){
1102 rd = &ctlr->rdba[rdh];1111 rd = &ctlr->rdba[rdh];
1103 1112
1104 if(!(rd->status & Rdd))1113 if(!(rd->status & Rdd))
1105 break;1114 break;
1106 1115
1107 /*1116 /*
1108 * Accept eop packets with no errors.1117 * Accept eop packets with no errors.
1109 * With no errors and the Ixsm bit set,1118 * With no errors and the Ixsm bit set,
@@ -1150,7 +1159,7 @@ igberproc(void* arg) · 40 unmodified lines
1150 rdh = NEXT(rdh, ctlr->nrd);1159 rdh = NEXT(rdh, ctlr->nrd);
1151 }1160 }
1152 ctlr->rdh = rdh;1161 ctlr->rdh = rdh;
1153 1162
1154 if(ctlr->rdfree < ctlr->nrd/2 || (ctlr->rim & Rxdmt0))1163 if(ctlr->rdfree < ctlr->nrd/2 || (ctlr->rim & Rxdmt0))
1155 igbereplenish(ctlr);1164 igbereplenish(ctlr);
1156 }1165 }
@@ -1164,6 +1173,7 @@ igbeattach(Ether* edev) · 7 unmodified lines
1164 char name[KNAMELEN];1173 char name[KNAMELEN];
1165 1174
1166 ctlr = edev->ctlr;1175 ctlr = edev->ctlr;
1176 ctlr->edev = edev; /* point back to Ether* */
1167 qlock(&ctlr->alock);1177 qlock(&ctlr->alock);
1168 if(ctlr->alloc != nil){1178 if(ctlr->alloc != nil){
1169 qunlock(&ctlr->alock);1179 qunlock(&ctlr->alock);
@@ -1177,7 +1187,7 @@ igbeattach(Ether* edev) · 7 unmodified lines
1177 qunlock(&ctlr->alock);1187 qunlock(&ctlr->alock);
1178 return;1188 return;
1179 }1189 }
1180 ctlr->rdba = (Rd*)ROUNDUP((ulong)ctlr->alloc, 128);1190 ctlr->rdba = (Rd*)ROUNDUP((uintptr)ctlr->alloc, 128);
1181 ctlr->tdba = (Td*)(ctlr->rdba+ctlr->nrd);1191 ctlr->tdba = (Td*)(ctlr->rdba+ctlr->nrd);
1182 1192
1183 ctlr->rb = malloc(ctlr->nrd*sizeof(Block*));1193 ctlr->rb = malloc(ctlr->nrd*sizeof(Block*));
@@ -1448,6 +1458,7 @@ igbemii(Ctlr* ctlr) · 264 unmodified lines
1448 case i82540eplp:1458 case i82540eplp:
1449 case i82547gi:1459 case i82547gi:
1450 case i82541gi:1460 case i82541gi:
1461 case i82541gi2:
1451 case i82541pi:1462 case i82541pi:
1452 case i82545gmc:1463 case i82545gmc:
1453 case i82546gb:1464 case i82546gb:
@@ -1468,7 +1479,8 @@ igbemii(Ctlr* ctlr) · 14 unmodified lines
1468 ctlr->mii = nil;1479 ctlr->mii = nil;
1469 return -1;1480 return -1;
1470 }1481 }
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);
1472 1484
1473 /*1485 /*
1474 * 8254X-specific PHY registers not in 802.3:1486 * 8254X-specific PHY registers not in 802.3:
@@ -1480,6 +1492,7 @@ igbemii(Ctlr* ctlr) · 5 unmodified lines
1480 switch(ctlr->id){1492 switch(ctlr->id){
1481 case i82547gi:1493 case i82547gi:
1482 case i82541gi:1494 case i82541gi:
1495 case i82541gi2:
1483 case i82541pi:1496 case i82541pi:
1484 case i82545gmc:1497 case i82545gmc:
1485 case i82546gb:1498 case i82546gb:
@@ -1491,13 +1504,13 @@ igbemii(Ctlr* ctlr) · 5 unmodified lines
1491 r |= 0x0060; /* auto-crossover all speeds */1504 r |= 0x0060; /* auto-crossover all speeds */
1492 r |= 0x0002; /* polarity reversal enabled */1505 r |= 0x0002; /* polarity reversal enabled */
1493 miimiw(ctlr->mii, 16, r);1506 miimiw(ctlr->mii, 16, r);
1494 1507
1495 r = miimir(ctlr->mii, 20);1508 r = miimir(ctlr->mii, 20);
1496 r |= 0x0070; /* +25MHz clock */1509 r |= 0x0070; /* +25MHz clock */
1497 r &= ~0x0F00;1510 r &= ~0x0F00;
1498 r |= 0x0100; /* 1x downshift */1511 r |= 0x0100; /* 1x downshift */
1499 miimiw(ctlr->mii, 20, r);1512 miimiw(ctlr->mii, 20, r);
1500 1513
1501 miireset(ctlr->mii);1514 miireset(ctlr->mii);
1502 p = 0;1515 p = 0;
1503 if(ctlr->txcw & TxcwPs)1516 if(ctlr->txcw & TxcwPs)
@@ -1578,7 +1591,7 @@ at93c46io(Ctlr* ctlr, char* op, int data) · 74 unmodified lines
1578 break;1591 break;
1579 }1592 }
1580 csr32w(ctlr, Eecd, eecd);1593 csr32w(ctlr, Eecd, eecd);
1581 microdelay(1);1594 microdelay(50);
1582 }1595 }
1583 if(loop >= 0)1596 if(loop >= 0)
1584 return -1;1597 return -1;
@@ -1597,11 +1610,10 @@ at93c46r(Ctlr* ctlr) · 12 unmodified lines
1597 print("igbe: SPI EEPROM access not implemented\n");1610 print("igbe: SPI EEPROM access not implemented\n");
1598 return 0;1611 return 0;
1599 }1612 }
1600 if(eecd & Eesz256)1613 if(eecd & (Eeszaddr|Eesz256))
1601 bits = 8;1614 bits = 8;
1602 else1615 else
1603 bits = 6;1616 bits = 6;
1604 snprint(rop, sizeof(rop), "S :%dDCc;", bits+3);
1605 1617
1606 sum = 0;1618 sum = 0;
1607 1619
@@ -1609,11 +1621,12 @@ at93c46r(Ctlr* ctlr) · 1 unmodified line
1609 default:1621 default:
1610 areq = 0;1622 areq = 0;
1611 break;1623 break;
1624 case i82541gi:
1625 case i82547gi:
1612 case i82540em:1626 case i82540em:
1613 case i82540eplp:1627 case i82540eplp:
1614 case i82541gi:
1615 case i82541pi:1628 case i82541pi:
1616 case i82547gi:1629 case i82541gi2:
1617 case i82545gmc:1630 case i82545gmc:
1618 case i82546gb:1631 case i82546gb:
1619 case i82546eb:1632 case i82546eb:
@@ -1630,6 +1643,7 @@ at93c46r(Ctlr* ctlr) · 10 unmodified lines
1630 }1643 }
1631 break;1644 break;
1632 }1645 }
1646 snprint(rop, sizeof(rop), "S :%dDCc;", bits+3);
1633 1647
1634 for(addr = 0; addr < 0x40; addr++){1648 for(addr = 0; addr < 0x40; addr++){
1635 /*1649 /*
@@ -1698,6 +1712,7 @@ igbedetach(Ctlr* ctlr) · 62 unmodified lines
1698 case i82541gi:1712 case i82541gi:
1699 case i82541pi:1713 case i82541pi:
1700 case i82547gi:1714 case i82547gi:
1715 case i82541gi2:
1701 case i82545gmc:1716 case i82545gmc:
1702 case i82546gb:1717 case i82546gb:
1703 case i82546eb:1718 case i82546eb:
@@ -1751,6 +1766,8 @@ igbereset(Ctlr* ctlr) · 47 unmodified lines
1751 if ((ctlr->id == i82546gb || ctlr->id == i82546eb) && BUSFNO(ctlr->pcidev->tbdf) == 1)1766 if ((ctlr->id == i82546gb || ctlr->id == i82546eb) && BUSFNO(ctlr->pcidev->tbdf) == 1)
1752 ctlr->eeprom[Ea+2] += 0x100; // second interface1767 ctlr->eeprom[Ea+2] += 0x100; // second interface
1753 for(i = Ea; i < Eaddrlen/2; i++){1768 for(i = Ea; i < Eaddrlen/2; i++){
1769if(i == Ea && ctlr->id == i82541gi && ctlr->eeprom[i] == 0xFFFF)
1770 ctlr->eeprom[i] = 0xD000;
1754 ctlr->ra[2*i] = ctlr->eeprom[i];1771 ctlr->ra[2*i] = ctlr->eeprom[i];
1755 ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;1772 ctlr->ra[2*i+1] = ctlr->eeprom[i]>>8;
1756 }1773 }
@@ -1773,14 +1790,14 @@ igbereset(Ctlr* ctlr) · 16 unmodified lines
1773 1790
1774 /*1791 /*
1775 * Just in case the Eerst didn't load the defaults1792 * 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.
1777 */1794 */
1778 if (ctlr->id == i82543gc) { // 825431795 if (ctlr->id == i82543gc) {
1779 txcw = csr32r(ctlr, Txcw);1796 txcw = csr32r(ctlr, Txcw);
1780 txcw &= ~(TxcwAne|TxcwPauseMASK|TxcwFd);1797 txcw &= ~(TxcwAne|TxcwPauseMASK|TxcwFd);
1781 ctrl = csr32r(ctlr, Ctrl);1798 ctrl = csr32r(ctlr, Ctrl);
1782 ctrl &= ~(SwdpioloMASK|Frcspd|Ilos|Lrst|Fd);1799 ctrl &= ~(SwdpioloMASK|Frcspd|Ilos|Lrst|Fd);
1783 1800
1784 if(ctlr->eeprom[Icw1] & 0x0400){1801 if(ctlr->eeprom[Icw1] & 0x0400){
1785 ctrl |= Fd;1802 ctrl |= Fd;
1786 txcw |= TxcwFd;1803 txcw |= TxcwFd;
@@ -1794,7 +1811,7 @@ igbereset(Ctlr* ctlr) · 7 unmodified lines
1794 swdpio = (ctlr->eeprom[Icw1] & 0x01E0)>>5;1811 swdpio = (ctlr->eeprom[Icw1] & 0x01E0)>>5;
1795 ctrl |= swdpio<<SwdpioloSHIFT;1812 ctrl |= swdpio<<SwdpioloSHIFT;
1796 csr32w(ctlr, Ctrl, ctrl);1813 csr32w(ctlr, Ctrl, ctrl);
1797 1814
1798 ctrl = csr32r(ctlr, Ctrlext);1815 ctrl = csr32r(ctlr, Ctrlext);
1799 ctrl &= ~(Ips|SwdpiohiMASK);1816 ctrl &= ~(Ips|SwdpiohiMASK);
1800 swdpio = (ctlr->eeprom[Icw2] & 0x00F0)>>4;1817 swdpio = (ctlr->eeprom[Icw2] & 0x00F0)>>4;
@@ -1802,7 +1819,7 @@ igbereset(Ctlr* ctlr) · 1 unmodified line
1802 ctrl |= Ips;1819 ctrl |= Ips;
1803 ctrl |= swdpio<<SwdpiohiSHIFT;1820 ctrl |= swdpio<<SwdpiohiSHIFT;
1804 csr32w(ctlr, Ctrlext, ctrl);1821 csr32w(ctlr, Ctrlext, ctrl);
1805 1822
1806 if(ctlr->eeprom[Icw2] & 0x0800)1823 if(ctlr->eeprom[Icw2] & 0x0800)
1807 txcw |= TxcwAne;1824 txcw |= TxcwAne;
1808 pause = (ctlr->eeprom[Icw2] & 0x3000)>>12;1825 pause = (ctlr->eeprom[Icw2] & 0x3000)>>12;
@@ -1827,7 +1844,7 @@ igbereset(Ctlr* ctlr) · 18 unmodified lines
1827 csr32w(ctlr, Txcw, txcw);1844 csr32w(ctlr, Txcw, txcw);
1828 }1845 }
1829 1846
1830 1847
1831 /*1848 /*
1832 * Flow control - values from the datasheet.1849 * Flow control - values from the datasheet.
1833 */1850 */
@@ -1848,9 +1865,10 @@ igbereset(Ctlr* ctlr) · 14 unmodified lines
1848static void1865static void
1849igbepci(void)1866igbepci(void)
1850{1867{
1851 int port, cls;1868 int cls;
1852 Pcidev *p;1869 Pcidev *p;
1853 Ctlr *ctlr;1870 Ctlr *ctlr;
1871 void *mem;
1854 1872
1855 p = nil;1873 p = nil;
1856 while(p = pcimatch(p, 0, 0)){1874 while(p = pcimatch(p, 0, 0)){
@@ -1865,8 +1883,9 @@ igbepci(void) · 8 unmodified lines
1865 case i82547ei:1883 case i82547ei:
1866 case i82540em:1884 case i82540em:
1867 case i82540eplp:1885 case i82540eplp:
1868 case i82547gi:
1869 case i82541gi:1886 case i82541gi:
1887 case i82547gi:
1888 case i82541gi2:
1870 case i82541pi:1889 case i82541pi:
1871 case i82545gmc:1890 case i82545gmc:
1872 case i82546gb:1891 case i82546gb:
@@ -1874,8 +1893,8 @@ igbepci(void) · 1 unmodified line
1874 break;1893 break;
1875 }1894 }
1876 1895
1877 port = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);1896 mem = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
1878 if(port == 0){1897 if(mem == nil){
1879 print("igbe: can't map %8.8luX\n", p->mem[0].bar);1898 print("igbe: can't map %8.8luX\n", p->mem[0].bar);
1880 continue;1899 continue;
1881 }1900 }
@@ -1893,14 +1912,15 @@ igbepci(void) · 11 unmodified lines
1893 break;1912 break;
1894 }1913 }
1895 ctlr = malloc(sizeof(Ctlr));1914 ctlr = malloc(sizeof(Ctlr));
1896 ctlr->port = port;1915 ctlr->port = p->mem[0].bar & ~0x0F;
1897 ctlr->pcidev = p;1916 ctlr->pcidev = p;
1898 ctlr->id = (p->did<<16)|p->vid;1917 ctlr->id = (p->did<<16)|p->vid;
1899 ctlr->cls = cls*4;1918 ctlr->cls = cls*4;
1900 ctlr->nic = KADDR(ctlr->port);1919 ctlr->nic = mem;
1901 1920
1902 if(igbereset(ctlr)){1921 if(igbereset(ctlr)){
1903 free(ctlr);1922 free(ctlr);
1923 vunmap(mem, p->mem[0].size);
1904 continue;1924 continue;
1905 }1925 }
1906 pcisetbme(p);1926 pcisetbme(p);
@@ -1966,3 +1986,4 @@ etherigbelink(void) · 59 unmodified lines
1966 addethercard("i82543", igbepnp);1986 addethercard("i82543", igbepnp);
1967 addethercard("igbe", igbepnp);1987 addethercard("igbe", igbepnp);
1968}1988}
1989
os/pc/ethersmc.c+1−0
@@ -713,6 +713,7 @@ reset(Ether* ether) · 712 unmodified lines
713 if (ctlr == 0) {713 if (ctlr == 0) {
714 iofree(ether->port);714 iofree(ether->port);
715 pcmspecialclose(slot);715 pcmspecialclose(slot);
716 return -1;
716 }717 }
717 718
718 ilock(ctlr);719 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
24enum {
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
43enum { /* 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
61enum { /* 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
74enum { /* 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
90enum { /* 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
109enum { /* 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
117enum { /* 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
139enum { /* 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
152enum { /* 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
163enum { /* 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
171enum { /* 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 */
187typedef struct Ds Ds;
188typedef 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
200enum { /* 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
222enum { /* 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
236enum { /* 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
246enum {
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
257typedef struct Ctlr Ctlr;
258typedef 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
303static Ctlr* vt6102ctlrhead;
304static 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
313static 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};
323static 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
334static long
335vt6102ifstat(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
385static void
386vt6102promiscuous(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
402static void
403vt6102multicast(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
413static int
414vt6102wakeup(void* v)
415{
416 return *((int*)v) != 0;
417}
418
419static void
420vt6102imr(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
428static void
429vt6102lproc(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);
451enable:
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
462static void
463vt6102attach(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
572static void
573vt6102transmit(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
694static void
695vt6102receive(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
735static void
736vt6102interrupt(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
793static int
794vt6102miimicmd(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
823static int
824vt6102miimir(Mii* mii, int pa, int ra)
825{
826 return vt6102miimicmd(mii, pa, ra, Rcmd, 0);
827}
828
829static int
830vt6102miimiw(Mii* mii, int pa, int ra, int data)
831{
832 return vt6102miimicmd(mii, pa, ra, Wcmd, data);
833}
834
835static int
836vt6102detach(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
855static int
856vt6102reset(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
919static void
920vt6102pci(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
974static int
975vt6102pnp(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
1020void
1021ethervt6102link(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
87 int did;87 int did;
88} wavelanpci[] = {88} wavelanpci[] = {
89 0x1260, 0x3873, /* Intersil Prism2.5 */89 0x1260, 0x3873, /* Intersil Prism2.5 */
90 0x1737, 0x0019, /* Linksys WPC-11 untested */
90};91};
91 92
92static Ctlr *ctlrhead, *ctlrtail;93static Ctlr *ctlrhead, *ctlrtail;
@@ -95,7 +96,7 @@ static void · 2 unmodified lines
95wavelanpciscan(void)96wavelanpciscan(void)
96{97{
97 int i;98 int i;
98 ulong pa;99 void *mem;
99 Pcidev *p;100 Pcidev *p;
100 Ctlr *ctlr;101 Ctlr *ctlr;
101 102
@@ -117,13 +118,13 @@ wavelanpciscan(void) · 15 unmodified lines
117 118
118 ctlr = malloc(sizeof(Ctlr));119 ctlr = malloc(sizeof(Ctlr));
119 ctlr->pcidev = p;120 ctlr->pcidev = p;
120 pa = upamalloc(p->mem[0].bar&~0xF, p->mem[0].size, 0);121 mem = vmap(p->mem[0].bar&~0xF, p->mem[0].size);
121 if(pa == 0){122 if(mem == nil){
122 print("wavelanpci: %.4ux %.4ux: upamalloc 0x%.8lux %d failed\n", p->vid, p->did, p->mem[0].bar&~0xF, p->mem[0].size);123 print("wavelanpci: %.4ux %.4ux: vmap 0x%.8lux %d failed\n", p->vid, p->did, p->mem[0].bar&~0xF, p->mem[0].size);
123 free(ctlr);124 free(ctlr);
124 continue;125 continue;
125 }126 }
126 ctlr->mmb = (ushort*)KADDR(pa);127 ctlr->mmb = mem;
127 if(ctlrhead != nil)128 if(ctlrhead != nil)
128 ctlrtail->next = ctlr;129 ctlrtail->next = ctlr;
129 else130 else
os/pc/fns.h+4−0
@@ -104,6 +104,7 @@ void pcicfgw16(Pcidev*, int, int); · 103 unmodified lines
104void pcicfgw32(Pcidev*, int, int);104void pcicfgw32(Pcidev*, int, int);
105void pciclrbme(Pcidev*);105void pciclrbme(Pcidev*);
106void pciclrioe(Pcidev*);106void pciclrioe(Pcidev*);
107void pciclrmwi(Pcidev*);
107int pcigetpms(Pcidev*);108int pcigetpms(Pcidev*);
108void pcihinv(Pcidev*);109void pcihinv(Pcidev*);
109uchar pciipin(Pcidev*, uchar);110uchar pciipin(Pcidev*, uchar);
@@ -144,7 +145,10 @@ ulong umbrwmalloc(ulong, int, int); · 34 unmodified lines
144void umbrwfree(ulong, int);145void umbrwfree(ulong, int);
145ulong upamalloc(ulong, int, int);146ulong upamalloc(ulong, int, int);
146void upafree(ulong, int);147void upafree(ulong, int);
148void upareserve(ulong, int);
147void vectortable(void);149void vectortable(void);
150void* vmap(ulong, int);
151void vunmap(void*, int);
148void wrmsr(ulong, ulong);152void wrmsr(ulong, ulong);
149int xchgw(ushort*, int);153int xchgw(ushort*, int);
150ulong kzeromap(ulong, ulong, int);154ulong kzeromap(ulong, ulong, int);
os/pc/i8253.c+1−1
@@ -201,7 +201,7 @@ i8253timerset(uvlong next) · 200 unmodified lines
201 period = want - now;201 period = want - now;
202 if(period < MinPeriod)202 if(period < MinPeriod)
203 period = MinPeriod;203 period = MinPeriod;
204 else if(period > (4*MaxPeriod)/5) /* strong attraction to MaxPeriod */204 else if(period > MaxPeriod)
205 period = MaxPeriod;205 period = MaxPeriod;
206 }206 }
207 207
os/pc/io.h+49−1
@@ -95,7 +95,7 @@ enum { · 94 unmodified lines
95/*95/*
96 * PCI support code.96 * PCI support code.
97 */97 */
98enum { /* type 0 and type 1 pre-defined header */98enum { /* type 0 & type 1 pre-defined header */
99 PciVID = 0x00, /* vendor ID */99 PciVID = 0x00, /* vendor ID */
100 PciDID = 0x02, /* device ID */100 PciDID = 0x02, /* device ID */
101 PciPCR = 0x04, /* command */101 PciPCR = 0x04, /* command */
@@ -116,6 +116,54 @@ enum { /* type 0 and type 1 pre-defined header */ · 14 unmodified lines
116 PciINTP = 0x3D, /* interrupt pin */116 PciINTP = 0x3D, /* interrupt pin */
117};117};
118 118
119/* ccrb (base class code) values; controller types */
120enum {
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 */
142enum {
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
119enum { /* type 0 pre-defined header */167enum { /* type 0 pre-defined header */
120 PciCIS = 0x28, /* cardbus CIS pointer */168 PciCIS = 0x28, /* cardbus CIS pointer */
121 PciSVID = 0x2C, /* subsystem vendor ID */169 PciSVID = 0x2C, /* subsystem vendor ID */
os/pc/memory.c+18−0
@@ -568,3 +568,21 @@ upafree(ulong pa, int size) · 567 unmodified lines
568{568{
569 mapfree(&xrmapupa, pa, size);569 mapfree(&xrmapupa, pa, size);
570}570}
571
572void
573upareserve(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
319 319
320 return pa;320 return pa;
321}321}
322
323void*
324vmap(ulong pa, int size)
325{
326 pa = upamalloc(pa, size, 0);
327 if(pa == 0)
328 return nil;
329 return KADDR(pa);
330}
331
332void
333vunmap(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
176 int ntb, i, size, rno, hole;176 int ntb, i, size, rno, hole;
177 ulong v, mema, ioa, sioa, smema, base, limit;177 ulong v, mema, ioa, sioa, smema, base, limit;
178 Pcisiz *table, *tptr, *mtb, *itb;178 Pcisiz *table, *tptr, *mtb, *itb;
179 extern void qsort(void*, long, long, int (*)(void*, void*));
180 179
181 if(!nobios)180 if(!nobios)
182 return;181 return;
os/port/chan.c+17−17
@@ -1297,25 +1297,25 @@ if(c->umh != nil){ · 1296 unmodified lines
1297 c = cnew;1297 c = cnew;
1298 c->name = addelem(c->name, e.elems[e.nelems-1]);1298 c->name = addelem(c->name, e.elems[e.nelems-1]);
1299 break;1299 break;
1300 }else{ /* create failed */1300 }
1301 cclose(cnew);1301
1302 if(m)1302 /* create failed */
1303 putmhead(m);1303 cclose(cnew);
1304 if(omode & OEXCL)1304 if(m)
1305 nexterror();1305 putmhead(m);
1306 /* save error */1306 if(omode & OEXCL)
1307 createerr = up->env->errstr;1307 nexterror();
1308 up->env->errstr = tmperrbuf;1308 /* save error */
1309 /* note: we depend that walk does not error */1309 createerr = up->env->errstr;
1310 if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) < 0){1310 up->env->errstr = tmperrbuf;
1311 up->env->errstr = createerr;1311 /* note: we depend that walk does not error */
1312 error(createerr); /* report true error */1312 if(walk(&c, e.elems+e.nelems-1, 1, nomount, nil) < 0){
1313 }
1314 up->env->errstr = createerr;1313 up->env->errstr = createerr;
1315 omode |= OTRUNC;1314 error(createerr); /* report true error */
1316 goto Open;
1317 }1315 }
1318 panic("namec: not reached"); 1316 up->env->errstr = createerr;
1317 omode |= OTRUNC;
1318 goto Open;
1319 1319
1320 default:1320 default:
1321 panic("unknown namec access %d\n", amode);1321 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
258 }258 }
259 break;259 break;
260 }260 }
261 error(Egreg); /* not reached? */
262 return -1;
263}261}
264 262
265long263long
os/port/ethermii.c+3−3
@@ -177,13 +177,13 @@ miistatus(Mii* mii) · 176 unmodified lines
177 bmsr = mii->mir(mii, phyno, Bmsr);177 bmsr = mii->mir(mii, phyno, Bmsr);
178 if(!(bmsr & (BmsrAnc|BmsrAna)))178 if(!(bmsr & (BmsrAnc|BmsrAna)))
179{179{
180print("miistatus 1\n");180print("miistatus: auto-neg incomplete\n");
181 return -1;181 return -1;
182}182}
183 183
184 bmsr = mii->mir(mii, phyno, Bmsr);184 bmsr = mii->mir(mii, phyno, Bmsr);
185 if(!(bmsr & BmsrLs)){185 if(!(bmsr & BmsrLs)){
186print("miistatus 2\n");186print("miistatus: link down\n");
187 phy->link = 0;187 phy->link = 0;
188 return -1;188 return -1;
189 }189 }
@@ -217,7 +217,7 @@ print("miistatus 2\n"); · 27 unmodified lines
217 }217 }
218 if(phy->speed == 0)218 if(phy->speed == 0)
219{219{
220print("miistatus 3\n");220print("miistatus: phy speed 0\n");
221 return -1;221 return -1;
222}222}
223 223
os/port/lib.h+3−2
@@ -2,9 +2,9 @@ · 1 unmodified line
2/*2/*
3 * functions (possibly) linked in, complete, from libc.3 * functions (possibly) linked in, complete, from libc.
4 */4 */
5#define nelem(n) (sizeof(n)/sizeof(n[0]))5#define nelem(x) (sizeof(x)/sizeof((x)[0]))
6#define offsetof(s, m) (ulong)(&(((s*)0)->m))6#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")
8 8
9/*9/*
10 * mem routines10 * mem routines
@@ -123,6 +123,7 @@ extern char end[]; · 112 unmodified lines
123extern int getfields(char*, char**, int, int, char*);123extern int getfields(char*, char**, int, int, char*);
124extern int tokenize(char*, char**, int);124extern int tokenize(char*, char**, int);
125extern int dec64(uchar*, int, char*, int);125extern int dec64(uchar*, int, char*, int);
126extern void qsort(void*, long, long, int (*)(void*, void*));
126 127
127extern int toupper(int);128extern int toupper(int);
128extern char* netmkaddr(char*, char*, char*);129extern char* netmkaddr(char*, char*, char*);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t