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