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