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