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