Unified · Split
| @@ -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 | ||
| 1039 | static void | 1037 | static void |
| @@ -669,5 +669,4 @@ extern Chan* chandial(char*, char*, char*, Chan**); · 668 unmodified lines | |||
| 669 | /* | 669 | /* |
| 670 | * global to all of the stack | 670 | * global to all of the stack |
| 671 | */ | 671 | */ |
| 672 | extern int debug; | ||
| 673 | extern void (*igmpreportfn)(Ipifc*, uchar*); | 672 | extern void (*igmpreportfn)(Ipifc*, uchar*); |
| @@ -11,11 +11,11 @@ · 10 unmodified lines | |||
| 11 | #define DPRINT if(0)print | 11 | #define DPRINT if(0)print |
| 12 | 12 | ||
| 13 | enum { | 13 | enum { |
| 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 | ||
| 21 | Medium *media[Maxmedia] = | 21 | Medium *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 | else | 137 | 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 managed | 147 | ifc->rp.mflag = 0; // default not managed |
| 148 | ifc->rp.oflag = 0; | 148 | ifc->rp.oflag = 0; |
| 149 | ifc->rp.maxraint = 600000; // millisecs | 149 | ifc->rp.maxraint = 600000; // millisecs |
| 150 | ifc->rp.minraint = 200000; | 150 | ifc->rp.minraint = 200000; |
| 151 | ifc->rp.linkmtu = 0; // no mtu sent | 151 | 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 ctl | 332 | * called after last close of ipifc data or ctl |
| 333 | * called with c locked, we must unlock | 333 | * 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 | ||
| 536 | out: | 536 | out: |
| 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 | ||
| 1099 | int | 1099 | int |
| 1100 | iptentative(Fs *f, uchar *addr) | 1100 | iptentative(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 | ||
| 1213 | void | 1213 | static void |
| 1214 | findprimaryip6(Fs *f, uchar *local) | 1214 | findprimaryipv6(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 | */ |
| 1248 | void | 1248 | static void |
| 1249 | findprimaryip(Fs *f, uchar *local) | 1249 | findprimaryipv4(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 generated | 1646 | if(!(force) && (strcmp(r->tag,"ra")!=0)) // route entries generated |
| 1647 | return; // by all other means take | 1647 | return; // by all other means take |
| 1648 | // precedence over router annc | 1648 | // 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 | else | 1710 | else |
| 1711 | return Ebadarg; | 1711 | return Ebadarg; |
| @@ -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){ |
| @@ -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 & constants | 99 | // 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 | }; |
| @@ -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 | ||
| 287 | int tcp_irtt = DEF_RTT; /* Initial guess at round trip time */ | 287 | int tcp_irtt = DEF_RTT; /* Initial guess at round trip time */ |
| 288 | ushort tcp_mss = DEF_MSS; /* Maximum segment size to be sent */ | 288 | ushort tcp_mss = DEF_MSS; /* Maximum segment size to be sent */ |
| 289 | 289 | ||
| 290 | enum { | 290 | enum { |
| 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's | 354 | * Setting tcpporthogdefense to non-zero enables Dong Lin's |
| 355 | * solution to hijacked systems staking out port's as a form | 355 | * 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 | |||
| 375 | void tcpacktimer(void*); | 375 | void tcpacktimer(void*); |
| 376 | void tcpkeepalive(void*); | 376 | void tcpkeepalive(void*); |
| 377 | void tcpsetkacounter(Tcpctl*); | 377 | void tcpsetkacounter(Tcpctl*); |
| 378 | void tcprxmit(Conv*); | 378 | void tcprxmit(Conv*); |
| 379 | void tcpsettimer(Tcpctl*); | 379 | void tcpsettimer(Tcpctl*); |
| 380 | void tcpsynackrtt(Conv*); | 380 | void tcpsynackrtt(Conv*); |
| 381 | void tcpsetscale(Conv*, Tcpctl*, ushort, ushort); | 381 | void tcpsetscale(Conv*, Tcpctl*, ushort, ushort); |
| @@ -711,7 +711,7 @@ backoff(int n) · 329 unmodified lines | |||
| 711 | } | 711 | } |
| 712 | 712 | ||
| 713 | void | 713 | void |
| 714 | localclose(Conv *s, char *reason) /* called with tcb locked */ | 714 | localclose(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 window | 1805 | * 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 is | 2281 | * Force an ack every 2 data messages. This is |
| 2282 | * a hack for rob to make his home system run | 2282 | * 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 | |||
| 2841 | addreseq(Tcpctl *tcb, Tcppriv *tpriv, Tcp *seg, Block *bp, ushort length) | 2841 | addreseq(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) |
| @@ -132,7 +132,6 @@ ne2000pnp(Ether* edev) · 131 unmodified lines | |||
| 132 | static int | 132 | static int |
| 133 | ne2000reset(Ether* edev) | 133 | ne2000reset(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 be | 197 | * initialisation has been tried, but that wouldn't be |
| 199 | * enough, there are other ethernet boards which could | 198 | * 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; |
| @@ -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 | ||
| 195 | typedef struct Ctlr Ctlr; | 196 | typedef 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 *4 | 1704 | * 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 | |||
| 1823 | void | 1825 | void |
| 1824 | ether2114xlink(void) | 1826 | ether2114xlink(void) |
| 1825 | { | 1827 | { |
| 1826 | addethercard("21140", reset); | ||
| 1827 | addethercard("2114x", reset); | 1828 | addethercard("2114x", reset); |
| 1829 | addethercard("21140", reset); | ||
| 1828 | } | 1830 | } |
| @@ -300,6 +300,12 @@ promiscuous(void* arg, int on) · 299 unmodified lines | |||
| 300 | iunlock(ctlr); | 300 | iunlock(ctlr); |
| 301 | } | 301 | } |
| 302 | 302 | ||
| 303 | static void | ||
| 304 | multicast(void* arg, uchar*, int) | ||
| 305 | { | ||
| 306 | promiscuous(arg, 1); | ||
| 307 | } | ||
| 308 | |||
| 303 | static void | 309 | static void |
| 304 | txstart(Ether* ether) | 310 | txstart(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); |
| 525 | iprint("#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); |
| 542 | iprint("#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 | } |
| @@ -234,6 +234,12 @@ rtl8139promiscuous(void* arg, int on) · 233 unmodified lines | |||
| 234 | iunlock(&ctlr->ilock); | 234 | iunlock(&ctlr->ilock); |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | static void | ||
| 238 | rtl8139multicast(void* arg, uchar*, int) | ||
| 239 | { | ||
| 240 | rtl8139promiscuous(arg, 1); | ||
| 241 | } | ||
| 242 | |||
| 237 | static long | 243 | static long |
| 238 | rtl8139ifstat(Ether* edev, void* a, long n, ulong offset) | 244 | rtl8139ifstat(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. |
| @@ -1243,7 +1243,8 @@ gc82543watchdog(void* arg) · 1242 unmodified lines | |||
| 1243 | static void | 1243 | static void |
| 1244 | gc82543pci(void) | 1244 | gc82543pci(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); |
| @@ -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 whether | 1101 | * Eeprom[6] indicates whether there is a PHY and whether |
| @@ -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 | ||
| 82 | enum { /* Variants */ | 82 | enum { /* 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 | ||
| 87 | typedef struct Ctlr Ctlr; | 100 | typedef struct Ctlr Ctlr; |
| @@ -456,9 +469,9 @@ txrxcfg(Ctlr *ctlr, int txdrth) · 368 unmodified lines | |||
| 456 | static void | 469 | static void |
| 457 | interrupt(Ureg*, void* arg) | 470 | interrupt(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 | ||
| 801 | static char* mediatable[9] = { | 830 | static char* mediatable[9] = { |
| @@ -810,8 +839,82 @@ static char* mediatable[9] = { · 8 unmodified lines | |||
| 810 | "100BASE-FXFD", | 839 | "100BASE-FXFD", |
| 811 | }; | 840 | }; |
| 812 | 841 | ||
| 842 | static int | ||
| 843 | is630(ulong id, Pcidev *p) | ||
| 844 | { | ||
| 845 | if(id == SiS900) | ||
| 846 | switch (p->rid) { | ||
| 847 | case SiSrev630s: | ||
| 848 | case SiSrev630e: | ||
| 849 | case SiSrev630ea1: | ||
| 850 | return 1; | ||
| 851 | } | ||
| 852 | return 0; | ||
| 853 | } | ||
| 854 | |||
| 855 | enum { | ||
| 856 | MagicReg = 0x48, | ||
| 857 | MagicRegSz = 1, | ||
| 858 | Magicrden = 0x40, /* read enable, apparently */ | ||
| 859 | Paddr= 0x70, /* address port */ | ||
| 860 | Pdata= 0x71, /* data port */ | ||
| 861 | }; | ||
| 862 | |||
| 863 | /* rcmos() originally from LANL's SiS 900 driver's rcmos() */ | ||
| 864 | static int | ||
| 865 | sisrdcmos(Ctlr *ctlr) | ||
| 866 | { | ||
| 867 | int i; | ||
| 868 | unsigned reg; | ||
| 869 | ulong port; | ||
| 870 | Pcidev *p; | ||
| 871 | |||
| 872 | debug("ns83815: SiS 630 rev. %ux reading mac address from cmos\n", ctlr->pcidev->rid); | ||
| 873 | p = pcimatch(nil, SiS, SiS630bridge); | ||
| 874 | if(p == nil) { | ||
| 875 | print("ns83815: no SiS 630 rev. %ux bridge for mac addr\n", | ||
| 876 | ctlr->pcidev->rid); | ||
| 877 | return 0; | ||
| 878 | } | ||
| 879 | port = p->mem[0].bar & ~0x01; | ||
| 880 | debug("ns83815: SiS 630 rev. %ux reading mac addr from cmos via bridge at port 0x%lux\n", ctlr->pcidev->rid, port); | ||
| 881 | |||
| 882 | reg = pcicfgr8(p, MagicReg); | ||
| 883 | pcicfgw8(p, MagicReg, reg|Magicrden); | ||
| 884 | |||
| 885 | for (i = 0; i < Eaddrlen; i++) { | ||
| 886 | outb(port+Paddr, SiS630eenodeaddr + i); | ||
| 887 | ctlr->sromea[i] = inb(port+Pdata); | ||
| 888 | } | ||
| 889 | |||
| 890 | pcicfgw8(p, MagicReg, reg & ~Magicrden); | ||
| 891 | return 1; | ||
| 892 | } | ||
| 893 | |||
| 894 | /* | ||
| 895 | * If this is a SiS 630E chipset with an embedded SiS 900 controller, | ||
| 896 | * we have to read the MAC address from the APC CMOS RAM. - sez freebsd. | ||
| 897 | * However, CMOS *is* NVRAM normally. See devrtc.c:440, memory.c:88. | ||
| 898 | */ | ||
| 813 | static void | 899 | static void |
| 814 | srom(Ctlr* ctlr) | 900 | sissrom(Ctlr *ctlr) |
| 901 | { | ||
| 902 | union { | ||
| 903 | uchar eaddr[Eaddrlen]; | ||
| 904 | ushort alignment; | ||
| 905 | } ee; | ||
| 906 | int i, off = SiSeenodeaddr, cnt = sizeof ee.eaddr / sizeof(short); | ||
| 907 | ushort *shp = (ushort *)ee.eaddr; | ||
| 908 | |||
| 909 | if(!is630(ctlr->id, ctlr->pcidev) || !sisrdcmos(ctlr)) { | ||
| 910 | for (i = 0; i < cnt; i++) | ||
| 911 | *shp++ = eegetw(ctlr, off++); | ||
| 912 | memmove(ctlr->sromea, ee.eaddr, sizeof ctlr->sromea); | ||
| 913 | } | ||
| 914 | } | ||
| 915 | |||
| 916 | static void | ||
| 917 | nssrom(Ctlr* ctlr) | ||
| 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 boundaries | 925 | * 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 | ||
| 934 | static void | ||
| 935 | srom(Ctlr* ctlr) | ||
| 936 | { | ||
| 937 | memset(ctlr->sromea, 0, sizeof(ctlr->sromea)); | ||
| 938 | switch (ctlr->id) { | ||
| 939 | case SiS900: | ||
| 940 | case SiS7016: | ||
| 941 | sissrom(ctlr); | ||
| 942 | break; | ||
| 943 | case Nat83815: | ||
| 944 | nssrom(ctlr); | ||
| 945 | break; | ||
| 946 | default: | ||
| 947 | print("ns83815: srom: unknown id 0x%ux\n", ctlr->id); | ||
| 948 | break; | ||
| 949 | } | ||
| 950 | } | ||
| 951 | |||
| 832 | static void | 952 | static void |
| 833 | scanpci83815(void) | 953 | scanpci83815(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); |
| @@ -400,7 +400,7 @@ receive(Ether* ether) · 399 unmodified lines | |||
| 400 | */ | 400 | */ |
| 401 | if(hdr.next < ctlr->pstart || hdr.next >= ctlr->pstop | 401 | 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 | /* |
| @@ -0,0 +1,1246 @@ | |||
| 1 | /* | ||
| 2 | * National Semiconductor DP83820 | ||
| 3 | * 10/100/1000 Mb/s Ethernet Network Interface Controller | ||
| 4 | * (Gig-NIC). | ||
| 5 | * Driver assumes little-endian and 32-bit host throughout. | ||
| 6 | */ | ||
| 7 | #include "u.h" | ||
| 8 | #include "../port/lib.h" | ||
| 9 | #include "mem.h" | ||
| 10 | #include "dat.h" | ||
| 11 | #include "fns.h" | ||
| 12 | #include "io.h" | ||
| 13 | #include "../port/error.h" | ||
| 14 | #include "../port/netif.h" | ||
| 15 | |||
| 16 | #include "etherif.h" | ||
| 17 | #include "ethermii.h" | ||
| 18 | |||
| 19 | enum { /* Registers */ | ||
| 20 | Cr = 0x00, /* Command */ | ||
| 21 | Cfg = 0x04, /* Configuration and Media Status */ | ||
| 22 | Mear = 0x08, /* MII/EEPROM Access */ | ||
| 23 | Ptscr = 0x0C, /* PCI Test Control */ | ||
| 24 | Isr = 0x10, /* Interrupt Status */ | ||
| 25 | Imr = 0x14, /* Interrupt Mask */ | ||
| 26 | Ier = 0x18, /* Interrupt Enable */ | ||
| 27 | Ihr = 0x1C, /* Interrupt Holdoff */ | ||
| 28 | Txdp = 0x20, /* Transmit Descriptor Pointer */ | ||
| 29 | Txdphi = 0x24, /* Transmit Descriptor Pointer Hi */ | ||
| 30 | Txcfg = 0x28, /* Transmit Configuration */ | ||
| 31 | Gpior = 0x2C, /* General Purpose I/O Control */ | ||
| 32 | Rxdp = 0x30, /* Receive Descriptor Pointer */ | ||
| 33 | Rxdphi = 0x34, /* Receive Descriptor Pointer Hi */ | ||
| 34 | Rxcfg = 0x38, /* Receive Configuration */ | ||
| 35 | Pqcr = 0x3C, /* Priority Queueing Control */ | ||
| 36 | Wcsr = 0x40, /* Wake on LAN Control/Status */ | ||
| 37 | Pcr = 0x44, /* Pause Control/Status */ | ||
| 38 | Rfcr = 0x48, /* Receive Filter/Match Control */ | ||
| 39 | Rfdr = 0x4C, /* Receive Filter/Match Data */ | ||
| 40 | Brar = 0x50, /* Boot ROM Address */ | ||
| 41 | Brdr = 0x54, /* Boot ROM Data */ | ||
| 42 | Srr = 0x58, /* Silicon Revision */ | ||
| 43 | Mibc = 0x5C, /* MIB Control */ | ||
| 44 | Mibd = 0x60, /* MIB Data */ | ||
| 45 | Txdp1 = 0xA0, /* Txdp Priority 1 */ | ||
| 46 | Txdp2 = 0xA4, /* Txdp Priority 2 */ | ||
| 47 | Txdp3 = 0xA8, /* Txdp Priority 3 */ | ||
| 48 | Rxdp1 = 0xB0, /* Rxdp Priority 1 */ | ||
| 49 | Rxdp2 = 0xB4, /* Rxdp Priority 2 */ | ||
| 50 | Rxdp3 = 0xB8, /* Rxdp Priority 3 */ | ||
| 51 | Vrcr = 0xBC, /* VLAN/IP Receive Control */ | ||
| 52 | Vtcr = 0xC0, /* VLAN/IP Transmit Control */ | ||
| 53 | Vdr = 0xC4, /* VLAN Data */ | ||
| 54 | Ccsr = 0xCC, /* Clockrun Control/Status */ | ||
| 55 | Tbicr = 0xE0, /* TBI Control */ | ||
| 56 | Tbisr = 0xE4, /* TBI Status */ | ||
| 57 | Tanar = 0xE8, /* TBI ANAR */ | ||
| 58 | Tanlpar = 0xEC, /* TBI ANLPAR */ | ||
| 59 | Taner = 0xF0, /* TBI ANER */ | ||
| 60 | Tesr = 0xF4, /* TBI ESR */ | ||
| 61 | }; | ||
| 62 | |||
| 63 | enum { /* Cr */ | ||
| 64 | Txe = 0x00000001, /* Transmit Enable */ | ||
| 65 | Txd = 0x00000002, /* Transmit Disable */ | ||
| 66 | Rxe = 0x00000004, /* Receiver Enable */ | ||
| 67 | Rxd = 0x00000008, /* Receiver Disable */ | ||
| 68 | Txr = 0x00000010, /* Transmitter Reset */ | ||
| 69 | Rxr = 0x00000020, /* Receiver Reset */ | ||
| 70 | Swien = 0x00000080, /* Software Interrupt Enable */ | ||
| 71 | Rst = 0x00000100, /* Reset */ | ||
| 72 | TxpriSHFT = 9, /* Tx Priority Queue Select */ | ||
| 73 | TxpriMASK = 0x00001E00, | ||
| 74 | RxpriSHFT = 13, /* Rx Priority Queue Select */ | ||
| 75 | RxpriMASK = 0x0001E000, | ||
| 76 | }; | ||
| 77 | |||
| 78 | enum { /* Configuration and Media Status */ | ||
| 79 | Bem = 0x00000001, /* Big Endian Mode */ | ||
| 80 | Ext125 = 0x00000002, /* External 125MHz reference Select */ | ||
| 81 | Bromdis = 0x00000004, /* Disable Boot ROM interface */ | ||
| 82 | Pesel = 0x00000008, /* Parity Error Detection Action */ | ||
| 83 | Exd = 0x00000010, /* Excessive Deferral Abort */ | ||
| 84 | Pow = 0x00000020, /* Program Out of Window Timer */ | ||
| 85 | Sb = 0x00000040, /* Single Back-off */ | ||
| 86 | Reqalg = 0x00000080, /* PCI Bus Request Algorithm */ | ||
| 87 | Extstsen = 0x00000100, /* Extended Status Enable */ | ||
| 88 | Phydis = 0x00000200, /* Disable PHY */ | ||
| 89 | Phyrst = 0x00000400, /* Reset PHY */ | ||
| 90 | M64addren = 0x00000800, /* Master 64-bit Addressing Enable */ | ||
| 91 | Data64en = 0x00001000, /* 64-bit Data Enable */ | ||
| 92 | Pci64det = 0x00002000, /* PCI 64-bit Bus Detected */ | ||
| 93 | T64addren = 0x00004000, /* Target 64-bit Addressing Enable */ | ||
| 94 | Mwidis = 0x00008000, /* MWI Disable */ | ||
| 95 | Mrmdis = 0x00010000, /* MRM Disable */ | ||
| 96 | Tmrtest = 0x00020000, /* Timer Test Mode */ | ||
| 97 | Spdstsien = 0x00040000, /* PHY Spdsts Interrupt Enable */ | ||
| 98 | Lnkstsien = 0x00080000, /* PHY Lnksts Interrupt Enable */ | ||
| 99 | Dupstsien = 0x00100000, /* PHY Dupsts Interrupt Enable */ | ||
| 100 | Mode1000 = 0x00400000, /* 1000Mb/s Mode Control */ | ||
| 101 | Tbien = 0x01000000, /* Ten-Bit Interface Enable */ | ||
| 102 | Dupsts = 0x10000000, /* Full Duplex Status */ | ||
| 103 | Spdsts100 = 0x20000000, /* SPEED100 Input Pin Status */ | ||
| 104 | Spdsts1000 = 0x40000000, /* SPEED1000 Input Pin Status */ | ||
| 105 | Lnksts = 0x80000000, /* Link Status */ | ||
| 106 | }; | ||
| 107 | |||
| 108 | enum { /* MII/EEPROM Access */ | ||
| 109 | Eedi = 0x00000001, /* EEPROM Data In */ | ||
| 110 | Eedo = 0x00000002, /* EEPROM Data Out */ | ||
| 111 | Eeclk = 0x00000004, /* EEPROM Serial Clock */ | ||
| 112 | Eesel = 0x00000008, /* EEPROM Chip Select */ | ||
| 113 | Mdio = 0x00000010, /* MII Management Data */ | ||
| 114 | Mddir = 0x00000020, /* MII Management Direction */ | ||
| 115 | Mdc = 0x00000040, /* MII Management Clock */ | ||
| 116 | }; | ||
| 117 | |||
| 118 | enum { /* Interrupts */ | ||
| 119 | Rxok = 0x00000001, /* Rx OK */ | ||
| 120 | Rxdesc = 0x00000002, /* Rx Descriptor */ | ||
| 121 | Rxerr = 0x00000004, /* Rx Packet Error */ | ||
| 122 | Rxearly = 0x00000008, /* Rx Early Threshold */ | ||
| 123 | Rxidle = 0x00000010, /* Rx Idle */ | ||
| 124 | Rxorn = 0x00000020, /* Rx Overrun */ | ||
| 125 | Txok = 0x00000040, /* Tx Packet OK */ | ||
| 126 | Txdesc = 0x00000080, /* Tx Descriptor */ | ||
| 127 | Txerr = 0x00000100, /* Tx Packet Error */ | ||
| 128 | Txidle = 0x00000200, /* Tx Idle */ | ||
| 129 | Txurn = 0x00000400, /* Tx Underrun */ | ||
| 130 | Mib = 0x00000800, /* MIB Service */ | ||
| 131 | Swi = 0x00001000, /* Software Interrupt */ | ||
| 132 | Pme = 0x00002000, /* Power Management Event */ | ||
| 133 | Phy = 0x00004000, /* PHY Interrupt */ | ||
| 134 | Hibint = 0x00008000, /* High Bits Interrupt Set */ | ||
| 135 | Rxsovr = 0x00010000, /* Rx Status FIFO Overrun */ | ||
| 136 | Rtabt = 0x00020000, /* Received Target Abort */ | ||
| 137 | Rmabt = 0x00040000, /* Received Master Abort */ | ||
| 138 | Sserr = 0x00080000, /* Signalled System Error */ | ||
| 139 | Dperr = 0x00100000, /* Detected Parity Error */ | ||
| 140 | Rxrcmp = 0x00200000, /* Receive Reset Complete */ | ||
| 141 | Txrcmp = 0x00400000, /* Transmit Reset Complete */ | ||
| 142 | Rxdesc0 = 0x00800000, /* Rx Descriptor for Priority Queue 0 */ | ||
| 143 | Rxdesc1 = 0x01000000, /* Rx Descriptor for Priority Queue 1 */ | ||
| 144 | Rxdesc2 = 0x02000000, /* Rx Descriptor for Priority Queue 2 */ | ||
| 145 | Rxdesc3 = 0x04000000, /* Rx Descriptor for Priority Queue 3 */ | ||
| 146 | Txdesc0 = 0x08000000, /* Tx Descriptor for Priority Queue 0 */ | ||
| 147 | Txdesc1 = 0x10000000, /* Tx Descriptor for Priority Queue 1 */ | ||
| 148 | Txdesc2 = 0x20000000, /* Tx Descriptor for Priority Queue 2 */ | ||
| 149 | Txdesc3 = 0x40000000, /* Tx Descriptor for Priority Queue 3 */ | ||
| 150 | }; | ||
| 151 | |||
| 152 | enum { /* Interrupt Enable */ | ||
| 153 | Ien = 0x00000001, /* Interrupt Enable */ | ||
| 154 | }; | ||
| 155 | |||
| 156 | enum { /* Interrupt Holdoff */ | ||
| 157 | IhSHFT = 0, /* Interrupt Holdoff */ | ||
| 158 | IhMASK = 0x000000FF, | ||
| 159 | Ihctl = 0x00000100, /* Interrupt Holdoff Control */ | ||
| 160 | }; | ||
| 161 | |||
| 162 | enum { /* Transmit Configuration */ | ||
| 163 | TxdrthSHFT = 0, /* Tx Drain Threshold */ | ||
| 164 | TxdrthMASK = 0x000000FF, | ||
| 165 | FlthSHFT = 16, /* Tx Fill Threshold */ | ||
| 166 | FlthMASK = 0x0000FF00, | ||
| 167 | Brstdis = 0x00080000, /* 1000Mb/s Burst Disable */ | ||
| 168 | MxdmaSHFT = 20, /* Max Size per Tx DMA Burst */ | ||
| 169 | MxdmaMASK = 0x00700000, | ||
| 170 | Ecretryen = 0x00800000, /* Excessive Collision Retry Enable */ | ||
| 171 | Atp = 0x10000000, /* Automatic Transmit Padding */ | ||
| 172 | Mlb = 0x20000000, /* MAC Loopback */ | ||
| 173 | Hbi = 0x40000000, /* Heartbeat Ignore */ | ||
| 174 | Csi = 0x80000000, /* Carrier Sense Ignore */ | ||
| 175 | }; | ||
| 176 | |||
| 177 | enum { /* Receive Configuration */ | ||
| 178 | RxdrthSHFT = 1, /* Rx Drain Threshold */ | ||
| 179 | RxdrthMASK = 0x0000003E, | ||
| 180 | Airl = 0x04000000, /* Accept In-Range Length Errored */ | ||
| 181 | Alp = 0x08000000, /* Accept Long Packets */ | ||
| 182 | Rxfd = 0x10000000, /* Receive Full Duplex */ | ||
| 183 | Stripcrc = 0x20000000, /* Strip CRC */ | ||
| 184 | Arp = 0x40000000, /* Accept Runt Packets */ | ||
| 185 | Aep = 0x80000000, /* Accept Errored Packets */ | ||
| 186 | }; | ||
| 187 | |||
| 188 | enum { /* Priority Queueing Control */ | ||
| 189 | Txpqen = 0x00000001, /* Transmit Priority Queuing Enable */ | ||
| 190 | Txfairen = 0x00000002, /* Transmit Fairness Enable */ | ||
| 191 | RxpqenSHFT = 2, /* Receive Priority Queue Enable */ | ||
| 192 | RxpqenMASK = 0x0000000C, | ||
| 193 | }; | ||
| 194 | |||
| 195 | enum { /* Pause Control/Status */ | ||
| 196 | PscntSHFT = 0, /* Pause Counter Value */ | ||
| 197 | PscntMASK = 0x0000FFFF, | ||
| 198 | Pstx = 0x00020000, /* Transmit Pause Frame */ | ||
| 199 | PsffloSHFT = 18, /* Rx Data FIFO Lo Threshold */ | ||
| 200 | PsffloMASK = 0x000C0000, | ||
| 201 | PsffhiSHFT = 20, /* Rx Data FIFO Hi Threshold */ | ||
| 202 | PsffhiMASK = 0x00300000, | ||
| 203 | PsstloSHFT = 22, /* Rx Stat FIFO Hi Threshold */ | ||
| 204 | PsstloMASK = 0x00C00000, | ||
| 205 | PssthiSHFT = 24, /* Rx Stat FIFO Hi Threshold */ | ||
| 206 | PssthiMASK = 0x03000000, | ||
| 207 | Psrcvd = 0x08000000, /* Pause Frame Received */ | ||
| 208 | Psact = 0x10000000, /* Pause Active */ | ||
| 209 | Psda = 0x20000000, /* Pause on Destination Address */ | ||
| 210 | Psmcast = 0x40000000, /* Pause on Multicast */ | ||
| 211 | Psen = 0x80000000, /* Pause Enable */ | ||
| 212 | }; | ||
| 213 | |||
| 214 | enum { /* Receive Filter/Match Control */ | ||
| 215 | RfaddrSHFT = 0, /* Extended Register Address */ | ||
| 216 | RfaddrMASK = 0x000003FF, | ||
| 217 | Ulm = 0x00080000, /* U/L bit mask */ | ||
| 218 | Uhen = 0x00100000, /* Unicast Hash Enable */ | ||
| 219 | Mhen = 0x00200000, /* Multicast Hash Enable */ | ||
| 220 | Aarp = 0x00400000, /* Accept ARP Packets */ | ||
| 221 | ApatSHFT = 23, /* Accept on Pattern Match */ | ||
| 222 | ApatMASK = 0x07800000, | ||
| 223 | Apm = 0x08000000, /* Accept on Perfect Match */ | ||
| 224 | Aau = 0x10000000, /* Accept All Unicast */ | ||
| 225 | Aam = 0x20000000, /* Accept All Multicast */ | ||
| 226 | Aab = 0x40000000, /* Accept All Broadcast */ | ||
| 227 | Rfen = 0x80000000, /* Rx Filter Enable */ | ||
| 228 | }; | ||
| 229 | |||
| 230 | enum { /* Receive Filter/Match Data */ | ||
| 231 | RfdataSHFT = 0, /* Receive Filter Data */ | ||
| 232 | RfdataMASK = 0x0000FFFF, | ||
| 233 | BmaskSHFT = 16, /* Byte Mask */ | ||
| 234 | BmaskMASK = 0x00030000, | ||
| 235 | }; | ||
| 236 | |||
| 237 | enum { /* MIB Control */ | ||
| 238 | Wrn = 0x00000001, /* Warning Test Indicator */ | ||
| 239 | Frz = 0x00000002, /* Freeze All Counters */ | ||
| 240 | Aclr = 0x00000004, /* Clear All Counters */ | ||
| 241 | Mibs = 0x00000008, /* MIB Counter Strobe */ | ||
| 242 | }; | ||
| 243 | |||
| 244 | enum { /* MIB Data */ | ||
| 245 | Nmibd = 11, /* Number of MIB Data Registers */ | ||
| 246 | }; | ||
| 247 | |||
| 248 | enum { /* VLAN/IP Receive Control */ | ||
| 249 | Vtden = 0x00000001, /* VLAN Tag Detection Enable */ | ||
| 250 | Vtren = 0x00000002, /* VLAN Tag Removal Enable */ | ||
| 251 | Dvtf = 0x00000004, /* Discard VLAN Tagged Frames */ | ||
| 252 | Dutf = 0x00000008, /* Discard Untagged Frames */ | ||
| 253 | Ipen = 0x00000010, /* IP Checksum Enable */ | ||
| 254 | Ripe = 0x00000020, /* Reject IP Checksum Errors */ | ||
| 255 | Rtcpe = 0x00000040, /* Reject TCP Checksum Errors */ | ||
| 256 | Rudpe = 0x00000080, /* Reject UDP Checksum Errors */ | ||
| 257 | }; | ||
| 258 | |||
| 259 | enum { /* VLAN/IP Transmit Control */ | ||
| 260 | Vgti = 0x00000001, /* VLAN Global Tag Insertion */ | ||
| 261 | Vppti = 0x00000002, /* VLAN Per-Packet Tag Insertion */ | ||
| 262 | Gchk = 0x00000004, /* Global Checksum Generation */ | ||
| 263 | Ppchk = 0x00000008, /* Per-Packet Checksum Generation */ | ||
| 264 | }; | ||
| 265 | |||
| 266 | enum { /* VLAN Data */ | ||
| 267 | VtypeSHFT = 0, /* VLAN Type Field */ | ||
| 268 | VtypeMASK = 0x0000FFFF, | ||
| 269 | VtciSHFT = 16, /* VLAN Tag Control Information */ | ||
| 270 | VtciMASK = 0xFFFF0000, | ||
| 271 | }; | ||
| 272 | |||
| 273 | enum { /* Clockrun Control/Status */ | ||
| 274 | Clkrunen = 0x00000001, /* CLKRUN Enable */ | ||
| 275 | Pmeen = 0x00000100, /* PME Enable */ | ||
| 276 | Pmests = 0x00008000, /* PME Status */ | ||
| 277 | }; | ||
| 278 | |||
| 279 | typedef struct { | ||
| 280 | u32int link; /* Link to the next descriptor */ | ||
| 281 | u32int bufptr; /* pointer to data Buffer */ | ||
| 282 | int cmdsts; /* Command/Status */ | ||
| 283 | int extsts; /* optional Extended Status */ | ||
| 284 | |||
| 285 | Block* bp; /* Block containing bufptr */ | ||
| 286 | u32int unused; /* pad to 64-bit */ | ||
| 287 | } Desc; | ||
| 288 | |||
| 289 | enum { /* Common cmdsts bits */ | ||
| 290 | SizeMASK = 0x0000FFFF, /* Descriptor Byte Count */ | ||
| 291 | SizeSHFT = 0, | ||
| 292 | Ok = 0x08000000, /* Packet OK */ | ||
| 293 | Crc = 0x10000000, /* Suppress/Include CRC */ | ||
| 294 | Intr = 0x20000000, /* Interrupt on ownership transfer */ | ||
| 295 | More = 0x40000000, /* not last descriptor in a packet */ | ||
| 296 | Own = 0x80000000, /* Descriptor Ownership */ | ||
| 297 | }; | ||
| 298 | |||
| 299 | enum { /* Transmit cmdsts bits */ | ||
| 300 | CcntMASK = 0x000F0000, /* Collision Count */ | ||
| 301 | CcntSHFT = 16, | ||
| 302 | Ec = 0x00100000, /* Excessive Collisions */ | ||
| 303 | Owc = 0x00200000, /* Out of Window Collision */ | ||
| 304 | Ed = 0x00400000, /* Excessive Deferral */ | ||
| 305 | Td = 0x00800000, /* Transmit Deferred */ | ||
| 306 | Crs = 0x01000000, /* Carrier Sense Lost */ | ||
| 307 | Tfu = 0x02000000, /* Transmit FIFO Underrun */ | ||
| 308 | Txa = 0x04000000, /* Transmit Abort */ | ||
| 309 | }; | ||
| 310 | |||
| 311 | enum { /* Receive cmdsts bits */ | ||
| 312 | Irl = 0x00010000, /* In-Range Length Error */ | ||
| 313 | Lbp = 0x00020000, /* Loopback Packet */ | ||
| 314 | Fae = 0x00040000, /* Frame Alignment Error */ | ||
| 315 | Crce = 0x00080000, /* CRC Error */ | ||
| 316 | Ise = 0x00100000, /* Invalid Symbol Error */ | ||
| 317 | Runt = 0x00200000, /* Runt Packet Received */ | ||
| 318 | Long = 0x00400000, /* Too Long Packet Received */ | ||
| 319 | DestMASK = 0x01800000, /* Destination Class */ | ||
| 320 | DestSHFT = 23, | ||
| 321 | Rxo = 0x02000000, /* Receive Overrun */ | ||
| 322 | Rxa = 0x04000000, /* Receive Aborted */ | ||
| 323 | }; | ||
| 324 | |||
| 325 | enum { /* extsts bits */ | ||
| 326 | EvtciMASK = 0x0000FFFF, /* VLAN Tag Control Information */ | ||
| 327 | EvtciSHFT = 0, | ||
| 328 | Vpkt = 0x00010000, /* VLAN Packet */ | ||
| 329 | Ippkt = 0x00020000, /* IP Packet */ | ||
| 330 | Iperr = 0x00040000, /* IP Checksum Error */ | ||
| 331 | Tcppkt = 0x00080000, /* TCP Packet */ | ||
| 332 | Tcperr = 0x00100000, /* TCP Checksum Error */ | ||
| 333 | Udppkt = 0x00200000, /* UDP Packet */ | ||
| 334 | Udperr = 0x00400000, /* UDP Checksum Error */ | ||
| 335 | }; | ||
| 336 | |||
| 337 | enum { | ||
| 338 | Nrd = 256, | ||
| 339 | Nrb = 4*Nrd, | ||
| 340 | Rbsz = ROUNDUP(sizeof(Etherpkt)+8, 8), | ||
| 341 | Ntd = 128, | ||
| 342 | }; | ||
| 343 | |||
| 344 | typedef struct Ctlr Ctlr; | ||
| 345 | typedef struct Ctlr { | ||
| 346 | int port; | ||
| 347 | Pcidev* pcidev; | ||
| 348 | Ctlr* next; | ||
| 349 | int active; | ||
| 350 | int id; | ||
| 351 | |||
| 352 | int eepromsz; /* address size in bits */ | ||
| 353 | ushort* eeprom; | ||
| 354 | |||
| 355 | int* nic; | ||
| 356 | int cfg; | ||
| 357 | int imr; | ||
| 358 | |||
| 359 | QLock alock; /* attach */ | ||
| 360 | Lock ilock; /* init */ | ||
| 361 | void* alloc; /* base of per-Ctlr allocated data */ | ||
| 362 | |||
| 363 | Mii* mii; | ||
| 364 | |||
| 365 | Lock rdlock; /* receive */ | ||
| 366 | Desc* rd; | ||
| 367 | int nrd; | ||
| 368 | int nrb; | ||
| 369 | int rdx; | ||
| 370 | int rxcfg; | ||
| 371 | |||
| 372 | Lock tlock; /* transmit */ | ||
| 373 | Desc* td; | ||
| 374 | int ntd; | ||
| 375 | int tdh; | ||
| 376 | int tdt; | ||
| 377 | int ntq; | ||
| 378 | int txcfg; | ||
| 379 | |||
| 380 | int rxidle; | ||
| 381 | |||
| 382 | uint mibd[Nmibd]; | ||
| 383 | |||
| 384 | int ec; | ||
| 385 | int owc; | ||
| 386 | int ed; | ||
| 387 | int crs; | ||
| 388 | int tfu; | ||
| 389 | int txa; | ||
| 390 | } Ctlr; | ||
| 391 | |||
| 392 | #define csr32r(c, r) (*((c)->nic+((r)/4))) | ||
| 393 | #define csr32w(c, r, v) (*((c)->nic+((r)/4)) = (v)) | ||
| 394 | |||
| 395 | static Ctlr* dp83820ctlrhead; | ||
| 396 | static Ctlr* dp83820ctlrtail; | ||
| 397 | |||
| 398 | static Lock dp83820rblock; /* free receive Blocks */ | ||
| 399 | static Block* dp83820rbpool; | ||
| 400 | |||
| 401 | static char* dp83820mibs[Nmibd] = { | ||
| 402 | "RXErroredPkts", | ||
| 403 | "RXFCSErrors", | ||
| 404 | "RXMsdPktErrors", | ||
| 405 | "RXFAErrors", | ||
| 406 | "RXSymbolErrors", | ||
| 407 | "RXFrameToLong", | ||
| 408 | "RXIRLErrors", | ||
| 409 | "RXBadOpcodes", | ||
| 410 | "RXPauseFrames", | ||
| 411 | "TXPauseFrames", | ||
| 412 | "TXSQEErrors", | ||
| 413 | }; | ||
| 414 | |||
| 415 | static int | ||
| 416 | mdior(Ctlr* ctlr, int n) | ||
| 417 | { | ||
| 418 | int data, i, mear, r; | ||
| 419 | |||
| 420 | mear = csr32r(ctlr, Mear); | ||
| 421 | r = ~(Mdc|Mddir) & mear; | ||
| 422 | data = 0; | ||
| 423 | for(i = n-1; i >= 0; i--){ | ||
| 424 | if(csr32r(ctlr, Mear) & Mdio) | ||
| 425 | data |= (1<<i); | ||
| 426 | csr32w(ctlr, Mear, Mdc|r); | ||
| 427 | csr32w(ctlr, Mear, r); | ||
| 428 | } | ||
| 429 | csr32w(ctlr, Mear, mear); | ||
| 430 | |||
| 431 | return data; | ||
| 432 | } | ||
| 433 | |||
| 434 | static void | ||
| 435 | mdiow(Ctlr* ctlr, int bits, int n) | ||
| 436 | { | ||
| 437 | int i, mear, r; | ||
| 438 | |||
| 439 | mear = csr32r(ctlr, Mear); | ||
| 440 | r = Mddir|(~Mdc & mear); | ||
| 441 | for(i = n-1; i >= 0; i--){ | ||
| 442 | if(bits & (1<<i)) | ||
| 443 | r |= Mdio; | ||
| 444 | else | ||
| 445 | r &= ~Mdio; | ||
| 446 | csr32w(ctlr, Mear, r); | ||
| 447 | csr32w(ctlr, Mear, Mdc|r); | ||
| 448 | } | ||
| 449 | csr32w(ctlr, Mear, mear); | ||
| 450 | } | ||
| 451 | |||
| 452 | static int | ||
| 453 | dp83820miimir(Mii* mii, int pa, int ra) | ||
| 454 | { | ||
| 455 | int data; | ||
| 456 | Ctlr *ctlr; | ||
| 457 | |||
| 458 | ctlr = mii->ctlr; | ||
| 459 | |||
| 460 | /* | ||
| 461 | * MII Management Interface Read. | ||
| 462 | * | ||
| 463 | * Preamble; | ||
| 464 | * ST+OP+PA+RA; | ||
| 465 | * LT + 16 data bits. | ||
| 466 | */ | ||
| 467 | mdiow(ctlr, 0xFFFFFFFF, 32); | ||
| 468 | mdiow(ctlr, 0x1800|(pa<<5)|ra, 14); | ||
| 469 | data = mdior(ctlr, 18); | ||
| 470 | |||
| 471 | if(data & 0x10000) | ||
| 472 | return -1; | ||
| 473 | |||
| 474 | return data & 0xFFFF; | ||
| 475 | } | ||
| 476 | |||
| 477 | static int | ||
| 478 | dp83820miimiw(Mii* mii, int pa, int ra, int data) | ||
| 479 | { | ||
| 480 | Ctlr *ctlr; | ||
| 481 | |||
| 482 | ctlr = mii->ctlr; | ||
| 483 | |||
| 484 | /* | ||
| 485 | * MII Management Interface Write. | ||
| 486 | * | ||
| 487 | * Preamble; | ||
| 488 | * ST+OP+PA+RA+LT + 16 data bits; | ||
| 489 | * Z. | ||
| 490 | */ | ||
| 491 | mdiow(ctlr, 0xFFFFFFFF, 32); | ||
| 492 | data &= 0xFFFF; | ||
| 493 | data |= (0x05<<(5+5+2+16))|(pa<<(5+2+16))|(ra<<(2+16))|(0x02<<16); | ||
| 494 | mdiow(ctlr, data, 32); | ||
| 495 | |||
| 496 | return 0; | ||
| 497 | } | ||
| 498 | |||
| 499 | static Block * | ||
| 500 | dp83820rballoc(Desc* desc) | ||
| 501 | { | ||
| 502 | Block *bp; | ||
| 503 | |||
| 504 | if(desc->bp == nil){ | ||
| 505 | ilock(&dp83820rblock); | ||
| 506 | if((bp = dp83820rbpool) == nil){ | ||
| 507 | iunlock(&dp83820rblock); | ||
| 508 | desc->bp = nil; | ||
| 509 | desc->cmdsts = Own; | ||
| 510 | return nil; | ||
| 511 | } | ||
| 512 | dp83820rbpool = bp->next; | ||
| 513 | bp->next = nil; | ||
| 514 | iunlock(&dp83820rblock); | ||
| 515 | |||
| 516 | desc->bufptr = PCIWADDR(bp->rp); | ||
| 517 | desc->bp = bp; | ||
| 518 | } | ||
| 519 | else{ | ||
| 520 | bp = desc->bp; | ||
| 521 | bp->rp = bp->lim - Rbsz; | ||
| 522 | bp->wp = bp->rp; | ||
| 523 | } | ||
| 524 | |||
| 525 | coherence(); | ||
| 526 | desc->cmdsts = Intr|Rbsz; | ||
| 527 | |||
| 528 | return bp; | ||
| 529 | } | ||
| 530 | |||
| 531 | static void | ||
| 532 | dp83820rbfree(Block *bp) | ||
| 533 | { | ||
| 534 | bp->rp = bp->lim - Rbsz; | ||
| 535 | bp->wp = bp->rp; | ||
| 536 | |||
| 537 | ilock(&dp83820rblock); | ||
| 538 | bp->next = dp83820rbpool; | ||
| 539 | dp83820rbpool = bp; | ||
| 540 | iunlock(&dp83820rblock); | ||
| 541 | } | ||
| 542 | |||
| 543 | static void | ||
| 544 | dp83820halt(Ctlr* ctlr) | ||
| 545 | { | ||
| 546 | int i, timeo; | ||
| 547 | |||
| 548 | ilock(&ctlr->ilock); | ||
| 549 | csr32w(ctlr, Imr, 0); | ||
| 550 | csr32w(ctlr, Ier, 0); | ||
| 551 | csr32w(ctlr, Cr, Rxd|Txd); | ||
| 552 | for(timeo = 0; timeo < 1000; timeo++){ | ||
| 553 | if(!(csr32r(ctlr, Cr) & (Rxe|Txe))) | ||
| 554 | break; | ||
| 555 | microdelay(1); | ||
| 556 | } | ||
| 557 | csr32w(ctlr, Mibc, Frz); | ||
| 558 | iunlock(&ctlr->ilock); | ||
| 559 | |||
| 560 | if(ctlr->rd != nil){ | ||
| 561 | for(i = 0; i < ctlr->nrd; i++){ | ||
| 562 | if(ctlr->rd[i].bp == nil) | ||
| 563 | continue; | ||
| 564 | freeb(ctlr->rd[i].bp); | ||
| 565 | ctlr->rd[i].bp = nil; | ||
| 566 | } | ||
| 567 | } | ||
| 568 | if(ctlr->td != nil){ | ||
| 569 | for(i = 0; i < ctlr->ntd; i++){ | ||
| 570 | if(ctlr->td[i].bp == nil) | ||
| 571 | continue; | ||
| 572 | freeb(ctlr->td[i].bp); | ||
| 573 | ctlr->td[i].bp = nil; | ||
| 574 | } | ||
| 575 | } | ||
| 576 | } | ||
| 577 | |||
| 578 | static void | ||
| 579 | dp83820cfg(Ctlr* ctlr) | ||
| 580 | { | ||
| 581 | int cfg; | ||
| 582 | |||
| 583 | /* | ||
| 584 | * Don't know how to deal with a TBI yet. | ||
| 585 | */ | ||
| 586 | if(ctlr->mii == nil) | ||
| 587 | return; | ||
| 588 | |||
| 589 | /* | ||
| 590 | * The polarity of these bits is at the mercy | ||
| 591 | * of the board designer. | ||
| 592 | * The correct answer for all speed and duplex questions | ||
| 593 | * should be to query the phy. | ||
| 594 | */ | ||
| 595 | cfg = csr32r(ctlr, Cfg); | ||
| 596 | if(!(cfg & Dupsts)){ | ||
| 597 | ctlr->rxcfg |= Rxfd; | ||
| 598 | ctlr->txcfg |= Csi|Hbi; | ||
| 599 | iprint("83820: full duplex, "); | ||
| 600 | } | ||
| 601 | else{ | ||
| 602 | ctlr->rxcfg &= ~Rxfd; | ||
| 603 | ctlr->txcfg &= ~(Csi|Hbi); | ||
| 604 | iprint("83820: half duplex, "); | ||
| 605 | } | ||
| 606 | csr32w(ctlr, Rxcfg, ctlr->rxcfg); | ||
| 607 | csr32w(ctlr, Txcfg, ctlr->txcfg); | ||
| 608 | |||
| 609 | switch(cfg & (Spdsts1000|Spdsts100)){ | ||
| 610 | case Spdsts1000: /* 100Mbps */ | ||
| 611 | default: /* 10Mbps */ | ||
| 612 | ctlr->cfg &= ~Mode1000; | ||
| 613 | if((cfg & (Spdsts1000|Spdsts100)) == Spdsts1000) | ||
| 614 | iprint("100Mb/s\n"); | ||
| 615 | else | ||
| 616 | iprint("10Mb/s\n"); | ||
| 617 | break; | ||
| 618 | case Spdsts100: /* 1Gbps */ | ||
| 619 | ctlr->cfg |= Mode1000; | ||
| 620 | iprint("1Gb/s\n"); | ||
| 621 | break; | ||
| 622 | } | ||
| 623 | csr32w(ctlr, Cfg, ctlr->cfg); | ||
| 624 | } | ||
| 625 | |||
| 626 | static void | ||
| 627 | dp83820init(Ether* edev) | ||
| 628 | { | ||
| 629 | int i; | ||
| 630 | Ctlr *ctlr; | ||
| 631 | Desc *desc; | ||
| 632 | uchar *alloc; | ||
| 633 | |||
| 634 | ctlr = edev->ctlr; | ||
| 635 | |||
| 636 | dp83820halt(ctlr); | ||
| 637 | |||
| 638 | /* | ||
| 639 | * Receiver | ||
| 640 | */ | ||
| 641 | alloc = (uchar*)ROUNDUP((ulong)ctlr->alloc, 8); | ||
| 642 | ctlr->rd = (Desc*)alloc; | ||
| 643 | alloc += ctlr->nrd*sizeof(Desc); | ||
| 644 | memset(ctlr->rd, 0, ctlr->nrd*sizeof(Desc)); | ||
| 645 | ctlr->rdx = 0; | ||
| 646 | for(i = 0; i < ctlr->nrd; i++){ | ||
| 647 | desc = &ctlr->rd[i]; | ||
| 648 | desc->link = PCIWADDR(&ctlr->rd[NEXT(i, ctlr->nrd)]); | ||
| 649 | if(dp83820rballoc(desc) == nil) | ||
| 650 | continue; | ||
| 651 | } | ||
| 652 | csr32w(ctlr, Rxdphi, 0); | ||
| 653 | csr32w(ctlr, Rxdp, PCIWADDR(ctlr->rd)); | ||
| 654 | |||
| 655 | for(i = 0; i < Eaddrlen; i += 2){ | ||
| 656 | csr32w(ctlr, Rfcr, i); | ||
| 657 | csr32w(ctlr, Rfdr, (edev->ea[i+1]<<8)|edev->ea[i]); | ||
| 658 | } | ||
| 659 | csr32w(ctlr, Rfcr, Rfen|Aab|Aam|Apm); | ||
| 660 | |||
| 661 | ctlr->rxcfg = Stripcrc|(((2*(ETHERMINTU+4))/8)<<RxdrthSHFT); | ||
| 662 | ctlr->imr |= Rxorn|Rxidle|Rxearly|Rxdesc|Rxok; | ||
| 663 | |||
| 664 | /* | ||
| 665 | * Transmitter. | ||
| 666 | */ | ||
| 667 | ctlr->td = (Desc*)alloc; | ||
| 668 | memset(ctlr->td, 0, ctlr->ntd*sizeof(Desc)); | ||
| 669 | ctlr->tdh = ctlr->tdt = ctlr->ntq = 0; | ||
| 670 | for(i = 0; i < ctlr->ntd; i++){ | ||
| 671 | desc = &ctlr->td[i]; | ||
| 672 | desc->link = PCIWADDR(&ctlr->td[NEXT(i, ctlr->ntd)]); | ||
| 673 | } | ||
| 674 | csr32w(ctlr, Txdphi, 0); | ||
| 675 | csr32w(ctlr, Txdp, PCIWADDR(ctlr->td)); | ||
| 676 | |||
| 677 | ctlr->txcfg = Atp|(((2*(ETHERMINTU+4))/32)<<FlthSHFT)|((4096/32)<<TxdrthSHFT); | ||
| 678 | ctlr->imr |= Txurn|Txidle|Txdesc|Txok; | ||
| 679 | |||
| 680 | ilock(&ctlr->ilock); | ||
| 681 | |||
| 682 | dp83820cfg(ctlr); | ||
| 683 | |||
| 684 | csr32w(ctlr, Mibc, Aclr); | ||
| 685 | ctlr->imr |= Mib; | ||
| 686 | |||
| 687 | csr32w(ctlr, Imr, ctlr->imr); | ||
| 688 | |||
| 689 | /* try coalescing adjacent interrupts; use hold-off interval of 100µs */ | ||
| 690 | csr32w(ctlr, Ihr, Ihctl|(1<<IhSHFT)); | ||
| 691 | |||
| 692 | csr32w(ctlr, Ier, Ien); | ||
| 693 | csr32w(ctlr, Cr, Rxe|Txe); | ||
| 694 | |||
| 695 | iunlock(&ctlr->ilock); | ||
| 696 | } | ||
| 697 | |||
| 698 | static void | ||
| 699 | dp83820attach(Ether* edev) | ||
| 700 | { | ||
| 701 | Block *bp; | ||
| 702 | Ctlr *ctlr; | ||
| 703 | |||
| 704 | ctlr = edev->ctlr; | ||
| 705 | qlock(&ctlr->alock); | ||
| 706 | if(ctlr->alloc != nil){ | ||
| 707 | qunlock(&ctlr->alock); | ||
| 708 | return; | ||
| 709 | } | ||
| 710 | |||
| 711 | if(waserror()){ | ||
| 712 | if(ctlr->mii != nil){ | ||
| 713 | free(ctlr->mii); | ||
| 714 | ctlr->mii = nil; | ||
| 715 | } | ||
| 716 | if(ctlr->alloc != nil){ | ||
| 717 | free(ctlr->alloc); | ||
| 718 | ctlr->alloc = nil; | ||
| 719 | } | ||
| 720 | qunlock(&ctlr->alock); | ||
| 721 | nexterror(); | ||
| 722 | } | ||
| 723 | |||
| 724 | if(!(ctlr->cfg & Tbien)){ | ||
| 725 | if((ctlr->mii = malloc(sizeof(Mii))) == nil) | ||
| 726 | error(Enomem); | ||
| 727 | ctlr->mii->ctlr = ctlr; | ||
| 728 | ctlr->mii->mir = dp83820miimir; | ||
| 729 | ctlr->mii->miw = dp83820miimiw; | ||
| 730 | if(mii(ctlr->mii, ~0) == 0) | ||
| 731 | error("no PHY"); | ||
| 732 | ctlr->cfg |= Dupstsien|Lnkstsien|Spdstsien; | ||
| 733 | ctlr->imr |= Phy; | ||
| 734 | } | ||
| 735 | |||
| 736 | ctlr->nrd = Nrd; | ||
| 737 | ctlr->nrb = Nrb; | ||
| 738 | ctlr->ntd = Ntd; | ||
| 739 | ctlr->alloc = mallocz((ctlr->nrd+ctlr->ntd)*sizeof(Desc) + 7, 0); | ||
| 740 | if(ctlr->alloc == nil) | ||
| 741 | error(Enomem); | ||
| 742 | |||
| 743 | for(ctlr->nrb = 0; ctlr->nrb < Nrb; ctlr->nrb++){ | ||
| 744 | if((bp = allocb(Rbsz)) == nil) | ||
| 745 | break; | ||
| 746 | bp->free = dp83820rbfree; | ||
| 747 | dp83820rbfree(bp); | ||
| 748 | } | ||
| 749 | |||
| 750 | dp83820init(edev); | ||
| 751 | |||
| 752 | qunlock(&ctlr->alock); | ||
| 753 | poperror(); | ||
| 754 | } | ||
| 755 | |||
| 756 | static void | ||
| 757 | dp83820transmit(Ether* edev) | ||
| 758 | { | ||
| 759 | Block *bp; | ||
| 760 | Ctlr *ctlr; | ||
| 761 | Desc *desc; | ||
| 762 | int cmdsts, r, x; | ||
| 763 | |||
| 764 | ctlr = edev->ctlr; | ||
| 765 | |||
| 766 | ilock(&ctlr->tlock); | ||
| 767 | |||
| 768 | bp = nil; | ||
| 769 | for(x = ctlr->tdh; ctlr->ntq; x = NEXT(x, ctlr->ntd)){ | ||
| 770 | desc = &ctlr->td[x]; | ||
| 771 | if((cmdsts = desc->cmdsts) & Own) | ||
| 772 | break; | ||
| 773 | if(!(cmdsts & Ok)){ | ||
| 774 | if(cmdsts & Ec) | ||
| 775 | ctlr->ec++; | ||
| 776 | if(cmdsts & Owc) | ||
| 777 | ctlr->owc++; | ||
| 778 | if(cmdsts & Ed) | ||
| 779 | ctlr->ed++; | ||
| 780 | if(cmdsts & Crs) | ||
| 781 | ctlr->crs++; | ||
| 782 | if(cmdsts & Tfu) | ||
| 783 | ctlr->tfu++; | ||
| 784 | if(cmdsts & Txa) | ||
| 785 | ctlr->txa++; | ||
| 786 | edev->oerrs++; | ||
| 787 | } | ||
| 788 | desc->bp->next = bp; | ||
| 789 | bp = desc->bp; | ||
| 790 | desc->bp = nil; | ||
| 791 | |||
| 792 | ctlr->ntq--; | ||
| 793 | } | ||
| 794 | ctlr->tdh = x; | ||
| 795 | if(bp != nil) | ||
| 796 | freeblist(bp); | ||
| 797 | |||
| 798 | x = ctlr->tdt; | ||
| 799 | while(ctlr->ntq < (ctlr->ntd-1)){ | ||
| 800 | if((bp = qget(edev->oq)) == nil) | ||
| 801 | break; | ||
| 802 | |||
| 803 | desc = &ctlr->td[x]; | ||
| 804 | desc->bufptr = PCIWADDR(bp->rp); | ||
| 805 | desc->bp = bp; | ||
| 806 | ctlr->ntq++; | ||
| 807 | coherence(); | ||
| 808 | desc->cmdsts = Own|Intr|BLEN(bp); | ||
| 809 | |||
| 810 | x = NEXT(x, ctlr->ntd); | ||
| 811 | } | ||
| 812 | if(x != ctlr->tdt){ | ||
| 813 | ctlr->tdt = x; | ||
| 814 | r = csr32r(ctlr, Cr); | ||
| 815 | csr32w(ctlr, Cr, Txe|r); | ||
| 816 | } | ||
| 817 | |||
| 818 | iunlock(&ctlr->tlock); | ||
| 819 | } | ||
| 820 | |||
| 821 | static void | ||
| 822 | dp83820interrupt(Ureg*, void* arg) | ||
| 823 | { | ||
| 824 | Block *bp; | ||
| 825 | Ctlr *ctlr; | ||
| 826 | Desc *desc; | ||
| 827 | Ether *edev; | ||
| 828 | int cmdsts, i, isr, r, x; | ||
| 829 | |||
| 830 | edev = arg; | ||
| 831 | ctlr = edev->ctlr; | ||
| 832 | |||
| 833 | for(isr = csr32r(ctlr, Isr); isr & ctlr->imr; isr = csr32r(ctlr, Isr)){ | ||
| 834 | if(isr & (Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok)){ | ||
| 835 | x = ctlr->rdx; | ||
| 836 | desc = &ctlr->rd[x]; | ||
| 837 | while((cmdsts = desc->cmdsts) & Own){ | ||
| 838 | if((cmdsts & Ok) && desc->bp != nil){ | ||
| 839 | bp = desc->bp; | ||
| 840 | desc->bp = nil; | ||
| 841 | bp->wp += cmdsts & SizeMASK; | ||
| 842 | etheriq(edev, bp, 1); | ||
| 843 | } | ||
| 844 | //else if(!(cmdsts & Ok)){ | ||
| 845 | // iprint("dp83820: rx %8.8uX:", cmdsts); | ||
| 846 | // bp = desc->bp; | ||
| 847 | // for(i = 0; i < 20; i++) | ||
| 848 | // iprint(" %2.2uX", bp->rp[i]); | ||
| 849 | // iprint("\n"); | ||
| 850 | //} | ||
| 851 | dp83820rballoc(desc); | ||
| 852 | |||
| 853 | x = NEXT(x, ctlr->nrd); | ||
| 854 | desc = &ctlr->rd[x]; | ||
| 855 | } | ||
| 856 | ctlr->rdx = x; | ||
| 857 | |||
| 858 | if(isr & Rxidle){ | ||
| 859 | r = csr32r(ctlr, Cr); | ||
| 860 | csr32w(ctlr, Cr, Rxe|r); | ||
| 861 | ctlr->rxidle++; | ||
| 862 | } | ||
| 863 | |||
| 864 | isr &= ~(Rxorn|Rxidle|Rxearly|Rxerr|Rxdesc|Rxok); | ||
| 865 | } | ||
| 866 | |||
| 867 | if(isr & Txurn){ | ||
| 868 | x = (ctlr->txcfg & TxdrthMASK)>>TxdrthSHFT; | ||
| 869 | r = (ctlr->txcfg & FlthMASK)>>FlthSHFT; | ||
| 870 | if(x < ((TxdrthMASK)>>TxdrthSHFT) | ||
| 871 | && x < (2048/32 - r)){ | ||
| 872 | ctlr->txcfg &= ~TxdrthMASK; | ||
| 873 | x++; | ||
| 874 | ctlr->txcfg |= x<<TxdrthSHFT; | ||
| 875 | csr32w(ctlr, Txcfg, ctlr->txcfg); | ||
| 876 | } | ||
| 877 | } | ||
| 878 | |||
| 879 | if(isr & (Txurn|Txidle|Txdesc|Txok)){ | ||
| 880 | dp83820transmit(edev); | ||
| 881 | isr &= ~(Txurn|Txidle|Txdesc|Txok); | ||
| 882 | } | ||
| 883 | |||
| 884 | if(isr & Mib){ | ||
| 885 | for(i = 0; i < Nmibd; i++){ | ||
| 886 | r = csr32r(ctlr, Mibd+(i*sizeof(int))); | ||
| 887 | ctlr->mibd[i] += r & 0xFFFF; | ||
| 888 | } | ||
| 889 | isr &= ~Mib; | ||
| 890 | } | ||
| 891 | |||
| 892 | if((isr & Phy) && ctlr->mii != nil){ | ||
| 893 | ctlr->mii->mir(ctlr->mii, 1, Bmsr); | ||
| 894 | print("phy: cfg %8.8uX bmsr %4.4uX\n", | ||
| 895 | csr32r(ctlr, Cfg), | ||
| 896 | ctlr->mii->mir(ctlr->mii, 1, Bmsr)); | ||
| 897 | dp83820cfg(ctlr); | ||
| 898 | isr &= ~Phy; | ||
| 899 | } | ||
| 900 | if(isr) | ||
| 901 | iprint("dp83820: isr %8.8uX\n", isr); | ||
| 902 | } | ||
| 903 | } | ||
| 904 | |||
| 905 | static long | ||
| 906 | dp83820ifstat(Ether* edev, void* a, long n, ulong offset) | ||
| 907 | { | ||
| 908 | char *p; | ||
| 909 | Ctlr *ctlr; | ||
| 910 | int i, l, r; | ||
| 911 | |||
| 912 | ctlr = edev->ctlr; | ||
| 913 | |||
| 914 | edev->crcs = ctlr->mibd[Mibd+(1*sizeof(int))]; | ||
| 915 | edev->frames = ctlr->mibd[Mibd+(3*sizeof(int))]; | ||
| 916 | edev->buffs = ctlr->mibd[Mibd+(5*sizeof(int))]; | ||
| 917 | edev->overflows = ctlr->mibd[Mibd+(2*sizeof(int))]; | ||
| 918 | |||
| 919 | if(n == 0) | ||
| 920 | return 0; | ||
| 921 | |||
| 922 | p = malloc(READSTR); | ||
| 923 | l = 0; | ||
| 924 | for(i = 0; i < Nmibd; i++){ | ||
| 925 | r = csr32r(ctlr, Mibd+(i*sizeof(int))); | ||
| 926 | ctlr->mibd[i] += r & 0xFFFF; | ||
| 927 | if(ctlr->mibd[i] != 0 && dp83820mibs[i] != nil) | ||
| 928 | l += snprint(p+l, READSTR-l, "%s: %ud %ud\n", | ||
| 929 | dp83820mibs[i], ctlr->mibd[i], r); | ||
| 930 | } | ||
| 931 | l += snprint(p+l, READSTR-l, "rxidle %d\n", ctlr->rxidle); | ||
| 932 | l += snprint(p+l, READSTR-l, "ec %d\n", ctlr->ec); | ||
| 933 | l += snprint(p+l, READSTR-l, "owc %d\n", ctlr->owc); | ||
| 934 | l += snprint(p+l, READSTR-l, "ed %d\n", ctlr->ed); | ||
| 935 | l += snprint(p+l, READSTR-l, "crs %d\n", ctlr->crs); | ||
| 936 | l += snprint(p+l, READSTR-l, "tfu %d\n", ctlr->tfu); | ||
| 937 | l += snprint(p+l, READSTR-l, "txa %d\n", ctlr->txa); | ||
| 938 | |||
| 939 | l += snprint(p+l, READSTR, "rom:"); | ||
| 940 | for(i = 0; i < 0x10; i++){ | ||
| 941 | if(i && ((i & 0x07) == 0)) | ||
| 942 | l += snprint(p+l, READSTR-l, "\n "); | ||
| 943 | l += snprint(p+l, READSTR-l, " %4.4uX", ctlr->eeprom[i]); | ||
| 944 | } | ||
| 945 | l += snprint(p+l, READSTR-l, "\n"); | ||
| 946 | |||
| 947 | if(ctlr->mii != nil && ctlr->mii->curphy != nil){ | ||
| 948 | l += snprint(p+l, READSTR, "phy:"); | ||
| 949 | for(i = 0; i < NMiiPhyr; i++){ | ||
| 950 | if(i && ((i & 0x07) == 0)) | ||
| 951 | l += snprint(p+l, READSTR-l, "\n "); | ||
| 952 | r = miimir(ctlr->mii, i); | ||
| 953 | l += snprint(p+l, READSTR-l, " %4.4uX", r); | ||
| 954 | } | ||
| 955 | snprint(p+l, READSTR-l, "\n"); | ||
| 956 | } | ||
| 957 | |||
| 958 | n = readstr(offset, a, n, p); | ||
| 959 | free(p); | ||
| 960 | |||
| 961 | return n; | ||
| 962 | } | ||
| 963 | |||
| 964 | static void | ||
| 965 | dp83820promiscuous(void* arg, int on) | ||
| 966 | { | ||
| 967 | USED(arg, on); | ||
| 968 | } | ||
| 969 | |||
| 970 | /* multicast already on, don't need to do anything */ | ||
| 971 | static void | ||
| 972 | dp83820multicast(void*, uchar*, int) | ||
| 973 | { | ||
| 974 | } | ||
| 975 | |||
| 976 | static int | ||
| 977 | dp83820detach(Ctlr* ctlr) | ||
| 978 | { | ||
| 979 | /* | ||
| 980 | * Soft reset the controller. | ||
| 981 | */ | ||
| 982 | csr32w(ctlr, Cr, Rst); | ||
| 983 | delay(1); | ||
| 984 | while(csr32r(ctlr, Cr) & Rst) | ||
| 985 | delay(1); | ||
| 986 | return 0; | ||
| 987 | } | ||
| 988 | |||
| 989 | static void | ||
| 990 | dp83820shutdown(Ether* ether) | ||
| 991 | { | ||
| 992 | print("dp83820shutdown\n"); | ||
| 993 | dp83820detach(ether->ctlr); | ||
| 994 | } | ||
| 995 | |||
| 996 | static int | ||
| 997 | atc93c46r(Ctlr* ctlr, int address) | ||
| 998 | { | ||
| 999 | int data, i, mear, r, size; | ||
| 1000 | |||
| 1001 | /* | ||
| 1002 | * Analog Technology, Inc. ATC93C46 | ||
| 1003 | * or equivalent serial EEPROM. | ||
| 1004 | */ | ||
| 1005 | mear = csr32r(ctlr, Mear); | ||
| 1006 | mear &= ~(Eesel|Eeclk|Eedo|Eedi); | ||
| 1007 | r = Eesel|mear; | ||
| 1008 | |||
| 1009 | reread: | ||
| 1010 | csr32w(ctlr, Mear, r); | ||
| 1011 | data = 0x06; | ||
| 1012 | for(i = 3-1; i >= 0; i--){ | ||
| 1013 | if(data & (1<<i)) | ||
| 1014 | r |= Eedi; | ||
| 1015 | else | ||
| 1016 | r &= ~Eedi; | ||
| 1017 | csr32w(ctlr, Mear, r); | ||
| 1018 | csr32w(ctlr, Mear, Eeclk|r); | ||
| 1019 | microdelay(1); | ||
| 1020 | csr32w(ctlr, Mear, r); | ||
| 1021 | microdelay(1); | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | /* | ||
| 1025 | * First time through must work out the EEPROM size. | ||
| 1026 | */ | ||
| 1027 | if((size = ctlr->eepromsz) == 0) | ||
| 1028 | size = 8; | ||
| 1029 | |||
| 1030 | for(size = size-1; size >= 0; size--){ | ||
| 1031 | if(address & (1<<size)) | ||
| 1032 | r |= Eedi; | ||
| 1033 | else | ||
| 1034 | r &= ~Eedi; | ||
| 1035 | csr32w(ctlr, Mear, r); | ||
| 1036 | microdelay(1); | ||
| 1037 | csr32w(ctlr, Mear, Eeclk|r); | ||
| 1038 | microdelay(1); | ||
| 1039 | csr32w(ctlr, Mear, r); | ||
| 1040 | microdelay(1); | ||
| 1041 | if(!(csr32r(ctlr, Mear) & Eedo)) | ||
| 1042 | break; | ||
| 1043 | } | ||
| 1044 | r &= ~Eedi; | ||
| 1045 | |||
| 1046 | data = 0; | ||
| 1047 | for(i = 16-1; i >= 0; i--){ | ||
| 1048 | csr32w(ctlr, Mear, Eeclk|r); | ||
| 1049 | microdelay(1); | ||
| 1050 | if(csr32r(ctlr, Mear) & Eedo) | ||
| 1051 | data |= (1<<i); | ||
| 1052 | csr32w(ctlr, Mear, r); | ||
| 1053 | microdelay(1); | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | csr32w(ctlr, Mear, mear); | ||
| 1057 | |||
| 1058 | if(ctlr->eepromsz == 0){ | ||
| 1059 | ctlr->eepromsz = 8-size; | ||
| 1060 | ctlr->eeprom = malloc((1<<ctlr->eepromsz)*sizeof(ushort)); | ||
| 1061 | goto reread; | ||
| 1062 | } | ||
| 1063 | |||
| 1064 | return data; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | static int | ||
| 1068 | dp83820reset(Ctlr* ctlr) | ||
| 1069 | { | ||
| 1070 | int i, r; | ||
| 1071 | unsigned char sum; | ||
| 1072 | |||
| 1073 | /* | ||
| 1074 | * Soft reset the controller; | ||
| 1075 | * read the EEPROM to get the initial settings | ||
| 1076 | * of the Cfg and Gpior bits which should be cleared by | ||
| 1077 | * the reset. | ||
| 1078 | */ | ||
| 1079 | dp83820detach(ctlr); | ||
| 1080 | |||
| 1081 | atc93c46r(ctlr, 0); | ||
| 1082 | if(ctlr->eeprom == nil) { | ||
| 1083 | print("dp83820reset: no eeprom\n"); | ||
| 1084 | return -1; | ||
| 1085 | } | ||
| 1086 | sum = 0; | ||
| 1087 | for(i = 0; i < 0x0E; i++){ | ||
| 1088 | r = atc93c46r(ctlr, i); | ||
| 1089 | ctlr->eeprom[i] = r; | ||
| 1090 | sum += r; | ||
| 1091 | sum += r>>8; | ||
| 1092 | } | ||
| 1093 | |||
| 1094 | if(sum != 0){ | ||
| 1095 | print("dp83820reset: bad EEPROM checksum\n"); | ||
| 1096 | return -1; | ||
| 1097 | } | ||
| 1098 | |||
| 1099 | #ifdef notdef | ||
| 1100 | csr32w(ctlr, Gpior, ctlr->eeprom[4]); | ||
| 1101 | |||
| 1102 | cfg = Extstsen|Exd; | ||
| 1103 | r = csr32r(ctlr, Cfg); | ||
| 1104 | if(ctlr->eeprom[5] & 0x0001) | ||
| 1105 | cfg |= Ext125; | ||
| 1106 | if(ctlr->eeprom[5] & 0x0002) | ||
| 1107 | cfg |= M64addren; | ||
| 1108 | if((ctlr->eeprom[5] & 0x0004) && (r & Pci64det)) | ||
| 1109 | cfg |= Data64en; | ||
| 1110 | if(ctlr->eeprom[5] & 0x0008) | ||
| 1111 | cfg |= T64addren; | ||
| 1112 | if(!(pcicfgr16(ctlr->pcidev, PciPCR) & 0x10)) | ||
| 1113 | cfg |= Mwidis; | ||
| 1114 | if(ctlr->eeprom[5] & 0x0020) | ||
| 1115 | cfg |= Mrmdis; | ||
| 1116 | if(ctlr->eeprom[5] & 0x0080) | ||
| 1117 | cfg |= Mode1000; | ||
| 1118 | if(ctlr->eeprom[5] & 0x0200) | ||
| 1119 | cfg |= Tbien|Mode1000; | ||
| 1120 | /* | ||
| 1121 | * What about RO bits we might have destroyed with Rst? | ||
| 1122 | * What about Exd, Tmrtest, Extstsen, Pintctl? | ||
| 1123 | * Why does it think it has detected a 64-bit bus when | ||
| 1124 | * it hasn't? | ||
| 1125 | */ | ||
| 1126 | #else | ||
| 1127 | //r = csr32r(ctlr, Cfg); | ||
| 1128 | //r &= ~(Mode1000|T64addren|Data64en|M64addren); | ||
| 1129 | //csr32w(ctlr, Cfg, r); | ||
| 1130 | //csr32w(ctlr, Cfg, 0x2000); | ||
| 1131 | #endif /* notdef */ | ||
| 1132 | ctlr->cfg = csr32r(ctlr, Cfg); | ||
| 1133 | print("cfg %8.8uX pcicfg %8.8uX\n", ctlr->cfg, pcicfgr32(ctlr->pcidev, PciPCR)); | ||
| 1134 | ctlr->cfg &= ~(T64addren|Data64en|M64addren); | ||
| 1135 | csr32w(ctlr, Cfg, ctlr->cfg); | ||
| 1136 | csr32w(ctlr, Mibc, Aclr|Frz); | ||
| 1137 | |||
| 1138 | return 0; | ||
| 1139 | } | ||
| 1140 | |||
| 1141 | static void | ||
| 1142 | dp83820pci(void) | ||
| 1143 | { | ||
| 1144 | void *mem; | ||
| 1145 | Pcidev *p; | ||
| 1146 | Ctlr *ctlr; | ||
| 1147 | |||
| 1148 | p = nil; | ||
| 1149 | while(p = pcimatch(p, 0, 0)){ | ||
| 1150 | if(p->ccrb != Pcibcnet || p->ccru != Pciscether) | ||
| 1151 | continue; | ||
| 1152 | |||
| 1153 | switch((p->did<<16)|p->vid){ | ||
| 1154 | default: | ||
| 1155 | continue; | ||
| 1156 | case (0x0022<<16)|0x100B: /* DP83820 (Gig-NIC) */ | ||
| 1157 | break; | ||
| 1158 | } | ||
| 1159 | |||
| 1160 | mem = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size); | ||
| 1161 | if(mem == 0){ | ||
| 1162 | print("DP83820: can't map %8.8luX\n", p->mem[1].bar); | ||
| 1163 | continue; | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | ctlr = malloc(sizeof(Ctlr)); | ||
| 1167 | ctlr->port = p->mem[1].bar & ~0x0F; | ||
| 1168 | ctlr->pcidev = p; | ||
| 1169 | ctlr->id = (p->did<<16)|p->vid; | ||
| 1170 | |||
| 1171 | ctlr->nic = mem; | ||
| 1172 | if(dp83820reset(ctlr)){ | ||
| 1173 | free(ctlr); | ||
| 1174 | continue; | ||
| 1175 | } | ||
| 1176 | pcisetbme(p); | ||
| 1177 | |||
| 1178 | if(dp83820ctlrhead != nil) | ||
| 1179 | dp83820ctlrtail->next = ctlr; | ||
| 1180 | else | ||
| 1181 | dp83820ctlrhead = ctlr; | ||
| 1182 | dp83820ctlrtail = ctlr; | ||
| 1183 | } | ||
| 1184 | } | ||
| 1185 | |||
| 1186 | static int | ||
| 1187 | dp83820pnp(Ether* edev) | ||
| 1188 | { | ||
| 1189 | int i; | ||
| 1190 | Ctlr *ctlr; | ||
| 1191 | uchar ea[Eaddrlen]; | ||
| 1192 | |||
| 1193 | if(dp83820ctlrhead == nil) | ||
| 1194 | dp83820pci(); | ||
| 1195 | |||
| 1196 | /* | ||
| 1197 | * Any adapter matches if no edev->port is supplied, | ||
| 1198 | * otherwise the ports must match. | ||
| 1199 | */ | ||
| 1200 | for(ctlr = dp83820ctlrhead; ctlr != nil; ctlr = ctlr->next){ | ||
| 1201 | if(ctlr->active) | ||
| 1202 | continue; | ||
| 1203 | if(edev->port == 0 || edev->port == ctlr->port){ | ||
| 1204 | ctlr->active = 1; | ||
| 1205 | break; | ||
| 1206 | } | ||
| 1207 | } | ||
| 1208 | if(ctlr == nil) | ||
| 1209 | return -1; | ||
| 1210 | |||
| 1211 | edev->ctlr = ctlr; | ||
| 1212 | edev->port = ctlr->port; | ||
| 1213 | edev->irq = ctlr->pcidev->intl; | ||
| 1214 | edev->tbdf = ctlr->pcidev->tbdf; | ||
| 1215 | edev->mbps = 1000; | ||
| 1216 | |||
| 1217 | /* | ||
| 1218 | * Check if the adapter's station address is to be overridden. | ||
| 1219 | * If not, read it from the EEPROM and set in ether->ea prior to | ||
| 1220 | * loading the station address in the hardware. | ||
| 1221 | */ | ||
| 1222 | memset(ea, 0, Eaddrlen); | ||
| 1223 | if(memcmp(ea, edev->ea, Eaddrlen) == 0) | ||
| 1224 | for(i = 0; i < Eaddrlen/2; i++){ | ||
| 1225 | edev->ea[2*i] = ctlr->eeprom[0x0C-i]; | ||
| 1226 | edev->ea[2*i+1] = ctlr->eeprom[0x0C-i]>>8; | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | edev->attach = dp83820attach; | ||
| 1230 | edev->transmit = dp83820transmit; | ||
| 1231 | edev->interrupt = dp83820interrupt; | ||
| 1232 | edev->ifstat = dp83820ifstat; | ||
| 1233 | |||
| 1234 | edev->arg = edev; | ||
| 1235 | edev->promiscuous = dp83820promiscuous; | ||
| 1236 | edev->multicast = dp83820multicast; | ||
| 1237 | edev->shutdown = dp83820shutdown; | ||
| 1238 | |||
| 1239 | return 0; | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | void | ||
| 1243 | etherdp83820link(void) | ||
| 1244 | { | ||
| 1245 | addethercard("DP83820", dp83820pnp); | ||
| 1246 | } | ||
| @@ -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 | }; |
| @@ -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; |
| @@ -124,7 +124,11 @@ enum { /* Om */ · 123 unmodified lines | |||
| 124 | enum { /* Lmw */ | 124 | enum { /* 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 | ||
| 130 | enum { /* Link */ | 134 | enum { /* Link */ |
| @@ -146,17 +150,17 @@ typedef struct Host64 { · 15 unmodified lines | |||
| 146 | } Host64; | 150 | } Host64; |
| 147 | 151 | ||
| 148 | typedef struct Ere { /* Event Ring Element */ | 152 | typedef 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 | ||
| 153 | typedef int Cmd; /* (cmd<<24)|(flags<<12)|index */ | 157 | typedef int Cmd; /* cmd<<24 | flags<<12 | index */ |
| 154 | 158 | ||
| 155 | typedef struct Rbd { /* Receive Buffer Descriptor */ | 159 | typedef 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 | ||
| 165 | typedef struct Sbd { /* Send Buffer Descriptor */ | 169 | typedef 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 | ||
| 193 | typedef struct Rcb { /* Ring Control Block */ | 197 | typedef 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 | */ | ||
| 226 | enum { /* Host/NIC Interface ring sizes */ | 234 | enum { /* 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 | ||
| 245 | typedef struct Ctlr Ctlr; | 253 | typedef struct Ctlr Ctlr; |
| 246 | typedef struct Ctlr { | 254 | struct 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 | ||
| 291 | static Ctlr* ctlrhead; | 299 | static Ctlr* ctlrhead; |
| 292 | static Ctlr* ctlrtail; | 300 | static 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 | ||
| 552 | static void | 560 | static void |
| 553 | ga620event(Ctlr* ctlr, int eci, int epi) | 561 | ga620event(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); |
| 563 | print("%8.8uX: %8.8uX\n", ctlr->port, event); | 579 | print("#l%d: ga620: port %8.8uX: firmware is up\n", |
| 580 | edev->ctlrno, ctlr->port); | ||
| 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 */ |
| 568 | print("%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 send | 788 | * 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 need | 789 | * 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* associated | 794 | * 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 | else | 817 | 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 | |||
| 1056 | static int | 1086 | static int |
| 1057 | ga620reset(Ctlr* ctlr) | 1087 | ga620reset(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 | |||
| 1114 | static void | 1145 | static void |
| 1115 | ga620pci(void) | 1146 | ga620pci(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 fiber | 1162 | 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 | ||
| 1194 | static void | ||
| 1195 | ga620promiscuous(void *arg, int on) | ||
| 1196 | { | ||
| 1197 | Ether *ether = arg; | ||
| 1198 | |||
| 1199 | /* 3rd arg: 1 enables, 2 disables */ | ||
| 1200 | ga620command(ether->ctlr, 0xa, (on? 1: 2), 0); | ||
| 1201 | } | ||
| 1202 | |||
| 1203 | static void | ||
| 1204 | ga620multicast(void *arg, uchar *addr, int on) | ||
| 1205 | { | ||
| 1206 | Ether *ether = arg; | ||
| 1207 | |||
| 1208 | USED(addr); | ||
| 1209 | /* 3rd arg: 1 enables, 2 disables */ | ||
| 1210 | ga620command(ether->ctlr, 0xe, (on? 1: 2), 0); | ||
| 1211 | } | ||
| 1212 | |||
| 1163 | static int | 1213 | static int |
| 1164 | ga620pnp(Ether* edev) | 1214 | ga620pnp(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 | } |
| @@ -29,16 +29,17 @@ · 28 unmodified lines | |||
| 29 | #include "ethermii.h" | 29 | #include "ethermii.h" |
| 30 | 30 | ||
| 31 | enum { | 31 | enum { |
| 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 | |||
| 508 | static Ctlr* igbectlrtail; | 512 | static Ctlr* igbectlrtail; |
| 509 | 513 | ||
| 510 | static Lock igberblock; /* free receive Blocks */ | 514 | static Lock igberblock; /* free receive Blocks */ |
| 511 | static Block* igberbpool; | 515 | static Block* igberbpool; /* receive Blocks for all igbe controllers */ |
| 512 | 516 | ||
| 513 | static char* statistics[Nstatistics] = { | 517 | static 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 | else | 741 | 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 | else | 1615 | 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 interface | 1767 | ctlr->eeprom[Ea+2] += 0x100; // second interface |
| 1753 | for(i = Ea; i < Eaddrlen/2; i++){ | 1768 | for(i = Ea; i < Eaddrlen/2; i++){ |
| 1769 | if(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 defaults | 1792 | * 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) { // 82543 | 1795 | 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 | |||
| 1848 | static void | 1865 | static void |
| 1849 | igbepci(void) | 1866 | igbepci(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 | |||
| @@ -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); |
| @@ -0,0 +1,1025 @@ | |||
| 1 | /* | ||
| 2 | * VIA VT6102 Fast Ethernet Controller (Rhine II). | ||
| 3 | * To do: | ||
| 4 | * cache-line size alignments - done | ||
| 5 | * reduce tx interrupts | ||
| 6 | * use 2 descriptors on tx for alignment - done | ||
| 7 | * reorganise initialisation/shutdown/reset | ||
| 8 | * adjust Tx FIFO threshold on underflow - untested | ||
| 9 | * why does the link status never cause an interrupt? | ||
| 10 | * use the lproc as a periodic timer for stalls, etc. | ||
| 11 | */ | ||
| 12 | #include "u.h" | ||
| 13 | #include "../port/lib.h" | ||
| 14 | #include "mem.h" | ||
| 15 | #include "dat.h" | ||
| 16 | #include "fns.h" | ||
| 17 | #include "io.h" | ||
| 18 | #include "../port/error.h" | ||
| 19 | #include "../port/netif.h" | ||
| 20 | |||
| 21 | #include "etherif.h" | ||
| 22 | #include "ethermii.h" | ||
| 23 | |||
| 24 | enum { | ||
| 25 | Par0 = 0x00, /* Ethernet Address */ | ||
| 26 | Rcr = 0x06, /* Receive Configuration */ | ||
| 27 | Tcr = 0x07, /* Transmit Configuration */ | ||
| 28 | Cr = 0x08, /* Control */ | ||
| 29 | Isr = 0x0C, /* Interrupt Status */ | ||
| 30 | Imr = 0x0E, /* Interrupt Mask */ | ||
| 31 | Rxdaddr = 0x18, /* Current Rx Descriptor Address */ | ||
| 32 | Txdaddr = 0x1C, /* Current Tx Descriptor Address */ | ||
| 33 | Phyadr = 0x6C, /* Phy Address */ | ||
| 34 | Miisr = 0x6D, /* MII Status */ | ||
| 35 | Bcr0 = 0x6E, /* Bus Control */ | ||
| 36 | Bcr1 = 0x6F, | ||
| 37 | Miicr = 0x70, /* MII Control */ | ||
| 38 | Miiadr = 0x71, /* MII Address */ | ||
| 39 | Miidata = 0x72, /* MII Data */ | ||
| 40 | Eecsr = 0x74, /* EEPROM Control and Status */ | ||
| 41 | }; | ||
| 42 | |||
| 43 | enum { /* Rcr */ | ||
| 44 | Sep = 0x01, /* Accept Error Packets */ | ||
| 45 | Ar = 0x02, /* Accept Small Packets */ | ||
| 46 | Am = 0x04, /* Accept Multicast */ | ||
| 47 | Ab = 0x08, /* Accept Broadcast */ | ||
| 48 | Prom = 0x10, /* Accept Physical Address Packets */ | ||
| 49 | RrftMASK = 0xE0, /* Receive FIFO Threshold */ | ||
| 50 | RrftSHIFT = 5, | ||
| 51 | Rrft64 = 0<<RrftSHIFT, | ||
| 52 | Rrft32 = 1<<RrftSHIFT, | ||
| 53 | Rrft128 = 2<<RrftSHIFT, | ||
| 54 | Rrft256 = 3<<RrftSHIFT, | ||
| 55 | Rrft512 = 4<<RrftSHIFT, | ||
| 56 | Rrft768 = 5<<RrftSHIFT, | ||
| 57 | Rrft1024 = 6<<RrftSHIFT, | ||
| 58 | RrftSAF = 7<<RrftSHIFT, | ||
| 59 | }; | ||
| 60 | |||
| 61 | enum { /* Tcr */ | ||
| 62 | Lb0 = 0x02, /* Loopback Mode */ | ||
| 63 | Lb1 = 0x04, | ||
| 64 | Ofset = 0x08, /* Back-off Priority Selection */ | ||
| 65 | RtsfMASK = 0xE0, /* Transmit FIFO Threshold */ | ||
| 66 | RtsfSHIFT = 5, | ||
| 67 | Rtsf128 = 0<<RtsfSHIFT, | ||
| 68 | Rtsf256 = 1<<RtsfSHIFT, | ||
| 69 | Rtsf512 = 2<<RtsfSHIFT, | ||
| 70 | Rtsf1024 = 3<<RtsfSHIFT, | ||
| 71 | RtsfSAF = 7<<RtsfSHIFT, | ||
| 72 | }; | ||
| 73 | |||
| 74 | enum { /* Cr */ | ||
| 75 | Init = 0x0001, /* INIT Process Begin */ | ||
| 76 | Strt = 0x0002, /* Start NIC */ | ||
| 77 | Stop = 0x0004, /* Stop NIC */ | ||
| 78 | Rxon = 0x0008, /* Turn on Receive Process */ | ||
| 79 | Txon = 0x0010, /* Turn on Transmit Process */ | ||
| 80 | Tdmd = 0x0020, /* Transmit Poll Demand */ | ||
| 81 | Rdmd = 0x0040, /* Receive Poll Demand */ | ||
| 82 | Eren = 0x0100, /* Early Receive Enable */ | ||
| 83 | Fdx = 0x0400, /* Set MAC to Full Duplex Mode */ | ||
| 84 | Dpoll = 0x0800, /* Disable Td/Rd Auto Polling */ | ||
| 85 | Tdmd1 = 0x2000, /* Transmit Poll Demand 1 */ | ||
| 86 | Rdmd1 = 0x4000, /* Receive Poll Demand 1 */ | ||
| 87 | Sfrst = 0x8000, /* Software Reset */ | ||
| 88 | }; | ||
| 89 | |||
| 90 | enum { /* Isr/Imr */ | ||
| 91 | Prx = 0x0001, /* Received Packet Successfully */ | ||
| 92 | Ptx = 0x0002, /* Transmitted Packet Successfully */ | ||
| 93 | Rxe = 0x0004, /* Receive Error */ | ||
| 94 | Txe = 0x0008, /* Transmit Error */ | ||
| 95 | Tu = 0x0010, /* Transmit Buffer Underflow */ | ||
| 96 | Ru = 0x0020, /* Receive Buffer Link Error */ | ||
| 97 | Be = 0x0040, /* PCI Bus Error */ | ||
| 98 | Cnt = 0x0080, /* Counter Overflow */ | ||
| 99 | Eri = 0x0100, /* Early Receive Interrupt */ | ||
| 100 | Udfi = 0x0200, /* Tx FIFO Underflow */ | ||
| 101 | Ovfi = 0x0400, /* Receive FIFO Overflow */ | ||
| 102 | Pktrace = 0x0800, /* Hmmm... */ | ||
| 103 | Norbf = 0x1000, /* No Receive Buffers */ | ||
| 104 | Abti = 0x2000, /* Transmission Abort */ | ||
| 105 | Srci = 0x4000, /* Port State Change */ | ||
| 106 | Geni = 0x8000, /* General Purpose Interrupt */ | ||
| 107 | }; | ||
| 108 | |||
| 109 | enum { /* Phyadr */ | ||
| 110 | PhyadMASK = 0x1F, /* PHY Address */ | ||
| 111 | PhyadSHIFT = 0, | ||
| 112 | Mfdc = 0x20, /* Accelerate MDC Speed */ | ||
| 113 | Mpo0 = 0x40, /* MII Polling Timer Interval */ | ||
| 114 | Mpo1 = 0x80, | ||
| 115 | }; | ||
| 116 | |||
| 117 | enum { /* Bcr0 */ | ||
| 118 | DmaMASK = 0x07, /* DMA Length */ | ||
| 119 | DmaSHIFT = 0, | ||
| 120 | Dma32 = 0<<DmaSHIFT, | ||
| 121 | Dma64 = 1<<DmaSHIFT, | ||
| 122 | Dma128 = 2<<DmaSHIFT, | ||
| 123 | Dma256 = 3<<DmaSHIFT, | ||
| 124 | Dma512 = 4<<DmaSHIFT, | ||
| 125 | Dma1024 = 5<<DmaSHIFT, | ||
| 126 | DmaSAF = 7<<DmaSHIFT, | ||
| 127 | CrftMASK = 0x38, /* Rx FIFO Threshold */ | ||
| 128 | CrftSHIFT = 3, | ||
| 129 | Crft64 = 1<<CrftSHIFT, | ||
| 130 | Crft128 = 2<<CrftSHIFT, | ||
| 131 | Crft256 = 3<<CrftSHIFT, | ||
| 132 | Crft512 = 4<<CrftSHIFT, | ||
| 133 | Crft1024 = 5<<CrftSHIFT, | ||
| 134 | CrftSAF = 7<<CrftSHIFT, | ||
| 135 | Extled = 0x40, /* Extra LED Support Control */ | ||
| 136 | Med2 = 0x80, /* Medium Select Control */ | ||
| 137 | }; | ||
| 138 | |||
| 139 | enum { /* Bcr1 */ | ||
| 140 | PotMASK = 0x07, /* Polling Timer Interval */ | ||
| 141 | PotSHIFT = 0, | ||
| 142 | CtftMASK = 0x38, /* Tx FIFO Threshold */ | ||
| 143 | CtftSHIFT = 3, | ||
| 144 | Ctft64 = 1<<CtftSHIFT, | ||
| 145 | Ctft128 = 2<<CtftSHIFT, | ||
| 146 | Ctft256 = 3<<CtftSHIFT, | ||
| 147 | Ctft512 = 4<<CtftSHIFT, | ||
| 148 | Ctft1024 = 5<<CtftSHIFT, | ||
| 149 | CtftSAF = 7<<CtftSHIFT, | ||
| 150 | }; | ||
| 151 | |||
| 152 | enum { /* Miicr */ | ||
| 153 | Mdc = 0x01, /* Clock */ | ||
| 154 | Mdi = 0x02, /* Data In */ | ||
| 155 | Mdo = 0x04, /* Data Out */ | ||
| 156 | Mout = 0x08, /* Output Enable */ | ||
| 157 | Mdpm = 0x10, /* Direct Program Mode Enable */ | ||
| 158 | Wcmd = 0x20, /* Write Enable */ | ||
| 159 | Rcmd = 0x40, /* Read Enable */ | ||
| 160 | Mauto = 0x80, /* Auto Polling Enable */ | ||
| 161 | }; | ||
| 162 | |||
| 163 | enum { /* Miiadr */ | ||
| 164 | MadMASK = 0x1F, /* MII Port Address */ | ||
| 165 | MadSHIFT = 0, | ||
| 166 | Mdone = 0x20, /* Accelerate MDC Speed */ | ||
| 167 | Msrcen = 0x40, /* MII Polling Timer Interval */ | ||
| 168 | Midle = 0x80, | ||
| 169 | }; | ||
| 170 | |||
| 171 | enum { /* Eecsr */ | ||
| 172 | Edo = 0x01, /* Data Out */ | ||
| 173 | Edi = 0x02, /* Data In */ | ||
| 174 | Eck = 0x04, /* Clock */ | ||
| 175 | Ecs = 0x08, /* Chip Select */ | ||
| 176 | Dpm = 0x10, /* Direct Program Mode Enable */ | ||
| 177 | Autold = 0x20, /* Dynamic Reload */ | ||
| 178 | Embp = 0x40, /* Embedded Program Enable */ | ||
| 179 | Eepr = 0x80, /* Programmed */ | ||
| 180 | }; | ||
| 181 | |||
| 182 | /* | ||
| 183 | * Ring descriptor. The space allocated for each | ||
| 184 | * of these will be rounded up to a cache-line boundary. | ||
| 185 | * The first 4 elements are known to the hardware. | ||
| 186 | */ | ||
| 187 | typedef struct Ds Ds; | ||
| 188 | typedef struct Ds { | ||
| 189 | uint status; | ||
| 190 | uint control; | ||
| 191 | uint addr; | ||
| 192 | uint branch; | ||
| 193 | |||
| 194 | Block* bp; | ||
| 195 | void* bounce; | ||
| 196 | Ds* next; | ||
| 197 | Ds* prev; | ||
| 198 | } Ds; | ||
| 199 | |||
| 200 | enum { /* Rx Ds status */ | ||
| 201 | Rerr = 0x00000001, /* Receiver Error */ | ||
| 202 | Crc = 0x00000002, /* CRC Error */ | ||
| 203 | Fae = 0x00000004, /* Frame Alignment Error */ | ||
| 204 | Fov = 0x00000008, /* FIFO Overflow */ | ||
| 205 | Long = 0x00000010, /* A Long Packet */ | ||
| 206 | Runt = 0x00000020, /* A Runt Packet */ | ||
| 207 | Rxserr = 0x00000040, /* System Error */ | ||
| 208 | Buff = 0x00000080, /* Buffer Underflow Error */ | ||
| 209 | Rxedp = 0x00000100, /* End of Packet Buffer */ | ||
| 210 | Rxstp = 0x00000200, /* Packet Start */ | ||
| 211 | Chn = 0x00000400, /* Chain Buffer */ | ||
| 212 | Phy = 0x00000800, /* Physical Address Packet */ | ||
| 213 | Bar = 0x00001000, /* Broadcast Packet */ | ||
| 214 | Mar = 0x00002000, /* Multicast Packet */ | ||
| 215 | Rxok = 0x00008000, /* Packet Received Successfully */ | ||
| 216 | LengthMASK = 0x07FF0000, /* Received Packet Length */ | ||
| 217 | LengthSHIFT = 16, | ||
| 218 | |||
| 219 | Own = 0x80000000, /* Descriptor Owned by NIC */ | ||
| 220 | }; | ||
| 221 | |||
| 222 | enum { /* Tx Ds status */ | ||
| 223 | NcrMASK = 0x0000000F, /* Collision Retry Count */ | ||
| 224 | NcrSHIFT = 0, | ||
| 225 | Cols = 0x00000010, /* Experienced Collisions */ | ||
| 226 | Cdh = 0x00000080, /* CD Heartbeat */ | ||
| 227 | Abt = 0x00000100, /* Aborted after Excessive Collisions */ | ||
| 228 | Owc = 0x00000200, /* Out of Window Collision Seen */ | ||
| 229 | Crs = 0x00000400, /* Carrier Sense Lost */ | ||
| 230 | Udf = 0x00000800, /* FIFO Underflow */ | ||
| 231 | Tbuff = 0x00001000, /* Invalid Td */ | ||
| 232 | Txserr = 0x00002000, /* System Error */ | ||
| 233 | Terr = 0x00008000, /* Excessive Collisions */ | ||
| 234 | }; | ||
| 235 | |||
| 236 | enum { /* Tx Ds control */ | ||
| 237 | TbsMASK = 0x000007FF, /* Tx Buffer Size */ | ||
| 238 | TbsSHIFT = 0, | ||
| 239 | Chain = 0x00008000, /* Chain Buffer */ | ||
| 240 | Crcdisable = 0x00010000, /* Disable CRC generation */ | ||
| 241 | Stp = 0x00200000, /* Start of Packet */ | ||
| 242 | Edp = 0x00400000, /* End of Packet */ | ||
| 243 | Ic = 0x00800000, /* Assert Interrupt Immediately */ | ||
| 244 | }; | ||
| 245 | |||
| 246 | enum { | ||
| 247 | Nrd = 64, | ||
| 248 | Ntd = 64, | ||
| 249 | Rdbsz = ROUNDUP(ETHERMAXTU+4, 4), | ||
| 250 | |||
| 251 | Nrxstats = 8, | ||
| 252 | Ntxstats = 9, | ||
| 253 | |||
| 254 | Txcopy = 128, | ||
| 255 | }; | ||
| 256 | |||
| 257 | typedef struct Ctlr Ctlr; | ||
| 258 | typedef struct Ctlr { | ||
| 259 | int port; | ||
| 260 | Pcidev* pcidev; | ||
| 261 | Ctlr* next; | ||
| 262 | int active; | ||
| 263 | int id; | ||
| 264 | uchar par[Eaddrlen]; | ||
| 265 | |||
| 266 | QLock alock; /* attach */ | ||
| 267 | void* alloc; /* receive/transmit descriptors */ | ||
| 268 | int cls; /* alignment */ | ||
| 269 | int nrd; | ||
| 270 | int ntd; | ||
| 271 | |||
| 272 | Ds* rd; | ||
| 273 | Ds* rdh; | ||
| 274 | |||
| 275 | Lock tlock; | ||
| 276 | Ds* td; | ||
| 277 | Ds* tdh; | ||
| 278 | Ds* tdt; | ||
| 279 | int tdused; | ||
| 280 | |||
| 281 | Lock clock; /* */ | ||
| 282 | int cr; | ||
| 283 | int imr; | ||
| 284 | int tft; /* Tx threshold */ | ||
| 285 | |||
| 286 | Mii* mii; | ||
| 287 | Rendez lrendez; | ||
| 288 | int lwakeup; | ||
| 289 | |||
| 290 | uint rxstats[Nrxstats]; /* statistics */ | ||
| 291 | uint txstats[Ntxstats]; | ||
| 292 | uint intr; | ||
| 293 | uint lintr; | ||
| 294 | uint lsleep; | ||
| 295 | uint rintr; | ||
| 296 | uint tintr; | ||
| 297 | uint taligned; | ||
| 298 | uint tsplit; | ||
| 299 | uint tcopied; | ||
| 300 | uint txdw; | ||
| 301 | } Ctlr; | ||
| 302 | |||
| 303 | static Ctlr* vt6102ctlrhead; | ||
| 304 | static Ctlr* vt6102ctlrtail; | ||
| 305 | |||
| 306 | #define csr8r(c, r) (inb((c)->port+(r))) | ||
| 307 | #define csr16r(c, r) (ins((c)->port+(r))) | ||
| 308 | #define csr32r(c, r) (inl((c)->port+(r))) | ||
| 309 | #define csr8w(c, r, b) (outb((c)->port+(r), (int)(b))) | ||
| 310 | #define csr16w(c, r, w) (outs((c)->port+(r), (ushort)(w))) | ||
| 311 | #define csr32w(c, r, w) (outl((c)->port+(r), (ulong)(w))) | ||
| 312 | |||
| 313 | static char* rxstats[Nrxstats] = { | ||
| 314 | "Receiver Error", | ||
| 315 | "CRC Error", | ||
| 316 | "Frame Alignment Error", | ||
| 317 | "FIFO Overflow", | ||
| 318 | "Long Packet", | ||
| 319 | "Runt Packet", | ||
| 320 | "System Error", | ||
| 321 | "Buffer Underflow Error", | ||
| 322 | }; | ||
| 323 | static char* txstats[Ntxstats] = { | ||
| 324 | "Aborted after Excessive Collisions", | ||
| 325 | "Out of Window Collision Seen", | ||
| 326 | "Carrier Sense Lost", | ||
| 327 | "FIFO Underflow", | ||
| 328 | "Invalid Td", | ||
| 329 | "System Error", | ||
| 330 | nil, | ||
| 331 | "Excessive Collisions", | ||
| 332 | }; | ||
| 333 | |||
| 334 | static long | ||
| 335 | vt6102ifstat(Ether* edev, void* a, long n, ulong offset) | ||
| 336 | { | ||
| 337 | char *p; | ||
| 338 | Ctlr *ctlr; | ||
| 339 | int i, l, r; | ||
| 340 | |||
| 341 | ctlr = edev->ctlr; | ||
| 342 | |||
| 343 | p = malloc(2*READSTR); | ||
| 344 | l = 0; | ||
| 345 | for(i = 0; i < Nrxstats; i++){ | ||
| 346 | l += snprint(p+l, 2*READSTR-l, "%s: %ud\n", | ||
| 347 | rxstats[i], ctlr->rxstats[i]); | ||
| 348 | } | ||
| 349 | for(i = 0; i < Ntxstats; i++){ | ||
| 350 | if(txstats[i] == nil) | ||
| 351 | continue; | ||
| 352 | l += snprint(p+l, 2*READSTR-l, "%s: %ud\n", | ||
| 353 | txstats[i], ctlr->txstats[i]); | ||
| 354 | } | ||
| 355 | l += snprint(p+l, 2*READSTR-l, "cls: %ud\n", ctlr->cls); | ||
| 356 | l += snprint(p+l, 2*READSTR-l, "intr: %ud\n", ctlr->intr); | ||
| 357 | l += snprint(p+l, 2*READSTR-l, "lintr: %ud\n", ctlr->lintr); | ||
| 358 | l += snprint(p+l, 2*READSTR-l, "lsleep: %ud\n", ctlr->lsleep); | ||
| 359 | l += snprint(p+l, 2*READSTR-l, "rintr: %ud\n", ctlr->rintr); | ||
| 360 | l += snprint(p+l, 2*READSTR-l, "tintr: %ud\n", ctlr->tintr); | ||
| 361 | l += snprint(p+l, 2*READSTR-l, "taligned: %ud\n", ctlr->taligned); | ||
| 362 | l += snprint(p+l, 2*READSTR-l, "tsplit: %ud\n", ctlr->tsplit); | ||
| 363 | l += snprint(p+l, 2*READSTR-l, "tcopied: %ud\n", ctlr->tcopied); | ||
| 364 | l += snprint(p+l, 2*READSTR-l, "txdw: %ud\n", ctlr->txdw); | ||
| 365 | l += snprint(p+l, 2*READSTR-l, "tft: %ud\n", ctlr->tft); | ||
| 366 | |||
| 367 | if(ctlr->mii != nil && ctlr->mii->curphy != nil){ | ||
| 368 | l += snprint(p+l, 2*READSTR, "phy: "); | ||
| 369 | for(i = 0; i < NMiiPhyr; i++){ | ||
| 370 | if(i && ((i & 0x07) == 0)) | ||
| 371 | l += snprint(p+l, 2*READSTR-l, "\n "); | ||
| 372 | r = miimir(ctlr->mii, i); | ||
| 373 | l += snprint(p+l, 2*READSTR-l, " %4.4uX", r); | ||
| 374 | } | ||
| 375 | snprint(p+l, 2*READSTR-l, "\n"); | ||
| 376 | } | ||
| 377 | snprint(p+l, 2*READSTR-l, "\n"); | ||
| 378 | |||
| 379 | n = readstr(offset, a, n, p); | ||
| 380 | free(p); | ||
| 381 | |||
| 382 | return n; | ||
| 383 | } | ||
| 384 | |||
| 385 | static void | ||
| 386 | vt6102promiscuous(void* arg, int on) | ||
| 387 | { | ||
| 388 | int rcr; | ||
| 389 | Ctlr *ctlr; | ||
| 390 | Ether *edev; | ||
| 391 | |||
| 392 | edev = arg; | ||
| 393 | ctlr = edev->ctlr; | ||
| 394 | rcr = csr8r(ctlr, Rcr); | ||
| 395 | if(on) | ||
| 396 | rcr |= Prom; | ||
| 397 | else | ||
| 398 | rcr &= ~Prom; | ||
| 399 | csr8w(ctlr, Rcr, rcr); | ||
| 400 | } | ||
| 401 | |||
| 402 | static void | ||
| 403 | vt6102multicast(void* arg, uchar* addr, int on) | ||
| 404 | { | ||
| 405 | /* | ||
| 406 | * For now Am is set in Rcr. | ||
| 407 | * Will need to interlock with promiscuous | ||
| 408 | * when this gets filled in. | ||
| 409 | */ | ||
| 410 | USED(arg, addr, on); | ||
| 411 | } | ||
| 412 | |||
| 413 | static int | ||
| 414 | vt6102wakeup(void* v) | ||
| 415 | { | ||
| 416 | return *((int*)v) != 0; | ||
| 417 | } | ||
| 418 | |||
| 419 | static void | ||
| 420 | vt6102imr(Ctlr* ctlr, int imr) | ||
| 421 | { | ||
| 422 | ilock(&ctlr->clock); | ||
| 423 | ctlr->imr |= imr; | ||
| 424 | csr16w(ctlr, Imr, ctlr->imr); | ||
| 425 | iunlock(&ctlr->clock); | ||
| 426 | } | ||
| 427 | |||
| 428 | static void | ||
| 429 | vt6102lproc(void* arg) | ||
| 430 | { | ||
| 431 | Ctlr *ctlr; | ||
| 432 | Ether *edev; | ||
| 433 | MiiPhy *phy; | ||
| 434 | |||
| 435 | edev = arg; | ||
| 436 | ctlr = edev->ctlr; | ||
| 437 | for(;;){ | ||
| 438 | if(ctlr->mii == nil || ctlr->mii->curphy == nil) | ||
| 439 | break; | ||
| 440 | if(miistatus(ctlr->mii) < 0) | ||
| 441 | goto enable; | ||
| 442 | |||
| 443 | phy = ctlr->mii->curphy; | ||
| 444 | ilock(&ctlr->clock); | ||
| 445 | if(phy->fd) | ||
| 446 | ctlr->cr |= Fdx; | ||
| 447 | else | ||
| 448 | ctlr->cr &= ~Fdx; | ||
| 449 | csr16w(ctlr, Cr, ctlr->cr); | ||
| 450 | iunlock(&ctlr->clock); | ||
| 451 | enable: | ||
| 452 | ctlr->lwakeup = 0; | ||
| 453 | vt6102imr(ctlr, Srci); | ||
| 454 | |||
| 455 | ctlr->lsleep++; | ||
| 456 | sleep(&ctlr->lrendez, vt6102wakeup, &ctlr->lwakeup); | ||
| 457 | |||
| 458 | } | ||
| 459 | pexit("vt6102lproc: done", 1); | ||
| 460 | } | ||
| 461 | |||
| 462 | static void | ||
| 463 | vt6102attach(Ether* edev) | ||
| 464 | { | ||
| 465 | int i; | ||
| 466 | Ctlr *ctlr; | ||
| 467 | Ds *ds, *prev; | ||
| 468 | uchar *alloc, *bounce; | ||
| 469 | char name[KNAMELEN]; | ||
| 470 | |||
| 471 | ctlr = edev->ctlr; | ||
| 472 | qlock(&ctlr->alock); | ||
| 473 | if(ctlr->alloc != nil){ | ||
| 474 | qunlock(&ctlr->alock); | ||
| 475 | return; | ||
| 476 | } | ||
| 477 | |||
| 478 | /* | ||
| 479 | * Descriptor and bounce-buffer space. | ||
| 480 | * Must all be aligned on a 4-byte boundary, | ||
| 481 | * but try to align on cache-lines. | ||
| 482 | */ | ||
| 483 | ctlr->nrd = Nrd; | ||
| 484 | ctlr->ntd = Ntd; | ||
| 485 | alloc = malloc((ctlr->nrd+ctlr->ntd)*ctlr->cls + ctlr->ntd*Txcopy + ctlr->cls-1); | ||
| 486 | if(alloc == nil){ | ||
| 487 | qunlock(&ctlr->alock); | ||
| 488 | return; | ||
| 489 | } | ||
| 490 | ctlr->alloc = alloc; | ||
| 491 | alloc = (uchar*)ROUNDUP((ulong)alloc, ctlr->cls); | ||
| 492 | |||
| 493 | ctlr->rd = (Ds*)alloc; | ||
| 494 | |||
| 495 | if(waserror()){ | ||
| 496 | ds = ctlr->rd; | ||
| 497 | for(i = 0; i < ctlr->nrd; i++){ | ||
| 498 | if(ds->bp != nil){ | ||
| 499 | freeb(ds->bp); | ||
| 500 | ds->bp = nil; | ||
| 501 | } | ||
| 502 | if((ds = ds->next) == nil) | ||
| 503 | break; | ||
| 504 | } | ||
| 505 | free(ctlr->alloc); | ||
| 506 | ctlr->alloc = nil; | ||
| 507 | qunlock(&ctlr->alock); | ||
| 508 | nexterror(); | ||
| 509 | } | ||
| 510 | |||
| 511 | prev = ctlr->rd + ctlr->nrd-1; | ||
| 512 | for(i = 0; i < ctlr->nrd; i++){ | ||
| 513 | ds = (Ds*)alloc; | ||
| 514 | alloc += ctlr->cls; | ||
| 515 | |||
| 516 | ds->control = Rdbsz; | ||
| 517 | ds->branch = PCIWADDR(alloc); | ||
| 518 | |||
| 519 | ds->bp = iallocb(Rdbsz+3); | ||
| 520 | if(ds->bp == nil) | ||
| 521 | error("vt6102: can't allocate receive ring\n"); | ||
| 522 | ds->bp->rp = (uchar*)ROUNDUP((ulong)ds->bp->rp, 4); | ||
| 523 | ds->addr = PCIWADDR(ds->bp->rp); | ||
| 524 | |||
| 525 | ds->next = (Ds*)alloc; | ||
| 526 | ds->prev = prev; | ||
| 527 | prev = ds; | ||
| 528 | |||
| 529 | ds->status = Own; | ||
| 530 | } | ||
| 531 | prev->branch = 0; | ||
| 532 | prev->next = ctlr->rd; | ||
| 533 | prev->status = 0; | ||
| 534 | ctlr->rdh = ctlr->rd; | ||
| 535 | |||
| 536 | ctlr->td = (Ds*)alloc; | ||
| 537 | prev = ctlr->td + ctlr->ntd-1; | ||
| 538 | bounce = alloc + ctlr->ntd*ctlr->cls; | ||
| 539 | for(i = 0; i < ctlr->ntd; i++){ | ||
| 540 | ds = (Ds*)alloc; | ||
| 541 | alloc += ctlr->cls; | ||
| 542 | |||
| 543 | ds->bounce = bounce; | ||
| 544 | bounce += Txcopy; | ||
| 545 | ds->next = (Ds*)alloc; | ||
| 546 | ds->prev = prev; | ||
| 547 | prev = ds; | ||
| 548 | } | ||
| 549 | prev->next = ctlr->td; | ||
| 550 | ctlr->tdh = ctlr->tdt = ctlr->td; | ||
| 551 | ctlr->tdused = 0; | ||
| 552 | |||
| 553 | ctlr->cr = Dpoll|Rdmd|Txon|Rxon|Strt; | ||
| 554 | /*Srci|Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx*/ | ||
| 555 | ctlr->imr = Abti|Norbf|Pktrace|Ovfi|Udfi|Be|Ru|Tu|Txe|Rxe|Ptx|Prx; | ||
| 556 | |||
| 557 | ilock(&ctlr->clock); | ||
| 558 | csr32w(ctlr, Rxdaddr, PCIWADDR(ctlr->rd)); | ||
| 559 | csr32w(ctlr, Txdaddr, PCIWADDR(ctlr->td)); | ||
| 560 | csr16w(ctlr, Isr, ~0); | ||
| 561 | csr16w(ctlr, Imr, ctlr->imr); | ||
| 562 | csr16w(ctlr, Cr, ctlr->cr); | ||
| 563 | iunlock(&ctlr->clock); | ||
| 564 | |||
| 565 | snprint(name, KNAMELEN, "#l%dlproc", edev->ctlrno); | ||
| 566 | kproc(name, vt6102lproc, edev, 0); | ||
| 567 | |||
| 568 | qunlock(&ctlr->alock); | ||
| 569 | poperror(); | ||
| 570 | } | ||
| 571 | |||
| 572 | static void | ||
| 573 | vt6102transmit(Ether* edev) | ||
| 574 | { | ||
| 575 | Block *bp; | ||
| 576 | Ctlr *ctlr; | ||
| 577 | Ds *ds, *next; | ||
| 578 | int control, i, o, prefix, size, tdused, timeo; | ||
| 579 | |||
| 580 | ctlr = edev->ctlr; | ||
| 581 | |||
| 582 | ilock(&ctlr->tlock); | ||
| 583 | |||
| 584 | /* | ||
| 585 | * Free any completed packets | ||
| 586 | */ | ||
| 587 | ds = ctlr->tdh; | ||
| 588 | for(tdused = ctlr->tdused; tdused > 0; tdused--){ | ||
| 589 | /* | ||
| 590 | * For some errors the chip will turn the Tx engine | ||
| 591 | * off. Wait for that to happen. | ||
| 592 | * Could reset and re-init the chip here if it doesn't | ||
| 593 | * play fair. | ||
| 594 | * To do: adjust Tx FIFO threshold on underflow. | ||
| 595 | */ | ||
| 596 | if(ds->status & (Abt|Tbuff|Udf)){ | ||
| 597 | for(timeo = 0; timeo < 1000; timeo++){ | ||
| 598 | if(!(csr16r(ctlr, Cr) & Txon)) | ||
| 599 | break; | ||
| 600 | microdelay(1); | ||
| 601 | } | ||
| 602 | ds->status = Own; | ||
| 603 | csr32w(ctlr, Txdaddr, PCIWADDR(ds)); | ||
| 604 | } | ||
| 605 | |||
| 606 | if(ds->status & Own) | ||
| 607 | break; | ||
| 608 | ds->addr = 0; | ||
| 609 | ds->branch = 0; | ||
| 610 | |||
| 611 | if(ds->bp != nil){ | ||
| 612 | freeb(ds->bp); | ||
| 613 | ds->bp = nil; | ||
| 614 | } | ||
| 615 | for(i = 0; i < Ntxstats-1; i++){ | ||
| 616 | if(ds->status & (1<<i)) | ||
| 617 | ctlr->txstats[i]++; | ||
| 618 | } | ||
| 619 | ctlr->txstats[i] += (ds->status & NcrMASK)>>NcrSHIFT; | ||
| 620 | |||
| 621 | ds = ds->next; | ||
| 622 | } | ||
| 623 | ctlr->tdh = ds; | ||
| 624 | |||
| 625 | /* | ||
| 626 | * Try to fill the ring back up. | ||
| 627 | */ | ||
| 628 | ds = ctlr->tdt; | ||
| 629 | while(tdused < ctlr->ntd-2){ | ||
| 630 | if((bp = qget(edev->oq)) == nil) | ||
| 631 | break; | ||
| 632 | tdused++; | ||
| 633 | |||
| 634 | size = BLEN(bp); | ||
| 635 | prefix = 0; | ||
| 636 | |||
| 637 | if(o = (((int)bp->rp) & 0x03)){ | ||
| 638 | prefix = Txcopy-o; | ||
| 639 | if(prefix > size) | ||
| 640 | prefix = size; | ||
| 641 | memmove(ds->bounce, bp->rp, prefix); | ||
| 642 | ds->addr = PCIWADDR(ds->bounce); | ||
| 643 | bp->rp += prefix; | ||
| 644 | size -= prefix; | ||
| 645 | } | ||
| 646 | |||
| 647 | next = ds->next; | ||
| 648 | ds->branch = PCIWADDR(ds->next); | ||
| 649 | |||
| 650 | if(size){ | ||
| 651 | if(prefix){ | ||
| 652 | next->bp = bp; | ||
| 653 | next->addr = PCIWADDR(bp->rp); | ||
| 654 | next->branch = PCIWADDR(next->next); | ||
| 655 | next->control = Edp|Chain|((size<<TbsSHIFT) & TbsMASK); | ||
| 656 | |||
| 657 | control = Stp|Chain|((prefix<<TbsSHIFT) & TbsMASK); | ||
| 658 | |||
| 659 | next = next->next; | ||
| 660 | tdused++; | ||
| 661 | ctlr->tsplit++; | ||
| 662 | } | ||
| 663 | else{ | ||
| 664 | ds->bp = bp; | ||
| 665 | ds->addr = PCIWADDR(bp->rp); | ||
| 666 | control = Edp|Stp|((size<<TbsSHIFT) & TbsMASK); | ||
| 667 | ctlr->taligned++; | ||
| 668 | } | ||
| 669 | } | ||
| 670 | else{ | ||
| 671 | freeb(bp); | ||
| 672 | control = Edp|Stp|((prefix<<TbsSHIFT) & TbsMASK); | ||
| 673 | ctlr->tcopied++; | ||
| 674 | } | ||
| 675 | |||
| 676 | ds->control = control; | ||
| 677 | if(tdused >= ctlr->ntd-2){ | ||
| 678 | ds->control |= Ic; | ||
| 679 | ctlr->txdw++; | ||
| 680 | } | ||
| 681 | coherence(); | ||
| 682 | ds->status = Own; | ||
| 683 | |||
| 684 | ds = next; | ||
| 685 | } | ||
| 686 | ctlr->tdt = ds; | ||
| 687 | ctlr->tdused = tdused; | ||
| 688 | if(ctlr->tdused) | ||
| 689 | csr16w(ctlr, Cr, Tdmd|ctlr->cr); | ||
| 690 | |||
| 691 | iunlock(&ctlr->tlock); | ||
| 692 | } | ||
| 693 | |||
| 694 | static void | ||
| 695 | vt6102receive(Ether* edev) | ||
| 696 | { | ||
| 697 | Ds *ds; | ||
| 698 | Block *bp; | ||
| 699 | Ctlr *ctlr; | ||
| 700 | int i, len; | ||
| 701 | |||
| 702 | ctlr = edev->ctlr; | ||
| 703 | |||
| 704 | ds = ctlr->rdh; | ||
| 705 | while(!(ds->status & Own) && ds->status != 0){ | ||
| 706 | if(ds->status & Rerr){ | ||
| 707 | for(i = 0; i < Nrxstats; i++){ | ||
| 708 | if(ds->status & (1<<i)) | ||
| 709 | ctlr->rxstats[i]++; | ||
| 710 | } | ||
| 711 | } | ||
| 712 | else if(bp = iallocb(Rdbsz+3)){ | ||
| 713 | len = ((ds->status & LengthMASK)>>LengthSHIFT)-4; | ||
| 714 | ds->bp->wp = ds->bp->rp+len; | ||
| 715 | etheriq(edev, ds->bp, 1); | ||
| 716 | bp->rp = (uchar*)ROUNDUP((ulong)bp->rp, 4); | ||
| 717 | ds->addr = PCIWADDR(bp->rp); | ||
| 718 | ds->bp = bp; | ||
| 719 | } | ||
| 720 | ds->control = Rdbsz; | ||
| 721 | ds->branch = 0; | ||
| 722 | ds->status = 0; | ||
| 723 | |||
| 724 | ds->prev->branch = PCIWADDR(ds); | ||
| 725 | coherence(); | ||
| 726 | ds->prev->status = Own; | ||
| 727 | |||
| 728 | ds = ds->next; | ||
| 729 | } | ||
| 730 | ctlr->rdh = ds; | ||
| 731 | |||
| 732 | csr16w(ctlr, Cr, ctlr->cr); | ||
| 733 | } | ||
| 734 | |||
| 735 | static void | ||
| 736 | vt6102interrupt(Ureg*, void* arg) | ||
| 737 | { | ||
| 738 | Ctlr *ctlr; | ||
| 739 | Ether *edev; | ||
| 740 | int imr, isr, r, timeo; | ||
| 741 | |||
| 742 | edev = arg; | ||
| 743 | ctlr = edev->ctlr; | ||
| 744 | |||
| 745 | ilock(&ctlr->clock); | ||
| 746 | csr16w(ctlr, Imr, 0); | ||
| 747 | imr = ctlr->imr; | ||
| 748 | ctlr->intr++; | ||
| 749 | for(;;){ | ||
| 750 | if((isr = csr16r(ctlr, Isr)) != 0) | ||
| 751 | csr16w(ctlr, Isr, isr); | ||
| 752 | if((isr & ctlr->imr) == 0) | ||
| 753 | break; | ||
| 754 | |||
| 755 | if(isr & Srci){ | ||
| 756 | imr &= ~Srci; | ||
| 757 | ctlr->lwakeup = isr & Srci; | ||
| 758 | wakeup(&ctlr->lrendez); | ||
| 759 | isr &= ~Srci; | ||
| 760 | ctlr->lintr++; | ||
| 761 | } | ||
| 762 | if(isr & (Norbf|Pktrace|Ovfi|Ru|Rxe|Prx)){ | ||
| 763 | vt6102receive(edev); | ||
| 764 | isr &= ~(Norbf|Pktrace|Ovfi|Ru|Rxe|Prx); | ||
| 765 | ctlr->rintr++; | ||
| 766 | } | ||
| 767 | if(isr & (Abti|Udfi|Tu|Txe|Ptx)){ | ||
| 768 | if(isr & (Abti|Udfi|Tu)){ | ||
| 769 | for(timeo = 0; timeo < 1000; timeo++){ | ||
| 770 | if(!(csr16r(ctlr, Cr) & Txon)) | ||
| 771 | break; | ||
| 772 | microdelay(1); | ||
| 773 | } | ||
| 774 | |||
| 775 | if((isr & Udfi) && ctlr->tft < CtftSAF){ | ||
| 776 | ctlr->tft += 1<<CtftSHIFT; | ||
| 777 | r = csr8r(ctlr, Bcr1) & ~CtftMASK; | ||
| 778 | csr8w(ctlr, Bcr1, r|ctlr->tft); | ||
| 779 | } | ||
| 780 | } | ||
| 781 | vt6102transmit(edev); | ||
| 782 | isr &= ~(Abti|Udfi|Tu|Txe|Ptx); | ||
| 783 | ctlr->tintr++; | ||
| 784 | } | ||
| 785 | if(isr) | ||
| 786 | panic("vt6102: isr %4.4uX\n", isr); | ||
| 787 | } | ||
| 788 | ctlr->imr = imr; | ||
| 789 | csr16w(ctlr, Imr, ctlr->imr); | ||
| 790 | iunlock(&ctlr->clock); | ||
| 791 | } | ||
| 792 | |||
| 793 | static int | ||
| 794 | vt6102miimicmd(Mii* mii, int pa, int ra, int cmd, int data) | ||
| 795 | { | ||
| 796 | Ctlr *ctlr; | ||
| 797 | int r, timeo; | ||
| 798 | |||
| 799 | ctlr = mii->ctlr; | ||
| 800 | |||
| 801 | csr8w(ctlr, Miicr, 0); | ||
| 802 | r = csr8r(ctlr, Phyadr); | ||
| 803 | csr8w(ctlr, Phyadr, (r & ~PhyadMASK)|pa); | ||
| 804 | csr8w(ctlr, Phyadr, pa); | ||
| 805 | csr8w(ctlr, Miiadr, ra); | ||
| 806 | if(cmd == Wcmd) | ||
| 807 | csr16w(ctlr, Miidata, data); | ||
| 808 | csr8w(ctlr, Miicr, cmd); | ||
| 809 | |||
| 810 | for(timeo = 0; timeo < 10000; timeo++){ | ||
| 811 | if(!(csr8r(ctlr, Miicr) & cmd)) | ||
| 812 | break; | ||
| 813 | microdelay(1); | ||
| 814 | } | ||
| 815 | if(timeo >= 10000) | ||
| 816 | return -1; | ||
| 817 | |||
| 818 | if(cmd == Wcmd) | ||
| 819 | return 0; | ||
| 820 | return csr16r(ctlr, Miidata); | ||
| 821 | } | ||
| 822 | |||
| 823 | static int | ||
| 824 | vt6102miimir(Mii* mii, int pa, int ra) | ||
| 825 | { | ||
| 826 | return vt6102miimicmd(mii, pa, ra, Rcmd, 0); | ||
| 827 | } | ||
| 828 | |||
| 829 | static int | ||
| 830 | vt6102miimiw(Mii* mii, int pa, int ra, int data) | ||
| 831 | { | ||
| 832 | return vt6102miimicmd(mii, pa, ra, Wcmd, data); | ||
| 833 | } | ||
| 834 | |||
| 835 | static int | ||
| 836 | vt6102detach(Ctlr* ctlr) | ||
| 837 | { | ||
| 838 | int timeo; | ||
| 839 | |||
| 840 | /* | ||
| 841 | * Soft reset the controller. | ||
| 842 | */ | ||
| 843 | csr16w(ctlr, Cr, Sfrst); | ||
| 844 | for(timeo = 0; timeo < 10000; timeo++){ | ||
| 845 | if(!(csr16r(ctlr, Cr) & Sfrst)) | ||
| 846 | break; | ||
| 847 | microdelay(1); | ||
| 848 | } | ||
| 849 | if(timeo >= 1000) | ||
| 850 | return -1; | ||
| 851 | |||
| 852 | return 0; | ||
| 853 | } | ||
| 854 | |||
| 855 | static int | ||
| 856 | vt6102reset(Ctlr* ctlr) | ||
| 857 | { | ||
| 858 | MiiPhy *phy; | ||
| 859 | int i, r, timeo; | ||
| 860 | |||
| 861 | if(vt6102detach(ctlr) < 0) | ||
| 862 | return -1; | ||
| 863 | |||
| 864 | /* | ||
| 865 | * Load the MAC address into the PAR[01] | ||
| 866 | * registers. | ||
| 867 | */ | ||
| 868 | r = csr8r(ctlr, Eecsr); | ||
| 869 | csr8w(ctlr, Eecsr, Autold|r); | ||
| 870 | for(timeo = 0; timeo < 100; timeo++){ | ||
| 871 | if(!(csr8r(ctlr, Cr) & Autold)) | ||
| 872 | break; | ||
| 873 | microdelay(1); | ||
| 874 | } | ||
| 875 | if(timeo >= 100) | ||
| 876 | return -1; | ||
| 877 | |||
| 878 | for(i = 0; i < Eaddrlen; i++) | ||
| 879 | ctlr->par[i] = csr8r(ctlr, Par0+i); | ||
| 880 | |||
| 881 | /* | ||
| 882 | * Configure DMA and Rx/Tx thresholds. | ||
| 883 | * If the Rx/Tx threshold bits in Bcr[01] are 0 then | ||
| 884 | * the thresholds are determined by Rcr/Tcr. | ||
| 885 | */ | ||
| 886 | r = csr8r(ctlr, Bcr0) & ~(CrftMASK|DmaMASK); | ||
| 887 | csr8w(ctlr, Bcr0, r|Crft64|Dma64); | ||
| 888 | r = csr8r(ctlr, Bcr1) & ~CtftMASK; | ||
| 889 | csr8w(ctlr, Bcr1, r|ctlr->tft); | ||
| 890 | |||
| 891 | r = csr8r(ctlr, Rcr) & ~(RrftMASK|Prom|Ar|Sep); | ||
| 892 | csr8w(ctlr, Rcr, r|Ab|Am); | ||
| 893 | |||
| 894 | r = csr8r(ctlr, Tcr) & ~(RtsfMASK|Ofset|Lb1|Lb0); | ||
| 895 | csr8w(ctlr, Tcr, r); | ||
| 896 | |||
| 897 | /* | ||
| 898 | * Link management. | ||
| 899 | */ | ||
| 900 | if((ctlr->mii = malloc(sizeof(Mii))) == nil) | ||
| 901 | return -1; | ||
| 902 | ctlr->mii->mir = vt6102miimir; | ||
| 903 | ctlr->mii->miw = vt6102miimiw; | ||
| 904 | ctlr->mii->ctlr = ctlr; | ||
| 905 | |||
| 906 | if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){ | ||
| 907 | free(ctlr->mii); | ||
| 908 | ctlr->mii = nil; | ||
| 909 | return -1; | ||
| 910 | } | ||
| 911 | // print("oui %X phyno %d\n", phy->oui, phy->phyno); | ||
| 912 | USED(phy); | ||
| 913 | |||
| 914 | //miiane(ctlr->mii, ~0, ~0, ~0); | ||
| 915 | |||
| 916 | return 0; | ||
| 917 | } | ||
| 918 | |||
| 919 | static void | ||
| 920 | vt6102pci(void) | ||
| 921 | { | ||
| 922 | Pcidev *p; | ||
| 923 | Ctlr *ctlr; | ||
| 924 | int cls, port; | ||
| 925 | |||
| 926 | p = nil; | ||
| 927 | while(p = pcimatch(p, 0, 0)){ | ||
| 928 | if(p->ccrb != Pcibcnet || p->ccru != Pciscether) | ||
| 929 | continue; | ||
| 930 | |||
| 931 | switch((p->did<<16)|p->vid){ | ||
| 932 | default: | ||
| 933 | continue; | ||
| 934 | case (0x3065<<16)|0x1106: /* Rhine II */ | ||
| 935 | case (0x3106<<16)|0x1106: /* Rhine III */ | ||
| 936 | break; | ||
| 937 | } | ||
| 938 | |||
| 939 | port = p->mem[0].bar & ~0x01; | ||
| 940 | if(ioalloc(port, p->mem[0].size, 0, "vt6102") < 0){ | ||
| 941 | print("vt6102: port 0x%uX in use\n", port); | ||
| 942 | continue; | ||
| 943 | } | ||
| 944 | ctlr = malloc(sizeof(Ctlr)); | ||
| 945 | ctlr->port = port; | ||
| 946 | ctlr->pcidev = p; | ||
| 947 | ctlr->id = (p->did<<16)|p->vid; | ||
| 948 | if((cls = pcicfgr8(p, PciCLS)) == 0 || cls == 0xFF) | ||
| 949 | cls = 0x10; | ||
| 950 | ctlr->cls = cls*4; | ||
| 951 | if(ctlr->cls < sizeof(Ds)){ | ||
| 952 | print("vt6102: cls %d < sizeof(Ds)\n", ctlr->cls); | ||
| 953 | iofree(port); | ||
| 954 | free(ctlr); | ||
| 955 | continue; | ||
| 956 | } | ||
| 957 | ctlr->tft = Ctft64; | ||
| 958 | |||
| 959 | if(vt6102reset(ctlr)){ | ||
| 960 | iofree(port); | ||
| 961 | free(ctlr); | ||
| 962 | continue; | ||
| 963 | } | ||
| 964 | pcisetbme(p); | ||
| 965 | |||
| 966 | if(vt6102ctlrhead != nil) | ||
| 967 | vt6102ctlrtail->next = ctlr; | ||
| 968 | else | ||
| 969 | vt6102ctlrhead = ctlr; | ||
| 970 | vt6102ctlrtail = ctlr; | ||
| 971 | } | ||
| 972 | } | ||
| 973 | |||
| 974 | static int | ||
| 975 | vt6102pnp(Ether* edev) | ||
| 976 | { | ||
| 977 | Ctlr *ctlr; | ||
| 978 | |||
| 979 | if(vt6102ctlrhead == nil) | ||
| 980 | vt6102pci(); | ||
| 981 | |||
| 982 | /* | ||
| 983 | * Any adapter matches if no edev->port is supplied, | ||
| 984 | * otherwise the ports must match. | ||
| 985 | */ | ||
| 986 | for(ctlr = vt6102ctlrhead; ctlr != nil; ctlr = ctlr->next){ | ||
| 987 | if(ctlr->active) | ||
| 988 | continue; | ||
| 989 | if(edev->port == 0 || edev->port == ctlr->port){ | ||
| 990 | ctlr->active = 1; | ||
| 991 | break; | ||
| 992 | } | ||
| 993 | } | ||
| 994 | if(ctlr == nil) | ||
| 995 | return -1; | ||
| 996 | |||
| 997 | edev->ctlr = ctlr; | ||
| 998 | edev->port = ctlr->port; | ||
| 999 | edev->irq = ctlr->pcidev->intl; | ||
| 1000 | edev->tbdf = ctlr->pcidev->tbdf; | ||
| 1001 | edev->mbps = 100; | ||
| 1002 | memmove(edev->ea, ctlr->par, Eaddrlen); | ||
| 1003 | |||
| 1004 | /* | ||
| 1005 | * Linkage to the generic ethernet driver. | ||
| 1006 | */ | ||
| 1007 | edev->attach = vt6102attach; | ||
| 1008 | edev->transmit = vt6102transmit; | ||
| 1009 | edev->interrupt = vt6102interrupt; | ||
| 1010 | edev->ifstat = vt6102ifstat; | ||
| 1011 | edev->ctl = nil; | ||
| 1012 | |||
| 1013 | edev->arg = edev; | ||
| 1014 | edev->promiscuous = vt6102promiscuous; | ||
| 1015 | edev->multicast = vt6102multicast; | ||
| 1016 | |||
| 1017 | return 0; | ||
| 1018 | } | ||
| 1019 | |||
| 1020 | void | ||
| 1021 | ethervt6102link(void) | ||
| 1022 | { | ||
| 1023 | addethercard("vt6102", vt6102pnp); | ||
| 1024 | addethercard("rhine", vt6102pnp); | ||
| 1025 | } | ||
| @@ -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 | ||
| 92 | static Ctlr *ctlrhead, *ctlrtail; | 93 | static Ctlr *ctlrhead, *ctlrtail; |
| @@ -95,7 +96,7 @@ static void · 2 unmodified lines | |||
| 95 | wavelanpciscan(void) | 96 | wavelanpciscan(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 | else | 130 | else |
| @@ -104,6 +104,7 @@ void pcicfgw16(Pcidev*, int, int); · 103 unmodified lines | |||
| 104 | void pcicfgw32(Pcidev*, int, int); | 104 | void pcicfgw32(Pcidev*, int, int); |
| 105 | void pciclrbme(Pcidev*); | 105 | void pciclrbme(Pcidev*); |
| 106 | void pciclrioe(Pcidev*); | 106 | void pciclrioe(Pcidev*); |
| 107 | void pciclrmwi(Pcidev*); | ||
| 107 | int pcigetpms(Pcidev*); | 108 | int pcigetpms(Pcidev*); |
| 108 | void pcihinv(Pcidev*); | 109 | void pcihinv(Pcidev*); |
| 109 | uchar pciipin(Pcidev*, uchar); | 110 | uchar pciipin(Pcidev*, uchar); |
| @@ -144,7 +145,10 @@ ulong umbrwmalloc(ulong, int, int); · 34 unmodified lines | |||
| 144 | void umbrwfree(ulong, int); | 145 | void umbrwfree(ulong, int); |
| 145 | ulong upamalloc(ulong, int, int); | 146 | ulong upamalloc(ulong, int, int); |
| 146 | void upafree(ulong, int); | 147 | void upafree(ulong, int); |
| 148 | void upareserve(ulong, int); | ||
| 147 | void vectortable(void); | 149 | void vectortable(void); |
| 150 | void* vmap(ulong, int); | ||
| 151 | void vunmap(void*, int); | ||
| 148 | void wrmsr(ulong, ulong); | 152 | void wrmsr(ulong, ulong); |
| 149 | int xchgw(ushort*, int); | 153 | int xchgw(ushort*, int); |
| 150 | ulong kzeromap(ulong, ulong, int); | 154 | ulong kzeromap(ulong, ulong, int); |
| @@ -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 | ||
| @@ -95,7 +95,7 @@ enum { · 94 unmodified lines | |||
| 95 | /* | 95 | /* |
| 96 | * PCI support code. | 96 | * PCI support code. |
| 97 | */ | 97 | */ |
| 98 | enum { /* type 0 and type 1 pre-defined header */ | 98 | enum { /* 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 */ | ||
| 120 | enum { | ||
| 121 | Pcibcpci1 = 0, /* pci 1.0; no class codes defined */ | ||
| 122 | Pcibcstore = 1, /* mass storage */ | ||
| 123 | Pcibcnet = 2, /* network */ | ||
| 124 | Pcibcdisp = 3, /* display */ | ||
| 125 | Pcibcmmedia = 4, /* multimedia */ | ||
| 126 | Pcibcmem = 5, /* memory */ | ||
| 127 | Pcibcbridge = 6, /* bridge */ | ||
| 128 | Pcibccomm = 7, /* simple comms (e.g., serial) */ | ||
| 129 | Pcibcbasesys = 8, /* base system */ | ||
| 130 | Pcibcinput = 9, /* input */ | ||
| 131 | Pcibcdock = 0xa, /* docking stations */ | ||
| 132 | Pcibcproc = 0xb, /* processors */ | ||
| 133 | Pcibcserial = 0xc, /* serial bus (e.g., USB) */ | ||
| 134 | Pcibcwireless = 0xd, /* wireless */ | ||
| 135 | Pcibcintell = 0xe, /* intelligent i/o */ | ||
| 136 | Pcibcsatcom = 0xf, /* satellite comms */ | ||
| 137 | Pcibccrypto = 0x10, /* encryption/decryption */ | ||
| 138 | Pcibcdacq = 0x11, /* data acquisition & signal proc. */ | ||
| 139 | }; | ||
| 140 | |||
| 141 | /* ccru (sub-class code) values; common cases only */ | ||
| 142 | enum { | ||
| 143 | /* mass storage */ | ||
| 144 | Pciscscsi = 0, /* SCSI */ | ||
| 145 | Pciscide = 1, /* IDE (ATA) */ | ||
| 146 | |||
| 147 | /* network */ | ||
| 148 | Pciscether = 0, /* Ethernet */ | ||
| 149 | |||
| 150 | /* display */ | ||
| 151 | Pciscvga = 0, /* VGA */ | ||
| 152 | Pciscxga = 1, /* XGA */ | ||
| 153 | Pcisc3d = 2, /* 3D */ | ||
| 154 | |||
| 155 | /* bridges */ | ||
| 156 | Pcischostpci = 0, /* host/pci */ | ||
| 157 | Pciscpcicpci = 1, /* pci/pci */ | ||
| 158 | |||
| 159 | /* simple comms */ | ||
| 160 | Pciscserial = 0, /* 16450, etc. */ | ||
| 161 | Pciscmultiser = 1, /* multiport serial */ | ||
| 162 | |||
| 163 | /* serial bus */ | ||
| 164 | Pciscusb = 3, /* USB */ | ||
| 165 | }; | ||
| 166 | |||
| 119 | enum { /* type 0 pre-defined header */ | 167 | enum { /* 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 */ |
| @@ -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 | |||
| 572 | void | ||
| 573 | upareserve(ulong pa, int size) | ||
| 574 | { | ||
| 575 | ulong a; | ||
| 576 | |||
| 577 | a = mapalloc(&rmapupa, pa, size, 0); | ||
| 578 | if(a != pa){ | ||
| 579 | /* | ||
| 580 | * This can happen when we're using the E820 | ||
| 581 | * map, which might have already reserved some | ||
| 582 | * of the regions claimed by the pci devices. | ||
| 583 | */ | ||
| 584 | // print("upareserve: cannot reserve pa=%#.8lux size=%d\n", pa, size); | ||
| 585 | if(a != 0) | ||
| 586 | mapfree(&rmapupa, a, size); | ||
| 587 | } | ||
| 588 | } | ||
| @@ -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 | |||
| 323 | void* | ||
| 324 | vmap(ulong pa, int size) | ||
| 325 | { | ||
| 326 | pa = upamalloc(pa, size, 0); | ||
| 327 | if(pa == 0) | ||
| 328 | return nil; | ||
| 329 | return KADDR(pa); | ||
| 330 | } | ||
| 331 | |||
| 332 | void | ||
| 333 | vunmap(void *va, int size) | ||
| 334 | { | ||
| 335 | if(va != nil) | ||
| 336 | upafree(PADDR(va), size); | ||
| 337 | } | ||
| @@ -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; |
| @@ -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); |
| @@ -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 | ||
| 265 | long | 263 | long |
| @@ -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 | { |
| 180 | print("miistatus 1\n"); | 180 | print("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)){ |
| 186 | print("miistatus 2\n"); | 186 | print("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 | { |
| 220 | print("miistatus 3\n"); | 220 | print("miistatus: phy speed 0\n"); |
| 221 | return -1; | 221 | return -1; |
| 222 | } | 222 | } |
| 223 | 223 | ||
| @@ -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 routines | 10 | * mem routines |
| @@ -123,6 +123,7 @@ extern char end[]; · 112 unmodified lines | |||
| 123 | extern int getfields(char*, char**, int, int, char*); | 123 | extern int getfields(char*, char**, int, int, char*); |
| 124 | extern int tokenize(char*, char**, int); | 124 | extern int tokenize(char*, char**, int); |
| 125 | extern int dec64(uchar*, int, char*, int); | 125 | extern int dec64(uchar*, int, char*, int); |
| 126 | extern void qsort(void*, long, long, int (*)(void*, void*)); | ||
| 126 | 127 | ||
| 127 | extern int toupper(int); | 128 | extern int toupper(int); |
| 128 | extern char* netmkaddr(char*, char*, char*); | 129 | extern char* netmkaddr(char*, char*, char*); |