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