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