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