|
|
1.1 root 1: #ifndef LEBOOT
2: #ifndef lint
3: static char sccsid[] = "@(#)if_le.c 1.1 86/02/03 Copyr 1985 Sun Micro";
4: #endif
5: #endif
6:
7: /*
8: * Copyright (c) 1985 by Sun Microsystems, Inc.
9: */
10:
11: /*
12: * For Sun-3/25 debugging we want DEBUG on. For production, turn it off.
13: */
14: /* #define DEBUG */
15: /* #define DEBUG1 */
16:
17: #define LANCEBUG 1 /* Rev C Lance chip bug */
18:
19: /*
20: * Parameters controlling TIMEBOMB action: times out if chip hangs.
21: *
22: */
23: #define TIMEBOMB 1000000 /* One million times around is all... */
24:
25: /*
26: * Sun Lance Ethernet Controller interface
27: */
28: #include "saio.h"
29: #include "param.h"
30: #include "../h/socket.h"
31: #include "../sunif/if_lereg.h"
32: #include "../net/if.h"
33: #include "../netinet/in.h"
34: #include "../netinet/if_ether.h"
35: #include "../mon/idprom.h"
36: #include "../mon/cpu.map.h"
37:
38: /* Determine whether we are PROM or not. */
39: #ifdef LEBOOT
40: #define PROM
41: #endif LEBOOT
42:
43: int lancexmit(), lancepoll(), lancereset();
44:
45: struct saif leif = {
46: lancexmit,
47: lancepoll,
48: lancereset,
49: };
50:
51: #define LANCERBUFSIZ 1600
52: #define LANCETBUFSIZ 1600
53:
54: struct lance_softc {
55: char es_scrat[PROTOSCRATCH]; /* work space for nd */
56: struct le_device *es_lance; /* Device register address */
57: struct ether_addr es_enaddr; /* Our Ethernet address */
58: struct le_init_block es_ib; /* Initialization block */
59: struct le_md *es_rmdp[2]; /* Receive Desc Ring ptrs */
60: struct le_md *es_tmdp; /* Transmit Desc Ring ptr */
61: u_char es_rbuf[2][LANCERBUFSIZ]; /* Receive Buffers */
62: #ifndef PROM
63: u_char es_tbuf[LANCETBUFSIZ]; /* Transmit Buffer */
64: #endif PROM
65: int es_next_rmd; /* Next descriptor in ring */
66: /*
67: * The transmit and receive ring descriptors. The es_{r,t}mdp
68: * entries point into these arrays. We allocate an extra one of
69: * each so that we can guarantee 8-byte alignment. (That is, we
70: * don't necessarily point locations an integral number of le_mds
71: * from the start of the arrays.
72: */
73: struct le_md es_rmd[3],
74: es_tmd[2];
75: };
76:
77:
78: /*
79: * Need to initialize the Ethernet control reg to:
80: * Reset is active
81: * Loopback is NOT active
82: * Interrupt enable is not active.
83: */
84: u_long lancestd[] = {VIOPG_AMD_ETHER << BYTES_PG_SHIFT};
85:
86: struct devinfo lanceinfo = {
87: sizeof (struct le_device),
88: sizeof (struct lance_softc),
89: 0, /* Local bytes (we use dma) */
90: 1, /* Standard addr count */
91: lancestd, /* Standard addrs */
92: MAP_OBIO, /* Device type */
93: 0, /* transfer size handled by ND */
94: };
95:
96: int lanceprobe(), xxboot(), lanceopen(), lanceclose(), etherstrategy();
97: int nullsys();
98:
99: struct boottab ledriver = {
100: "le", lanceprobe, xxboot, lanceopen, lanceclose,
101: etherstrategy, "le: Sun/Lance Ethernet", &lanceinfo,
102: };
103:
104: extern struct ether_addr etherbroadcastaddr;
105:
106: /*
107: * Probe for device.
108: * Must return -1 for failure for monitor probe
109: */
110: lanceprobe(sip)
111: struct saioreq *sip;
112: {
113: register short *sp;
114: struct idprom id;
115:
116: if (IDFORM_1 == idprom(IDFORM_1, &id)
117: && id.id_machine == IDM_SUN3_M25)
118: return (0);
119: else
120: return (-1);
121: }
122:
123: /*
124: * Open Lance Ethernet nd connection, return -1 for errors.
125: */
126: lanceopen(sip)
127: struct saioreq *sip;
128: {
129: register int result;
130:
131: #ifdef DEBUG1
132: printf("le: lanceopen[\n");
133: #endif
134: sip->si_sif = &leif;
135: if ( lanceinit(sip) || (result = etheropen(sip)) < 0 ) {
136: lanceclose(sip); /* Make sure we kill chip */
137: #ifdef DEBUG1
138: printf("le: lanceopen --> -1\n");
139: #endif
140: return (-1);
141: }
142: #ifdef DEBUG1
143: printf("le: lanceopen --> %x\n", result);
144: #endif
145: return (result);
146: }
147:
148: /*
149: * Set up memory maps and Ethernet chip.
150: * Returns 1 for error (after printing message), 0 for ok.
151: */
152: int
153: lanceinit(sip)
154: struct saioreq *sip;
155: {
156: register struct lance_softc *es;
157: int paddr;
158: int i;
159: struct idprom id;
160:
161: /*
162: * Our locals were obtined from DMA space, now put the locals
163: * pointer in the standard place. This is OK since close()
164: * will only deallocate from devdata if its size in devinfo is >0.
165: */
166: es = (struct lance_softc *)sip->si_dmaaddr;
167: sip->si_devdata = (caddr_t)es;
168: es->es_lance = (struct le_device *) sip->si_devaddr;
169:
170: if (IDFORM_1 != idprom(IDFORM_1, &id)) {
171: printf("le: No ID PROM\n");
172: return 1;
173: }
174:
175: return lancereset(es, sip);
176: }
177:
178: /*
179: * Basic Lance initialization
180: * Returns 1 for error (after printing message), 0 for ok.
181: */
182: int
183: lancereset(es, sip)
184: register struct lance_softc *es;
185: struct saioreq *sip;
186: {
187: register struct le_device *le = es->es_lance;
188: register struct le_init_block *ib = &es->es_ib;
189: int timeout = TIMEBOMB;
190: int i;
191:
192: #ifdef DEBUG1
193: printf("le: lancereset(%x, %x)\n", es, sip);
194: #endif
195:
196: /* Reset the chip */
197: le->le_rap = LE_CSR0;
198: le->le_csr = LE_STOP;
199:
200: /* Perform the basic initialization */
201:
202: /* Construct the initialization block */
203: bzero((caddr_t)&es->es_ib, sizeof (struct le_init_block));
204:
205: /* Leave the mode word 0 for normal operating mode */
206:
207: myetheraddr(&es->es_enaddr);
208:
209: /* Oh, for a consistent byte ordering among processors */
210: ib->ib_padr[0] = es->es_enaddr.ether_addr_octet[1];
211: ib->ib_padr[1] = es->es_enaddr.ether_addr_octet[0];
212: ib->ib_padr[2] = es->es_enaddr.ether_addr_octet[3];
213: ib->ib_padr[3] = es->es_enaddr.ether_addr_octet[2];
214: ib->ib_padr[4] = es->es_enaddr.ether_addr_octet[5];
215: ib->ib_padr[5] = es->es_enaddr.ether_addr_octet[4];
216:
217: /* Leave address filter 0 -- we don't want Multicast packets */
218:
219: /*
220: * Set up transmit and receive ring pointers,
221: * taking the 8-byte alignment requirement into account.
222: */
223: es->es_rmdp[0] = (struct le_md *) ((u_long)(&es->es_rmd[0]) & ~07) + 1;
224: es->es_rmdp[1] = es->es_rmdp[0] + 1;
225: es->es_tmdp = (struct le_md *) ((u_long)(&es->es_tmd[0]) & ~07) + 1;
226:
227: ib->ib_rdrp.drp_laddr = (long)es->es_rmdp[0];
228: ib->ib_rdrp.drp_haddr = (long)es->es_rmdp[0] >> 16;
229: ib->ib_rdrp.drp_len = 1; /* 2 to the 1 power = 2 */
230:
231: ib->ib_tdrp.drp_laddr = (long)es->es_tmdp;
232: ib->ib_tdrp.drp_haddr = (long)es->es_tmdp >> 16;
233: ib->ib_tdrp.drp_len = 0; /* 2 to the 0 power = 1 */
234:
235: /* Clear all the descriptors */
236: bzero((caddr_t)es->es_rmdp[0], 2 * sizeof (struct le_md));
237: bzero((caddr_t)es->es_tmdp, sizeof (struct le_md));
238:
239: /* Give the init block to the chip */
240: le->le_rap = LE_CSR1; /* select the low address register */
241: le->le_rdp = (long)ib & 0xffff;
242:
243: le->le_rap = LE_CSR2; /* select the high address register */
244: le->le_rdp = ((long)ib >> 16) & 0xff;
245:
246: le->le_rap = LE_CSR3; /* Bus Master control register */
247: le->le_rdp = LE_BSWP;
248:
249: le->le_rap = LE_CSR0; /* main control/status register */
250: le->le_csr = LE_INIT;
251:
252: while( ! (le->le_csr & LE_IDON) ) {
253: if (timeout-- <= 0) {
254: printf("le: cannot initialize\n");
255: return (1);
256: }
257: }
258: le->le_csr = LE_IDON; /* Clear the indication */
259:
260: /* Hang out the receive buffers */
261: es->es_next_rmd = 0;
262:
263: install_buf_in_rmd(es->es_rbuf[0], es->es_rmdp[0]);
264: install_buf_in_rmd(es->es_rbuf[1], es->es_rmdp[1]);
265:
266: le->le_csr = LE_STRT;
267:
268: #ifdef DEBUG1
269: printf("le: lancereset returns OK\n");
270: #endif
271: return 0; /* It all worked! */
272: }
273:
274: install_buf_in_rmd(buffer, rmd)
275: u_char *buffer;
276: register struct le_md *rmd;
277: {
278: rmd->lmd_ladr = (u_short)buffer;
279: rmd->lmd_hadr = (long)buffer >> 16;
280: rmd->lmd_bcnt = -LANCERBUFSIZ;
281: rmd->lmd_mcnt = 0;
282: rmd->lmd_flags = LMD_OWN;
283: }
284:
285: /*
286: * Transmit a packet.
287: * If possible, just points to the packet without copying it anywhere.
288: */
289: lancexmit(es, buf, count)
290: register struct lance_softc *es;
291: char *buf;
292: int count;
293: {
294: register struct le_device *le = es->es_lance;
295: struct le_md *tmd = es->es_tmdp; /* Transmit Msg. Descriptor */
296: caddr_t tbuf;
297: int timeout = TIMEBOMB;
298:
299: #ifdef DEBUG2
300: printf( "xmit np_blkno %x\n",
301: ((struct ndpack *)(buf+14))->np_blkno);
302: #endif
303: /*
304: * We assume the buffer is in an area accessible by the chip.
305: * The caller of xmit is currently ndxmit(), which only sends
306: * an nd structure, which we happen to know is allocated in the
307: * right area (in fact, it's part of the struct nd which
308: * is the first thing in our own es structure). If we wish to
309: * use xmit for some other purpose, the buffer might not be
310: * accessible by the chip, so to be general we ought to copy
311: * into some accessible place. HOWEVER, PROM space is really tight,
312: * so this generality is not free.
313: */
314: #ifdef PROM
315: tbuf = buf;
316: #else PROM
317: /* FIXME, constant address masks here! */
318: if ( ((int)buf & 0x0F000000) == 0x0F000000) { /* we can point to it */
319: tbuf = buf;
320: } else {
321: tbuf = (caddr_t)es->es_tbuf;
322: bcopy((caddr_t)buf, tbuf, count);
323: }
324: #endif PROM
325:
326: tmd->lmd_hadr = (int)tbuf >> 16;
327: tmd->lmd_ladr = (u_short) tbuf;
328: tmd->lmd_bcnt = -count;
329:
330: #ifdef notdef
331: if (tmd->lmd_bcnt < -MINPACKET)
332: tmd->lmd_bcnt = -MINPACKET;
333: #endif
334: tmd->lmd_flags3 = 0;
335: tmd->lmd_flags = LMD_STP | LMD_ENP | LMD_OWN;
336:
337: le->le_csr = LE_TDMD;
338:
339: do {
340: if ( le->le_csr & LE_TINT ) {
341: le->le_csr = LE_TINT; /* Clear interrupt */
342: break;
343: }
344: } while ( --timeout > 0);
345:
346: if ( (tmd->lmd_flags & LMD_ERR)
347: || (tmd->lmd_flags3 & TMD_BUFF)
348: || (timeout <= 0) ) {
349: #ifdef DEBUG
350: printf("le: xmit failed - tmd1 flags %x tmd3 %x\n",
351: tmd->lmd_flags, tmd->lmd_flags3);
352: #endif
353: return (1);
354: }
355:
356: return (0);
357: }
358:
359: int
360: lancepoll(es, buf)
361: register struct lance_softc *es;
362: char *buf;
363: {
364: register struct le_device *le = es->es_lance;
365: register struct le_md *rmd;
366: register struct ether_header *header;
367: int length;
368:
369: #ifdef DEBUG1
370: printf("le: poll\n");
371: #endif
372: if ( ! (le->le_csr & LE_RINT) )
373: return (0); /* No packet yet */
374:
375: #ifdef DEBUG1
376: printf("le: received packet\n");
377: #endif
378:
379: le->le_csr = LE_RINT; /* Clear interrupt */
380:
381: rmd = es->es_rmdp[es->es_next_rmd];
382:
383: if ( (rmd->lmd_flags & ~RMD_OFLO) != (LMD_STP|LMD_ENP) ) {
384: #ifdef DEBUG
385: printf("Receive packet error - rmd flags %x\n",rmd->lmd_flags);
386: #endif
387: length = 0;
388: goto restorebuf;
389: }
390:
391: /* Get input data length and a pointer to the ethernet header */
392:
393: length = rmd->lmd_mcnt - 4; /* don't count the 4 CRC bytes */
394: header = (struct ether_header *)es->es_rbuf[es->es_next_rmd];
395:
396: #ifdef LANCEBUG
397: /*
398: * Check for unreported packet errors. Rev C of the LANCE chip
399: * has a bug which can cause "random" bytes to be prepended to
400: * the start of the packet. The work-around is to make sure that
401: * the Ethernet destination address in the packet matches our
402: * address.
403: */
404: #define ether_addr_not_equal(a,b) \
405: ( ( *(long *)(&a.ether_addr_octet[0]) != \
406: *(long *)(&b.ether_addr_octet[0]) ) \
407: || ( *(short *)(&a.ether_addr_octet[4]) != \
408: *(short *)(&b.ether_addr_octet[4]) ) \
409: )
410:
411: if( ether_addr_not_equal(header->ether_dhost, es->es_enaddr)
412: && ether_addr_not_equal(header->ether_dhost, etherbroadcastaddr) ) {
413: printf("le: LANCE Rev C Extra Byte(s) bug; Packet punted\n");
414: length = 0;
415: /* Don't return directly; restore the buffer first */
416: }
417: #endif LANCEBUG
418:
419: #ifdef DEBUG2
420: if( header->ether_dhost.ether_addr_octet[0] == 0xff )
421: printf("Broadcast packet\n");
422: else printf("recv np_blkno %x\n",
423: ((struct ndpack *)(buf+14))->np_blkno);
424: #endif
425:
426: /* Copy packet to user's buffer */
427: if ( length > 0 )
428: bcopy((caddr_t)header, buf, length);
429:
430: restorebuf:
431: rmd->lmd_mcnt = 0;
432: rmd->lmd_flags = LMD_OWN;
433:
434: /* Get ready to use the other buffer next time */
435: /* What about errors ? */
436: es->es_next_rmd = 1 - es->es_next_rmd;
437:
438: return (length);
439: }
440:
441: /*
442: * Close down Lance Ethernet device.
443: * On the Model 25, we reset the chip and take it off the wire, since
444: * it is sharing main memory with us (occasionally reading and writing),
445: * and most programs don't know how to deal with that -- they just assume
446: * that main memory is theirs to play with.
447: */
448: lanceclose(sip)
449: struct saioreq *sip;
450: {
451: struct lance_softc *es = (struct lance_softc *) sip->si_devdata;
452: struct le_device *le = es->es_lance;
453:
454: /* Reset the chip */
455: le->le_rap = LE_CSR0;
456: le->le_csr = LE_STOP;
457: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.