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