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