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