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