am7990.c revision 1.73 1 /* $NetBSD: am7990.c,v 1.73 2010/04/05 07:19:33 joerg Exp $ */
2
3 /*-
4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
9 * Simulation Facility, NASA Ames Research Center.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*-
34 * Copyright (c) 1992, 1993
35 * The Regents of the University of California. All rights reserved.
36 *
37 * This code is derived from software contributed to Berkeley by
38 * Ralph Campbell and Rick Macklem.
39 *
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
42 * are met:
43 * 1. Redistributions of source code must retain the above copyright
44 * notice, this list of conditions and the following disclaimer.
45 * 2. Redistributions in binary form must reproduce the above copyright
46 * notice, this list of conditions and the following disclaimer in the
47 * documentation and/or other materials provided with the distribution.
48 * 3. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 * @(#)if_le.c 8.2 (Berkeley) 11/16/93
65 */
66
67 #include <sys/cdefs.h>
68 __KERNEL_RCSID(0, "$NetBSD: am7990.c,v 1.73 2010/04/05 07:19:33 joerg Exp $");
69
70 #include "rnd.h"
71
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/mbuf.h>
75 #include <sys/syslog.h>
76 #include <sys/socket.h>
77 #include <sys/device.h>
78 #include <sys/malloc.h>
79 #include <sys/ioctl.h>
80 #include <sys/errno.h>
81 #if NRND > 0
82 #include <sys/rnd.h>
83 #endif
84
85 #include <net/if.h>
86 #include <net/if_dl.h>
87 #include <net/if_ether.h>
88 #include <net/if_media.h>
89
90 #include <net/bpf.h>
91 #include <net/bpfdesc.h>
92
93 #include <dev/ic/lancereg.h>
94 #include <dev/ic/lancevar.h>
95 #include <dev/ic/am7990reg.h>
96 #include <dev/ic/am7990var.h>
97
98 static void am7990_meminit(struct lance_softc *);
99 static void am7990_start(struct ifnet *);
100
101 #if defined(_KERNEL_OPT)
102 #include "opt_ddb.h"
103 #endif
104
105 #ifdef LEDEBUG
106 static void am7990_recv_print(struct lance_softc *, int);
107 static void am7990_xmit_print(struct lance_softc *, int);
108 #endif
109
110 #define ifp (&sc->sc_ethercom.ec_if)
111
112 void
113 am7990_config(struct am7990_softc *sc)
114 {
115 int mem, i;
116
117 sc->lsc.sc_meminit = am7990_meminit;
118 sc->lsc.sc_start = am7990_start;
119
120 lance_config(&sc->lsc);
121
122 mem = 0;
123 sc->lsc.sc_initaddr = mem;
124 mem += sizeof(struct leinit);
125 sc->lsc.sc_rmdaddr = mem;
126 mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf;
127 sc->lsc.sc_tmdaddr = mem;
128 mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf;
129 for (i = 0; i < sc->lsc.sc_nrbuf; i++, mem += LEBLEN)
130 sc->lsc.sc_rbufaddr[i] = mem;
131 for (i = 0; i < sc->lsc.sc_ntbuf; i++, mem += LEBLEN)
132 sc->lsc.sc_tbufaddr[i] = mem;
133 #ifdef notyet
134 if (mem > ...)
135 panic(...);
136 #endif
137 }
138
139 /*
140 * Set up the initialization block and the descriptor rings.
141 */
142 static void
143 am7990_meminit(struct lance_softc *sc)
144 {
145 u_long a;
146 int bix;
147 struct leinit init;
148 struct lermd rmd;
149 struct letmd tmd;
150 uint8_t *myaddr;
151
152 if (ifp->if_flags & IFF_PROMISC)
153 init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM;
154 else
155 init.init_mode = LE_MODE_NORMAL;
156 if (sc->sc_initmodemedia == 1)
157 init.init_mode |= LE_MODE_PSEL0;
158
159 /*
160 * Update our private copy of the Ethernet address.
161 * We NEED the copy so we can ensure its alignment!
162 */
163 memcpy(sc->sc_enaddr, CLLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
164 myaddr = sc->sc_enaddr;
165
166 init.init_padr[0] = (myaddr[1] << 8) | myaddr[0];
167 init.init_padr[1] = (myaddr[3] << 8) | myaddr[2];
168 init.init_padr[2] = (myaddr[5] << 8) | myaddr[4];
169 lance_setladrf(&sc->sc_ethercom, init.init_ladrf);
170
171 sc->sc_last_rd = 0;
172 sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
173
174 a = sc->sc_addr + LE_RMDADDR(sc, 0);
175 init.init_rdra = a;
176 init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13);
177
178 a = sc->sc_addr + LE_TMDADDR(sc, 0);
179 init.init_tdra = a;
180 init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13);
181
182 (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
183
184 /*
185 * Set up receive ring descriptors.
186 */
187 for (bix = 0; bix < sc->sc_nrbuf; bix++) {
188 a = sc->sc_addr + LE_RBUFADDR(sc, bix);
189 rmd.rmd0 = a;
190 rmd.rmd1_hadr = a >> 16;
191 rmd.rmd1_bits = LE_R1_OWN;
192 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
193 rmd.rmd3 = 0;
194 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
195 sizeof(rmd));
196 }
197
198 /*
199 * Set up transmit ring descriptors.
200 */
201 for (bix = 0; bix < sc->sc_ntbuf; bix++) {
202 a = sc->sc_addr + LE_TBUFADDR(sc, bix);
203 tmd.tmd0 = a;
204 tmd.tmd1_hadr = a >> 16;
205 tmd.tmd1_bits = 0;
206 tmd.tmd2 = 0 | LE_XMD2_ONES;
207 tmd.tmd3 = 0;
208 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
209 sizeof(tmd));
210 }
211 }
212
213 static void
214 am7990_rint(struct lance_softc *sc)
215 {
216 int bix;
217 int rp;
218 struct lermd rmd;
219
220 bix = sc->sc_last_rd;
221
222 /* Process all buffers with valid data. */
223 for (;;) {
224 rp = LE_RMDADDR(sc, bix);
225 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
226
227 if (rmd.rmd1_bits & LE_R1_OWN)
228 break;
229
230 if (rmd.rmd1_bits & LE_R1_ERR) {
231 if (rmd.rmd1_bits & LE_R1_ENP) {
232 #ifdef LEDEBUG
233 if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) {
234 if (rmd.rmd1_bits & LE_R1_FRAM)
235 printf("%s: framing error\n",
236 device_xname(sc->sc_dev));
237 if (rmd.rmd1_bits & LE_R1_CRC)
238 printf("%s: crc mismatch\n",
239 device_xname(sc->sc_dev));
240 }
241 #endif
242 } else {
243 if (rmd.rmd1_bits & LE_R1_OFLO)
244 printf("%s: overflow\n",
245 device_xname(sc->sc_dev));
246 }
247 if (rmd.rmd1_bits & LE_R1_BUFF)
248 printf("%s: receive buffer error\n",
249 device_xname(sc->sc_dev));
250 ifp->if_ierrors++;
251 } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) !=
252 (LE_R1_STP | LE_R1_ENP)) {
253 printf("%s: dropping chained buffer\n",
254 device_xname(sc->sc_dev));
255 ifp->if_ierrors++;
256 } else {
257 #ifdef LEDEBUG
258 if (sc->sc_debug > 1)
259 am7990_recv_print(sc, sc->sc_last_rd);
260 #endif
261 lance_read(sc, LE_RBUFADDR(sc, bix),
262 (int)rmd.rmd3 - 4);
263 }
264
265 rmd.rmd1_bits = LE_R1_OWN;
266 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
267 rmd.rmd3 = 0;
268 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
269
270 #ifdef LEDEBUG
271 if (sc->sc_debug)
272 printf("sc->sc_last_rd = %x, rmd: "
273 "ladr %04x, hadr %02x, flags %02x, "
274 "bcnt %04x, mcnt %04x\n",
275 sc->sc_last_rd,
276 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits,
277 rmd.rmd2, rmd.rmd3);
278 #endif
279
280 if (++bix == sc->sc_nrbuf)
281 bix = 0;
282 }
283
284 sc->sc_last_rd = bix;
285 }
286
287 static void
288 am7990_tint(struct lance_softc *sc)
289 {
290 int bix;
291 struct letmd tmd;
292
293 bix = sc->sc_first_td;
294
295 for (;;) {
296 if (sc->sc_no_td <= 0)
297 break;
298
299 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
300 sizeof(tmd));
301
302 #ifdef LEDEBUG
303 if (sc->sc_debug)
304 printf("trans tmd: "
305 "ladr %04x, hadr %02x, flags %02x, "
306 "bcnt %04x, mcnt %04x\n",
307 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits,
308 tmd.tmd2, tmd.tmd3);
309 #endif
310
311 if (tmd.tmd1_bits & LE_T1_OWN)
312 break;
313
314 ifp->if_flags &= ~IFF_OACTIVE;
315
316 if (tmd.tmd1_bits & LE_T1_ERR) {
317 if (tmd.tmd3 & LE_T3_BUFF)
318 printf("%s: transmit buffer error\n",
319 device_xname(sc->sc_dev));
320 else if (tmd.tmd3 & LE_T3_UFLO)
321 printf("%s: underflow\n",
322 device_xname(sc->sc_dev));
323 if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) {
324 lance_reset(sc);
325 return;
326 }
327 if (tmd.tmd3 & LE_T3_LCAR) {
328 sc->sc_havecarrier = 0;
329 if (sc->sc_nocarrier)
330 (*sc->sc_nocarrier)(sc);
331 else
332 printf("%s: lost carrier\n",
333 device_xname(sc->sc_dev));
334 }
335 if (tmd.tmd3 & LE_T3_LCOL)
336 ifp->if_collisions++;
337 if (tmd.tmd3 & LE_T3_RTRY) {
338 #ifdef LEDEBUG
339 printf("%s: excessive collisions, tdr %d\n",
340 device_xname(sc->sc_dev),
341 tmd.tmd3 & LE_T3_TDR_MASK);
342 #endif
343 ifp->if_collisions += 16;
344 }
345 ifp->if_oerrors++;
346 } else {
347 if (tmd.tmd1_bits & LE_T1_ONE)
348 ifp->if_collisions++;
349 else if (tmd.tmd1_bits & LE_T1_MORE)
350 /* Real number is unknown. */
351 ifp->if_collisions += 2;
352 ifp->if_opackets++;
353 }
354
355 if (++bix == sc->sc_ntbuf)
356 bix = 0;
357
358 --sc->sc_no_td;
359 }
360
361 sc->sc_first_td = bix;
362
363 am7990_start(ifp);
364
365 if (sc->sc_no_td == 0)
366 ifp->if_timer = 0;
367 }
368
369 /*
370 * Controller interrupt.
371 */
372 int
373 am7990_intr(void *arg)
374 {
375 struct lance_softc *sc = arg;
376 uint16_t isr;
377
378 isr = (*sc->sc_rdcsr)(sc, LE_CSR0) | sc->sc_saved_csr0;
379 sc->sc_saved_csr0 = 0;
380 #if defined(LEDEBUG) && LEDEBUG > 1
381 if (sc->sc_debug)
382 printf("%s: am7990_intr entering with isr=%04x\n",
383 device_xname(sc->sc_dev), isr);
384 #endif
385 if ((isr & LE_C0_INTR) == 0)
386 return (0);
387
388 #ifdef __vax__
389 /*
390 * DEC needs this write order to the registers, don't know
391 * the results on other arch's. Ragge 991029
392 */
393 isr &= ~LE_C0_INEA;
394 (*sc->sc_wrcsr)(sc, LE_CSR0, isr);
395 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA);
396 #else
397 (*sc->sc_wrcsr)(sc, LE_CSR0,
398 isr & (LE_C0_INEA | LE_C0_BABL | LE_C0_MISS | LE_C0_MERR |
399 LE_C0_RINT | LE_C0_TINT | LE_C0_IDON));
400 #endif
401 if (isr & LE_C0_ERR) {
402 if (isr & LE_C0_BABL) {
403 #ifdef LEDEBUG
404 printf("%s: babble\n", device_xname(sc->sc_dev));
405 #endif
406 ifp->if_oerrors++;
407 }
408 #if 0
409 if (isr & LE_C0_CERR) {
410 printf("%s: collision error\n",
411 device_xname(sc->sc_dev));
412 ifp->if_collisions++;
413 }
414 #endif
415 if (isr & LE_C0_MISS) {
416 #ifdef LEDEBUG
417 printf("%s: missed packet\n", device_xname(sc->sc_dev));
418 #endif
419 ifp->if_ierrors++;
420 }
421 if (isr & LE_C0_MERR) {
422 printf("%s: memory error\n", device_xname(sc->sc_dev));
423 lance_reset(sc);
424 return (1);
425 }
426 }
427
428 if ((isr & LE_C0_RXON) == 0) {
429 printf("%s: receiver disabled\n", device_xname(sc->sc_dev));
430 ifp->if_ierrors++;
431 lance_reset(sc);
432 return (1);
433 }
434 if ((isr & LE_C0_TXON) == 0) {
435 printf("%s: transmitter disabled\n", device_xname(sc->sc_dev));
436 ifp->if_oerrors++;
437 lance_reset(sc);
438 return (1);
439 }
440
441 /*
442 * Pretend we have carrier; if we don't this will be cleared
443 * shortly.
444 */
445 sc->sc_havecarrier = 1;
446
447 if (isr & LE_C0_RINT)
448 am7990_rint(sc);
449 if (isr & LE_C0_TINT)
450 am7990_tint(sc);
451
452 #if NRND > 0
453 rnd_add_uint32(&sc->rnd_source, isr);
454 #endif
455
456 return (1);
457 }
458
459 #undef ifp
460
461 /*
462 * Setup output on interface.
463 * Get another datagram to send off of the interface queue, and map it to the
464 * interface before starting the output.
465 * Called only at splnet or interrupt level.
466 */
467 static void
468 am7990_start(struct ifnet *ifp)
469 {
470 struct lance_softc *sc = ifp->if_softc;
471 int bix;
472 struct mbuf *m;
473 struct letmd tmd;
474 int rp;
475 int len;
476
477 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
478 return;
479
480 bix = sc->sc_last_td;
481
482 for (;;) {
483 rp = LE_TMDADDR(sc, bix);
484 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
485
486 if (tmd.tmd1_bits & LE_T1_OWN) {
487 ifp->if_flags |= IFF_OACTIVE;
488 printf("missing buffer, no_td = %d, last_td = %d\n",
489 sc->sc_no_td, sc->sc_last_td);
490 }
491
492 IFQ_DEQUEUE(&ifp->if_snd, m);
493 if (m == 0)
494 break;
495
496 /*
497 * If BPF is listening on this interface, let it see the packet
498 * before we commit it to the wire.
499 */
500 bpf_mtap(ifp, m);
501
502 /*
503 * Copy the mbuf chain into the transmit buffer.
504 */
505 len = lance_put(sc, LE_TBUFADDR(sc, bix), m);
506
507 #ifdef LEDEBUG
508 if (len > ETHERMTU + sizeof(struct ether_header))
509 printf("packet length %d\n", len);
510 #endif
511
512 ifp->if_timer = 5;
513
514 /*
515 * Init transmit registers, and set transmit start flag.
516 */
517 tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
518 tmd.tmd2 = -len | LE_XMD2_ONES;
519 tmd.tmd3 = 0;
520
521 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
522
523 #ifdef LEDEBUG
524 if (sc->sc_debug > 1)
525 am7990_xmit_print(sc, sc->sc_last_td);
526 #endif
527
528 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
529
530 if (++bix == sc->sc_ntbuf)
531 bix = 0;
532
533 if (++sc->sc_no_td == sc->sc_ntbuf) {
534 ifp->if_flags |= IFF_OACTIVE;
535 break;
536 }
537
538 }
539
540 sc->sc_last_td = bix;
541 }
542
543 #ifdef LEDEBUG
544 static void
545 am7990_recv_print(struct lance_softc *sc, int no)
546 {
547 struct lermd rmd;
548 uint16_t len;
549 struct ether_header eh;
550
551 (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
552 len = rmd.rmd3;
553 printf("%s: receive buffer %d, len = %d\n",
554 device_xname(sc->sc_dev), no, len);
555 printf("%s: status %04x\n", device_xname(sc->sc_dev),
556 (*sc->sc_rdcsr)(sc, LE_CSR0));
557 printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
558 device_xname(sc->sc_dev),
559 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3);
560 if (len >= sizeof(eh)) {
561 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
562 printf("%s: dst %s", device_xname(sc->sc_dev),
563 ether_sprintf(eh.ether_dhost));
564 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
565 ntohs(eh.ether_type));
566 }
567 }
568
569 static void
570 am7990_xmit_print(struct lance_softc *sc, int no)
571 {
572 struct letmd tmd;
573 uint16_t len;
574 struct ether_header eh;
575
576 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
577 len = -tmd.tmd2;
578 printf("%s: transmit buffer %d, len = %d\n",
579 device_xname(sc->sc_dev), no, len);
580 printf("%s: status %04x\n", device_xname(sc->sc_dev),
581 (*sc->sc_rdcsr)(sc, LE_CSR0));
582 printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
583 device_xname(sc->sc_dev),
584 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3);
585 if (len >= sizeof(eh)) {
586 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
587 printf("%s: dst %s", device_xname(sc->sc_dev),
588 ether_sprintf(eh.ether_dhost));
589 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
590 ntohs(eh.ether_type));
591 }
592 }
593 #endif /* LEDEBUG */
594