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