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