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