lemac.c revision 1.2 1 /* $NetBSD: lemac.c,v 1.2 1997/10/15 05:55:45 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 "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 struct cfdriver lc_cd = {
87 NULL, "lc", DV_IFNET
88 };
89
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 bcopy(&sc->sc_eeprom[LEMAC_EEP_PRDNM], sc->sc_prodname, 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 /*
296 * If this is single cast but not to us
297 * drop it!
298 */
299 if ((eh.ether_dhost[0] & 1) == 0
300 #if NBPFILTER > 0
301 && (sc->sc_if.if_flags & IFF_PROMISC) == 0
302 #endif
303 && !LEMAC_ADDREQUAL(eh.ether_dhost, LLADDR(sc->sc_if.if_sadl)))
304 return;
305
306 MGETHDR(m, M_DONTWAIT, MT_DATA);
307 if (m == NULL) {
308 sc->sc_if.if_ierrors++;
309 return;
310 }
311 if (length + 2 > MHLEN) {
312 MCLGET(m, M_DONTWAIT);
313 if ((m->m_flags & M_EXT) == 0) {
314 m_free(m);
315 sc->sc_if.if_ierrors++;
316 return;
317 }
318 }
319 m->m_data += 2;
320 bcopy((caddr_t)&eh, m->m_data, sizeof(eh));
321 if (LEMAC_USE_PIO_MODE(sc)) {
322 LEMAC_INSB(sc, LEMAC_REG_DAT, length - sizeof(eh),
323 mtod(m, caddr_t) + sizeof(eh));
324 } else {
325 LEMAC_GETBUF16(sc, offset + sizeof(eh), (length - sizeof(eh)) / 2,
326 (void *) (mtod(m, caddr_t) + sizeof(eh)));
327 if (length & 1)
328 m->m_data[length - 1] = LEMAC_GET8(sc, offset + length - 1);
329 }
330 #if NBPFILTER > 0
331 if (sc->sc_if.if_bpf != NULL) {
332 m->m_pkthdr.len = m->m_len = length;
333 bpf_mtap(sc->sc_if.if_bpf, m);
334 }
335 /*
336 * If this is single cast but not to us
337 * drop it!
338 */
339 if ((eh.ether_dhost[0] & 1) == 0
340 && !LEMAC_ADDREQUAL(eh.ether_dhost, LLADDR(sc->sc_if.if_sadl))) {
341 m_freem(m);
342 return;
343 }
344 #endif
345 m->m_pkthdr.len = m->m_len = length - sizeof(eh);
346 m->m_data += sizeof(eh);
347 m->m_pkthdr.rcvif = &sc->sc_if;
348 ether_input(&sc->sc_if, &eh, m);
349 }
350
351 static void
353 lemac_rne_intr(
354 lemac_softc_t *sc)
355 {
356 int rxcount;
357
358 sc->sc_cntrs.cntr_rne_intrs++;
359 rxcount = LEMAC_INB(sc, LEMAC_REG_RQC);
360 while (rxcount--) {
361 unsigned rxpg = LEMAC_INB(sc, LEMAC_REG_RQ);
362 u_int32_t rxlen;
363
364 sc->sc_if.if_ipackets++;
365 if (LEMAC_USE_PIO_MODE(sc)) {
366 LEMAC_OUTB(sc, LEMAC_REG_IOP, rxpg);
367 LEMAC_OUTB(sc, LEMAC_REG_PI1, 0);
368 LEMAC_OUTB(sc, LEMAC_REG_PI2, 0);
369 LEMAC_INSB(sc, LEMAC_REG_DAT, sizeof(rxlen), (void *) &rxlen);
370 } else {
371 LEMAC_OUTB(sc, LEMAC_REG_MPN, rxpg);
372 rxlen = LEMAC_GET32(sc, 0);
373 }
374 if (rxlen & LEMAC_RX_OK) {
375 sc->sc_flags |= LEMAC_LINKUP;
376 /*
377 * Get receive length - subtract out checksum.
378 */
379 rxlen = ((rxlen >> 8) & 0x7FF) - 4;
380 lemac_input(sc, sizeof(rxlen), rxlen);
381 } else {
382 sc->sc_if.if_ierrors++;
383 }
384 LEMAC_OUTB(sc, LEMAC_REG_FMQ, rxpg); /* Return this page to Free Memory Queue */
385 } /* end while (recv_count--) */
386
387 return;
388 }
389
390 /*
392 * This is the standard method of reading the DEC Address ROMS.
393 * I don't understand it but it does work.
394 */
395 static int
396 lemac_read_macaddr(
397 unsigned char *hwaddr,
398 const bus_space_tag_t iot,
399 const bus_space_handle_t ioh,
400 const bus_addr_t ioreg,
401 int skippat)
402 {
403 int cksum, rom_cksum;
404 unsigned char addrbuf[6];
405
406 if (!skippat) {
407 int idx, idx2, found, octet;
408 static u_char testpat[] = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA };
409 idx2 = found = 0;
410
411 for (idx = 0; idx < 32; idx++) {
412 octet = bus_space_read_1(iot, ioh, ioreg);
413
414 if (octet == testpat[idx2]) {
415 if (++idx2 == sizeof(testpat)) {
416 ++found;
417 break;
418 }
419 } else {
420 idx2 = 0;
421 }
422 }
423
424 if (!found)
425 return -1;
426 }
427
428 if (hwaddr == NULL)
429 hwaddr = addrbuf;
430
431 cksum = 0;
432 hwaddr[0] = bus_space_read_1(iot, ioh, ioreg);
433 hwaddr[1] = bus_space_read_1(iot, ioh, ioreg);
434
435 /* hardware adddress can't be multicast */
436 if (hwaddr[0] & 1)
437 return -1;
438
439 cksum = *(u_short *) &hwaddr[0];
440
441 hwaddr[2] = bus_space_read_1(iot, ioh, ioreg);
442 hwaddr[3] = bus_space_read_1(iot, ioh, ioreg);
443 cksum *= 2;
444 if (cksum > 65535) cksum -= 65535;
445 cksum += *(u_short *) &hwaddr[2];
446 if (cksum > 65535) cksum -= 65535;
447
448 hwaddr[4] = bus_space_read_1(iot, ioh, ioreg);
449 hwaddr[5] = bus_space_read_1(iot, ioh, ioreg);
450 cksum *= 2;
451 if (cksum > 65535) cksum -= 65535;
452 cksum += *(u_short *) &hwaddr[4];
453 if (cksum >= 65535) cksum -= 65535;
454
455 /* 00-00-00 is an illegal OUI */
456 if (hwaddr[0] == 0 && hwaddr[1] == 0 && hwaddr[2] == 0)
457 return -1;
458
459 rom_cksum = bus_space_read_1(iot, ioh, ioreg);
460 rom_cksum |= bus_space_read_1(iot, ioh, ioreg) << 8;
461
462 if (cksum != rom_cksum)
463 return -1;
464 return 0;
465 }
466
467 static void
469 lemac_multicast_op(
470 u_int16_t *mctbl,
471 const u_char *mca,
472 int enable)
473 {
474 u_int idx, bit, data, crc = 0xFFFFFFFFUL;
475
476 for (idx = 0; idx < 6; idx++)
477 for (data = *mca++, bit = 0; bit < 8; bit++, data >>= 1)
478 crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LEMAC_CRC32_POLY : 0);
479 /*
480 * The following two lines convert the N bit index into a longword index
481 * and a longword mask.
482 */
483 #if LEMAC_MCTBL_BITS < 0
484 crc >>= (32 + LEMAC_MCTBL_BITS);
485 crc &= (1 << -LEMAC_MCTBL_BITS) - 1;
486 #else
487 crc &= (1 << LEMAC_MCTBL_BITS) - 1;
488 #endif
489 bit = 1 << (crc & 0x0F);
490 idx = crc >> 4;
491
492 /*
493 * Set or clear hash filter bit in our table.
494 */
495 if (enable) {
496 mctbl[idx] |= bit; /* Set Bit */
497 } else {
498 mctbl[idx] &= ~bit; /* Clear Bit */
499 }
500 }
501
502 static void
504 lemac_multicast_filter(
505 lemac_softc_t *sc)
506 {
507 struct ether_multistep step;
508 struct ether_multi *enm;
509
510 bzero(sc->sc_mctbl, LEMAC_MCTBL_BITS / 8);
511
512 lemac_multicast_op(sc->sc_mctbl, etherbroadcastaddr, TRUE);
513
514 ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
515 while (enm != NULL) {
516 if (!LEMAC_ADDREQUAL(enm->enm_addrlo, enm->enm_addrhi)) {
517 sc->sc_flags |= LEMAC_ALLMULTI;
518 sc->sc_if.if_flags |= IFF_ALLMULTI;
519 return;
520 }
521 lemac_multicast_op(sc->sc_mctbl, enm->enm_addrlo, TRUE);
522 ETHER_NEXT_MULTI(step, enm);
523 }
524 sc->sc_flags &= ~LEMAC_ALLMULTI;
525 sc->sc_if.if_flags &= ~IFF_ALLMULTI;
526 }
527
528 /*
530 * Do a hard reset of the board;
531 */
532 static void
533 lemac_reset(
534 lemac_softc_t * const sc)
535 {
536 unsigned data;
537
538 /*
539 * Initialize board..
540 */
541 sc->sc_flags &= ~LEMAC_LINKUP;
542 sc->sc_if.if_flags &= ~IFF_OACTIVE;
543 LEMAC_INTR_DISABLE(sc);
544
545 LEMAC_OUTB(sc, LEMAC_REG_IOP, LEMAC_IOP_EEINIT);
546 DELAY(LEMAC_EEP_DELAY);
547
548 /*
549 * Read EEPROM information. NOTE - the placement of this function
550 * is important because functions hereafter may rely on information
551 * read from the EEPROM.
552 */
553 if ((data = lemac_read_eeprom(sc)) != LEMAC_EEP_CKSUM) {
554 printf("%s: reset: EEPROM checksum failed (0x%x)\n",
555 sc->sc_if.if_xname, data);
556 return;
557 }
558
559 /*
560 * Update the control register to reflect the media choice
561 */
562 data = LEMAC_INB(sc, LEMAC_REG_CTL);
563 if ((data & (LEMAC_CTL_APD|LEMAC_CTL_PSL)) != sc->sc_ctlmode) {
564 data &= ~(LEMAC_CTL_APD|LEMAC_CTL_PSL);
565 data |= sc->sc_ctlmode;
566 LEMAC_OUTB(sc, LEMAC_REG_CTL, data);
567 }
568
569 /*
570 * Force to 2K mode if not already configured.
571 */
572
573 data = LEMAC_INB(sc, LEMAC_REG_MBR);
574 if (LEMAC_IS_2K_MODE(data)) {
575 sc->sc_flags |= LEMAC_2K_MODE;
576 } else if (LEMAC_IS_64K_MODE(data)) {
577 data = (((data * 2) & 0xF) << 4);
578 sc->sc_flags |= LEMAC_WAS_64K_MODE;
579 LEMAC_OUTB(sc, LEMAC_REG_MBR, data);
580 } else if (LEMAC_IS_32K_MODE(data)) {
581 data = ((data & 0xF) << 4);
582 sc->sc_flags |= LEMAC_WAS_32K_MODE;
583 LEMAC_OUTB(sc, LEMAC_REG_MBR, data);
584 } else {
585 sc->sc_flags |= LEMAC_PIO_MODE;
586 /* PIO mode */
587 }
588
589 /*
590 * Initialize Free Memory Queue, Init mcast table with broadcast.
591 */
592
593 lemac_init_adapmem(sc);
594 sc->sc_flags |= LEMAC_ALIVE;
595 }
596
597 static void
599 lemac_init(
600 lemac_softc_t * const sc)
601 {
602 if ((sc->sc_flags & LEMAC_ALIVE) == 0)
603 return;
604
605 /*
606 * If the interface has the up flag
607 */
608 if (sc->sc_if.if_flags & IFF_UP) {
609 int saved_cs = LEMAC_INB(sc, LEMAC_REG_CS);
610 LEMAC_OUTB(sc, LEMAC_REG_CS, saved_cs | (LEMAC_CS_TXD | LEMAC_CS_RXD));
611 LEMAC_OUTB(sc, LEMAC_REG_PA0, LLADDR(sc->sc_if.if_sadl)[0]);
612 LEMAC_OUTB(sc, LEMAC_REG_PA1, LLADDR(sc->sc_if.if_sadl)[1]);
613 LEMAC_OUTB(sc, LEMAC_REG_PA2, LLADDR(sc->sc_if.if_sadl)[2]);
614 LEMAC_OUTB(sc, LEMAC_REG_PA3, LLADDR(sc->sc_if.if_sadl)[3]);
615 LEMAC_OUTB(sc, LEMAC_REG_PA4, LLADDR(sc->sc_if.if_sadl)[4]);
616 LEMAC_OUTB(sc, LEMAC_REG_PA5, LLADDR(sc->sc_if.if_sadl)[5]);
617
618 LEMAC_OUTB(sc, LEMAC_REG_IC, LEMAC_INB(sc, LEMAC_REG_IC) | LEMAC_IC_IE);
619
620 if (sc->sc_if.if_flags & IFF_PROMISC) {
621 LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_MCE | LEMAC_CS_PME);
622 } else {
623 LEMAC_INTR_DISABLE(sc);
624 lemac_multicast_filter(sc);
625 if (sc->sc_flags & LEMAC_ALLMULTI)
626 bcopy(lemac_allmulti_mctbl, sc->sc_mctbl, sizeof(sc->sc_mctbl));
627 if (LEMAC_USE_PIO_MODE(sc)) {
628 LEMAC_OUTB(sc, LEMAC_REG_IOP, 0);
629 LEMAC_OUTB(sc, LEMAC_REG_PI1, LEMAC_MCTBL_OFF & 0xFF);
630 LEMAC_OUTB(sc, LEMAC_REG_PI2, LEMAC_MCTBL_OFF >> 8);
631 LEMAC_OUTSB(sc, LEMAC_REG_DAT, sizeof(sc->sc_mctbl), (void *) sc->sc_mctbl);
632 } else {
633 LEMAC_OUTB(sc, LEMAC_REG_MPN, 0);
634 LEMAC_PUTBUF8(sc, LEMAC_MCTBL_OFF, sizeof(sc->sc_mctbl), (void *) sc->sc_mctbl);
635 }
636
637 LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_MCE);
638 }
639
640 LEMAC_OUTB(sc, LEMAC_REG_CTL, LEMAC_INB(sc, LEMAC_REG_CTL) ^ LEMAC_CTL_LED);
641
642 LEMAC_INTR_ENABLE(sc);
643 sc->sc_if.if_flags |= IFF_RUNNING;
644 lemac_ifstart(&sc->sc_if);
645 } else {
646 LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_RXD|LEMAC_CS_TXD);
647
648 LEMAC_INTR_DISABLE(sc);
649 sc->sc_if.if_flags &= ~IFF_RUNNING;
650 }
651 }
652
653 static void
655 lemac_ifstart(
656 struct ifnet *ifp)
657 {
658 lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp);
659 struct ifqueue * const ifq = &ifp->if_snd;
660
661 if ((ifp->if_flags & IFF_RUNNING) == 0)
662 return;
663
664 LEMAC_INTR_DISABLE(sc);
665
666 while (ifq->ifq_head != NULL) {
667 struct mbuf *m;
668 struct mbuf *m0;
669 int tx_pg;
670
671 if ((sc->sc_csr.csr_tqc = LEMAC_INB(sc, LEMAC_REG_TQC)) >= lemac_txmax) {
672 sc->sc_cntrs.cntr_txfull++;
673 ifp->if_flags |= IFF_OACTIVE;
674 break;
675 }
676
677 /*
678 * get free memory page
679 */
680 tx_pg = sc->sc_csr.csr_fmq = LEMAC_INB(sc, LEMAC_REG_FMQ);
681 /*
682 * Check for good transmit page.
683 */
684 if (tx_pg == 0 || tx_pg > sc->sc_lastpage) {
685 sc->sc_cntrs.cntr_txnospc++;
686 ifp->if_flags |= IFF_OACTIVE;
687 break;
688 }
689
690 IF_DEQUEUE(ifq, m);
691
692 /*
693 * The first four bytes of each transmit buffer are for
694 * control information. The first byte is the control
695 * byte, then the length (why not word aligned??), then
696 * the offset to the buffer.
697 */
698
699 if (LEMAC_USE_PIO_MODE(sc)) {
700 LEMAC_OUTB(sc, LEMAC_REG_IOP, tx_pg); /* Shift 2K window. */
701 LEMAC_OUTB(sc, LEMAC_REG_PI1, 0);
702 LEMAC_OUTB(sc, LEMAC_REG_PI2, 0);
703 LEMAC_OUTB(sc, LEMAC_REG_DAT, sc->sc_txctl);
704 LEMAC_OUTB(sc, LEMAC_REG_DAT, (m->m_pkthdr.len >> 0) & 0xFF);
705 LEMAC_OUTB(sc, LEMAC_REG_DAT, (m->m_pkthdr.len >> 8) & 0xFF);
706 LEMAC_OUTB(sc, LEMAC_REG_DAT, LEMAC_TX_HDRSZ);
707 for (m0 = m; m0 != NULL; m0 = m0->m_next)
708 LEMAC_OUTSB(sc, LEMAC_REG_DAT, m0->m_len, m0->m_data);
709 } else {
710 bus_size_t txoff = /* (mtod(m, u_int32_t) & (sizeof(u_int32_t) - 1)) + */ LEMAC_TX_HDRSZ;
711 LEMAC_OUTB(sc, LEMAC_REG_MPN, tx_pg); /* Shift 2K window. */
712 LEMAC_PUT8(sc, 0, sc->sc_txctl);
713 LEMAC_PUT8(sc, 1, (m->m_pkthdr.len >> 0) & 0xFF);
714 LEMAC_PUT8(sc, 2, (m->m_pkthdr.len >> 8) & 0xFF);
715 LEMAC_PUT8(sc, 3, txoff);
716
717 /*
718 * Copy the packet to the board
719 */
720 for (m0 = m; m0 != NULL; m0 = m0->m_next) {
721 #if 0
722 LEMAC_PUTBUF8(sc, txoff, m0->m_len, m0->m_data);
723 txoff += m0->m_len;
724 #else
725 const u_int8_t *cp = m0->m_data;
726 int len = m0->m_len;
727 #if 0
728 if ((txoff & 3) == (((long)cp) & 3) && len >= 4) {
729 if (txoff & 3) {
730 int alen = (~txoff & 3);
731 LEMAC_PUTBUF8(sc, txoff, alen, cp);
732 cp += alen; txoff += alen; len -= alen;
733 }
734 if (len >= 4) {
735 LEMAC_PUTBUF32(sc, txoff, len / 4, cp);
736 cp += len & ~3; txoff += len & ~3; len &= 3;
737 }
738 }
739 #endif
740 if ((txoff & 1) == (((long)cp) & 1) && len >= 2) {
741 if (txoff & 1) {
742 int alen = (~txoff & 1);
743 LEMAC_PUTBUF8(sc, txoff, alen, cp);
744 cp += alen; txoff += alen; len -= alen;
745 }
746 if (len >= 2) {
747 LEMAC_PUTBUF16(sc, txoff, len / 2, (void *) cp);
748 cp += len & ~1; txoff += len & ~1; len &= 1;
749 }
750 }
751 if (len > 0) {
752 LEMAC_PUTBUF8(sc, txoff, len, cp);
753 txoff += len;
754 }
755 #endif
756 }
757 }
758
759 LEMAC_OUTB(sc, LEMAC_REG_TQ, tx_pg); /* tell chip to transmit this packet */
760 #if NBPFILTER > 0
761 if (sc->sc_if.if_bpf != NULL)
762 bpf_mtap(sc->sc_if.if_bpf, m);
763 #endif
764 m_freem(m); /* free the mbuf */
765 }
766 LEMAC_INTR_ENABLE(sc);
767 }
768
769 static int
771 lemac_ifioctl(
772 struct ifnet *ifp,
773 u_long cmd,
774 caddr_t data)
775 {
776 lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp);
777 int s;
778 int error = 0;
779
780 s = splnet();
781
782 switch (cmd) {
783 case SIOCSIFADDR: {
784 struct ifaddr *ifa = (struct ifaddr *)data;
785
786 ifp->if_flags |= IFF_UP;
787 lemac_init(sc);
788 switch (ifa->ifa_addr->sa_family) {
789 #ifdef INET
790 case AF_INET: {
791 arp_ifinit(&sc->sc_if, ifa);
792 break;
793 }
794 #endif /* INET */
795
796 #ifdef NS
797 /* This magic copied from if_is.c; I don't use XNS,
798 * so I have no way of telling if this actually
799 * works or not.
800 */
801 case AF_NS: {
802 struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
803 if (ns_nullhost(*ina)) {
804 ina->x_host = *(union ns_host *)LLADDR(ifp->if_sadl);
805 } else {
806 bcopy((caddr_t)ina->x_host.c_host,
807 LLADDR(ifp->if_sadl), ifp->if_addrlen);
808 }
809 break;
810 }
811 #endif /* NS */
812
813 default: {
814 break;
815 }
816 }
817 break;
818 }
819
820 case SIOCSIFFLAGS: {
821 lemac_init(sc);
822 break;
823 }
824
825 case SIOCADDMULTI:
826 case SIOCDELMULTI: {
827 /*
828 * Update multicast listeners
829 */
830 if (cmd == SIOCADDMULTI)
831 error = ether_addmulti((struct ifreq *)data, &sc->sc_ec);
832 else
833 error = ether_delmulti((struct ifreq *)data, &sc->sc_ec);
834
835 if (error == ENETRESET) {
836
837 /* reset multicast filtering */
838 lemac_init(sc);
839 error = 0;
840 }
841 break;
842 }
843
844 case SIOCSIFMEDIA:
845 case SIOCGIFMEDIA: {
846 error = ifmedia_ioctl(ifp, (struct ifreq *)data,
847 &sc->sc_ifmedia, cmd);
848 break;
849 }
850
851 default: {
852 error = EINVAL;
853 break;
854 }
855 }
856
857 splx(s);
858 return error;
859 }
860
861 static int
863 lemac_ifmedia_change(
864 struct ifnet * const ifp)
865 {
866 lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp);
867 unsigned new_ctl;
868
869 switch (IFM_SUBTYPE(sc->sc_ifmedia.ifm_media)) {
870 case IFM_10_T: new_ctl = LEMAC_CTL_APD; break;
871 case IFM_10_2:
872 case IFM_10_5: new_ctl = LEMAC_CTL_APD|LEMAC_CTL_PSL; break;
873 case IFM_AUTO: new_ctl = 0; break;
874 default: return EINVAL;
875 }
876 if (sc->sc_ctlmode != new_ctl) {
877 sc->sc_ctlmode = new_ctl;
878 lemac_reset(sc);
879 if (sc->sc_if.if_flags & IFF_UP)
880 lemac_init(sc);
881 }
882 return 0;
883 }
884
885 /*
886 * Media status callback
887 */
888 static void
889 lemac_ifmedia_status(
890 struct ifnet * const ifp,
891 struct ifmediareq *req)
892 {
893 lemac_softc_t *sc = LEMAC_IFP_TO_SOFTC(ifp);
894 unsigned data = LEMAC_INB(sc, LEMAC_REG_CNF);
895
896 req->ifm_status = IFM_AVALID;
897 if (sc->sc_flags & LEMAC_LINKUP)
898 req->ifm_status |= IFM_ACTIVE;
899
900 if (sc->sc_ctlmode & LEMAC_CTL_APD) {
901 if (sc->sc_ctlmode & LEMAC_CTL_PSL) {
902 req->ifm_active = IFM_10_5;
903 } else {
904 req->ifm_active = IFM_10_T;
905 }
906 } else {
907 /*
908 * The link bit of the configuration register reflects the
909 * current media choice when auto-port is enabled.
910 */
911 if (data & LEMAC_CNF_NOLINK) {
912 req->ifm_active = IFM_10_5;
913 } else {
914 req->ifm_active = IFM_10_T;
915 }
916 }
917
918 req->ifm_active |= IFM_ETHER;
919 }
920
921 int
923 lemac_port_check(
924 const bus_space_tag_t iot,
925 const bus_space_handle_t ioh)
926 {
927 unsigned char hwaddr[6];
928
929 if (lemac_read_macaddr(hwaddr, iot, ioh, LEMAC_REG_APD, 0) == 0)
930 return 1;
931 if (lemac_read_macaddr(hwaddr, iot, ioh, LEMAC_REG_APD, 1) == 0)
932 return 1;
933 return 0;
934 }
935
936 void
938 lemac_info_get(
939 const bus_space_tag_t iot,
940 const bus_space_handle_t ioh,
941 bus_addr_t *maddr_p,
942 bus_size_t *msize_p,
943 int *irq_p)
944 {
945 unsigned data;
946
947 *irq_p = LEMAC_DECODEIRQ(bus_space_read_1(iot, ioh, LEMAC_REG_IC) & LEMAC_IC_IRQMSK);
948
949 data = bus_space_read_1(iot, ioh, LEMAC_REG_MBR);
950 if (LEMAC_IS_2K_MODE(data)) {
951 *maddr_p = data * (2 * 1024) + (512 * 1024);
952 *msize_p = 2 * 1024;
953 } else if (LEMAC_IS_64K_MODE(data)) {
954 *maddr_p = data * 64 * 1024;
955 *msize_p = 64 * 1024;
956 } else if (LEMAC_IS_32K_MODE(data)) {
957 *maddr_p = data * 32 * 1024;
958 *msize_p = 32* 1024;
959 } else {
960 *maddr_p = 0;
961 *msize_p = 0;
962 }
963 }
964
965 /*
967 * What to do upon receipt of an interrupt.
968 */
969 int
970 lemac_intr(
971 void *arg)
972 {
973 lemac_softc_t * const sc = arg;
974 int cs_value;
975
976 LEMAC_INTR_DISABLE(sc); /* Mask interrupts */
977
978 /*
979 * Determine cause of interrupt. Receive events take
980 * priority over Transmit.
981 */
982
983 cs_value = LEMAC_INB(sc, LEMAC_REG_CS);
984
985 /*
986 * Check for Receive Queue not being empty.
987 * Check for Transmit Done Queue not being empty.
988 */
989
990 if (cs_value & LEMAC_CS_RNE)
991 lemac_rne_intr(sc);
992 if (cs_value & LEMAC_CS_TNE)
993 lemac_tne_intr(sc);
994
995 /*
996 * Check for Transmitter Disabled.
997 * Check for Receiver Disabled.
998 */
999
1000 if (cs_value & LEMAC_CS_TXD)
1001 lemac_txd_intr(sc, cs_value);
1002 if (cs_value & LEMAC_CS_RXD)
1003 lemac_rxd_intr(sc, cs_value);
1004
1005 /*
1006 * Toggle LED and unmask interrupts.
1007 */
1008
1009 sc->sc_csr.csr_cs = LEMAC_INB(sc, LEMAC_REG_CS);
1010
1011 LEMAC_OUTB(sc, LEMAC_REG_CTL, LEMAC_INB(sc, LEMAC_REG_CTL) ^ LEMAC_CTL_LED);
1012 LEMAC_INTR_ENABLE(sc); /* Unmask interrupts */
1013
1014 #if NRND > 0
1015 if (cs_value)
1016 rnd_add_uint32(&sc->rnd_source, cs_value);
1017 #endif
1018
1019 return 1;
1020 }
1021
1022 void
1023 lemac_shutdown(
1024 void *arg)
1025 {
1026 lemac_reset((lemac_softc_t *) arg);
1027 }
1028
1029 static const char * const lemac_modes[4] = {
1031 "PIO mode (internal 2KB window)",
1032 "2KB window",
1033 "changed 32KB window to 2KB",
1034 "changed 64KB window to 2KB",
1035 };
1036
1037 void
1038 lemac_ifattach(
1039 lemac_softc_t *sc)
1040 {
1041 struct ifnet * const ifp = &sc->sc_if;
1042
1043 bcopy(sc->sc_dv.dv_xname, ifp->if_xname, IFNAMSIZ);
1044
1045 lemac_reset(sc);
1046
1047 (void) lemac_read_macaddr(sc->sc_enaddr, sc->sc_iot, sc->sc_ioh,
1048 LEMAC_REG_APD, 0);
1049
1050 printf(": %s\n", sc->sc_prodname);
1051
1052 printf("%s: address %s, %dKB RAM, %s\n",
1053 ifp->if_xname,
1054 ether_sprintf(sc->sc_enaddr),
1055 sc->sc_lastpage * 2 + 2,
1056 lemac_modes[sc->sc_flags & LEMAC_MODE_MASK]);
1057
1058 ifp->if_baudrate = 10000000;
1059 ifp->if_softc = (void *) sc;
1060 ifp->if_start = lemac_ifstart;
1061 ifp->if_output = ether_output;
1062 ifp->if_ioctl = lemac_ifioctl;
1063
1064 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX
1065 #ifdef IFF_NOTRAILERS
1066 | IFF_NOTRAILERS
1067 #endif
1068 | IFF_MULTICAST;
1069
1070 if (sc->sc_flags & LEMAC_ALIVE) {
1071 int media;
1072
1073 if_attach(ifp);
1074 ether_ifattach(ifp, sc->sc_enaddr);
1075
1076 #if NBPFILTER > 0
1077 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
1078 #endif
1079
1080 #if NRND > 0
1081 rnd_attach_source(&sc->rnd_source, sc->sc_dv.dv_xname, RND_TYPE_NET);
1082 #endif
1083
1084 ifmedia_init(&sc->sc_ifmedia, 0,
1085 lemac_ifmedia_change,
1086 lemac_ifmedia_status);
1087 if (sc->sc_prodname[4] == '5') /* DE205 is UTP/AUI */
1088 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_AUTO, 0, 0);
1089 if (sc->sc_prodname[4] != '3') /* DE204 & 205 have UTP */
1090 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_T, 0, 0);
1091 if (sc->sc_prodname[4] != '4') /* DE203 & 205 have BNC */
1092 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_5, 0, 0);
1093 switch (sc->sc_prodname[4]) {
1094 case '3': media = IFM_10_5; break;
1095 case '4': media = IFM_10_T; break;
1096 default: media = IFM_AUTO; break;
1097 }
1098 ifmedia_set(&sc->sc_ifmedia, IFM_ETHER | media);
1099 } else {
1100 printf("%s: disabled due to error\n", ifp->if_xname);
1101 }
1102 }
1103