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