1 /** $MirOS: src/sys/dev/ic/am7990.c,v 1.2 2005/03/06 21:27:38 tg Exp $ */
2 /* $OpenBSD: am7990.c,v 1.34 2004/05/12 06:35:10 tedu Exp $ */
3 /* $NetBSD: am7990.c,v 1.22 1996/10/13 01:37:19 christos Exp $ */
4
5 /*-
6 * Copyright (c) 1995 Charles M. Hannum. All rights reserved.
7 * Copyright (c) 1992, 1993
8 * The Regents of the University of California. All rights reserved.
9 *
10 * This code is derived from software contributed to Berkeley by
11 * Ralph Campbell and Rick Macklem.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * @(#)if_le.c 8.2 (Berkeley) 11/16/93
38 */
39
40 #include "bpfilter.h"
41
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/mbuf.h>
45 #include <sys/syslog.h>
46 #include <sys/socket.h>
47 #include <sys/device.h>
48 #include <sys/malloc.h>
49 #include <sys/ioctl.h>
50 #include <sys/errno.h>
51
52 #include <net/if.h>
53 #include <net/if_media.h>
54
55 #ifdef INET
56 #include <netinet/in.h>
57 #include <netinet/if_ether.h>
58 #include <netinet/in_systm.h>
59 #include <netinet/in_var.h>
60 #include <netinet/ip.h>
61 #endif
62
63 #if NBPFILTER > 0
64 #include <net/bpf.h>
65 #endif
66
67 #include <dev/ic/am7990reg.h>
68 #include <dev/ic/am7990var.h>
69
70 #ifdef LEDEBUG
71 void am7990_recv_print(struct am7990_softc *, int);
72 void am7990_xmit_print(struct am7990_softc *, int);
73 #endif
74
75 integrate void am7990_rint(struct am7990_softc *);
76 integrate void am7990_tint(struct am7990_softc *);
77
78 integrate int am7990_put(struct am7990_softc *, int, struct mbuf *);
79 integrate struct mbuf *am7990_get(struct am7990_softc *, int, int);
80 integrate void am7990_read(struct am7990_softc *, int, int);
81
82 hide void am7990_shutdown(void *);
83
84 #define ifp (&sc->sc_arpcom.ac_if)
85
86 #if 0 /* XXX what do we do about this?! --thorpej */
87 static inline u_int16_t ether_cmp(void *, void *);
88
89 /*
90 * Compare two Ether/802 addresses for equality, inlined and
91 * unrolled for speed. I'd love to have an inline assembler
92 * version of this... XXX: Who wanted that? mycroft?
93 * I wrote one, but the following is just as efficient.
94 * This expands to 10 short m68k instructions! -gwr
95 * Note: use this like bcmp()
96 */
97 static inline u_short
98 ether_cmp(one, two)
99 void *one, *two;
100 {
101 register u_int16_t *a = (u_short *) one;
102 register u_int16_t *b = (u_short *) two;
103 register u_int16_t diff;
104
105 diff = *a++ - *b++;
106 diff |= *a++ - *b++;
107 diff |= *a++ - *b++;
108
109 return (diff);
110 }
111
112 #define ETHER_CMP ether_cmp
113 #endif /* XXX */
114
115 #ifndef ETHER_CMP
116 #define ETHER_CMP(a, b) bcmp((a), (b), ETHER_ADDR_LEN)
117 #endif
118
119 /*
120 * am7990 configuration driver. Attachments are provided by
121 * machine-dependent driver front-ends.
122 */
123 struct cfdriver le_cd = {
124 NULL, "le", DV_IFNET
125 };
126
127 void
am7990_config(sc)128 am7990_config(sc)
129 struct am7990_softc *sc;
130 {
131 int mem;
132
133 /* Make sure the chip is stopped. */
134 am7990_stop(sc);
135
136 /* Initialize ifnet structure. */
137 bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
138 ifp->if_softc = sc;
139 ifp->if_start = am7990_start;
140 ifp->if_ioctl = am7990_ioctl;
141 ifp->if_watchdog = am7990_watchdog;
142 ifp->if_flags =
143 IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST;
144 #ifdef LANCE_REVC_BUG
145 ifp->if_flags &= ~IFF_MULTICAST;
146 #endif
147 ifp->if_baudrate = IF_Mbps(10);
148 IFQ_SET_READY(&ifp->if_snd);
149
150 /* Attach the interface. */
151 if_attach(ifp);
152 ether_ifattach(ifp);
153
154 if (sc->sc_memsize > 262144)
155 sc->sc_memsize = 262144;
156
157 switch (sc->sc_memsize) {
158 case 8192:
159 sc->sc_nrbuf = 4;
160 sc->sc_ntbuf = 1;
161 break;
162 case 16384:
163 sc->sc_nrbuf = 8;
164 sc->sc_ntbuf = 2;
165 break;
166 case 32768:
167 sc->sc_nrbuf = 16;
168 sc->sc_ntbuf = 4;
169 break;
170 case 65536:
171 sc->sc_nrbuf = 32;
172 sc->sc_ntbuf = 8;
173 break;
174 case 131072:
175 sc->sc_nrbuf = 64;
176 sc->sc_ntbuf = 16;
177 break;
178 case 262144:
179 sc->sc_nrbuf = 128;
180 sc->sc_ntbuf = 32;
181 break;
182 default:
183 panic("am7990_config: weird memory size %lu",
184 (long)sc->sc_memsize);
185 }
186
187 printf(": address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
188 printf("%s: %d receive buffers, %d transmit buffers\n",
189 sc->sc_dev.dv_xname, sc->sc_nrbuf, sc->sc_ntbuf);
190
191 sc->sc_sh = shutdownhook_establish(am7990_shutdown, sc);
192 if (sc->sc_sh == NULL)
193 panic("am7990_config: can't establish shutdownhook");
194
195 mem = 0;
196 sc->sc_initaddr = mem;
197 mem += sizeof(struct leinit);
198 sc->sc_rmdaddr = mem;
199 mem += sizeof(struct lermd) * sc->sc_nrbuf;
200 sc->sc_tmdaddr = mem;
201 mem += sizeof(struct letmd) * sc->sc_ntbuf;
202 sc->sc_rbufaddr = mem;
203 mem += LEBLEN * sc->sc_nrbuf;
204 sc->sc_tbufaddr = mem;
205 mem += LEBLEN * sc->sc_ntbuf;
206 #ifdef notyet
207 if (mem > ...)
208 panic(...);
209 #endif
210 }
211
212 void
am7990_reset(sc)213 am7990_reset(sc)
214 struct am7990_softc *sc;
215 {
216 int s;
217
218 s = splimp();
219 am7990_init(sc);
220 splx(s);
221 }
222
223 /*
224 * Set up the initialization block and the descriptor rings.
225 */
226 void
am7990_meminit(sc)227 am7990_meminit(sc)
228 register struct am7990_softc *sc;
229 {
230 u_long a;
231 int bix;
232 struct leinit init;
233 struct lermd rmd;
234 struct letmd tmd;
235
236 #if NBPFILTER > 0
237 if (ifp->if_flags & IFF_PROMISC)
238 init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM;
239 else
240 #endif
241 init.init_mode = LE_MODE_NORMAL;
242 init.init_padr[0] =
243 (sc->sc_arpcom.ac_enaddr[1] << 8) | sc->sc_arpcom.ac_enaddr[0];
244 init.init_padr[1] =
245 (sc->sc_arpcom.ac_enaddr[3] << 8) | sc->sc_arpcom.ac_enaddr[2];
246 init.init_padr[2] =
247 (sc->sc_arpcom.ac_enaddr[5] << 8) | sc->sc_arpcom.ac_enaddr[4];
248 am7990_setladrf(&sc->sc_arpcom, init.init_ladrf);
249
250 sc->sc_last_rd = 0;
251 sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
252
253 a = sc->sc_addr + LE_RMDADDR(sc, 0);
254 init.init_rdra = a;
255 init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13);
256
257 a = sc->sc_addr + LE_TMDADDR(sc, 0);
258 init.init_tdra = a;
259 init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13);
260
261 (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
262
263 /*
264 * Set up receive ring descriptors.
265 */
266 for (bix = 0; bix < sc->sc_nrbuf; bix++) {
267 a = sc->sc_addr + LE_RBUFADDR(sc, bix);
268 rmd.rmd0 = a;
269 rmd.rmd1_hadr = a >> 16;
270 rmd.rmd1_bits = LE_R1_OWN;
271 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
272 rmd.rmd3 = 0;
273 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
274 sizeof(rmd));
275 }
276
277 /*
278 * Set up transmit ring descriptors.
279 */
280 for (bix = 0; bix < sc->sc_ntbuf; bix++) {
281 a = sc->sc_addr + LE_TBUFADDR(sc, bix);
282 tmd.tmd0 = a;
283 tmd.tmd1_hadr = a >> 16;
284 tmd.tmd1_bits = 0;
285 tmd.tmd2 = 0 | LE_XMD2_ONES;
286 tmd.tmd3 = 0;
287 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
288 sizeof(tmd));
289 }
290 }
291
292 void
am7990_stop(sc)293 am7990_stop(sc)
294 struct am7990_softc *sc;
295 {
296
297 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
298 }
299
300 /*
301 * Initialization of interface; set up initialization block
302 * and transmit/receive descriptor rings.
303 */
304 void
am7990_init(sc)305 am7990_init(sc)
306 register struct am7990_softc *sc;
307 {
308 register int timo;
309 u_long a;
310
311 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP);
312 DELAY(100);
313
314 /* Newer LANCE chips have a reset register */
315 if (sc->sc_hwreset)
316 (*sc->sc_hwreset)(sc);
317
318 /* Set the correct byte swapping mode, etc. */
319 (*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3);
320
321 /* Set up LANCE init block. */
322 am7990_meminit(sc);
323
324 /* Give LANCE the physical address of its init block. */
325 a = sc->sc_addr + LE_INITADDR(sc);
326 (*sc->sc_wrcsr)(sc, LE_CSR1, a);
327 (*sc->sc_wrcsr)(sc, LE_CSR2, a >> 16);
328
329 /* Try to initialize the LANCE. */
330 DELAY(100);
331 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INIT);
332
333 /* Wait for initialization to finish. */
334 for (timo = 100000; timo; timo--)
335 if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON)
336 break;
337
338 if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) {
339 /* Start the LANCE. */
340 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT |
341 LE_C0_IDON);
342 ifp->if_flags |= IFF_RUNNING;
343 ifp->if_flags &= ~IFF_OACTIVE;
344 ifp->if_timer = 0;
345 am7990_start(ifp);
346 } else
347 printf("%s: controller failed to initialize\n", sc->sc_dev.dv_xname);
348 if (sc->sc_hwinit)
349 (*sc->sc_hwinit)(sc);
350 }
351
352 /*
353 * Routine to copy from mbuf chain to transmit buffer in
354 * network buffer memory.
355 */
356 integrate int
am7990_put(sc,boff,m)357 am7990_put(sc, boff, m)
358 struct am7990_softc *sc;
359 int boff;
360 register struct mbuf *m;
361 {
362 register struct mbuf *n;
363 register int len, tlen = 0;
364
365 for (; m; m = n) {
366 len = m->m_len;
367 if (len == 0) {
368 MFREE(m, n);
369 continue;
370 }
371 (*sc->sc_copytobuf)(sc, mtod(m, caddr_t), boff, len);
372 boff += len;
373 tlen += len;
374 MFREE(m, n);
375 }
376 if (tlen < LEMINSIZE) {
377 (*sc->sc_zerobuf)(sc, boff, LEMINSIZE - tlen);
378 tlen = LEMINSIZE;
379 }
380 return (tlen);
381 }
382
383 /*
384 * Pull data off an interface.
385 * Len is length of data, with local net header stripped.
386 * We copy the data into mbufs. When full cluster sized units are present
387 * we copy into clusters.
388 */
389 integrate struct mbuf *
am7990_get(sc,boff,totlen)390 am7990_get(sc, boff, totlen)
391 struct am7990_softc *sc;
392 int boff, totlen;
393 {
394 register struct mbuf *m;
395 struct mbuf *top, **mp;
396 int len, pad;
397
398 MGETHDR(m, M_DONTWAIT, MT_DATA);
399 if (m == 0)
400 return (0);
401 m->m_pkthdr.rcvif = ifp;
402 m->m_pkthdr.len = totlen;
403 pad = ALIGN(sizeof(struct ether_header)) - sizeof(struct ether_header);
404 m->m_data += pad;
405 len = MHLEN - pad;
406 top = 0;
407 mp = ⊤
408
409 while (totlen > 0) {
410 if (top) {
411 MGET(m, M_DONTWAIT, MT_DATA);
412 if (m == 0) {
413 m_freem(top);
414 return 0;
415 }
416 len = MLEN;
417 }
418 if (totlen >= MINCLSIZE) {
419 MCLGET(m, M_DONTWAIT);
420 if (m->m_flags & M_EXT) {
421 len = MCLBYTES;
422 if (!top) {
423 m->m_data += pad;
424 len -= pad;
425 }
426 }
427 }
428 m->m_len = len = min(totlen, len);
429 (*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), boff, len);
430 boff += len;
431 totlen -= len;
432 *mp = m;
433 mp = &m->m_next;
434 }
435
436 return (top);
437 }
438
439 /*
440 * Pass a packet to the higher levels.
441 */
442 integrate void
am7990_read(sc,boff,len)443 am7990_read(sc, boff, len)
444 register struct am7990_softc *sc;
445 int boff, len;
446 {
447 struct mbuf *m;
448 #ifdef LANCE_REVC_BUG
449 struct ether_header *eh;
450 #endif
451
452 if (len <= sizeof(struct ether_header) ||
453 len > ETHERMTU + sizeof(struct ether_header)) {
454 #ifdef LEDEBUG
455 printf("%s: invalid packet size %d; dropping\n",
456 sc->sc_dev.dv_xname, len);
457 #endif
458 ifp->if_ierrors++;
459 return;
460 }
461
462 /* Pull packet off interface. */
463 m = am7990_get(sc, boff, len);
464 if (m == 0) {
465 ifp->if_ierrors++;
466 return;
467 }
468
469 ifp->if_ipackets++;
470
471 #if NBPFILTER > 0
472 /*
473 * Check if there's a BPF listener on this interface.
474 * If so, hand off the raw packet to BPF.
475 */
476 if (ifp->if_bpf)
477 bpf_mtap(ifp->if_bpf, m);
478 #endif
479
480 #ifdef LANCE_REVC_BUG
481 /*
482 * The old LANCE (Rev. C) chips have a bug which causes
483 * garbage to be inserted in front of the received packet.
484 * The work-around is to ignore packets with an invalid
485 * destination address (garbage will usually not match).
486 * Of course, this precludes multicast support...
487 */
488 eh = mtod(m, struct ether_header *);
489 if (ETHER_CMP(eh->ether_dhost, sc->sc_arpcom.ac_enaddr) &&
490 ETHER_CMP(eh->ether_dhost, etherbroadcastaddr)) {
491 m_freem(m);
492 return;
493 }
494 #endif
495
496 /* Pass the packet up. */
497 ether_input_mbuf(ifp, m);
498 }
499
500 integrate void
am7990_rint(sc)501 am7990_rint(sc)
502 struct am7990_softc *sc;
503 {
504 register int bix;
505 int rp;
506 struct lermd rmd;
507
508 bix = sc->sc_last_rd;
509
510 /* Process all buffers with valid data. */
511 for (;;) {
512 rp = LE_RMDADDR(sc, bix);
513 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
514
515 if (rmd.rmd1_bits & LE_R1_OWN)
516 break;
517
518 if (rmd.rmd1_bits & LE_R1_ERR) {
519 if (rmd.rmd1_bits & LE_R1_ENP) {
520 #ifdef LEDEBUG
521 if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) {
522 if (rmd.rmd1_bits & LE_R1_FRAM)
523 printf("%s: framing error\n",
524 sc->sc_dev.dv_xname);
525 if (rmd.rmd1_bits & LE_R1_CRC)
526 printf("%s: crc mismatch\n",
527 sc->sc_dev.dv_xname);
528 }
529 #endif
530 } else {
531 if (rmd.rmd1_bits & LE_R1_OFLO)
532 printf("%s: overflow\n",
533 sc->sc_dev.dv_xname);
534 }
535 if (rmd.rmd1_bits & LE_R1_BUFF)
536 printf("%s: receive buffer error\n",
537 sc->sc_dev.dv_xname);
538 ifp->if_ierrors++;
539 } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) !=
540 (LE_R1_STP | LE_R1_ENP)) {
541 printf("%s: dropping chained buffer\n",
542 sc->sc_dev.dv_xname);
543 ifp->if_ierrors++;
544 } else {
545 #ifdef LEDEBUG1
546 if (sc->sc_debug)
547 am7990_recv_print(sc, sc->sc_last_rd);
548 #endif
549 am7990_read(sc, LE_RBUFADDR(sc, bix),
550 (int)rmd.rmd3 - 4);
551 }
552
553 rmd.rmd1_bits = LE_R1_OWN;
554 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
555 rmd.rmd3 = 0;
556 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
557
558 #ifdef LEDEBUG1
559 if (sc->sc_debug)
560 printf("sc->sc_last_rd = %x, rmd: "
561 "ladr %04x, hadr %02x, flags %02x, "
562 "bcnt %04x, mcnt %04x\n",
563 sc->sc_last_rd,
564 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits,
565 rmd.rmd2, rmd.rmd3);
566 #endif
567
568 if (++bix == sc->sc_nrbuf)
569 bix = 0;
570 }
571
572 sc->sc_last_rd = bix;
573 }
574
575 integrate void
am7990_tint(sc)576 am7990_tint(sc)
577 register struct am7990_softc *sc;
578 {
579 register int bix;
580 struct letmd tmd;
581
582 bix = sc->sc_first_td;
583
584 for (;;) {
585 if (sc->sc_no_td <= 0)
586 break;
587
588 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
589 sizeof(tmd));
590
591 #ifdef LEDEBUG
592 if (sc->sc_debug)
593 printf("trans tmd: "
594 "ladr %04x, hadr %02x, flags %02x, "
595 "bcnt %04x, mcnt %04x\n",
596 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits,
597 tmd.tmd2, tmd.tmd3);
598 #endif
599
600 if (tmd.tmd1_bits & LE_T1_OWN)
601 break;
602
603 ifp->if_flags &= ~IFF_OACTIVE;
604
605 if (tmd.tmd1_bits & LE_T1_ERR) {
606 if (tmd.tmd3 & LE_T3_BUFF)
607 printf("%s: transmit buffer error\n",
608 sc->sc_dev.dv_xname);
609 else if (tmd.tmd3 & LE_T3_UFLO)
610 printf("%s: underflow\n", sc->sc_dev.dv_xname);
611 if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) {
612 am7990_reset(sc);
613 return;
614 }
615 if (tmd.tmd3 & LE_T3_LCAR) {
616 if (sc->sc_nocarrier)
617 (*sc->sc_nocarrier)(sc);
618 }
619 if (tmd.tmd3 & LE_T3_LCOL)
620 ifp->if_collisions++;
621 if (tmd.tmd3 & LE_T3_RTRY) {
622 printf("%s: excessive collisions, tdr %d\n",
623 sc->sc_dev.dv_xname,
624 tmd.tmd3 & LE_T3_TDR_MASK);
625 ifp->if_collisions += 16;
626 }
627 ifp->if_oerrors++;
628 } else {
629 if (tmd.tmd1_bits & LE_T1_ONE)
630 ifp->if_collisions++;
631 else if (tmd.tmd1_bits & LE_T1_MORE)
632 /* Real number is unknown. */
633 ifp->if_collisions += 2;
634 ifp->if_opackets++;
635 }
636
637 if (++bix == sc->sc_ntbuf)
638 bix = 0;
639
640 --sc->sc_no_td;
641 }
642
643 sc->sc_first_td = bix;
644
645 am7990_start(ifp);
646
647 if (sc->sc_no_td == 0)
648 ifp->if_timer = 0;
649 }
650
651 /*
652 * Controller interrupt.
653 */
654 int
am7990_intr(arg)655 am7990_intr(arg)
656 register void *arg;
657 {
658 register struct am7990_softc *sc = arg;
659 register u_int16_t isr;
660
661 isr = (*sc->sc_rdcsr)(sc, LE_CSR0);
662 #ifdef LEDEBUG
663 if (sc->sc_debug){
664 printf("%s: am7990_intr entering with isr=%04x\n",
665 sc->sc_dev.dv_xname, isr);
666 printf(" isr: 0x%b\n", isr, LE_C0_BITS);
667 }
668 #endif
669 if ((isr & LE_C0_INTR) == 0)
670 return (0);
671
672 /*
673 * After receiving an interrupt, we need to toggle the interrupt
674 * enable bit in order to keep receiving them (some chips works
675 * without this, some do not)
676 */
677 (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~LE_C0_INEA);
678 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA);
679
680 if (isr & LE_C0_ERR) {
681 if (isr & LE_C0_BABL) {
682 #ifdef LEDEBUG
683 printf("%s: babble\n", sc->sc_dev.dv_xname);
684 #endif
685 ifp->if_oerrors++;
686 }
687 #if 0
688 if (isr & LE_C0_CERR) {
689 printf("%s: collision error\n", sc->sc_dev.dv_xname);
690 ifp->if_collisions++;
691 }
692 #endif
693 if (isr & LE_C0_MISS) {
694 #ifdef LEDEBUG
695 printf("%s: missed packet\n", sc->sc_dev.dv_xname);
696 #endif
697 ifp->if_ierrors++;
698 }
699 if (isr & LE_C0_MERR) {
700 printf("%s: memory error\n", sc->sc_dev.dv_xname);
701 am7990_reset(sc);
702 return (1);
703 }
704 }
705
706 if ((isr & LE_C0_RXON) == 0) {
707 printf("%s: receiver disabled\n", sc->sc_dev.dv_xname);
708 ifp->if_ierrors++;
709 am7990_reset(sc);
710 return (1);
711 }
712 if ((isr & LE_C0_TXON) == 0) {
713 printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname);
714 ifp->if_oerrors++;
715 am7990_reset(sc);
716 return (1);
717 }
718
719 if (isr & LE_C0_RINT)
720 am7990_rint(sc);
721 if (isr & LE_C0_TINT)
722 am7990_tint(sc);
723
724 return (1);
725 }
726
727 #undef ifp
728
729 void
am7990_watchdog(ifp)730 am7990_watchdog(ifp)
731 struct ifnet *ifp;
732 {
733 struct am7990_softc *sc = ifp->if_softc;
734
735 log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname);
736 ++ifp->if_oerrors;
737
738 am7990_reset(sc);
739 }
740
741 /*
742 * Setup output on interface.
743 * Get another datagram to send off of the interface queue, and map it to the
744 * interface before starting the output.
745 * Called only at splimp or interrupt level.
746 */
747 void
am7990_start(ifp)748 am7990_start(ifp)
749 register struct ifnet *ifp;
750 {
751 register struct am7990_softc *sc = ifp->if_softc;
752 register int bix;
753 register struct mbuf *m;
754 struct letmd tmd;
755 int rp;
756 int len;
757
758 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
759 return;
760
761 bix = sc->sc_last_td;
762
763 for (;;) {
764 rp = LE_TMDADDR(sc, bix);
765 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
766
767 if (tmd.tmd1_bits & LE_T1_OWN) {
768 ifp->if_flags |= IFF_OACTIVE;
769 printf("missing buffer, no_td = %d, last_td = %d\n",
770 sc->sc_no_td, sc->sc_last_td);
771 }
772
773 IFQ_DEQUEUE(&ifp->if_snd, m);
774 if (m == 0)
775 break;
776
777 #if NBPFILTER > 0
778 /*
779 * If BPF is listening on this interface, let it see the packet
780 * before we commit it to the wire.
781 */
782 if (ifp->if_bpf)
783 bpf_mtap(ifp->if_bpf, m);
784 #endif
785
786 /*
787 * Copy the mbuf chain into the transmit buffer.
788 */
789 len = am7990_put(sc, LE_TBUFADDR(sc, bix), m);
790
791 #ifdef LEDEBUG
792 if (len > ETHERMTU + sizeof(struct ether_header))
793 printf("packet length %d\n", len);
794 #endif
795
796 ifp->if_timer = 5;
797
798 /*
799 * Init transmit registers, and set transmit start flag.
800 */
801 tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
802 tmd.tmd2 = -len | LE_XMD2_ONES;
803 tmd.tmd3 = 0;
804
805 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
806
807 #ifdef LEDEBUG
808 if (sc->sc_debug)
809 am7990_xmit_print(sc, sc->sc_last_td);
810 #endif
811
812 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
813
814 if (++bix == sc->sc_ntbuf)
815 bix = 0;
816
817 if (++sc->sc_no_td == sc->sc_ntbuf) {
818 #ifdef LEDEBUG
819 printf("\nequal!\n");
820 #endif
821 ifp->if_flags |= IFF_OACTIVE;
822 break;
823 }
824
825 }
826
827 sc->sc_last_td = bix;
828 }
829
830 /*
831 * Process an ioctl request.
832 */
833 int
am7990_ioctl(ifp,cmd,data)834 am7990_ioctl(ifp, cmd, data)
835 register struct ifnet *ifp;
836 u_long cmd;
837 caddr_t data;
838 {
839 register struct am7990_softc *sc = ifp->if_softc;
840 struct ifaddr *ifa = (struct ifaddr *)data;
841 struct ifreq *ifr = (struct ifreq *)data;
842 int s, error = 0;
843
844 s = splimp();
845
846 if ((error = ether_ioctl(ifp, &sc->sc_arpcom, cmd, data)) > 0) {
847 splx(s);
848 return error;
849 }
850
851 switch (cmd) {
852
853 case SIOCSIFADDR:
854 ifp->if_flags |= IFF_UP;
855
856 switch (ifa->ifa_addr->sa_family) {
857 #ifdef INET
858 case AF_INET:
859 am7990_init(sc);
860 arp_ifinit(&sc->sc_arpcom, ifa);
861 break;
862 #endif
863 default:
864 am7990_init(sc);
865 break;
866 }
867 break;
868
869 case SIOCSIFFLAGS:
870 if ((ifp->if_flags & IFF_UP) == 0 &&
871 (ifp->if_flags & IFF_RUNNING) != 0) {
872 /*
873 * If interface is marked down and it is running, then
874 * stop it.
875 */
876 am7990_stop(sc);
877 ifp->if_flags &= ~IFF_RUNNING;
878 } else if ((ifp->if_flags & IFF_UP) != 0 &&
879 (ifp->if_flags & IFF_RUNNING) == 0) {
880 /*
881 * If interface is marked up and it is stopped, then
882 * start it.
883 */
884 am7990_init(sc);
885 } else {
886 /*
887 * Reset the interface to pick up changes in any other
888 * flags that affect hardware registers.
889 */
890 /*am7990_stop(sc);*/
891 am7990_init(sc);
892 }
893 #ifdef LEDEBUG
894 if (ifp->if_flags & IFF_DEBUG)
895 sc->sc_debug = 1;
896 else
897 sc->sc_debug = 0;
898 #endif
899 break;
900
901 case SIOCADDMULTI:
902 case SIOCDELMULTI:
903 error = (cmd == SIOCADDMULTI) ?
904 ether_addmulti(ifr, &sc->sc_arpcom) :
905 ether_delmulti(ifr, &sc->sc_arpcom);
906
907 if (error == ENETRESET) {
908 /*
909 * Multicast list has changed; set the hardware filter
910 * accordingly.
911 */
912 am7990_reset(sc);
913 error = 0;
914 }
915 break;
916
917 case SIOCGIFMEDIA:
918 case SIOCSIFMEDIA:
919 if (sc->sc_hasifmedia)
920 error = ifmedia_ioctl(ifp, ifr, &sc->sc_ifmedia, cmd);
921 else
922 error = EINVAL;
923 break;
924
925 default:
926 error = EINVAL;
927 break;
928 }
929
930 splx(s);
931 return (error);
932 }
933
934 hide void
am7990_shutdown(arg)935 am7990_shutdown(arg)
936 void *arg;
937 {
938
939 am7990_stop((struct am7990_softc *)arg);
940 }
941
942 #ifdef LEDEBUG
943 void
am7990_recv_print(sc,no)944 am7990_recv_print(sc, no)
945 struct am7990_softc *sc;
946 int no;
947 {
948 struct lermd rmd;
949 u_int16_t len;
950 struct ether_header eh;
951
952 (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
953 len = rmd.rmd3;
954 printf("%s: receive buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
955 len);
956 printf("%s: status %04x\n", sc->sc_dev.dv_xname,
957 (*sc->sc_rdcsr)(sc, LE_CSR0));
958 printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
959 sc->sc_dev.dv_xname,
960 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3);
961 if (len >= sizeof(eh)) {
962 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
963 printf("%s: dst %s", sc->sc_dev.dv_xname,
964 ether_sprintf(eh.ether_dhost));
965 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
966 ntohs(eh.ether_type));
967 }
968 }
969
970 void
am7990_xmit_print(sc,no)971 am7990_xmit_print(sc, no)
972 struct am7990_softc *sc;
973 int no;
974 {
975 struct letmd tmd;
976 u_int16_t len;
977 struct ether_header eh;
978
979 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
980 len = -tmd.tmd2;
981 printf("%s: transmit buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
982 len);
983 printf("%s: status %04x\n", sc->sc_dev.dv_xname,
984 (*sc->sc_rdcsr)(sc, LE_CSR0));
985 printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
986 sc->sc_dev.dv_xname,
987 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3);
988 if (len >= sizeof(eh)) {
989 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
990 printf("%s: dst %s", sc->sc_dev.dv_xname,
991 ether_sprintf(eh.ether_dhost));
992 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
993 ntohs(eh.ether_type));
994 }
995 }
996 #endif /* LEDEBUG */
997
998 /*
999 * Set up the logical address filter.
1000 */
1001 void
am7990_setladrf(ac,af)1002 am7990_setladrf(ac, af)
1003 struct arpcom *ac;
1004 u_int16_t *af;
1005 {
1006 struct ifnet *ifp = &ac->ac_if;
1007 struct ether_multi *enm;
1008 register u_char *cp, c;
1009 register u_int32_t crc;
1010 register int i, len;
1011 struct ether_multistep step;
1012
1013 /*
1014 * Set up multicast address filter by passing all multicast addresses
1015 * through a crc generator, and then using the high order 6 bits as an
1016 * index into the 64 bit logical address filter. The high order bit
1017 * selects the word, while the rest of the bits select the bit within
1018 * the word.
1019 */
1020
1021 if (ifp->if_flags & IFF_PROMISC)
1022 goto allmulti;
1023
1024 af[0] = af[1] = af[2] = af[3] = 0x0000;
1025 ETHER_FIRST_MULTI(step, ac, enm);
1026 while (enm != NULL) {
1027 if (ETHER_CMP(enm->enm_addrlo, enm->enm_addrhi)) {
1028 /*
1029 * We must listen to a range of multicast addresses.
1030 * For now, just accept all multicasts, rather than
1031 * trying to set only those filter bits needed to match
1032 * the range. (At this time, the only use of address
1033 * ranges is for IP multicast routing, for which the
1034 * range is big enough to require all bits set.)
1035 */
1036 goto allmulti;
1037 }
1038
1039 cp = enm->enm_addrlo;
1040 crc = 0xffffffff;
1041 for (len = sizeof(enm->enm_addrlo); --len >= 0;) {
1042 c = *cp++;
1043 for (i = 8; --i >= 0;) {
1044 if ((crc & 0x01) ^ (c & 0x01)) {
1045 crc >>= 1;
1046 crc ^= 0xedb88320;
1047 } else
1048 crc >>= 1;
1049 c >>= 1;
1050 }
1051 }
1052 /* Just want the 6 most significant bits. */
1053 crc >>= 26;
1054
1055 /* Set the corresponding bit in the filter. */
1056 af[crc >> 4] |= 1 << (crc & 0xf);
1057
1058 ETHER_NEXT_MULTI(step, enm);
1059 }
1060 ifp->if_flags &= ~IFF_ALLMULTI;
1061 return;
1062
1063 allmulti:
1064 ifp->if_flags |= IFF_ALLMULTI;
1065 af[0] = af[1] = af[2] = af[3] = 0xffff;
1066 }
1067
1068
1069 /*
1070 * Routines for accessing the transmit and receive buffers.
1071 * The various CPU and adapter configurations supported by this
1072 * driver require three different access methods for buffers
1073 * and descriptors:
1074 * (1) contig (contiguous data; no padding),
1075 * (2) gap2 (two bytes of data followed by two bytes of padding),
1076 * (3) gap16 (16 bytes of data followed by 16 bytes of padding).
1077 */
1078
1079 /*
1080 * contig: contiguous data with no padding.
1081 *
1082 * Buffers may have any alignment.
1083 */
1084
1085 void
am7990_copytobuf_contig(sc,from,boff,len)1086 am7990_copytobuf_contig(sc, from, boff, len)
1087 struct am7990_softc *sc;
1088 void *from;
1089 int boff, len;
1090 {
1091 volatile caddr_t buf = sc->sc_mem;
1092
1093 /*
1094 * Just call bcopy() to do the work.
1095 */
1096 bcopy(from, buf + boff, len);
1097 }
1098
1099 void
am7990_copyfrombuf_contig(sc,to,boff,len)1100 am7990_copyfrombuf_contig(sc, to, boff, len)
1101 struct am7990_softc *sc;
1102 void *to;
1103 int boff, len;
1104 {
1105 volatile caddr_t buf = sc->sc_mem;
1106
1107 /*
1108 * Just call bcopy() to do the work.
1109 */
1110 bcopy(buf + boff, to, len);
1111 }
1112
1113 void
am7990_zerobuf_contig(sc,boff,len)1114 am7990_zerobuf_contig(sc, boff, len)
1115 struct am7990_softc *sc;
1116 int boff, len;
1117 {
1118 volatile caddr_t buf = sc->sc_mem;
1119
1120 /*
1121 * Just let bzero() do the work
1122 */
1123 bzero(buf + boff, len);
1124 }
1125
1126 #if 0
1127 /*
1128 * Examples only; duplicate these and tweak (if necessary) in
1129 * machine-specific front-ends.
1130 */
1131
1132 /*
1133 * gap2: two bytes of data followed by two bytes of pad.
1134 *
1135 * Buffers must be 4-byte aligned. The code doesn't worry about
1136 * doing an extra byte.
1137 */
1138
1139 void
1140 am7990_copytobuf_gap2(sc, fromv, boff, len)
1141 struct am7990_softc *sc;
1142 void *fromv;
1143 int boff;
1144 register int len;
1145 {
1146 volatile caddr_t buf = sc->sc_mem;
1147 register caddr_t from = fromv;
1148 register volatile u_int16_t *bptr;
1149
1150 if (boff & 0x1) {
1151 /* handle unaligned first byte */
1152 bptr = ((volatile u_int16_t *)buf) + (boff - 1);
1153 *bptr = (*from++ << 8) | (*bptr & 0xff);
1154 bptr += 2;
1155 len--;
1156 } else
1157 bptr = ((volatile u_int16_t *)buf) + boff;
1158 while (len > 1) {
1159 *bptr = (from[1] << 8) | (from[0] & 0xff);
1160 bptr += 2;
1161 from += 2;
1162 len -= 2;
1163 }
1164 if (len == 1)
1165 *bptr = (u_int16_t)*from;
1166 }
1167
1168 void
1169 am7990_copyfrombuf_gap2(sc, tov, boff, len)
1170 struct am7990_softc *sc;
1171 void *tov;
1172 int boff, len;
1173 {
1174 volatile caddr_t buf = sc->sc_mem;
1175 register caddr_t to = tov;
1176 register volatile u_int16_t *bptr;
1177 register u_int16_t tmp;
1178
1179 if (boff & 0x1) {
1180 /* handle unaligned first byte */
1181 bptr = ((volatile u_int16_t *)buf) + (boff - 1);
1182 *to++ = (*bptr >> 8) & 0xff;
1183 bptr += 2;
1184 len--;
1185 } else
1186 bptr = ((volatile u_int16_t *)buf) + boff;
1187 while (len > 1) {
1188 tmp = *bptr;
1189 *to++ = tmp & 0xff;
1190 *to++ = (tmp >> 8) & 0xff;
1191 bptr += 2;
1192 len -= 2;
1193 }
1194 if (len == 1)
1195 *to = *bptr & 0xff;
1196 }
1197
1198 void
1199 am7990_zerobuf_gap2(sc, boff, len)
1200 struct am7990_softc *sc;
1201 int boff, len;
1202 {
1203 volatile caddr_t buf = sc->sc_mem;
1204 register volatile u_int16_t *bptr;
1205
1206 if ((unsigned)boff & 0x1) {
1207 bptr = ((volatile u_int16_t *)buf) + (boff - 1);
1208 *bptr &= 0xff;
1209 bptr += 2;
1210 len--;
1211 } else
1212 bptr = ((volatile u_int16_t *)buf) + boff;
1213 while (len > 0) {
1214 *bptr = 0;
1215 bptr += 2;
1216 len -= 2;
1217 }
1218 }
1219
1220 /*
1221 * gap16: 16 bytes of data followed by 16 bytes of pad.
1222 *
1223 * Buffers must be 32-byte aligned.
1224 */
1225
1226 void
1227 am7990_copytobuf_gap16(sc, fromv, boff, len)
1228 struct am7990_softc *sc;
1229 void *fromv;
1230 int boff;
1231 register int len;
1232 {
1233 volatile caddr_t buf = sc->sc_mem;
1234 register caddr_t from = fromv;
1235 register caddr_t bptr;
1236 register int xfer;
1237
1238 bptr = buf + ((boff << 1) & ~0x1f);
1239 boff &= 0xf;
1240 xfer = min(len, 16 - boff);
1241 while (len > 0) {
1242 bcopy(from, bptr + boff, xfer);
1243 from += xfer;
1244 bptr += 32;
1245 boff = 0;
1246 len -= xfer;
1247 xfer = min(len, 16);
1248 }
1249 }
1250
1251 void
1252 am7990_copyfrombuf_gap16(sc, tov, boff, len)
1253 struct am7990_softc *sc;
1254 void *tov;
1255 int boff, len;
1256 {
1257 volatile caddr_t buf = sc->sc_mem;
1258 register caddr_t to = tov;
1259 register caddr_t bptr;
1260 register int xfer;
1261
1262 bptr = buf + ((boff << 1) & ~0x1f);
1263 boff &= 0xf;
1264 xfer = min(len, 16 - boff);
1265 while (len > 0) {
1266 bcopy(bptr + boff, to, xfer);
1267 to += xfer;
1268 bptr += 32;
1269 boff = 0;
1270 len -= xfer;
1271 xfer = min(len, 16);
1272 }
1273 }
1274
1275 void
1276 am7990_zerobuf_gap16(sc, boff, len)
1277 struct am7990_softc *sc;
1278 int boff, len;
1279 {
1280 volatile caddr_t buf = sc->sc_mem;
1281 register caddr_t bptr;
1282 register int xfer;
1283
1284 bptr = buf + ((boff << 1) & ~0x1f);
1285 boff &= 0xf;
1286 xfer = min(len, 16 - boff);
1287 while (len > 0) {
1288 bzero(bptr + boff, xfer);
1289 bptr += 32;
1290 boff = 0;
1291 len -= xfer;
1292 xfer = min(len, 16);
1293 }
1294 }
1295 #endif /* Example only */
1296