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