lemac.c revision 1.4 1 /* $NetBSD: lemac.c,v 1.4 1998/03/29 22:08:03 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, bit, crc = 0xFFFFFFFFUL;
470
471 for (idx = 0; idx < 6; idx++) {
472 crc ^= (*mca++) << 0;
473 for (bit = 0; bit < 8; bit++)
474 crc = (crc >> 1) ^ ((crc & 1) ? LEMAC_CRC32_POLY : 0);
475 }
476 /*
477 * The following two lines convert the N bit index into a longword index
478 * and a longword mask.
479 */
480 #if LEMAC_MCTBL_BITS < 0
481 crc >>= (32 + LEMAC_MCTBL_BITS);
482 crc &= (1 << -LEMAC_MCTBL_BITS) - 1;
483 #else
484 crc &= (1 << LEMAC_MCTBL_BITS) - 1;
485 #endif
486 bit = 1 << (crc & 0x0F);
487 idx = crc >> 4;
488
489 /*
490 * Set or clear hash filter bit in our table.
491 */
492 if (enable) {
493 mctbl[idx] |= bit; /* Set Bit */
494 } else {
495 mctbl[idx] &= ~bit; /* Clear Bit */
496 }
497 }
498
499 static void
501 lemac_multicast_filter(
502 lemac_softc_t *sc)
503 {
504 struct ether_multistep step;
505 struct ether_multi *enm;
506
507 bzero(sc->sc_mctbl, LEMAC_MCTBL_BITS / 8);
508
509 lemac_multicast_op(sc->sc_mctbl, etherbroadcastaddr, TRUE);
510
511 ETHER_FIRST_MULTI(step, &sc->sc_ec, enm);
512 while (enm != NULL) {
513 if (!LEMAC_ADDREQUAL(enm->enm_addrlo, enm->enm_addrhi)) {
514 sc->sc_flags |= LEMAC_ALLMULTI;
515 sc->sc_if.if_flags |= IFF_ALLMULTI;
516 return;
517 }
518 lemac_multicast_op(sc->sc_mctbl, enm->enm_addrlo, TRUE);
519 ETHER_NEXT_MULTI(step, enm);
520 }
521 sc->sc_flags &= ~LEMAC_ALLMULTI;
522 sc->sc_if.if_flags &= ~IFF_ALLMULTI;
523 }
524
525 /*
527 * Do a hard reset of the board;
528 */
529 static void
530 lemac_reset(
531 lemac_softc_t * const sc)
532 {
533 unsigned data;
534
535 /*
536 * Initialize board..
537 */
538 sc->sc_flags &= ~LEMAC_LINKUP;
539 sc->sc_if.if_flags &= ~IFF_OACTIVE;
540 LEMAC_INTR_DISABLE(sc);
541
542 LEMAC_OUTB(sc, LEMAC_REG_IOP, LEMAC_IOP_EEINIT);
543 DELAY(LEMAC_EEP_DELAY);
544
545 /*
546 * Read EEPROM information. NOTE - the placement of this function
547 * is important because functions hereafter may rely on information
548 * read from the EEPROM.
549 */
550 if ((data = lemac_read_eeprom(sc)) != LEMAC_EEP_CKSUM) {
551 printf("%s: reset: EEPROM checksum failed (0x%x)\n",
552 sc->sc_if.if_xname, data);
553 return;
554 }
555
556 /*
557 * Update the control register to reflect the media choice
558 */
559 data = LEMAC_INB(sc, LEMAC_REG_CTL);
560 if ((data & (LEMAC_CTL_APD|LEMAC_CTL_PSL)) != sc->sc_ctlmode) {
561 data &= ~(LEMAC_CTL_APD|LEMAC_CTL_PSL);
562 data |= sc->sc_ctlmode;
563 LEMAC_OUTB(sc, LEMAC_REG_CTL, data);
564 }
565
566 /*
567 * Force to 2K mode if not already configured.
568 */
569
570 data = LEMAC_INB(sc, LEMAC_REG_MBR);
571 if (LEMAC_IS_2K_MODE(data)) {
572 sc->sc_flags |= LEMAC_2K_MODE;
573 } else if (LEMAC_IS_64K_MODE(data)) {
574 data = (((data * 2) & 0xF) << 4);
575 sc->sc_flags |= LEMAC_WAS_64K_MODE;
576 LEMAC_OUTB(sc, LEMAC_REG_MBR, data);
577 } else if (LEMAC_IS_32K_MODE(data)) {
578 data = ((data & 0xF) << 4);
579 sc->sc_flags |= LEMAC_WAS_32K_MODE;
580 LEMAC_OUTB(sc, LEMAC_REG_MBR, data);
581 } else {
582 sc->sc_flags |= LEMAC_PIO_MODE;
583 /* PIO mode */
584 }
585
586 /*
587 * Initialize Free Memory Queue, Init mcast table with broadcast.
588 */
589
590 lemac_init_adapmem(sc);
591 sc->sc_flags |= LEMAC_ALIVE;
592 }
593
594 static void
596 lemac_init(
597 lemac_softc_t * const sc)
598 {
599 if ((sc->sc_flags & LEMAC_ALIVE) == 0)
600 return;
601
602 /*
603 * If the interface has the up flag
604 */
605 if (sc->sc_if.if_flags & IFF_UP) {
606 int saved_cs = LEMAC_INB(sc, LEMAC_REG_CS);
607 LEMAC_OUTB(sc, LEMAC_REG_CS, saved_cs | (LEMAC_CS_TXD | LEMAC_CS_RXD));
608 LEMAC_OUTB(sc, LEMAC_REG_PA0, LLADDR(sc->sc_if.if_sadl)[0]);
609 LEMAC_OUTB(sc, LEMAC_REG_PA1, LLADDR(sc->sc_if.if_sadl)[1]);
610 LEMAC_OUTB(sc, LEMAC_REG_PA2, LLADDR(sc->sc_if.if_sadl)[2]);
611 LEMAC_OUTB(sc, LEMAC_REG_PA3, LLADDR(sc->sc_if.if_sadl)[3]);
612 LEMAC_OUTB(sc, LEMAC_REG_PA4, LLADDR(sc->sc_if.if_sadl)[4]);
613 LEMAC_OUTB(sc, LEMAC_REG_PA5, LLADDR(sc->sc_if.if_sadl)[5]);
614
615 LEMAC_OUTB(sc, LEMAC_REG_IC, LEMAC_INB(sc, LEMAC_REG_IC) | LEMAC_IC_IE);
616
617 if (sc->sc_if.if_flags & IFF_PROMISC) {
618 LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_MCE | LEMAC_CS_PME);
619 } else {
620 LEMAC_INTR_DISABLE(sc);
621 lemac_multicast_filter(sc);
622 if (sc->sc_flags & LEMAC_ALLMULTI)
623 bcopy(lemac_allmulti_mctbl, sc->sc_mctbl, sizeof(sc->sc_mctbl));
624 if (LEMAC_USE_PIO_MODE(sc)) {
625 LEMAC_OUTB(sc, LEMAC_REG_IOP, 0);
626 LEMAC_OUTB(sc, LEMAC_REG_PI1, LEMAC_MCTBL_OFF & 0xFF);
627 LEMAC_OUTB(sc, LEMAC_REG_PI2, LEMAC_MCTBL_OFF >> 8);
628 LEMAC_OUTSB(sc, LEMAC_REG_DAT, sizeof(sc->sc_mctbl), (void *) sc->sc_mctbl);
629 } else {
630 LEMAC_OUTB(sc, LEMAC_REG_MPN, 0);
631 LEMAC_PUTBUF8(sc, LEMAC_MCTBL_OFF, sizeof(sc->sc_mctbl), (void *) sc->sc_mctbl);
632 }
633
634 LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_MCE);
635 }
636
637 LEMAC_OUTB(sc, LEMAC_REG_CTL, LEMAC_INB(sc, LEMAC_REG_CTL) ^ LEMAC_CTL_LED);
638
639 LEMAC_INTR_ENABLE(sc);
640 sc->sc_if.if_flags |= IFF_RUNNING;
641 lemac_ifstart(&sc->sc_if);
642 } else {
643 LEMAC_OUTB(sc, LEMAC_REG_CS, LEMAC_CS_RXD|LEMAC_CS_TXD);
644
645 LEMAC_INTR_DISABLE(sc);
646 sc->sc_if.if_flags &= ~IFF_RUNNING;
647 }
648 }
649
650 static void
652 lemac_ifstart(
653 struct ifnet *ifp)
654 {
655 lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp);
656 struct ifqueue * const ifq = &ifp->if_snd;
657
658 if ((ifp->if_flags & IFF_RUNNING) == 0)
659 return;
660
661 LEMAC_INTR_DISABLE(sc);
662
663 while (ifq->ifq_head != NULL) {
664 struct mbuf *m;
665 struct mbuf *m0;
666 int tx_pg;
667
668 if ((sc->sc_csr.csr_tqc = LEMAC_INB(sc, LEMAC_REG_TQC)) >= lemac_txmax) {
669 sc->sc_cntrs.cntr_txfull++;
670 ifp->if_flags |= IFF_OACTIVE;
671 break;
672 }
673
674 /*
675 * get free memory page
676 */
677 tx_pg = sc->sc_csr.csr_fmq = LEMAC_INB(sc, LEMAC_REG_FMQ);
678 /*
679 * Check for good transmit page.
680 */
681 if (tx_pg == 0 || tx_pg > sc->sc_lastpage) {
682 sc->sc_cntrs.cntr_txnospc++;
683 ifp->if_flags |= IFF_OACTIVE;
684 break;
685 }
686
687 IF_DEQUEUE(ifq, m);
688
689 /*
690 * The first four bytes of each transmit buffer are for
691 * control information. The first byte is the control
692 * byte, then the length (why not word aligned??), then
693 * the offset to the buffer.
694 */
695
696 if (LEMAC_USE_PIO_MODE(sc)) {
697 LEMAC_OUTB(sc, LEMAC_REG_IOP, tx_pg); /* Shift 2K window. */
698 LEMAC_OUTB(sc, LEMAC_REG_PI1, 0);
699 LEMAC_OUTB(sc, LEMAC_REG_PI2, 0);
700 LEMAC_OUTB(sc, LEMAC_REG_DAT, sc->sc_txctl);
701 LEMAC_OUTB(sc, LEMAC_REG_DAT, (m->m_pkthdr.len >> 0) & 0xFF);
702 LEMAC_OUTB(sc, LEMAC_REG_DAT, (m->m_pkthdr.len >> 8) & 0xFF);
703 LEMAC_OUTB(sc, LEMAC_REG_DAT, LEMAC_TX_HDRSZ);
704 for (m0 = m; m0 != NULL; m0 = m0->m_next)
705 LEMAC_OUTSB(sc, LEMAC_REG_DAT, m0->m_len, m0->m_data);
706 } else {
707 bus_size_t txoff = /* (mtod(m, u_int32_t) & (sizeof(u_int32_t) - 1)) + */ LEMAC_TX_HDRSZ;
708 LEMAC_OUTB(sc, LEMAC_REG_MPN, tx_pg); /* Shift 2K window. */
709 LEMAC_PUT8(sc, 0, sc->sc_txctl);
710 LEMAC_PUT8(sc, 1, (m->m_pkthdr.len >> 0) & 0xFF);
711 LEMAC_PUT8(sc, 2, (m->m_pkthdr.len >> 8) & 0xFF);
712 LEMAC_PUT8(sc, 3, txoff);
713
714 /*
715 * Copy the packet to the board
716 */
717 for (m0 = m; m0 != NULL; m0 = m0->m_next) {
718 #if 0
719 LEMAC_PUTBUF8(sc, txoff, m0->m_len, m0->m_data);
720 txoff += m0->m_len;
721 #else
722 const u_int8_t *cp = m0->m_data;
723 int len = m0->m_len;
724 #if 0
725 if ((txoff & 3) == (((long)cp) & 3) && len >= 4) {
726 if (txoff & 3) {
727 int alen = (~txoff & 3);
728 LEMAC_PUTBUF8(sc, txoff, alen, cp);
729 cp += alen; txoff += alen; len -= alen;
730 }
731 if (len >= 4) {
732 LEMAC_PUTBUF32(sc, txoff, len / 4, cp);
733 cp += len & ~3; txoff += len & ~3; len &= 3;
734 }
735 }
736 #endif
737 if ((txoff & 1) == (((long)cp) & 1) && len >= 2) {
738 if (txoff & 1) {
739 int alen = (~txoff & 1);
740 LEMAC_PUTBUF8(sc, txoff, alen, cp);
741 cp += alen; txoff += alen; len -= alen;
742 }
743 if (len >= 2) {
744 LEMAC_PUTBUF16(sc, txoff, len / 2, (void *) cp);
745 cp += len & ~1; txoff += len & ~1; len &= 1;
746 }
747 }
748 if (len > 0) {
749 LEMAC_PUTBUF8(sc, txoff, len, cp);
750 txoff += len;
751 }
752 #endif
753 }
754 }
755
756 LEMAC_OUTB(sc, LEMAC_REG_TQ, tx_pg); /* tell chip to transmit this packet */
757 #if NBPFILTER > 0
758 if (sc->sc_if.if_bpf != NULL)
759 bpf_mtap(sc->sc_if.if_bpf, m);
760 #endif
761 m_freem(m); /* free the mbuf */
762 }
763 LEMAC_INTR_ENABLE(sc);
764 }
765
766 static int
768 lemac_ifioctl(
769 struct ifnet *ifp,
770 u_long cmd,
771 caddr_t data)
772 {
773 lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp);
774 int s;
775 int error = 0;
776
777 s = splnet();
778
779 switch (cmd) {
780 case SIOCSIFADDR: {
781 struct ifaddr *ifa = (struct ifaddr *)data;
782
783 ifp->if_flags |= IFF_UP;
784 lemac_init(sc);
785 switch (ifa->ifa_addr->sa_family) {
786 #ifdef INET
787 case AF_INET: {
788 arp_ifinit(&sc->sc_if, ifa);
789 break;
790 }
791 #endif /* INET */
792
793 #ifdef NS
794 /* This magic copied from if_is.c; I don't use XNS,
795 * so I have no way of telling if this actually
796 * works or not.
797 */
798 case AF_NS: {
799 struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr);
800 if (ns_nullhost(*ina)) {
801 ina->x_host = *(union ns_host *)LLADDR(ifp->if_sadl);
802 } else {
803 bcopy((caddr_t)ina->x_host.c_host,
804 LLADDR(ifp->if_sadl), ifp->if_addrlen);
805 }
806 break;
807 }
808 #endif /* NS */
809
810 default: {
811 break;
812 }
813 }
814 break;
815 }
816
817 case SIOCSIFFLAGS: {
818 lemac_init(sc);
819 break;
820 }
821
822 case SIOCADDMULTI:
823 case SIOCDELMULTI: {
824 /*
825 * Update multicast listeners
826 */
827 if (cmd == SIOCADDMULTI)
828 error = ether_addmulti((struct ifreq *)data, &sc->sc_ec);
829 else
830 error = ether_delmulti((struct ifreq *)data, &sc->sc_ec);
831
832 if (error == ENETRESET) {
833
834 /* reset multicast filtering */
835 lemac_init(sc);
836 error = 0;
837 }
838 break;
839 }
840
841 case SIOCSIFMEDIA:
842 case SIOCGIFMEDIA: {
843 error = ifmedia_ioctl(ifp, (struct ifreq *)data,
844 &sc->sc_ifmedia, cmd);
845 break;
846 }
847
848 default: {
849 error = EINVAL;
850 break;
851 }
852 }
853
854 splx(s);
855 return error;
856 }
857
858 static int
860 lemac_ifmedia_change(
861 struct ifnet * const ifp)
862 {
863 lemac_softc_t * const sc = LEMAC_IFP_TO_SOFTC(ifp);
864 unsigned new_ctl;
865
866 switch (IFM_SUBTYPE(sc->sc_ifmedia.ifm_media)) {
867 case IFM_10_T: new_ctl = LEMAC_CTL_APD; break;
868 case IFM_10_2:
869 case IFM_10_5: new_ctl = LEMAC_CTL_APD|LEMAC_CTL_PSL; break;
870 case IFM_AUTO: new_ctl = 0; break;
871 default: return EINVAL;
872 }
873 if (sc->sc_ctlmode != new_ctl) {
874 sc->sc_ctlmode = new_ctl;
875 lemac_reset(sc);
876 if (sc->sc_if.if_flags & IFF_UP)
877 lemac_init(sc);
878 }
879 return 0;
880 }
881
882 /*
883 * Media status callback
884 */
885 static void
886 lemac_ifmedia_status(
887 struct ifnet * const ifp,
888 struct ifmediareq *req)
889 {
890 lemac_softc_t *sc = LEMAC_IFP_TO_SOFTC(ifp);
891 unsigned data = LEMAC_INB(sc, LEMAC_REG_CNF);
892
893 req->ifm_status = IFM_AVALID;
894 if (sc->sc_flags & LEMAC_LINKUP)
895 req->ifm_status |= IFM_ACTIVE;
896
897 if (sc->sc_ctlmode & LEMAC_CTL_APD) {
898 if (sc->sc_ctlmode & LEMAC_CTL_PSL) {
899 req->ifm_active = IFM_10_5;
900 } else {
901 req->ifm_active = IFM_10_T;
902 }
903 } else {
904 /*
905 * The link bit of the configuration register reflects the
906 * current media choice when auto-port is enabled.
907 */
908 if (data & LEMAC_CNF_NOLINK) {
909 req->ifm_active = IFM_10_5;
910 } else {
911 req->ifm_active = IFM_10_T;
912 }
913 }
914
915 req->ifm_active |= IFM_ETHER;
916 }
917
918 int
920 lemac_port_check(
921 const bus_space_tag_t iot,
922 const bus_space_handle_t ioh)
923 {
924 unsigned char hwaddr[6];
925
926 if (lemac_read_macaddr(hwaddr, iot, ioh, LEMAC_REG_APD, 0) == 0)
927 return 1;
928 if (lemac_read_macaddr(hwaddr, iot, ioh, LEMAC_REG_APD, 1) == 0)
929 return 1;
930 return 0;
931 }
932
933 void
935 lemac_info_get(
936 const bus_space_tag_t iot,
937 const bus_space_handle_t ioh,
938 bus_addr_t *maddr_p,
939 bus_size_t *msize_p,
940 int *irq_p)
941 {
942 unsigned data;
943
944 *irq_p = LEMAC_DECODEIRQ(bus_space_read_1(iot, ioh, LEMAC_REG_IC) & LEMAC_IC_IRQMSK);
945
946 data = bus_space_read_1(iot, ioh, LEMAC_REG_MBR);
947 if (LEMAC_IS_2K_MODE(data)) {
948 *maddr_p = data * (2 * 1024) + (512 * 1024);
949 *msize_p = 2 * 1024;
950 } else if (LEMAC_IS_64K_MODE(data)) {
951 *maddr_p = data * 64 * 1024;
952 *msize_p = 64 * 1024;
953 } else if (LEMAC_IS_32K_MODE(data)) {
954 *maddr_p = data * 32 * 1024;
955 *msize_p = 32* 1024;
956 } else {
957 *maddr_p = 0;
958 *msize_p = 0;
959 }
960 }
961
962 /*
964 * What to do upon receipt of an interrupt.
965 */
966 int
967 lemac_intr(
968 void *arg)
969 {
970 lemac_softc_t * const sc = arg;
971 int cs_value;
972
973 LEMAC_INTR_DISABLE(sc); /* Mask interrupts */
974
975 /*
976 * Determine cause of interrupt. Receive events take
977 * priority over Transmit.
978 */
979
980 cs_value = LEMAC_INB(sc, LEMAC_REG_CS);
981
982 /*
983 * Check for Receive Queue not being empty.
984 * Check for Transmit Done Queue not being empty.
985 */
986
987 if (cs_value & LEMAC_CS_RNE)
988 lemac_rne_intr(sc);
989 if (cs_value & LEMAC_CS_TNE)
990 lemac_tne_intr(sc);
991
992 /*
993 * Check for Transmitter Disabled.
994 * Check for Receiver Disabled.
995 */
996
997 if (cs_value & LEMAC_CS_TXD)
998 lemac_txd_intr(sc, cs_value);
999 if (cs_value & LEMAC_CS_RXD)
1000 lemac_rxd_intr(sc, cs_value);
1001
1002 /*
1003 * Toggle LED and unmask interrupts.
1004 */
1005
1006 sc->sc_csr.csr_cs = LEMAC_INB(sc, LEMAC_REG_CS);
1007
1008 LEMAC_OUTB(sc, LEMAC_REG_CTL, LEMAC_INB(sc, LEMAC_REG_CTL) ^ LEMAC_CTL_LED);
1009 LEMAC_INTR_ENABLE(sc); /* Unmask interrupts */
1010
1011 #if NRND > 0
1012 if (cs_value)
1013 rnd_add_uint32(&sc->rnd_source, cs_value);
1014 #endif
1015
1016 return 1;
1017 }
1018
1019 void
1020 lemac_shutdown(
1021 void *arg)
1022 {
1023 lemac_reset((lemac_softc_t *) arg);
1024 }
1025
1026 static const char * const lemac_modes[4] = {
1028 "PIO mode (internal 2KB window)",
1029 "2KB window",
1030 "changed 32KB window to 2KB",
1031 "changed 64KB window to 2KB",
1032 };
1033
1034 void
1035 lemac_ifattach(
1036 lemac_softc_t *sc)
1037 {
1038 struct ifnet * const ifp = &sc->sc_if;
1039
1040 bcopy(sc->sc_dv.dv_xname, ifp->if_xname, IFNAMSIZ);
1041
1042 lemac_reset(sc);
1043
1044 (void) lemac_read_macaddr(sc->sc_enaddr, sc->sc_iot, sc->sc_ioh,
1045 LEMAC_REG_APD, 0);
1046
1047 printf(": %s\n", sc->sc_prodname);
1048
1049 printf("%s: address %s, %dKB RAM, %s\n",
1050 ifp->if_xname,
1051 ether_sprintf(sc->sc_enaddr),
1052 sc->sc_lastpage * 2 + 2,
1053 lemac_modes[sc->sc_flags & LEMAC_MODE_MASK]);
1054
1055 ifp->if_baudrate = 10000000;
1056 ifp->if_softc = (void *) sc;
1057 ifp->if_start = lemac_ifstart;
1058 ifp->if_output = ether_output;
1059 ifp->if_ioctl = lemac_ifioctl;
1060
1061 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX
1062 #ifdef IFF_NOTRAILERS
1063 | IFF_NOTRAILERS
1064 #endif
1065 | IFF_MULTICAST;
1066
1067 if (sc->sc_flags & LEMAC_ALIVE) {
1068 int media;
1069
1070 if_attach(ifp);
1071 ether_ifattach(ifp, sc->sc_enaddr);
1072
1073 #if NBPFILTER > 0
1074 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));
1075 #endif
1076
1077 #if NRND > 0
1078 rnd_attach_source(&sc->rnd_source, sc->sc_dv.dv_xname, RND_TYPE_NET);
1079 #endif
1080
1081 ifmedia_init(&sc->sc_ifmedia, 0,
1082 lemac_ifmedia_change,
1083 lemac_ifmedia_status);
1084 if (sc->sc_prodname[4] == '5') /* DE205 is UTP/AUI */
1085 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_AUTO, 0, 0);
1086 if (sc->sc_prodname[4] != '3') /* DE204 & 205 have UTP */
1087 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_T, 0, 0);
1088 if (sc->sc_prodname[4] != '4') /* DE203 & 205 have BNC */
1089 ifmedia_add(&sc->sc_ifmedia, IFM_ETHER | IFM_10_5, 0, 0);
1090 switch (sc->sc_prodname[4]) {
1091 case '3': media = IFM_10_5; break;
1092 case '4': media = IFM_10_T; break;
1093 default: media = IFM_AUTO; break;
1094 }
1095 ifmedia_set(&sc->sc_ifmedia, IFM_ETHER | media);
1096 } else {
1097 printf("%s: disabled due to error\n", ifp->if_xname);
1098 }
1099 }
1100