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