📄 ether2114x.c
字号:
}while((data & 0x80000000) && --i); if(i == 0) return -1; return data & 0xFFFF; } /* * Preamble; * ST+OP+PHYAD+REGAD; * TA + 16 data bits. */ miimdo(ctlr, 0xFFFFFFFF, 32); miimdo(ctlr, 0x1800|(phyad<<5)|regad, 14); data = miimdi(ctlr, 18); if(data & 0x10000) return -1; return data & 0xFFFF;}static voidmiiw(Ctlr* ctlr, int phyad, int regad, int data){ /* * Preamble; * ST+OP+PHYAD+REGAD+TA + 16 data bits; * Z. */ miimdo(ctlr, 0xFFFFFFFF, 32); data &= 0xFFFF; data |= (0x05<<(5+5+2+16))|(phyad<<(5+2+16))|(regad<<(2+16))|(0x02<<16); miimdo(ctlr, data, 32); csr9w(ctlr, Mdc); csr9w(ctlr, 0);}static intsromr(Ctlr* ctlr, int r){ int i, op, data, size; if(ctlr->id == Pnic){ i = 1000; csr32w(ctlr, 19, 0x600|r); do{ microdelay(1); data = csr32r(ctlr, 19); }while((data & 0x80000000) && --i); if(ctlr->sromsz == 0) ctlr->sromsz = 6; return csr32r(ctlr, 9) & 0xFFFF; } /* * This sequence for reading a 16-bit register 'r' * in the EEPROM is taken (pretty much) straight from Section * 7.4 of the 21140 Hardware Reference Manual. */reread: csr9w(ctlr, Rd|Ss); csr9w(ctlr, Rd|Ss|Scs); csr9w(ctlr, Rd|Ss|Sclk|Scs); csr9w(ctlr, Rd|Ss); op = 0x06; for(i = 3-1; i >= 0; i--){ data = Rd|Ss|(((op>>i) & 0x01)<<2)|Scs; csr9w(ctlr, data); csr9w(ctlr, data|Sclk); csr9w(ctlr, data); } /* * First time through must work out the EEPROM size. * This doesn't seem to work on the 21041 as implemented * in Virtual PC for the Mac, so wire any 21041 to 6, * it's the only 21041 this code will ever likely see. */ if((size = ctlr->sromsz) == 0){ if(ctlr->id == Tulip1) ctlr->sromsz = size = 6; else size = 8; } for(size = size-1; size >= 0; size--){ data = Rd|Ss|(((r>>size) & 0x01)<<2)|Scs; csr9w(ctlr, data); csr9w(ctlr, data|Sclk); csr9w(ctlr, data); microdelay(1); if(ctlr->sromsz == 0 && !(csr32r(ctlr, 9) & Sdo)) break; } data = 0; for(i = 16-1; i >= 0; i--){ csr9w(ctlr, Rd|Ss|Sclk|Scs); if(csr32r(ctlr, 9) & Sdo) data |= (1<<i); csr9w(ctlr, Rd|Ss|Scs); } csr9w(ctlr, 0); if(ctlr->sromsz == 0){ ctlr->sromsz = 8-size; goto reread; } return data & 0xFFFF;}static voidsoftreset(Ctlr* ctlr){ /* * Soft-reset the controller and initialise bus mode. * Delay should be >= 50 PCI cycles (2×S @ 25MHz). */ csr32w(ctlr, 0, Swr); microdelay(10); csr32w(ctlr, 0, Rml|Cal16); delay(1);}static inttype5block(Ctlr* ctlr, uchar* block){ int csr15, i, len; /* * Reset or GPR sequence. Reset should be once only, * before the GPR sequence. * Note 'block' is not a pointer to the block head but * a pointer to the data in the block starting at the * reset length value so type5block can be used for the * sequences contained in type 1 and type 3 blocks. * The SROM docs state the 21140 type 5 block is the * same as that for the 21143, but the two controllers * use different registers and sequence-element lengths * so the 21140 code here is a guess for a real type 5 * sequence. */ len = *block++; if(ctlr->id != Tulip3){ for(i = 0; i < len; i++){ csr32w(ctlr, 12, *block); block++; } return len; } for(i = 0; i < len; i++){ csr15 = *block++<<16; csr15 |= *block++<<24; csr32w(ctlr, 15, csr15); debug("%8.8uX ", csr15); } return 2*len;}static inttypephylink(Ctlr* ctlr, uchar*){ int an, bmcr, bmsr, csr6, x; /* * Fail if * auto-negotiataion enabled but not complete; * no valid link established. */ bmcr = miir(ctlr, ctlr->curphyad, Bmcr); miir(ctlr, ctlr->curphyad, Bmsr); bmsr = miir(ctlr, ctlr->curphyad, Bmsr); debug("bmcr 0x%2.2uX bmsr 0x%2.2uX\n", bmcr, bmsr); if(((bmcr & 0x1000) && !(bmsr & 0x0020)) || !(bmsr & 0x0004)) return 0; if(bmcr & 0x1000){ an = miir(ctlr, ctlr->curphyad, Anar); an &= miir(ctlr, ctlr->curphyad, Anlpar) & 0x3E0; debug("an 0x%2.uX 0x%2.2uX 0x%2.2uX\n", miir(ctlr, ctlr->curphyad, Anar), miir(ctlr, ctlr->curphyad, Anlpar), an); if(an & 0x0100) x = 0x4000; else if(an & 0x0080) x = 0x2000; else if(an & 0x0040) x = 0x1000; else if(an & 0x0020) x = 0x0800; else x = 0; } else if((bmcr & 0x2100) == 0x2100) x = 0x4000; 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; } else if(bmcr & 0x0100) x = 0x1000; else x = 0x0800; csr6 = Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb; if(ctlr->fdx & x) csr6 |= Fd; if(ctlr->ttm & x) csr6 |= Ttm; debug("csr6 0x%8.8uX 0x%8.8uX 0x%8.8luX\n", csr6, ctlr->csr6, csr32r(ctlr, 6)); if(csr6 != ctlr->csr6){ ctlr->csr6 = csr6; csr32w(ctlr, 6, csr6); } return 1;}static inttypephymode(Ctlr* ctlr, uchar* block, int wait){ uchar *p; int len, mc, nway, phyx, timeo; if(DEBUG){ int i; len = (block[0] & ~0x80)+1; for(i = 0; i < len; i++) debug("%2.2uX ", block[i]); debug("\n"); } if(block[1] == 1) len = 1; else if(block[1] == 3) len = 2; else return -1; /* * Snarf the media capabilities, nway advertisment, * FDX and TTM bitmaps. */ p = &block[5+len*block[3]+len*block[4+len*block[3]]]; mc = *p++; mc |= *p++<<8; nway = *p++; nway |= *p++<<8; ctlr->fdx = *p++; ctlr->fdx |= *p++<<8; ctlr->ttm = *p++; ctlr->ttm |= *p<<8; debug("mc %4.4uX nway %4.4uX fdx %4.4uX ttm %4.4uX\n", mc, nway, ctlr->fdx, ctlr->ttm); USED(mc); phyx = block[2]; ctlr->curphyad = ctlr->phy[phyx]; ctlr->csr6 = 0;//Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb; //csr32w(ctlr, 6, ctlr->csr6); if(typephylink(ctlr, block)) return 0; if(!(ctlr->phyreset & (1<<phyx))){ debug("reset seq: len %d: ", block[3]); if(ctlr->type5block) type5block(ctlr, &ctlr->type5block[2]); else type5block(ctlr, &block[4+len*block[3]]); debug("\n"); ctlr->phyreset |= (1<<phyx); } /* * GPR sequence. */ debug("gpr seq: len %d: ", block[3]); type5block(ctlr, &block[3]); debug("\n"); ctlr->csr6 = 0;//Sc|Mbo|Hbd|Ps|Ca|TrMODE|Sb; //csr32w(ctlr, 6, ctlr->csr6); if(typephylink(ctlr, block)) return 0; /* * Turn off auto-negotiation, set the auto-negotiation * advertisment register then start the auto-negotiation * process again. */ miiw(ctlr, ctlr->curphyad, Bmcr, 0); miiw(ctlr, ctlr->curphyad, Anar, nway|1); miiw(ctlr, ctlr->curphyad, Bmcr, 0x1000); if(!wait) return 0; for(timeo = 0; timeo < 30; timeo++){ if(typephylink(ctlr, block)) return 0; delay(100); } return -1;}static inttypesymmode(Ctlr *ctlr, uchar *block, int wait){ uint gpmode, gpdata, command; USED(wait); gpmode = block[3] | ((uint) block[4] << 8); gpdata = block[5] | ((uint) block[6] << 8); command = (block[7] | ((uint) block[8] << 8)) & 0x71; if (command & 0x8000) { print("ether2114x.c: FIXME: handle type 4 mode blocks where cmd.active_invalid != 0\n"); return -1; } csr32w(ctlr, 15, gpmode); csr32w(ctlr, 15, gpdata); ctlr->csr6 = (command & 0x71) << 18; csr32w(ctlr, 6, ctlr->csr6); return 0;}static inttype2mode(Ctlr* ctlr, uchar* block, int){ uchar *p; int csr6, csr13, csr14, csr15, gpc, gpd; csr6 = Sc|Mbo|Ca|TrMODE|Sb; debug("type2mode: medium 0x%2.2uX\n", block[2]); /* * Don't attempt full-duplex * unless explicitly requested. */ if((block[2] & 0x3F) == 0x04){ /* 10BASE-TFD */ if(!ctlr->fd) return -1; csr6 |= Fd; } /* * Operating mode programming values from the datasheet * unless media specific data is explicitly given. */ p = &block[3]; if(block[2] & 0x40){ csr13 = (block[4]<<8)|block[3]; csr14 = (block[6]<<8)|block[5]; csr15 = (block[8]<<8)|block[7]; p += 6; } else switch(block[2] & 0x3F){ default: return -1; case 0x00: /* 10BASE-T */ csr13 = 0x00000001; csr14 = 0x00007F3F; csr15 = 0x00000008; break; case 0x01: /* 10BASE-2 */ csr13 = 0x00000009; csr14 = 0x00000705; csr15 = 0x00000006; break; case 0x02: /* 10BASE-5 (AUI) */ csr13 = 0x00000009; csr14 = 0x00000705; csr15 = 0x0000000E; break; case 0x04: /* 10BASE-TFD */ csr13 = 0x00000001; csr14 = 0x00007F3D; csr15 = 0x00000008; break; } gpc = *p++<<16; gpc |= *p++<<24; gpd = *p++<<16; gpd |= *p<<24; csr32w(ctlr, 13, 0); csr32w(ctlr, 14, csr14); csr32w(ctlr, 15, gpc|csr15); delay(10); csr32w(ctlr, 15, gpd|csr15); csr32w(ctlr, 13, csr13); ctlr->csr6 = csr6; csr32w(ctlr, 6, ctlr->csr6); debug("type2mode: csr13 %8.8uX csr14 %8.8uX csr15 %8.8uX\n", csr13, csr14, csr15); debug("type2mode: gpc %8.8uX gpd %8.8uX csr6 %8.8uX\n", gpc, gpd, csr6); return 0;}static inttype0link(Ctlr* ctlr, uchar* block){ int m, polarity, sense; m = (block[3]<<8)|block[2]; sense = 1<<((m & 0x000E)>>1); if(m & 0x0080) polarity = sense; else polarity = 0; return (csr32r(ctlr, 12) & sense)^polarity;}static inttype0mode(Ctlr* ctlr, uchar* block, int wait){ int csr6, m, timeo; csr6 = Sc|Mbo|Hbd|Ca|TrMODE|Sb;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]){ default: break; case 0x04: /* 10BASE-TFD */ case 0x05: /* 100BASE-TXFD */ case 0x08: /* 100BASE-FXFD */ /* * Don't attempt full-duplex * unless explicitly requested. */ if(!ctlr->fd) return -1; csr6 |= Fd; break; } m = (block[3]<<8)|block[2]; if(m & 0x0001) csr6 |= Ps; if(m & 0x0010) csr6 |= Ttm; if(m & 0x0020) csr6 |= Pcs; if(m & 0x0040) csr6 |= Scr; csr32w(ctlr, 12, block[1]); microdelay(10); csr32w(ctlr, 6, csr6); ctlr->csr6 = csr6; if(!wait) return 0; for(timeo = 0; timeo < 30; timeo++){ if(type0link(ctlr, block)) return 0; delay(100); } return -1;}static intmedia21041(Ether* ether, int wait){ Ctlr* ctlr; uchar *block; int csr6, csr13, csr14, csr15, medium, timeo; ctlr = ether->ctlr; block = ctlr->infoblock[ctlr->curk]; debug("media21041: block[0] %2.2uX, medium %4.4uX sct %4.4uX\n", block[0], ctlr->medium, ctlr->sct); medium = block[0] & 0x3F; if(ctlr->medium >= 0 && medium != ctlr->medium) return 0; if(ctlr->sct != 0x0800 && (ctlr->sct & 0x3F) != medium) return 0; csr6 = Sc|Mbo|Ca|TrMODE|Sb; if(block[0] & 0x40){ csr13 = (block[2]<<8)|block[1]; csr14 = (block[4]<<8)|block[3]; csr15 = (block[6]<<8)|block[5]; } else switch(medium){ default: return -1; case 0x00: /* 10BASE-T */ csr13 = 0xEF01; csr14 = 0xFF3F; csr15 = 0x0008; break; case 0x01: /* 10BASE-2 */ csr13 = 0xEF09; csr14 = 0xF73D; csr15 = 0x0006; break; case 0x02: /* 10BASE-5 */ csr13 = 0xEF09; csr14 = 0xF73D; csr15 = 0x000E; break; case 0x04: /* 10BASE-TFD */ csr13 = 0xEF01; csr14 = 0xFF3D; csr15 = 0x0008; break; } csr32w(ctlr, 13, 0); csr32w(ctlr, 14, csr14); csr32w(ctlr, 15, csr15); csr32w(ctlr, 13, csr13); delay(10); if(medium == 0x04) csr6 |= Fd; ctlr->csr6 = csr6; csr32w(ctlr, 6, ctlr->csr6); debug("media21041: csr6 %8.8uX csr13 %4.4uX csr14 %4.4uX csr15 %4.4uX\n", csr6, csr13, csr14, csr15); if(!wait) return 0; for(timeo = 0; timeo < 30; timeo++){ if(!(csr32r(ctlr, 12) & 0x0002)){ debug("media21041: ok: csr12 %4.4luX timeo %d\n", csr32r(ctlr, 12), timeo); return 10;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -