| plan 9 kernel history: overview | file list | diff list |
2000/0401/alphapc/ether2114x.c (diff list | history)
| 2000/0401/sys/src/9/alphapc/ether2114x.c:19,45 – 2001/0403/sys/src/9/alphapc/ether2114x.c:19,48 (short | long | prev | next) | ||
| 1999/0422 | #include "etherif.h" | |
| 2001/0403 | #define DEBUG (1) | |
| 1999/0422 | #define debug if(DEBUG)print enum { Nrde = 64, Ntde = 64, | |
| 2000/0125 |
| |
| 1999/0422 | }; | |
| 2001/0403 | #define Rbsz ROUNDUP(sizeof(Etherpkt)+4, 4) | |
| 1999/0422 | enum { /* CRS0 - Bus Mode */ Swr = 0x00000001, /* Software Reset */ Bar = 0x00000002, /* Bus Arbitration */ | |
| 2001/0403 | DslMASK = 0x0000007C, /* Descriptor Skip Length */ DslSHIFT = 2, | |
| 1999/0422 | Ble = 0x00000080, /* Big/Little Endian */ | |
| 2001/0403 | PblMASK = 0x00003F00, /* Programmable Burst Length (field) */ PblSHIFT = 8, | |
| 1999/0422 | Cal = 0x0000C000, /* Cache Alignment (field) */ Cal8 = 0x00004000, /* 8 longword boundary alignment */ Cal16 = 0x00008000, /* 16 longword boundary alignment */ Cal32 = 0x0000C000, /* 32 longword boundary alignment */ | |
| 2001/0403 | TapMASK = 0x000E0000, /* Transmit Automatic Polling */ TapSHIFT = 17, | |
| 1999/0422 | Dbo = 0x00100000, /* Descriptor Byte Ordering Mode */ Rml = 0x00200000, /* Read Multiple */ }; | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:183,188 – 2001/0403/sys/src/9/alphapc/ether2114x.c:186,198 | ||
| 1999/0422 | Aner = 6, /* Auto-Negotiation Expansion */ }; | |
| 2001/0403 | enum { /* Variants */ Tulip0 = (0x0009<<16)|0x1011, Tulip3 = (0x0019<<16)|0x1011, Pnic = (0x0002<<16)|0x11AD, Pnic2 = (0xC115<<16)|0x11AD, }; | |
| 1999/0422 | typedef struct Ctlr Ctlr; typedef struct Ctlr { int port; | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:189,194 – 2001/0403/sys/src/9/alphapc/ether2114x.c:199,205 | ||
| 1999/0422 | Pcidev* pcidev; Ctlr* next; int active; | |
| 2001/0403 | int id; /* (pcidev->did<<16)|pcidev->vid */ | |
| 1999/0422 | uchar srom[128]; uchar* sromea; /* MAC address */ | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:457,463 – 2001/0403/sys/src/9/alphapc/ether2114x.c:468,474 | ||
| 1999/0422 | if(des->status & De) ctlr->de++; } | |
| 2000/0125 |
| |
| 2001/0403 | else if(bp = iallocb(Rbsz)){ | |
| 1999/0422 | len = ((des->status & Fl)>>16)-4; des->bp->wp = des->bp->rp+len; etheriq(ether, des->bp, 1); | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:466,472 – 2001/0403/sys/src/9/alphapc/ether2114x.c:477,483 | ||
| 1999/0422 | } des->control &= Er; | |
| 2000/0125 |
| |
| 2001/0403 | des->control |= Rbsz; | |
| 1999/0422 | coherence(); des->status = Own; | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:566,576 – 2001/0403/sys/src/9/alphapc/ether2114x.c:577,587 | ||
| 1999/0422 | * create and post a setup packet to initialise * the physical ethernet address. */ | |
| 2000/0125 |
| |
| 2001/0403 | ctlr->rdr = malloc(ctlr->nrdr*sizeof(Des)); | |
| 1999/0422 | for(des = ctlr->rdr; des < &ctlr->rdr[ctlr->nrdr]; des++){ | |
| 2000/0125 |
| |
| 2001/0403 | des->bp = allocb(Rbsz); | |
| 1999/0422 | des->status = Own; | |
| 2000/0125 |
| |
| 2001/0403 | des->control = Rbsz; | |
| 1999/0423 | des->addr = PCIWADDR(des->bp->rp); | |
| 1999/0422 | } ctlr->rdr[ctlr->nrdr-1].control |= Er; | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:583,589 – 2001/0403/sys/src/9/alphapc/ether2114x.c:594,605 | ||
| 1999/0422 | ctlr->tdri = 0; | |
| 1999/0423 | csr32w(ctlr, 4, PCIWADDR(ctlr->tdr)); | |
| 1999/0422 | ||
| 2001/0403 | /* * Clear any bits in the Status Register (CSR5) as * the PNIC has a different reset value from a true 2114x. */ | |
| 1999/0422 | ctlr->mask = Nis|Ais|Fbe|Rwt|Rps|Ru|Ri|Unf|Tjt|Tps|Ti; | |
| 2001/0403 | csr32w(ctlr, 5, ctlr->mask); | |
| 1999/0422 | csr32w(ctlr, 7, ctlr->mask); ctlr->csr6 |= St; csr32w(ctlr, 6, ctlr->csr6); | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:654,661 – 2001/0403/sys/src/9/alphapc/ether2114x.c:670,690 | ||
| 1999/0422 | static int miir(Ctlr* ctlr, int phyad, int regad) { | |
| 2001/0403 | int data, i; | |
| 1999/0422 | ||
| 2001/0403 | if(ctlr->id == Pnic){ i = 1000; csr32w(ctlr, 20, 0x60020000|(phyad<<23)|(regad<<18)); do{ microdelay(1); data = csr32r(ctlr, 20); }while((data & 0x80000000) && --i); if(i == 0) return -1; return data & 0xFFFF; } | |
| 1999/0422 | /* * Preamble; * ST+OP+PHYAD+REGAD; | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:692,697 – 2001/0403/sys/src/9/alphapc/ether2114x.c:721,737 | ||
| 1999/0422 | { int i, op, data; | |
| 2001/0403 | if(ctlr->id == Pnic){ i = 1000; csr32w(ctlr, 19, 0x600|r); do{ microdelay(1); data = csr32r(ctlr, 19); }while((data & 0x80000000) && --i); return csr32r(ctlr, 9) & 0xFFFF; } | |
| 1999/0422 | /* * This sequence for reading a 16-bit register 'r' * in the EEPROM is taken straight from Section | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:739,745 – 2001/0403/sys/src/9/alphapc/ether2114x.c:779,785 | ||
| 1999/0422 | */ csr32w(ctlr, 0, Swr); microdelay(10); | |
| 2001/0403 | csr32w(ctlr, 0, Rml|Cal16|(32<<PblSHIFT)); | |
| 1999/0422 | delay(1); } | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:762,768 – 2001/0403/sys/src/9/alphapc/ether2114x.c:802,808 | ||
| 1999/0422 | * sequence. */ len = *block++; | |
| 2001/0403 | if(ctlr->id != Tulip3){ | |
| 1999/0422 | for(i = 0; i < len; i++){ csr32w(ctlr, 12, *block); block++; | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:817,824 – 2001/0403/sys/src/9/alphapc/ether2114x.c:857,873 | ||
| 1999/0422 | } else if((bmcr & 0x2100) == 0x2100) x = 0x4000; | |
| 2001/0403 | else if(bmcr & 0x2000){ /* * If FD capable, force it if necessary. */ if((bmsr & 0x4000) && ctlr->fd){ miiw(ctlr, ctlr->curphyad, Bmcr, 0x2100); x = 0x4000; } else x = 0x2000; } | |
| 1999/0422 | else if(bmcr & 0x0100) x = 0x1000; else | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:949,955 – 2001/0403/sys/src/9/alphapc/ether2114x.c:998,1005 | ||
| 1999/0422 | { int csr6, m, timeo; | |
| 2001/0403 | // csr6 = Sc|Mbo|Hbd|Ca|Sb|TrMODE; csr6 = Mbo|Hbd|Sb|TrMODE; | |
| 1999/0422 | debug("type0: medium 0x%uX, fd %d: 0x%2.2uX 0x%2.2uX 0x%2.2uX 0x%2.2uX\n", ctlr->medium, ctlr->fd, block[0], block[1], block[2], block[3]); switch(block[0]){ | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:1132,1137 – 2001/0403/sys/src/9/alphapc/ether2114x.c:1182,1211 | ||
| 1999/0422 | nil, }; | |
| 2001/0403 | /* * Copied to ctlr->srom at offset 20. */ static uchar leafpnic[] = { 0x00, 0x00, 0x00, 0x00, /* MAC address */ 0x00, 0x00, 0x00, /* controller 0 device number */ 0x1E, 0x00, /* controller 0 info leaf offset */ 0x00, /* reserved */ 0x00, 0x08, /* selected connection type */ 0x00, /* general purpose control */ 0x01, /* block count */ 0x8C, /* format indicator and count */ 0x01, /* block type */ 0x00, /* PHY number */ 0x00, /* GPR sequence length */ 0x00, /* reset sequence length */ 0x00, 0x78, /* media capabilities */ 0xE0, 0x01, /* Nway advertisment */ 0x00, 0x50, /* FDX bitmap */ 0x00, 0x18, /* TTM bitmap */ }; | |
| 1999/0422 | static int srom(Ctlr* ctlr) { | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:1173,1178 – 2001/0403/sys/src/9/alphapc/ether2114x.c:1247,1265 | ||
| 1999/0422 | } /* | |
| 2001/0403 | * Fake up the SROM for the PNIC. * It looks like a 21140 with a PHY. * The MAC address is byte-swapped in the orginal SROM data. */ if(ctlr->id == Pnic){ memmove(&ctlr->srom[20], leafpnic, sizeof(leafpnic)); for(i = 0; i < Eaddrlen; i += 2){ ctlr->srom[20+i] = ctlr->srom[i+1]; ctlr->srom[20+i+1] = ctlr->srom[i]; } } /* | |
| 1999/0422 | * Next, try to find the info leaf in the SROM for media detection. * If it's a non-conforming card try to match the vendor ethernet code * and point p at a fake info leaf with compact 21140 entries. | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:1205,1211 – 2001/0403/sys/src/9/alphapc/ether2114x.c:1292,1298 | ||
| 1999/0422 | ctlr->leaf = p; ctlr->sct = *p++; ctlr->sct |= *p++<<8; | |
| 2001/0403 | if(ctlr->id != Tulip3){ | |
| 1999/0422 | csr32w(ctlr, 12, Gpc|*p++); delay(200); } | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:1220,1226 – 2001/0403/sys/src/9/alphapc/ether2114x.c:1307,1313 | ||
| 1999/0422 | * The RAMIX PMC665 has a badly-coded SROM, * hence the test for 21143 and type 3. */ | |
| 2001/0403 | if((*p & 0x80) || (ctlr->id == Tulip3 && *(p+1) == 3)){ | |
| 1999/0422 | *p |= 0x80; if(*(p+1) == 1 || *(p+1) == 3) phy = 1; | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:1271,1282 – 2001/0403/sys/src/9/alphapc/ether2114x.c:1358,1371 | ||
| 1999/0422 | int x; p = nil; | |
| 2001/0403 | while(p = pcimatch(p, 0, 0)){ if(p->ccrb != 0x02 || p->ccru != 0) continue; switch((p->did<<16)|p->vid){ | |
| 1999/0422 | default: continue; | |
| 2001/0403 | case Tulip3: /* 21143 */ | |
| 1999/0422 | /* * Exit sleep mode. */ | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:1285,1291 – 2001/0403/sys/src/9/alphapc/ether2114x.c:1374,1382 | ||
| 1999/0422 | pcicfgw32(p, 0x40, x); /*FALLTHROUGH*/ | |
| 2001/0403 | case Pnic: /* PNIC */ case Pnic2: /* PNIC-II */ case Tulip0: /* 21140 */ | |
| 1999/0422 | break; } | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:1296,1304 – 2001/0403/sys/src/9/alphapc/ether2114x.c:1387,1396 | ||
| 1999/0422 | ctlr = malloc(sizeof(Ctlr)); ctlr->port = p->mem[0].bar & ~0x01; ctlr->pcidev = p; | |
| 2001/0403 | ctlr->id = (p->did<<16)|p->vid; | |
| 1999/0422 | ||
| 2000/0401 | if(ioalloc(ctlr->port, p->mem[0].size, 0, "dec2114x") < 0){ | |
| 2001/0403 | print("dec2114x: port 0x%uX in use\n", ctlr->port); | |
| 2000/0401 | free(ctlr); continue; } | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:1312,1318 – 2001/0403/sys/src/9/alphapc/ether2114x.c:1404,1423 | ||
| 1999/0422 | softreset(ctlr); if(srom(ctlr)){ | |
| 2001/0403 | iofree(ctlr->port); | |
| 1999/0422 | free(ctlr); | |
| 2001/0403 | continue; } switch(ctlr->id){ default: // break; // // case Pnic: /* PNIC */ /* * Turn off the jabber timer. */ csr32w(ctlr, 15, 0x00000001); | |
| 1999/0422 | break; } | |
| 2000/0401/sys/src/9/alphapc/ether2114x.c:1424,1428 – 2001/0403/sys/src/9/alphapc/ether2114x.c:1529,1534 | ||
| 1999/0422 | void ether2114xlink(void) { | |
| 2001/0403 | addethercard("21140", reset); | |
| 1999/0507 | addethercard("2114x", reset); | |
| 1999/0422 | } | |