xref: /netbsd-src/sys/dev/ic/lemac.c (revision dc306354b0b29af51801a7632f1e95265a68cd81)
1 /* $NetBSD: lemac.c,v 1.10 1998/07/05 06:49:11 jonathan Exp $ */
2 
3 /*-
4  * Copyright (c) 1994, 1995, 1997 Matt Thomas <matt@3am-software.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. The name of the author may not be used to endorse or promote products
13  *    derived from this software withough specific prior written permission
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 /*
28  * DEC EtherWORKS 3 Ethernet Controllers
29  *
30  * Written by Matt Thomas
31  * BPF support code stolen directly from if_ec.c
32  *
33  *   This driver supports the LEMAC DE203/204/205 cards.
34  */
35 
36 #include "opt_inet.h"
37 #include "opt_ns.h"
38 #include "rnd.h"
39 
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/mbuf.h>
43 #include <sys/protosw.h>
44 #include <sys/socket.h>
45 #include <sys/sockio.h>
46 #include <sys/errno.h>
47 #include <sys/malloc.h>
48 #include <sys/device.h>
49 #if NRND > 0
50 #include <sys/rnd.h>
51 #endif
52 
53 #include <net/if.h>
54 #include <net/if_types.h>
55 #include <net/if_dl.h>
56 #include <net/route.h>
57 #include <net/if_ether.h>
58 #include <net/if_media.h>
59 
60 #ifdef INET
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/in_var.h>
64 #include <netinet/ip.h>
65 #include <netinet/if_inarp.h>
66 #endif
67 
68 #ifdef NS
69 #include <netns/ns.h>
70 #include <netns/ns_if.h>
71 #endif
72 
73 #include <machine/bus.h>
74 
75 #include <dev/ic/lemacreg.h>
76 #include <dev/ic/lemacvar.h>
77 #if 0
78 #include <i386/isa/decether.h>
79 #endif
80 
81 #include <vm/vm.h>
82 
83 #include "bpfilter.h"
84 #if NBPFILTER > 0
85 #include <net/bpf.h>
86 #endif
87 
88 static void lemac_init(lemac_softc_t *sc);
89 static void lemac_ifstart(struct ifnet *ifp);
90 static void lemac_reset(lemac_softc_t *sc);
91 static void lemac_rne_intr(lemac_softc_t *sc);
92 static void lemac_tne_intr(lemac_softc_t *sc);
93 static void lemac_txd_intr(lemac_softc_t *sc, unsigned cs_value);
94 static void lemac_rxd_intr(lemac_softc_t *sc, unsigned cs_value);
95 static int  lemac_read_eeprom(lemac_softc_t *sc);
96 static void lemac_init_adapmem(lemac_softc_t *sc);
97 
98 static const u_int16_t lemac_allmulti_mctbl[16] =  {
99     0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU,
100     0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU,
101     0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU,
102     0xFFFFU, 0xFFFFU, 0xFFFFU, 0xFFFFU,
103 };
104 
105 /*
106  * Some tuning/monitoring variables.
107  */
108 unsigned lemac_txmax = 16;
109 
110 static void
111 lemac_rxd_intr(
112     lemac_softc_t *sc,
113     unsigned cs_value)
114 {
115     /*
116      * Handle CS_RXD (Receiver disabled) here.
117      *
118      * Check Free Memory Queue Count. If not equal to zero
119      * then just turn Receiver back on. If it is equal to
120      * zero then check to see if transmitter is disabled.
121      * Process transmit TXD loop once more.  If all else
122      * fails then do software init (0xC0 to EEPROM Init)
123      * and rebuild Free Memory Queue.
124      */
125 
126     sc->sc_cntrs.cntr_rxd_intrs++;
127 
128     /*
129      *  Re-enable Receiver.
130      */
131 
132     cs_value &= ~LEMAC_CS_RXD;
133     LEMAC_OUTB(sc, LEMAC_REG_CS, cs_value);
134 
135     if (LEMAC_INB(sc, LEMAC_REG_FMC) > 0)
136 	return;
137 
138     if (cs_value & LEMAC_CS_TXD)
139 	lemac_txd_intr(sc, cs_value);
140 
141     if ((LEMAC_INB(sc, LEMAC_REG_CS) & LEMAC_CS_RXD) == 0)
142 	return;
143 
144     printf("%s: fatal RXD error, attempting recovery\n", sc->sc_if.if_xname);
145 
146     lemac_reset(sc);
147     if (sc->sc_if.if_flags & IFF_UP) {
148 	lemac_init(sc);
149 	return;
150     }
151 
152     /*
153      *  Error during initializion.  Mark card as disabled.
154      */
155     printf("%s: recovery failed -- board disabled\n", sc->sc_if.if_xname);
156 }
157 
158 static void
159 lemac_tne_intr(
160     lemac_softc_t *sc)
161 {
162     unsigned txcount = LEMAC_INB(sc, LEMAC_REG_TDC);
163 
164     sc->sc_cntrs.cntr_tne_intrs++;
165     while (txcount-- > 0) {
166 	unsigned txsts = LEMAC_INB(sc, LEMAC_REG_TDQ);
167 	sc->sc_if.if_opackets++;		/* another one done */
168 	if ((txsts & (LEMAC_TDQ_LCL|LEMAC_TDQ_NCL))
169 	        || (txsts & LEMAC_TDQ_COL) == LEMAC_TDQ_EXCCOL) {
170 	    if (txsts & LEMAC_TDQ_NCL)
171 		sc->sc_flags &= ~LEMAC_LINKUP;
172 	    sc->sc_if.if_oerrors++;
173 	} else {
174 	    sc->sc_flags |= LEMAC_LINKUP;
175 	    if ((txsts & LEMAC_TDQ_COL) != LEMAC_TDQ_NOCOL)
176 		sc->sc_if.if_collisions++;
177 	}
178     }
179     sc->sc_if.if_flags &= ~IFF_OACTIVE;
180     lemac_ifstart(&sc->sc_if);
181 }
182 
183 static void
184 lemac_txd_intr(
185     lemac_softc_t *sc,
186     unsigned cs_value)
187 {
188     /*
189      * Read transmit status, remove transmit buffer from
190      * transmit queue and place on free memory queue,
191      * then reset transmitter.
192      * Increment appropriate counters.
193      */
194 
195     sc->sc_cntrs.cntr_txd_intrs++;
196     if (sc->sc_txctl & LEMAC_TX_STP) {
197 	sc->sc_if.if_oerrors++;
198 	/* return page to free queue */
199 	LEMAC_OUTB(sc, LEMAC_REG_FMQ, LEMAC_INB(sc, LEMAC_REG_TDQ));
200     }
201 
202     /* Turn back on transmitter if disabled */
203     LEMAC_OUTB(sc, LEMAC_REG_CS, cs_value & ~LEMAC_CS_TXD);
204     sc->sc_if.if_flags &= ~IFF_OACTIVE;
205 }
206 
207 static int
208 lemac_read_eeprom(
209     lemac_softc_t *sc)
210 {
211     int	word_off, cksum;
212 
213     u_char *ep;
214 
215     cksum = 0;
216     ep = sc->sc_eeprom;
217     for (word_off = 0; word_off < LEMAC_EEP_SIZE / 2; word_off++) {
218 	LEMAC_OUTB(sc, LEMAC_REG_PI1, word_off);
219 	LEMAC_OUTB(sc, LEMAC_REG_IOP, LEMAC_IOP_EEREAD);
220 
221 	DELAY(LEMAC_EEP_DELAY);
222 
223 	*ep = LEMAC_INB(sc, LEMAC_REG_EE1);	cksum += *ep++;
224 	*ep = LEMAC_INB(sc, LEMAC_REG_EE2);	cksum += *ep++;
225     }
226 
227     /*
228      *  Set up Transmit Control Byte for use later during transmit.
229      */
230 
231     sc->sc_txctl |= LEMAC_TX_FLAGS;
232 
233     if ((sc->sc_eeprom[LEMAC_EEP_SWFLAGS] & LEMAC_EEP_SW_SQE) == 0)
234 	sc->sc_txctl &= ~LEMAC_TX_SQE;
235 
236     if (sc->sc_eeprom[LEMAC_EEP_SWFLAGS] & LEMAC_EEP_SW_LAB)
237 	sc->sc_txctl |= LEMAC_TX_LAB;
238 
239     bcopy(&sc->sc_eeprom[LEMAC_EEP_PRDNM], sc->sc_prodname, LEMAC_EEP_PRDNMSZ);
240     sc->sc_prodname[LEMAC_EEP_PRDNMSZ] = '\0';
241 
242     return cksum % 256;
243 }
244 
245 static void
246 lemac_init_adapmem(
247     lemac_softc_t *sc)
248 {
249     int pg, conf;
250 
251     conf = LEMAC_INB(sc, LEMAC_REG_CNF);
252 
253     if ((sc->sc_eeprom[LEMAC_EEP_SETUP] & LEMAC_EEP_ST_DRAM) == 0) {
254 	sc->sc_lastpage = 63;
255 	conf &= ~LEMAC_CNF_DRAM;
256     } else {
257 	sc->sc_lastpage = 127;
258 	conf |= LEMAC_CNF_DRAM;
259     }
260 
261     LEMAC_OUTB(sc, LEMAC_REG_CNF, conf);
262 
263     for (pg = 1; pg <= sc->sc_lastpage; pg++)
264 	LEMAC_OUTB(sc, LEMAC_REG_FMQ, pg);
265 }
266 
267 static void
268 lemac_input(
269     lemac_softc_t *sc,
270     bus_addr_t offset,
271     size_t length)
272 {
273     struct ether_header eh;
274     struct mbuf *m;
275 
276     if (length - sizeof(eh) > ETHERMTU
277 	    || length - sizeof(eh) < ETHERMIN) {
278 	sc->sc_if.if_ierrors++;
279 	return;
280     }
281     if (LEMAC_USE_PIO_MODE(sc)) {
282 	LEMAC_INSB(sc, LEMAC_REG_DAT, sizeof(eh), (void *) &eh);
283     } else {
284 	LEMAC_GETBUF16(sc, offset, sizeof(eh) / 2, (void *) &eh);
285     }
286 
287     /*
288      * If this is single cast but not to us
289      * drop it!
290      */
291     if ((eh.ether_dhost[0] & 1) == 0
292 #if NBPFILTER > 0
293 	    && (sc->sc_if.if_flags & IFF_PROMISC) == 0
294 #endif
295 	    && !LEMAC_ADDREQUAL(eh.ether_dhost, sc->sc_enaddr))
296 	return;
297 
298     MGETHDR(m, M_DONTWAIT, MT_DATA);
299     if (m == NULL) {
300 	sc->sc_if.if_ierrors++;
301 	return;
302     }
303     if (length + 2 > MHLEN) {
304 	MCLGET(m, M_DONTWAIT);
305 	if ((m->m_flags & M_EXT) == 0) {
306 	    m_free(m);
307 	    sc->sc_if.if_ierrors++;
308 	    return;
309 	}
310     }
311     m->m_data += 2;
312     bcopy((caddr_t)&eh, m->m_data, sizeof(eh));
313     if (LEMAC_USE_PIO_MODE(sc)) {
314 	LEMAC_INSB(sc, LEMAC_REG_DAT, length - sizeof(eh),
315 		   mtod(m, caddr_t) + sizeof(eh));
316     } else {
317 	LEMAC_GETBUF16(sc, offset + sizeof(eh), (length - sizeof(eh)) / 2,
318 		      (void *) (mtod(m, caddr_t) + sizeof(eh)));
319 	if (length & 1)
320 	    m->m_data[length - 1] = LEMAC_GET8(sc, offset + length - 1);
321     }
322 #if NBPFILTER > 0
323     if (sc->sc_if.if_bpf != NULL) {
324 	m->m_pkthdr.len = m->m_len = length;
325 	bpf_mtap(sc->sc_if.if_bpf, m);
326     }
327     /*
328      * If this is single cast but not to us
329      * drop it!
330      */
331     if ((eh.ether_dhost[0] & 1) == 0
332 	   && !LEMAC_ADDREQUAL(eh.ether_dhost, sc->sc_enaddr)) {
333 	m_freem(m);
334 	return;
335     }
336 #endif
337     m->m_pkthdr.len = m->m_len = length - sizeof(eh);
338     m->m_data += sizeof(eh);
339     m->m_pkthdr.rcvif = &sc->sc_if;
340     ether_input(&sc->sc_if, &eh, m);
341 }
342 
343 static void
344 lemac_rne_intr(
345     lemac_softc_t *sc)
346 {
347     int rxcount;
348 
349     sc->sc_cntrs.cntr_rne_intrs++;
350     rxcount = LEMAC_INB(sc, LEMAC_REG_RQC);
351     while (rxcount--) {
352 	unsigned rxpg = LEMAC_INB(sc, LEMAC_REG_RQ);
353 	u_int32_t rxlen;
354 
355 	sc->sc_if.if_ipackets++;
356 	if (LEMAC_USE_PIO_MODE(sc)) {
357 	    LEMAC_OUTB(sc, LEMAC_REG_IOP, rxpg);
358 	    LEMAC_OUTB(sc, LEMAC_REG_PI1, 0);
359 	    LEMAC_OUTB(sc, LEMAC_REG_PI2, 0);
360 	    LEMAC_INSB(sc, LEMAC_REG_DAT, sizeof(rxlen), (void *) &rxlen);
361 	} else {
362 	    LEMAC_OUTB(sc, LEMAC_REG_MPN, rxpg);
363 	    rxlen = LEMAC_GET32(sc, 0);
364 	}
365 	if (rxlen & LEMAC_RX_OK) {
366 	    sc->sc_flags |= LEMAC_LINKUP;
367 	    /*
368 	     * Get receive length - subtract out checksum.
369 	     */
370 	    rxlen = ((rxlen >> 8) & 0x7FF) - 4;
371 	    lemac_input(sc, sizeof(rxlen), rxlen);
372 	} else {
373 	    sc->sc_if.if_ierrors++;
374 	}
375 	LEMAC_OUTB(sc, LEMAC_REG_FMQ, rxpg);  /* Return this page to Free Memory Queue */
376     }  /* end while (recv_count--) */
377 
378     return;
379 }
380 
381 /*
382  *  This is the standard method of reading the DEC Address ROMS.
383  *  I don't understand it but it does work.
384  */
385 static int
386 lemac_read_macaddr(
387     unsigned char *hwaddr,
388     const bus_space_tag_t iot,
389     const bus_space_handle_t ioh,
390     const bus_addr_t ioreg,
391     int skippat)
392 {
393     int cksum, rom_cksum;
394     unsigned char addrbuf[6];
395 
396     if (!skippat) {
397 	int idx, idx2, found, octet;
398 	static u_char testpat[] = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA };
399 	idx2 = found = 0;
400 
401 	for (idx = 0; idx < 32; idx++) {
402 	    octet = bus_space_read_1(iot, ioh, ioreg);
403 
404 	    if (octet == testpat[idx2]) {
405 		if (++idx2 == sizeof(testpat)) {
406 		    ++found;
407 		    break;
408 		}
409 	    } else {
410 		idx2 = 0;
411 	    }
412 	}
413 
414 	if (!found)
415 	    return -1;
416     }
417 
418     if (hwaddr == NULL)
419 	hwaddr = addrbuf;
420 
421     cksum = 0;
422     hwaddr[0] = bus_space_read_1(iot, ioh, ioreg);
423     hwaddr[1] = bus_space_read_1(iot, ioh, ioreg);
424 
425     /* hardware adddress can't be multicast */
426     if (hwaddr[0] & 1)
427 	return -1;
428 
429     cksum = *(u_short *) &hwaddr[0];
430 
431     hwaddr[2] = bus_space_read_1(iot, ioh, ioreg);
432     hwaddr[3] = bus_space_read_1(iot, ioh, ioreg);
433     cksum *= 2;
434     if (cksum > 65535) cksum -= 65535;
435     cksum += *(u_short *) &hwaddr[2];
436     if (cksum > 65535) cksum -= 65535;
437 
438     hwaddr[4] = bus_space_read_1(iot, ioh, ioreg);
439     hwaddr[5] = bus_space_read_1(iot, ioh, ioreg);
440     cksum *= 2;
441     if (cksum > 65535) cksum -= 65535;
442     cksum += *(u_short *) &hwaddr[4];
443     if (cksum >= 65535) cksum -= 65535;
444 
445     /* 00-00-00 is an illegal OUI */
446     if (hwaddr[0] == 0 && hwaddr[1] == 0 && hwaddr[2] == 0)
447 	return -1;
448 
449     rom_cksum = bus_space_read_1(iot, ioh, ioreg);
450     rom_cksum |= bus_space_read_1(iot, ioh, ioreg) << 8;
451 
452     if (cksum != rom_cksum)
453 	return -1;
454     return 0;
455 }
456 
457 static void
458 lemac_multicast_op(
459     u_int16_t *mctbl,
460     const u_char *mca,
461     int enable)
462 {
463     u_int idx, bit, crc = 0xFFFFFFFFUL;
464     static const u_int crctab[] = {
465 	0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
466 	0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
467 	0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
468 	0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
469     };
470 
471     for (idx = 0; idx < 6; idx++) {
472 	crc ^= *mca++;
473 	crc = (crc >> 4) ^ crctab[crc & 0xf];
474 	crc = (crc >> 4) ^ crctab[crc & 0xf];
475     }
476     /*
477      * The following two lines convert the N bit index into a longword index
478      * and a longword mask.
479      */
480 #if LEMAC_MCTBL_BITS < 0
481     crc >>= (32 + LEMAC_MCTBL_BITS);
482     crc &= (1 << -LEMAC_MCTBL_BITS) - 1;
483 #else
484     crc &= (1 << LEMAC_MCTBL_BITS) - 1;
485 #endif
486     bit = 1 << (crc & 0x0F);
487     idx = crc >> 4;
488 
489     /*
490      * Set or clear hash filter bit in our table.
491      */
492     if (enable) {
493 	mctbl[idx] |= bit;		/* Set Bit */
494     } else {
495 	mctbl[idx] &= ~bit;		/* Clear Bit */
496     }
497 }
498 
499 static void
500 lemac_multicast_filter(
501     lemac_softc_t *sc)
502 {
503     struct ether_multistep step;
504     struct ether_multi *enm;
505 
506     bzero(sc->sc_mctbl, LEMAC_MCTBL_BITS / 8);
507 
508     lemac_multicast_op(sc->sc_mctbl, etherbroadcastaddr, TRUE);
509 
510     ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
511     while (enm != NULL) {
512 	if (!LEMAC_ADDREQUAL(enm->enm_addrlo, enm->enm_addrhi)) {
513 	    sc->sc_flags |= LEMAC_ALLMULTI;
514 	    sc->sc_if.if_flags |= IFF_ALLMULTI;
515 	    return;
516 	}
517 	lemac_multicast_op(sc->sc_mctbl, enm->enm_addrlo, TRUE);
518 	ETHER_NEXT_MULTI(step, enm);
519     }
520     sc->sc_flags &= ~LEMAC_ALLMULTI;
521     sc->sc_if.if_flags &= ~IFF_ALLMULTI;
522 }
523 
524 /*
525  * Do a hard reset of the board;
526  */
527 static void
528 lemac_reset(
529     lemac_softc_t * const sc)
530 {
531     unsigned data;
532 
533     /*
534      * Initialize board..
535      */
536     sc->sc_flags &= ~LEMAC_LINKUP;
537     sc->sc_if.if_flags &= ~IFF_OACTIVE;
538     LEMAC_INTR_DISABLE(sc);
539 
540     LEMAC_OUTB(sc, LEMAC_REG_IOP, LEMAC_IOP_EEINIT);
541     DELAY(LEMAC_EEP_DELAY);
542 
543     /*
544      * Read EEPROM information.  NOTE - the placement of this function
545      * is important because functions hereafter may rely on information
546      * read from the EEPROM.
547      */
548     if ((data = lemac_read_eeprom(sc)) != LEMAC_EEP_CKSUM) {
549 	printf("%s: reset: EEPROM checksum failed (0x%x)\n",
550 	       sc->sc_if.if_xname, data);
551 	return;
552     }
553 
554     /*
555      * Update the control register to reflect the media choice
556      */
557     data = LEMAC_INB(sc, LEMAC_REG_CTL);
558     if ((data & (LEMAC_CTL_APD|LEMAC_CTL_PSL)) != sc->sc_ctlmode) {
559 	data &= ~(LEMAC_CTL_APD|LEMAC_CTL_PSL);
560 	data |= sc->sc_ctlmode;
561 	LEMAC_OUTB(sc, LEMAC_REG_CTL, data);
562     }
563 
564     /*
565      *  Force to 2K mode if not already configured.
566      */
567 
568     data = LEMAC_INB(sc, LEMAC_REG_MBR);
569     if (LEMAC_IS_2K_MODE(data)) {
570 	sc->sc_flags |= LEMAC_2K_MODE;
571     } else if (LEMAC_IS_64K_MODE(data)) {
572 	data = (((data * 2) & 0xF) << 4);
573 	sc->sc_flags |= LEMAC_WAS_64K_MODE;
574 	LEMAC_OUTB(sc, LEMAC_REG_MBR, data);
575     } else if (LEMAC_IS_32K_MODE(data)) {
576 	data = ((data & 0xF) << 4);
577 	sc->sc_flags |= LEMAC_WAS_32K_MODE;
578 	LEMAC_OUTB(sc, LEMAC_REG_MBR, data);
579     } else {
580 	sc->sc_flags |= LEMAC_PIO_MODE;
581 	/* PIO mode */
582     }
583 
584     /*
585      *  Initialize Free Memory Queue, Init mcast table with broadcast.
586      */
587 
588     lemac_init_adapmem(sc);
589     sc->sc_flags |= LEMAC_ALIVE;
590 }
591 
592 static void
593 lemac_init(
594     lemac_softc_t * const sc)
595 {
596     if ((sc->sc_flags & LEMAC_ALIVE) == 0)
597 	return;
598 
599     /*
600      * If the interface has the up flag
601      */
602     if (sc->sc_if.if_flags & IFF_UP) {
603 	int saved_cs = LEMAC_INB(sc, LEMAC_REG_CS);
604 	LEMAC_OUTB(sc, LEMAC_REG_CS, saved_cs | (LEMAC_CS_TXD | LEMAC_CS_RXD));
605 	LEMAC_OUTB(sc, LEMAC_REG_PA0, sc->sc_enaddr[0]);
606 	LEMAC_OUTB(sc, LEMAC_REG_PA1, sc->sc_enaddr[1]);
607 	LEMAC_OUTB(sc, LEMAC_REG_PA2, sc->sc_enaddr[2]);
608 	LEMAC_OUTB(sc, LEMAC_REG_PA3, sc->sc_enaddr[3]);
609 	LEMAC_OUTB(sc, LEMAC_REG_PA4, sc->sc_enaddr[4]);
610 	LEMAC_OUTB(sc, LEMAC_REG_PA5, sc->sc_enaddr[5]);
611 
612 	LEMAC_OUTB(sc, LEMAC_REG_IC, LEMAC_INB(sc, LEMAC_REG_IC) | LEMAC_IC_IE);
613 
614 	if (sc->sc_if.if_flags & IFF_PROMISC) {
615 	    LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_MCE | LEMAC_CS_PME);
616 	} else {
617 	    LEMAC_INTR_DISABLE(sc);
618 	    lemac_multicast_filter(sc);
619 	    if (sc->sc_flags & LEMAC_ALLMULTI)
620 		bcopy(lemac_allmulti_mctbl, sc->sc_mctbl, sizeof(sc->sc_mctbl));
621 	    if (LEMAC_USE_PIO_MODE(sc)) {
622 		LEMAC_OUTB(sc, LEMAC_REG_IOP, 0);
623 		LEMAC_OUTB(sc, LEMAC_REG_PI1, LEMAC_MCTBL_OFF & 0xFF);
624 		LEMAC_OUTB(sc, LEMAC_REG_PI2, LEMAC_MCTBL_OFF >> 8);
625 		LEMAC_OUTSB(sc, LEMAC_REG_DAT, sizeof(sc->sc_mctbl), (void *) sc->sc_mctbl);
626 	    } else {
627 		LEMAC_OUTB(sc, LEMAC_REG_MPN, 0);
628 		LEMAC_PUTBUF8(sc, LEMAC_MCTBL_OFF, sizeof(sc->sc_mctbl), (void *) sc->sc_mctbl);
629 	    }
630 
631 	    LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_MCE);
632 	}
633 
634 	LEMAC_OUTB(sc, LEMAC_REG_CTL, LEMAC_INB(sc, LEMAC_REG_CTL) ^ LEMAC_CTL_LED);
635 
636 	LEMAC_INTR_ENABLE(sc);
637 	sc->sc_if.if_flags |= IFF_RUNNING;
638 	lemac_ifstart(&sc->sc_if);
639     } else {
640 	LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_RXD|LEMAC_CS_TXD);
641 
642 	LEMAC_INTR_DISABLE(sc);
643 	sc->sc_if.if_flags &= ~IFF_RUNNING;
644     }
645 }
646 
647 static void
648 lemac_ifstart(
649     struct ifnet *ifp)
650 {
651     lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp);
652     struct ifqueue * const ifq = &ifp->if_snd;
653 
654     if ((ifp->if_flags & IFF_RUNNING) == 0)
655 	return;
656 
657     LEMAC_INTR_DISABLE(sc);
658 
659     while (ifq->ifq_head != NULL) {
660 	struct mbuf *m;
661 	struct mbuf *m0;
662 	int tx_pg;
663 
664 	if ((sc->sc_csr.csr_tqc = LEMAC_INB(sc, LEMAC_REG_TQC)) >= lemac_txmax) {
665 	    sc->sc_cntrs.cntr_txfull++;
666 	    ifp->if_flags |= IFF_OACTIVE;
667 	    break;
668 	}
669 
670 	/*
671 	 * get free memory page
672 	 */
673 	tx_pg = sc->sc_csr.csr_fmq = LEMAC_INB(sc, LEMAC_REG_FMQ);
674 	/*
675 	 * Check for good transmit page.
676 	 */
677 	if (tx_pg == 0 || tx_pg > sc->sc_lastpage) {
678 	    sc->sc_cntrs.cntr_txnospc++;
679 	    ifp->if_flags |= IFF_OACTIVE;
680 	    break;
681 	}
682 
683 	IF_DEQUEUE(ifq, m);
684 
685 	/*
686 	 * The first four bytes of each transmit buffer are for
687 	 * control information.  The first byte is the control
688 	 * byte, then the length (why not word aligned??), then
689 	 * the offset to the buffer.
690 	 */
691 
692 	if (LEMAC_USE_PIO_MODE(sc)) {
693 	    LEMAC_OUTB(sc, LEMAC_REG_IOP, tx_pg);	/* Shift 2K window. */
694 	    LEMAC_OUTB(sc, LEMAC_REG_PI1, 0);
695 	    LEMAC_OUTB(sc, LEMAC_REG_PI2, 0);
696 	    LEMAC_OUTB(sc, LEMAC_REG_DAT, sc->sc_txctl);
697 	    LEMAC_OUTB(sc, LEMAC_REG_DAT, (m->m_pkthdr.len >> 0) & 0xFF);
698 	    LEMAC_OUTB(sc, LEMAC_REG_DAT, (m->m_pkthdr.len >> 8) & 0xFF);
699 	    LEMAC_OUTB(sc, LEMAC_REG_DAT, LEMAC_TX_HDRSZ);
700 	    for (m0 = m; m0 != NULL; m0 = m0->m_next)
701 		LEMAC_OUTSB(sc, LEMAC_REG_DAT, m0->m_len, m0->m_data);
702 	} else {
703 	    bus_size_t txoff = /* (mtod(m, u_int32_t) & (sizeof(u_int32_t) - 1)) + */ LEMAC_TX_HDRSZ;
704 	    LEMAC_OUTB(sc, LEMAC_REG_MPN, tx_pg);	/* Shift 2K window. */
705 	    LEMAC_PUT8(sc, 0, sc->sc_txctl);
706 	    LEMAC_PUT8(sc, 1, (m->m_pkthdr.len >> 0) & 0xFF);
707 	    LEMAC_PUT8(sc, 2, (m->m_pkthdr.len >> 8) & 0xFF);
708 	    LEMAC_PUT8(sc, 3, txoff);
709 
710 	    /*
711 	     * Copy the packet to the board
712 	     */
713 	    for (m0 = m; m0 != NULL; m0 = m0->m_next) {
714 #if 0
715 		LEMAC_PUTBUF8(sc, txoff, m0->m_len, m0->m_data);
716 		txoff += m0->m_len;
717 #else
718 		const u_int8_t *cp = m0->m_data;
719 		int len = m0->m_len;
720 #if 0
721 		if ((txoff & 3) == (((long)cp) & 3) && len >= 4) {
722 		    if (txoff & 3) {
723 			int alen = (~txoff & 3);
724 			LEMAC_PUTBUF8(sc, txoff, alen, cp);
725 			cp += alen; txoff += alen; len -= alen;
726 		    }
727 		    if (len >= 4) {
728 			LEMAC_PUTBUF32(sc, txoff, len / 4, cp);
729 			cp += len & ~3; txoff += len & ~3; len &= 3;
730 		    }
731 		}
732 #endif
733 		if ((txoff & 1) == (((long)cp) & 1) && len >= 2) {
734 		    if (txoff & 1) {
735 			int alen = (~txoff & 1);
736 			LEMAC_PUTBUF8(sc, txoff, alen, cp);
737 			cp += alen; txoff += alen; len -= alen;
738 		    }
739 		    if (len >= 2) {
740 			LEMAC_PUTBUF16(sc, txoff, len / 2, (void *) cp);
741 			cp += len & ~1; txoff += len & ~1; len &= 1;
742 		    }
743 		}
744 		if (len > 0) {
745 		    LEMAC_PUTBUF8(sc, txoff, len, cp);
746 		    txoff += len;
747 		}
748 #endif
749 	    }
750 	}
751 
752 	LEMAC_OUTB(sc, LEMAC_REG_TQ, tx_pg);	/* tell chip to transmit this packet */
753 #if NBPFILTER > 0
754 	if (sc->sc_if.if_bpf != NULL)
755 	    bpf_mtap(sc->sc_if.if_bpf, m);
756 #endif
757 	m_freem(m);			/* free the mbuf */
758     }
759     LEMAC_INTR_ENABLE(sc);
760 }
761 
762 static int
763 lemac_ifioctl(
764     struct ifnet *ifp,
765     u_long cmd,
766     caddr_t data)
767 {
768     lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp);
769     int s;
770     int error = 0;
771 
772     s = splnet();
773 
774     switch (cmd) {
775 	case SIOCSIFADDR: {
776 	    struct ifaddr *ifa = (struct ifaddr *)data;
777 
778 	    ifp->if_flags |= IFF_UP;
779 	    lemac_init(sc);
780 	    switch (ifa->ifa_addr->sa_family) {
781 #ifdef INET
782 		case AF_INET: {
783 		    arp_ifinit(&sc->sc_if, ifa);
784 		    break;
785 		}
786 #endif /* INET */
787 
788 #ifdef NS
789 		/* This magic copied from if_is.c; I don't use XNS,
790 		 * so I have no way of telling if this actually
791 		 * works or not.
792 		 */
793 		case AF_NS: {
794 		    struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
795 		    if (ns_nullhost(*ina)) {
796 			ina->x_host = *(union ns_host *)sc->sc_enaddr;
797 		    } else {
798 			bcopy((caddr_t)ina->x_host.c_host, sc->sc_enaddr,
799 			      ifp->if_addrlen);
800 		    }
801 		    break;
802 		}
803 #endif /* NS */
804 
805 		default: {
806 		    break;
807 		}
808 	    }
809 	    break;
810 	}
811 
812 	case SIOCSIFFLAGS: {
813 	    lemac_init(sc);
814 	    break;
815 	}
816 
817 	case SIOCADDMULTI:
818 	case SIOCDELMULTI: {
819 	    /*
820 	     * Update multicast listeners
821 	     */
822 	    if (cmd == SIOCADDMULTI)
823 		error = ether_addmulti((struct ifreq *)data, &sc->sc_ec);
824 	    else
825 		error = ether_delmulti((struct ifreq *)data, &sc->sc_ec);
826 
827 	    if (error == ENETRESET) {
828 
829 		/* reset multicast filtering */
830 		lemac_init(sc);
831 		error = 0;
832 	    }
833 	    break;
834 	}
835 
836 	case SIOCSIFMEDIA:
837 	case SIOCGIFMEDIA: {
838 	    error = ifmedia_ioctl(ifp, (struct ifreq *)data,
839 				  &sc->sc_ifmedia, cmd);
840 	    break;
841 	}
842 
843 	default: {
844 	    error = EINVAL;
845 	    break;
846 	}
847     }
848 
849     splx(s);
850     return error;
851 }
852 
853 static int
854 lemac_ifmedia_change(
855     struct ifnet * const ifp)
856 {
857     lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp);
858     unsigned new_ctl;
859 
860     switch (IFM_SUBTYPE(sc->sc_ifmedia.ifm_media)) {
861 	case IFM_10_T: new_ctl = LEMAC_CTL_APD; break;
862 	case IFM_10_2:
863 	case IFM_10_5: new_ctl = LEMAC_CTL_APD|LEMAC_CTL_PSL; break;
864 	case IFM_AUTO: new_ctl = 0; break;
865 	default:       return EINVAL;
866     }
867     if (sc->sc_ctlmode != new_ctl) {
868 	sc->sc_ctlmode = new_ctl;
869 	lemac_reset(sc);
870 	if (sc->sc_if.if_flags & IFF_UP)
871 	    lemac_init(sc);
872     }
873     return 0;
874 }
875 
876 /*
877  * Media status callback
878  */
879 static void
880 lemac_ifmedia_status(
881     struct ifnet * const ifp,
882     struct ifmediareq *req)
883 {
884     lemac_softc_t *sc = LEMAC_IFP_TO_SOFTC(ifp);
885     unsigned data = LEMAC_INB(sc, LEMAC_REG_CNF);
886 
887     req->ifm_status = IFM_AVALID;
888     if (sc->sc_flags & LEMAC_LINKUP)
889 	req->ifm_status |= IFM_ACTIVE;
890 
891     if (sc->sc_ctlmode & LEMAC_CTL_APD) {
892 	if (sc->sc_ctlmode & LEMAC_CTL_PSL) {
893 	    req->ifm_active = IFM_10_5;
894 	} else {
895 	    req->ifm_active = IFM_10_T;
896 	}
897     } else {
898 	/*
899 	 * The link bit of the configuration register reflects the
900 	 * current media choice when auto-port is enabled.
901 	 */
902 	if (data & LEMAC_CNF_NOLINK) {
903 	    req->ifm_active = IFM_10_5;
904 	} else {
905 	    req->ifm_active = IFM_10_T;
906 	}
907     }
908 
909     req->ifm_active |= IFM_ETHER;
910 }
911 
912 int
913 lemac_port_check(
914     const bus_space_tag_t iot,
915     const bus_space_handle_t ioh)
916 {
917     unsigned char hwaddr[6];
918 
919     if (lemac_read_macaddr(hwaddr, iot, ioh, LEMAC_REG_APD, 0) == 0)
920 	return 1;
921     if (lemac_read_macaddr(hwaddr, iot, ioh, LEMAC_REG_APD, 1) == 0)
922 	return 1;
923     return 0;
924 }
925 
926 void
927 lemac_info_get(
928     const bus_space_tag_t iot,
929     const bus_space_handle_t ioh,
930     bus_addr_t *maddr_p,
931     bus_size_t *msize_p,
932     int *irq_p)
933 {
934     unsigned data;
935 
936     *irq_p = LEMAC_DECODEIRQ(bus_space_read_1(iot, ioh, LEMAC_REG_IC) & LEMAC_IC_IRQMSK);
937 
938     data = bus_space_read_1(iot, ioh, LEMAC_REG_MBR);
939     if (LEMAC_IS_2K_MODE(data)) {
940 	*maddr_p = data * (2 * 1024) + (512 * 1024);
941 	*msize_p =  2 * 1024;
942     } else if (LEMAC_IS_64K_MODE(data)) {
943 	*maddr_p = data * 64 * 1024;
944 	*msize_p = 64 * 1024;
945     } else if (LEMAC_IS_32K_MODE(data)) {
946 	*maddr_p = data * 32 * 1024;
947 	*msize_p = 32* 1024;
948     } else {
949 	*maddr_p = 0;
950 	*msize_p = 0;
951     }
952 }
953 
954 /*
955  * What to do upon receipt of an interrupt.
956  */
957 int
958 lemac_intr(
959     void *arg)
960 {
961     lemac_softc_t * const sc = arg;
962     int cs_value;
963 
964     LEMAC_INTR_DISABLE(sc);	/* Mask interrupts */
965 
966     /*
967      * Determine cause of interrupt.  Receive events take
968      * priority over Transmit.
969      */
970 
971     cs_value = LEMAC_INB(sc, LEMAC_REG_CS);
972 
973     /*
974      * Check for Receive Queue not being empty.
975      * Check for Transmit Done Queue not being empty.
976      */
977 
978     if (cs_value & LEMAC_CS_RNE)
979 	lemac_rne_intr(sc);
980     if (cs_value & LEMAC_CS_TNE)
981 	lemac_tne_intr(sc);
982 
983     /*
984      * Check for Transmitter Disabled.
985      * Check for Receiver Disabled.
986      */
987 
988     if (cs_value & LEMAC_CS_TXD)
989 	lemac_txd_intr(sc, cs_value);
990     if (cs_value & LEMAC_CS_RXD)
991 	lemac_rxd_intr(sc, cs_value);
992 
993     /*
994      * Toggle LED and unmask interrupts.
995      */
996 
997     sc->sc_csr.csr_cs = LEMAC_INB(sc, LEMAC_REG_CS);
998 
999     LEMAC_OUTB(sc, LEMAC_REG_CTL, LEMAC_INB(sc, LEMAC_REG_CTL) ^ LEMAC_CTL_LED);
1000     LEMAC_INTR_ENABLE(sc);		/* Unmask interrupts */
1001 
1002 #if NRND > 0
1003     if (cs_value)
1004         rnd_add_uint32(&sc->rnd_source, cs_value);
1005 #endif
1006 
1007     return 1;
1008 }
1009 
1010 void
1011 lemac_shutdown(
1012     void *arg)
1013 {
1014     lemac_reset((lemac_softc_t *) arg);
1015 }
1016 
1017 static const char * const lemac_modes[4] = {
1018     "PIO mode (internal 2KB window)",
1019     "2KB window",
1020     "changed 32KB window to 2KB",
1021     "changed 64KB window to 2KB",
1022 };
1023 
1024 void
1025 lemac_ifattach(
1026     lemac_softc_t *sc)
1027 {
1028     struct ifnet * const ifp = &sc->sc_if;
1029 
1030     bcopy(sc->sc_dv.dv_xname, ifp->if_xname, IFNAMSIZ);
1031 
1032     lemac_reset(sc);
1033 
1034     (void) lemac_read_macaddr(sc->sc_enaddr, sc->sc_iot, sc->sc_ioh,
1035 			      LEMAC_REG_APD, 0);
1036 
1037     printf(": %s\n", sc->sc_prodname);
1038 
1039     printf("%s: address %s, %dKB RAM, %s\n",
1040 	   ifp->if_xname,
1041 	   ether_sprintf(sc->sc_enaddr),
1042 	   sc->sc_lastpage * 2 + 2,
1043 	   lemac_modes[sc->sc_flags & LEMAC_MODE_MASK]);
1044 
1045     ifp->if_baudrate = 10000000;
1046     ifp->if_softc = (void *) sc;
1047     ifp->if_start = lemac_ifstart;
1048     ifp->if_output = ether_output;
1049     ifp->if_ioctl = lemac_ifioctl;
1050 
1051     ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX
1052 #ifdef IFF_NOTRAILERS
1053 	| IFF_NOTRAILERS
1054 #endif
1055 	| IFF_MULTICAST;
1056 
1057     if (sc->sc_flags & LEMAC_ALIVE) {
1058 	int media;
1059 
1060 	if_attach(ifp);
1061 	ether_ifattach(ifp, sc->sc_enaddr);
1062 
1063 #if NBPFILTER > 0
1064 	bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
1065 #endif
1066 
1067 #if NRND > 0
1068 	rnd_attach_source(&sc->rnd_source, sc->sc_dv.dv_xname, RND_TYPE_NET);
1069 #endif
1070 
1071 	ifmedia_init(&sc->sc_ifmedia, 0,
1072 		     lemac_ifmedia_change,
1073 		     lemac_ifmedia_status);
1074 	if (sc->sc_prodname[4] == '5')	/* DE205 is UTP/AUI */
1075 	    ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_AUTO, 0, 0);
1076 	if (sc->sc_prodname[4] != '3')	/* DE204 & 205 have UTP */
1077 	    ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_T, 0, 0);
1078 	if (sc->sc_prodname[4] != '4')	/* DE203 & 205 have BNC */
1079 	    ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_5, 0, 0);
1080 	switch (sc->sc_prodname[4]) {
1081 	    case '3': media = IFM_10_5; break;
1082 	    case '4': media = IFM_10_T; break;
1083 	    default:  media = IFM_AUTO; break;
1084 	}
1085 	ifmedia_set(&sc->sc_ifmedia, IFM_ETHER | media);
1086     } else {
1087 	printf("%s: disabled due to error\n", ifp->if_xname);
1088     }
1089 }
1090