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