1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
45:
46: 47: 48: 49:
50:
51: #include "netdrv.h"
52:
53: 54: 55: 56:
57: 58: 59:
60: EXPORT ER AllocMem(W sz, VP *p)
61: {
62: T_RSMB msts;
63:
64: if (tk_ref_smb(&msts) >= E_OK) {
65: sz = (sz + msts.blksz - 1) / msts.blksz;
66: return tk_get_smb(p, sz, TA_RNG0);
67: }
68: return E_NOMEM;
69: }
70:
71: 72: 73:
74: EXPORT void FreeMem(VP p)
75: {
76: if (p != NULL) tk_rel_smb(p);
77: }
78: 79: 80:
81: 82: 83:
84: EXPORT ER SetRxBuf(NetInf *inf, VP bp)
85: {
86: UW imsk;
87:
88: if (bp == NULL) {
89: DI(imsk);
90: inf->ip_rxbuf = inf->op_rxbuf = 0;
91: EI(imsk);
92: } else {
93: if (inf->ip_rxbuf - inf->op_rxbuf >= N_RXBUF) return E_BUSY;
94: inf->rxbuf[inf->ip_rxbuf % N_RXBUF] = bp;
95: inf->ip_rxbuf++;
96: }
97: return E_OK;
98: }
99:
100: 101: 102:
103: EXPORT VP GetRxBuf(NetInf *inf)
104: {
105: if (inf->ip_rxbuf == inf->op_rxbuf) return NULL;
106: return inf->rxbuf[(inf->op_rxbuf++) % N_RXBUF];
107: }
108: 109: 110:
111: 112: 113:
114: EXPORT ER SendMsg(NetInf *inf, VP bp, W len)
115: {
116: ER er;
117: NetEvent evt;
118:
119: evt.buf = bp;
120: evt.len = len;
121:
122:
123: er = tk_snd_mbf(inf->mbfid, &evt, sizeof(evt), TMO_POL);
124: if (bp != NULL) {
125: if (er >= E_OK) inf->stinf.rxpkt++;
126: else {
127: inf->stinf.misspkt++;
128: SetRxBuf(inf, bp);
129: }
130: }
131: return er;
132: }
133: 134: 135:
136: 137: 138:
139: #define BMCR_RESET (1 << 15)
140: #define BMCR_SPEED0 (1 << 13)
141: #define BMCR_ANEG (1 << 12)
142: #define BMCR_PDN (1 << 11)
143: #define BMCR_ISOLATE (1 << 10)
144: #define BMCR_RANEG (1 << 9)
145: #define BMCR_FDX (1 << 8)
146: #define BMCR_SPEED1 (1 << 6)
147:
148: #define BMSR_GB (1 << 8)
149:
150: #define ANAR_TX_FD (1 << 8)
151: #define ANAR_TX_HD (1 << 7)
152: #define ANAR_10_FD (1 << 6)
153: #define ANAR_10_HD (1 << 5)
154:
155: #define GBCR_1000T_FD (1 << 9)
156: #define GBCR_1000T_HD (1 << 8)
157:
158: #define peek_mii(inf, adr, reg) (*inf->mii_read) ((inf), (adr), (reg))
159: #define poke_mii(inf, adr, reg, dat) \
160: (*inf->mii_write)((inf), (adr), (reg), (dat))
161: 162: 163:
164: EXPORT INT MIIfind(NetInf *inf, W target)
165: {
166: W i, adr, reg, val, prev;
167:
168: if (inf->mii_read == NULL || inf->mii_write == NULL) return E_NOMDA;
169:
170: for (i = 0; i < 32; i++) {
171: 172:
173: adr = (i + target) & 31;
174: prev = peek_mii(inf, adr, 0);
175: for (reg = 1; reg < 32; reg++) {
176: val = peek_mii(inf, adr, reg);
177: if (val != prev) goto fin;
178: prev = val;
179: }
180: }
181: adr = E_NOMDA;
182: fin:
183: return adr;
184: }
185:
186: 187: 188:
189: EXPORT INT MIIinit(NetInf *inf, W target)
190: {
191: W adr, mii_reg0, mii_reg4, mii_reg9;
192: W i, bmcr, gbe;
193:
194: if (inf->mii_read == NULL || inf->mii_write == NULL) return E_NOMDA;
195:
196:
197: adr = MIIfind(inf, target);
198: if (adr < 0) {
199: DP(("MIIinit(): MII not found\n"));
200: goto fin;
201: }
202:
203: DP(("MIIinit(): MII found, address #%d\n", adr));
204:
205:
206: poke_mii(inf, adr, 0, BMCR_RESET);
207: for (i = 0; i < 2000; i++) {
208: WaitUsec(500);
209: bmcr = peek_mii(inf, adr, 0);
210: if (!(bmcr & BMCR_RESET)) break;
211: }
212: DP(("MIIinit(): MII reset: wait: %d count(s)\n", i + 1));
213:
214:
215: gbe = peek_mii(inf, adr, 1) & BMSR_GB;
216: DP(("MIIinit(): GbE %supported\n", gbe ? "" : "not "));
217:
218: 219: 220:
221: mii_reg0 = 0;
222: mii_reg4 = peek_mii(inf, adr, 4) &
223: ~(ANAR_TX_FD | ANAR_TX_HD | ANAR_10_FD | ANAR_10_HD);
224: mii_reg4 |= (peek_mii(inf, adr, 1) & 0x7800) >> 6;
225: if (gbe) {
226: mii_reg9 = peek_mii(inf, adr, 9) &
227: ~(GBCR_1000T_FD | GBCR_1000T_HD);
228: mii_reg9 |= (peek_mii(inf, adr, 15) & 0x2000) >> 4;
229: } else {
230: mii_reg9 = 0;
231: }
232:
233: switch (inf->di.ifconn = IFC_TYPE(inf)) {
234: case IFC_AUI:
235: case IFC_TPE:
236: case IFC_BNC:
237: if (isFDX(inf)) mii_reg0 |= BMCR_FDX;
238: break;
239: case IFC_100TX:
240: case IFC_100FX:
241: mii_reg0 |= BMCR_SPEED0;
242: if (isFDX(inf)) mii_reg0 |= BMCR_FDX;
243: break;
244: case IFC_1000T:
245:
246:
247:
248: default:
249: inf->di.ifconn = IFC_AUTO;
250: mii_reg0 |= BMCR_ANEG | BMCR_RANEG;
251: if (!isFDX(inf)) {
252: mii_reg4 &= ~(ANAR_TX_FD | ANAR_10_FD);
253: mii_reg9 &= ~(GBCR_1000T_FD);
254: }
255: break;
256: }
257:
258: if (gbe) poke_mii(inf, adr, 9, mii_reg9);
259: poke_mii(inf, adr, 4, mii_reg4);
260: poke_mii(inf, adr, 0, mii_reg0);
261:
262: #ifdef DEBUG
263: for (i = 0; i < 32; i++) printf("%04x%c", peek_mii(inf, adr, i),
264: ((i + 1) % 16) ? ' ' : '\n');
265: #endif
266:
267:
268: peek_mii(inf, adr, 1);
269:
270: fin:
271: return adr;
272: }
273: 274: 275:
276: 277: 278:
279: EXPORT void SetProdName(NetInf *inf, UB **nm1, UB **nm2)
280: {
281: W n;
282:
283: if (nm1 == NULL) n = 0;
284: else {
285: nm1 += (inf->devix >> 8) & 0x0f;
286: strncpy(inf->di.name, *nm1, L_NETPNAME);
287: n = strlen(*nm1);
288: }
289: if (n < L_NETPNAME) {
290: nm2 += inf->devix & 0xff;
291: strncpy(&inf->di.name[n], *nm2, L_NETPNAME - n);
292: }
293:
294: DP(("Net%c: '%.40s'\n", NetUnit(inf), inf->di.name));
295:
296: }
297:
298: 299: 300: 301: 302: 303: 304:
305: EXPORT UW CalcCRC32(UB *data, W len)
306: {
307: #define CRC_POLY 0x04c11db6
308:
309: UW crc, byteindex, addrbyte, bitindex, carry;
310:
311: crc = 0xffffffff;
312:
313: for (byteindex = 0; byteindex < len; byteindex++) {
314: addrbyte = data[byteindex];
315:
316: for (bitindex = 0; bitindex < 8; bitindex++) {
317: carry = (crc >> 31) ^ (addrbyte & 1);
318: crc <<= 1;
319:
320: if (carry) crc = (crc ^ CRC_POLY) | carry;
321:
322: addrbyte >>= 1;
323: }
324: }
325:
326: return crc;
327: }
328: