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