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