am7990.c revision 1.77 1 /* $NetBSD: am7990.c,v 1.77 2017/05/23 04:51:31 ozaki-r 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.77 2017/05/23 04:51:31 ozaki-r Exp $");
69
70 #include <sys/param.h>
71 #include <sys/systm.h>
72 #include <sys/mbuf.h>
73 #include <sys/syslog.h>
74 #include <sys/socket.h>
75 #include <sys/device.h>
76 #include <sys/malloc.h>
77 #include <sys/ioctl.h>
78 #include <sys/errno.h>
79 #include <sys/rndsource.h>
80
81 #include <net/if.h>
82 #include <net/if_dl.h>
83 #include <net/if_ether.h>
84 #include <net/if_media.h>
85
86 #include <net/bpf.h>
87 #include <net/bpfdesc.h>
88
89 #include <dev/ic/lancereg.h>
90 #include <dev/ic/lancevar.h>
91 #include <dev/ic/am7990reg.h>
92 #include <dev/ic/am7990var.h>
93
94 static void am7990_meminit(struct lance_softc *);
95 static void am7990_start(struct ifnet *);
96
97 #if defined(_KERNEL_OPT)
98 #include "opt_ddb.h"
99 #endif
100
101 #ifdef LEDEBUG
102 static void am7990_recv_print(struct lance_softc *, int);
103 static void am7990_xmit_print(struct lance_softc *, int);
104 #endif
105
106 #define ifp (&sc->sc_ethercom.ec_if)
107
108 void
109 am7990_config(struct am7990_softc *sc)
110 {
111 int mem, i;
112
113 sc->lsc.sc_meminit = am7990_meminit;
114 sc->lsc.sc_start = am7990_start;
115
116 lance_config(&sc->lsc);
117 if_deferred_start_init(&sc->lsc.sc_ethercom.ec_if, NULL);
118
119 mem = 0;
120 sc->lsc.sc_initaddr = mem;
121 mem += sizeof(struct leinit);
122 sc->lsc.sc_rmdaddr = mem;
123 mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf;
124 sc->lsc.sc_tmdaddr = mem;
125 mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf;
126 for (i = 0; i < sc->lsc.sc_nrbuf; i++, mem += LEBLEN)
127 sc->lsc.sc_rbufaddr[i] = mem;
128 for (i = 0; i < sc->lsc.sc_ntbuf; i++, mem += LEBLEN)
129 sc->lsc.sc_tbufaddr[i] = mem;
130 #ifdef notyet
131 if (mem > ...)
132 panic(...);
133 #endif
134 }
135
136 /*
137 * Set up the initialization block and the descriptor rings.
138 */
139 static void
140 am7990_meminit(struct lance_softc *sc)
141 {
142 u_long a;
143 int bix;
144 struct leinit init;
145 struct lermd rmd;
146 struct letmd tmd;
147 uint8_t *myaddr;
148
149 if (ifp->if_flags & IFF_PROMISC)
150 init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM;
151 else
152 init.init_mode = LE_MODE_NORMAL;
153 if (sc->sc_initmodemedia == 1)
154 init.init_mode |= LE_MODE_PSEL0;
155
156 /*
157 * Update our private copy of the Ethernet address.
158 * We NEED the copy so we can ensure its alignment!
159 */
160 memcpy(sc->sc_enaddr, CLLADDR(ifp->if_sadl), ETHER_ADDR_LEN);
161 myaddr = sc->sc_enaddr;
162
163 init.init_padr[0] = (myaddr[1] << 8) | myaddr[0];
164 init.init_padr[1] = (myaddr[3] << 8) | myaddr[2];
165 init.init_padr[2] = (myaddr[5] << 8) | myaddr[4];
166 lance_setladrf(&sc->sc_ethercom, init.init_ladrf);
167
168 sc->sc_last_rd = 0;
169 sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
170
171 a = sc->sc_addr + LE_RMDADDR(sc, 0);
172 init.init_rdra = a;
173 init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13);
174
175 a = sc->sc_addr + LE_TMDADDR(sc, 0);
176 init.init_tdra = a;
177 init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13);
178
179 (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
180
181 /*
182 * Set up receive ring descriptors.
183 */
184 for (bix = 0; bix < sc->sc_nrbuf; bix++) {
185 a = sc->sc_addr + LE_RBUFADDR(sc, bix);
186 rmd.rmd0 = a;
187 rmd.rmd1_hadr = a >> 16;
188 rmd.rmd1_bits = LE_R1_OWN;
189 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
190 rmd.rmd3 = 0;
191 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
192 sizeof(rmd));
193 }
194
195 /*
196 * Set up transmit ring descriptors.
197 */
198 for (bix = 0; bix < sc->sc_ntbuf; bix++) {
199 a = sc->sc_addr + LE_TBUFADDR(sc, bix);
200 tmd.tmd0 = a;
201 tmd.tmd1_hadr = a >> 16;
202 tmd.tmd1_bits = 0;
203 tmd.tmd2 = 0 | LE_XMD2_ONES;
204 tmd.tmd3 = 0;
205 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
206 sizeof(tmd));
207 }
208 }
209
210 static void
211 am7990_rint(struct lance_softc *sc)
212 {
213 int bix;
214 int rp;
215 struct lermd rmd;
216
217 bix = sc->sc_last_rd;
218
219 /* Process all buffers with valid data. */
220 for (;;) {
221 rp = LE_RMDADDR(sc, bix);
222 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
223
224 if (rmd.rmd1_bits & LE_R1_OWN)
225 break;
226
227 if (rmd.rmd1_bits & LE_R1_ERR) {
228 if (rmd.rmd1_bits & LE_R1_ENP) {
229 #ifdef LEDEBUG
230 if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) {
231 if (rmd.rmd1_bits & LE_R1_FRAM)
232 printf("%s: framing error\n",
233 device_xname(sc->sc_dev));
234 if (rmd.rmd1_bits & LE_R1_CRC)
235 printf("%s: crc mismatch\n",
236 device_xname(sc->sc_dev));
237 }
238 #endif
239 } else {
240 if (rmd.rmd1_bits & LE_R1_OFLO)
241 printf("%s: overflow\n",
242 device_xname(sc->sc_dev));
243 }
244 if (rmd.rmd1_bits & LE_R1_BUFF)
245 printf("%s: receive buffer error\n",
246 device_xname(sc->sc_dev));
247 ifp->if_ierrors++;
248 } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) !=
249 (LE_R1_STP | LE_R1_ENP)) {
250 printf("%s: dropping chained buffer\n",
251 device_xname(sc->sc_dev));
252 ifp->if_ierrors++;
253 } else {
254 #ifdef LEDEBUG
255 if (sc->sc_debug > 1)
256 am7990_recv_print(sc, sc->sc_last_rd);
257 #endif
258 lance_read(sc, LE_RBUFADDR(sc, bix),
259 (int)rmd.rmd3 - 4);
260 }
261
262 rmd.rmd1_bits = LE_R1_OWN;
263 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
264 rmd.rmd3 = 0;
265 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
266
267 #ifdef LEDEBUG
268 if (sc->sc_debug)
269 printf("sc->sc_last_rd = %x, rmd: "
270 "ladr %04x, hadr %02x, flags %02x, "
271 "bcnt %04x, mcnt %04x\n",
272 sc->sc_last_rd,
273 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits,
274 rmd.rmd2, rmd.rmd3);
275 #endif
276
277 if (++bix == sc->sc_nrbuf)
278 bix = 0;
279 }
280
281 sc->sc_last_rd = bix;
282 }
283
284 static void
285 am7990_tint(struct lance_softc *sc)
286 {
287 int bix;
288 struct letmd tmd;
289
290 bix = sc->sc_first_td;
291
292 for (;;) {
293 if (sc->sc_no_td <= 0)
294 break;
295
296 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
297 sizeof(tmd));
298
299 #ifdef LEDEBUG
300 if (sc->sc_debug)
301 printf("trans tmd: "
302 "ladr %04x, hadr %02x, flags %02x, "
303 "bcnt %04x, mcnt %04x\n",
304 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits,
305 tmd.tmd2, tmd.tmd3);
306 #endif
307
308 if (tmd.tmd1_bits & LE_T1_OWN)
309 break;
310
311 ifp->if_flags &= ~IFF_OACTIVE;
312
313 if (tmd.tmd1_bits & LE_T1_ERR) {
314 if (tmd.tmd3 & LE_T3_BUFF)
315 printf("%s: transmit buffer error\n",
316 device_xname(sc->sc_dev));
317 else if (tmd.tmd3 & LE_T3_UFLO)
318 printf("%s: underflow\n",
319 device_xname(sc->sc_dev));
320 if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) {
321 lance_reset(sc);
322 return;
323 }
324 if (tmd.tmd3 & LE_T3_LCAR) {
325 sc->sc_havecarrier = 0;
326 if (sc->sc_nocarrier)
327 (*sc->sc_nocarrier)(sc);
328 else
329 printf("%s: lost carrier\n",
330 device_xname(sc->sc_dev));
331 }
332 if (tmd.tmd3 & LE_T3_LCOL)
333 ifp->if_collisions++;
334 if (tmd.tmd3 & LE_T3_RTRY) {
335 #ifdef LEDEBUG
336 printf("%s: excessive collisions, tdr %d\n",
337 device_xname(sc->sc_dev),
338 tmd.tmd3 & LE_T3_TDR_MASK);
339 #endif
340 ifp->if_collisions += 16;
341 }
342 ifp->if_oerrors++;
343 } else {
344 if (tmd.tmd1_bits & LE_T1_ONE)
345 ifp->if_collisions++;
346 else if (tmd.tmd1_bits & LE_T1_MORE)
347 /* Real number is unknown. */
348 ifp->if_collisions += 2;
349 ifp->if_opackets++;
350 }
351
352 if (++bix == sc->sc_ntbuf)
353 bix = 0;
354
355 --sc->sc_no_td;
356 }
357
358 sc->sc_first_td = bix;
359
360 if_schedule_deferred_start(ifp);
361
362 if (sc->sc_no_td == 0)
363 ifp->if_timer = 0;
364 }
365
366 /*
367 * Controller interrupt.
368 */
369 int
370 am7990_intr(void *arg)
371 {
372 struct lance_softc *sc = arg;
373 uint16_t isr;
374
375 isr = (*sc->sc_rdcsr)(sc, LE_CSR0) | sc->sc_saved_csr0;
376 sc->sc_saved_csr0 = 0;
377 #if defined(LEDEBUG) && LEDEBUG > 1
378 if (sc->sc_debug)
379 printf("%s: am7990_intr entering with isr=%04x\n",
380 device_xname(sc->sc_dev), isr);
381 #endif
382 if ((isr & LE_C0_INTR) == 0)
383 return (0);
384
385 #ifdef __vax__
386 /*
387 * DEC needs this write order to the registers, don't know
388 * the results on other arch's. Ragge 991029
389 */
390 isr &= ~LE_C0_INEA;
391 (*sc->sc_wrcsr)(sc, LE_CSR0, isr);
392 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA);
393 #else
394 (*sc->sc_wrcsr)(sc, LE_CSR0,
395 isr & (LE_C0_INEA | LE_C0_BABL | LE_C0_MISS | LE_C0_MERR |
396 LE_C0_RINT | LE_C0_TINT | LE_C0_IDON));
397 #endif
398 if (isr & LE_C0_ERR) {
399 if (isr & LE_C0_BABL) {
400 #ifdef LEDEBUG
401 printf("%s: babble\n", device_xname(sc->sc_dev));
402 #endif
403 ifp->if_oerrors++;
404 }
405 #if 0
406 if (isr & LE_C0_CERR) {
407 printf("%s: collision error\n",
408 device_xname(sc->sc_dev));
409 ifp->if_collisions++;
410 }
411 #endif
412 if (isr & LE_C0_MISS) {
413 #ifdef LEDEBUG
414 printf("%s: missed packet\n", device_xname(sc->sc_dev));
415 #endif
416 ifp->if_ierrors++;
417 }
418 if (isr & LE_C0_MERR) {
419 printf("%s: memory error\n", device_xname(sc->sc_dev));
420 lance_reset(sc);
421 return (1);
422 }
423 }
424
425 if ((isr & LE_C0_RXON) == 0) {
426 printf("%s: receiver disabled\n", device_xname(sc->sc_dev));
427 ifp->if_ierrors++;
428 lance_reset(sc);
429 return (1);
430 }
431 if ((isr & LE_C0_TXON) == 0) {
432 printf("%s: transmitter disabled\n", device_xname(sc->sc_dev));
433 ifp->if_oerrors++;
434 lance_reset(sc);
435 return (1);
436 }
437
438 /*
439 * Pretend we have carrier; if we don't this will be cleared
440 * shortly.
441 */
442 sc->sc_havecarrier = 1;
443
444 if (isr & LE_C0_RINT)
445 am7990_rint(sc);
446 if (isr & LE_C0_TINT)
447 am7990_tint(sc);
448
449 rnd_add_uint32(&sc->rnd_source, isr);
450
451 return (1);
452 }
453
454 #undef ifp
455
456 /*
457 * Setup output on interface.
458 * Get another datagram to send off of the interface queue, and map it to the
459 * interface before starting the output.
460 * Called only at splnet or interrupt level.
461 */
462 static void
463 am7990_start(struct ifnet *ifp)
464 {
465 struct lance_softc *sc = ifp->if_softc;
466 int bix;
467 struct mbuf *m;
468 struct letmd tmd;
469 int rp;
470 int len;
471
472 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING)
473 return;
474
475 bix = sc->sc_last_td;
476
477 for (;;) {
478 rp = LE_TMDADDR(sc, bix);
479 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
480
481 if (tmd.tmd1_bits & LE_T1_OWN) {
482 ifp->if_flags |= IFF_OACTIVE;
483 printf("missing buffer, no_td = %d, last_td = %d\n",
484 sc->sc_no_td, sc->sc_last_td);
485 }
486
487 IFQ_DEQUEUE(&ifp->if_snd, m);
488 if (m == 0)
489 break;
490
491 /*
492 * If BPF is listening on this interface, let it see the packet
493 * before we commit it to the wire.
494 */
495 bpf_mtap(ifp, m);
496
497 /*
498 * Copy the mbuf chain into the transmit buffer.
499 */
500 len = lance_put(sc, LE_TBUFADDR(sc, bix), m);
501
502 #ifdef LEDEBUG
503 if (len > ETHERMTU + sizeof(struct ether_header))
504 printf("packet length %d\n", len);
505 #endif
506
507 ifp->if_timer = 5;
508
509 /*
510 * Init transmit registers, and set transmit start flag.
511 */
512 tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
513 tmd.tmd2 = -len | LE_XMD2_ONES;
514 tmd.tmd3 = 0;
515
516 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
517
518 #ifdef LEDEBUG
519 if (sc->sc_debug > 1)
520 am7990_xmit_print(sc, sc->sc_last_td);
521 #endif
522
523 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
524
525 if (++bix == sc->sc_ntbuf)
526 bix = 0;
527
528 if (++sc->sc_no_td == sc->sc_ntbuf) {
529 ifp->if_flags |= IFF_OACTIVE;
530 break;
531 }
532
533 }
534
535 sc->sc_last_td = bix;
536 }
537
538 #ifdef LEDEBUG
539 static void
540 am7990_recv_print(struct lance_softc *sc, int no)
541 {
542 struct lermd rmd;
543 uint16_t len;
544 struct ether_header eh;
545
546 (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
547 len = rmd.rmd3;
548 printf("%s: receive buffer %d, len = %d\n",
549 device_xname(sc->sc_dev), no, len);
550 printf("%s: status %04x\n", device_xname(sc->sc_dev),
551 (*sc->sc_rdcsr)(sc, LE_CSR0));
552 printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
553 device_xname(sc->sc_dev),
554 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3);
555 if (len >= sizeof(eh)) {
556 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
557 printf("%s: dst %s", device_xname(sc->sc_dev),
558 ether_sprintf(eh.ether_dhost));
559 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
560 ntohs(eh.ether_type));
561 }
562 }
563
564 static void
565 am7990_xmit_print(struct lance_softc *sc, int no)
566 {
567 struct letmd tmd;
568 uint16_t len;
569 struct ether_header eh;
570
571 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
572 len = -tmd.tmd2;
573 printf("%s: transmit buffer %d, len = %d\n",
574 device_xname(sc->sc_dev), no, len);
575 printf("%s: status %04x\n", device_xname(sc->sc_dev),
576 (*sc->sc_rdcsr)(sc, LE_CSR0));
577 printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
578 device_xname(sc->sc_dev),
579 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3);
580 if (len >= sizeof(eh)) {
581 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
582 printf("%s: dst %s", device_xname(sc->sc_dev),
583 ether_sprintf(eh.ether_dhost));
584 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
585 ntohs(eh.ether_type));
586 }
587 }
588 #endif /* LEDEBUG */
589