1 /* $NetBSD: am79900.c,v 1.19 2008/04/04 12:25:07 tsutsui Exp $ */
4 * Copyright (c) 1997 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Copyright (c) 1992, 1993
34 * The Regents of the University of California. All rights reserved.
36 * This code is derived from software contributed to Berkeley by
37 * Ralph Campbell and Rick Macklem.
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * @(#)if_le.c 8.2 (Berkeley) 11/16/93
68 * Matthias Drochner. All rights reserved.
69 * Copyright (c) 1995 Charles M. Hannum. All rights reserved.
71 * This code is derived from software contributed to Berkeley by
72 * Ralph Campbell and Rick Macklem.
74 * Redistribution and use in source and binary forms, with or without
75 * modification, are permitted provided that the following conditions
77 * 1. Redistributions of source code must retain the above copyright
78 * notice, this list of conditions and the following disclaimer.
79 * 2. Redistributions in binary form must reproduce the above copyright
80 * notice, this list of conditions and the following disclaimer in the
81 * documentation and/or other materials provided with the distribution.
82 * 3. All advertising materials mentioning features or use of this software
83 * must display the following acknowledgement:
84 * This product includes software developed by the University of
85 * California, Berkeley and its contributors.
86 * 4. Neither the name of the University nor the names of its contributors
87 * may be used to endorse or promote products derived from this software
88 * without specific prior written permission.
90 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
91 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
92 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
93 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
94 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
95 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
96 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
97 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
98 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
99 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
102 * @(#)if_le.c 8.2 (Berkeley) 11/16/93
105 #include <sys/cdefs.h>
106 __KERNEL_RCSID(0, "$NetBSD: am79900.c,v 1.19 2008/04/04 12:25:07 tsutsui Exp $");
108 #include "bpfilter.h"
111 #include <sys/param.h>
112 #include <sys/systm.h>
113 #include <sys/mbuf.h>
114 #include <sys/syslog.h>
115 #include <sys/socket.h>
116 #include <sys/device.h>
117 #include <sys/malloc.h>
118 #include <sys/ioctl.h>
119 #include <sys/errno.h>
125 #include <net/if_dl.h>
126 #include <net/if_ether.h>
127 #include <net/if_media.h>
131 #include <net/bpfdesc.h>
134 #include <dev/ic/lancereg.h>
135 #include <dev/ic/lancevar.h>
136 #include <dev/ic/am79900reg.h>
137 #include <dev/ic/am79900var.h>
139 static void am79900_meminit(struct lance_softc
*);
140 static void am79900_start(struct ifnet
*);
142 #if defined(_KERNEL_OPT)
147 static void am79900_recv_print(struct lance_softc
*, int);
148 static void am79900_xmit_print(struct lance_softc
*, int);
151 #define ifp (&sc->sc_ethercom.ec_if)
154 am79900_config(struct am79900_softc
*sc
)
158 sc
->lsc
.sc_meminit
= am79900_meminit
;
159 sc
->lsc
.sc_start
= am79900_start
;
161 lance_config(&sc
->lsc
);
164 sc
->lsc
.sc_initaddr
= mem
;
165 mem
+= sizeof(struct leinit
);
166 sc
->lsc
.sc_rmdaddr
= mem
;
167 mem
+= sizeof(struct lermd
) * sc
->lsc
.sc_nrbuf
;
168 sc
->lsc
.sc_tmdaddr
= mem
;
169 mem
+= sizeof(struct letmd
) * sc
->lsc
.sc_ntbuf
;
170 for (i
= 0; i
< sc
->lsc
.sc_nrbuf
; i
++, mem
+= LEBLEN
)
171 sc
->lsc
.sc_rbufaddr
[i
] = mem
;
172 for (i
= 0; i
< sc
->lsc
.sc_ntbuf
; i
++, mem
+= LEBLEN
)
173 sc
->lsc
.sc_tbufaddr
[i
] = mem
;
175 if (mem
> sc
->lsc
.sc_memsize
)
176 panic("%s: memsize", device_xname(sc
->lsc
.sc_dev
));
180 * Set up the initialization block and the descriptor rings.
183 am79900_meminit(struct lance_softc
*sc
)
193 if (ifp
->if_flags
& IFF_PROMISC
)
194 init
.init_mode
= LE_MODE_NORMAL
| LE_MODE_PROM
;
197 init
.init_mode
= LE_MODE_NORMAL
;
198 if (sc
->sc_initmodemedia
== 1)
199 init
.init_mode
|= LE_MODE_PSEL0
;
201 init
.init_mode
|= ((ffs(sc
->sc_ntbuf
) - 1) << 28)
202 | ((ffs(sc
->sc_nrbuf
) - 1) << 20);
205 * Update our private copy of the Ethernet address.
206 * We NEED the copy so we can ensure its alignment!
208 memcpy(sc
->sc_enaddr
, CLLADDR(ifp
->if_sadl
), ETHER_ADDR_LEN
);
209 myaddr
= sc
->sc_enaddr
;
211 init
.init_padr
[0] = myaddr
[0] | (myaddr
[1] << 8)
212 | (myaddr
[2] << 16) | (myaddr
[3] << 24);
213 init
.init_padr
[1] = myaddr
[4] | (myaddr
[5] << 8);
214 lance_setladrf(&sc
->sc_ethercom
, init
.init_ladrf
);
217 sc
->sc_first_td
= sc
->sc_last_td
= sc
->sc_no_td
= 0;
219 a
= sc
->sc_addr
+ LE_RMDADDR(sc
, 0);
222 a
= sc
->sc_addr
+ LE_TMDADDR(sc
, 0);
225 (*sc
->sc_copytodesc
)(sc
, &init
, LE_INITADDR(sc
), sizeof(init
));
228 * Set up receive ring descriptors.
230 for (bix
= 0; bix
< sc
->sc_nrbuf
; bix
++) {
231 a
= sc
->sc_addr
+ LE_RBUFADDR(sc
, bix
);
233 rmd
.rmd1
= LE_R1_OWN
| LE_R1_ONES
| (-LEBLEN
& 0xfff);
236 (*sc
->sc_copytodesc
)(sc
, &rmd
, LE_RMDADDR(sc
, bix
),
241 * Set up transmit ring descriptors.
243 for (bix
= 0; bix
< sc
->sc_ntbuf
; bix
++) {
244 a
= sc
->sc_addr
+ LE_TBUFADDR(sc
, bix
);
246 tmd
.tmd1
= LE_T1_ONES
;
249 (*sc
->sc_copytodesc
)(sc
, &tmd
, LE_TMDADDR(sc
, bix
),
255 am79900_rint(struct lance_softc
*sc
)
261 bix
= sc
->sc_last_rd
;
263 /* Process all buffers with valid data. */
265 rp
= LE_RMDADDR(sc
, bix
);
266 (*sc
->sc_copyfromdesc
)(sc
, &rmd
, rp
, sizeof(rmd
));
268 if (rmd
.rmd1
& LE_R1_OWN
)
271 if (rmd
.rmd1
& LE_R1_ERR
) {
272 if (rmd
.rmd1
& LE_R1_ENP
) {
274 if ((rmd
.rmd1
& LE_R1_OFLO
) == 0) {
275 if (rmd
.rmd1
& LE_R1_FRAM
)
276 printf("%s: framing error\n",
277 device_xname(sc
->sc_dev
));
278 if (rmd
.rmd1
& LE_R1_CRC
)
279 printf("%s: crc mismatch\n",
280 device_xname(sc
->sc_dev
));
284 if (rmd
.rmd1
& LE_R1_OFLO
)
285 printf("%s: overflow\n",
286 device_xname(sc
->sc_dev
));
288 if (rmd
.rmd1
& LE_R1_BUFF
)
289 printf("%s: receive buffer error\n",
290 device_xname(sc
->sc_dev
));
292 } else if ((rmd
.rmd1
& (LE_R1_STP
| LE_R1_ENP
)) !=
293 (LE_R1_STP
| LE_R1_ENP
)) {
294 printf("%s: dropping chained buffer\n",
295 device_xname(sc
->sc_dev
));
300 am79900_recv_print(sc
, sc
->sc_last_rd
);
302 lance_read(sc
, LE_RBUFADDR(sc
, bix
),
303 (rmd
.rmd2
& 0xfff) - 4);
306 rmd
.rmd1
= LE_R1_OWN
| LE_R1_ONES
| (-LEBLEN
& 0xfff);
309 (*sc
->sc_copytodesc
)(sc
, &rmd
, rp
, sizeof(rmd
));
313 printf("sc->sc_last_rd = %x, rmd: "
314 "adr %08x, flags/blen %08x\n",
319 if (++bix
== sc
->sc_nrbuf
)
323 sc
->sc_last_rd
= bix
;
327 am79900_tint(struct lance_softc
*sc
)
332 bix
= sc
->sc_first_td
;
335 if (sc
->sc_no_td
<= 0)
338 (*sc
->sc_copyfromdesc
)(sc
, &tmd
, LE_TMDADDR(sc
, bix
),
344 "adr %08x, flags/blen %08x\n",
348 if (tmd
.tmd1
& LE_T1_OWN
)
351 ifp
->if_flags
&= ~IFF_OACTIVE
;
353 if (tmd
.tmd1
& LE_T1_ERR
) {
354 if (tmd
.tmd2
& LE_T2_BUFF
)
355 printf("%s: transmit buffer error\n",
356 device_xname(sc
->sc_dev
));
357 else if (tmd
.tmd2
& LE_T2_UFLO
)
358 printf("%s: underflow\n",
359 device_xname(sc
->sc_dev
));
360 if (tmd
.tmd2
& (LE_T2_BUFF
| LE_T2_UFLO
)) {
364 if (tmd
.tmd2
& LE_T2_LCAR
) {
365 sc
->sc_havecarrier
= 0;
366 if (sc
->sc_nocarrier
)
367 (*sc
->sc_nocarrier
)(sc
);
369 printf("%s: lost carrier\n",
370 device_xname(sc
->sc_dev
));
372 if (tmd
.tmd2
& LE_T2_LCOL
)
373 ifp
->if_collisions
++;
374 if (tmd
.tmd2
& LE_T2_RTRY
) {
376 printf("%s: excessive collisions\n",
377 device_xname(sc
->sc_dev
));
379 ifp
->if_collisions
+= 16;
383 if (tmd
.tmd1
& LE_T1_ONE
)
384 ifp
->if_collisions
++;
385 else if (tmd
.tmd1
& LE_T1_MORE
)
386 /* Real number is unknown. */
387 ifp
->if_collisions
+= 2;
391 if (++bix
== sc
->sc_ntbuf
)
397 sc
->sc_first_td
= bix
;
401 if (sc
->sc_no_td
== 0)
406 * Controller interrupt.
409 am79900_intr(void *arg
)
411 struct lance_softc
*sc
= arg
;
414 isr
= (*sc
->sc_rdcsr
)(sc
, LE_CSR0
) | sc
->sc_saved_csr0
;
415 sc
->sc_saved_csr0
= 0;
416 #if defined(LEDEBUG) && LEDEBUG > 1
418 printf("%s: am79900_intr entering with isr=%04x\n",
419 device_xname(sc
->sc_dev
), isr
);
421 if ((isr
& LE_C0_INTR
) == 0)
424 (*sc
->sc_wrcsr
)(sc
, LE_CSR0
,
425 isr
& (LE_C0_INEA
| LE_C0_BABL
| LE_C0_MISS
| LE_C0_MERR
|
426 LE_C0_RINT
| LE_C0_TINT
| LE_C0_IDON
));
427 if (isr
& LE_C0_ERR
) {
428 if (isr
& LE_C0_BABL
) {
430 printf("%s: babble\n", device_xname(sc
->sc_dev
));
435 if (isr
& LE_C0_CERR
) {
436 printf("%s: collision error\n",
437 device_xname(sc
->sc_dev
));
438 ifp
->if_collisions
++;
441 if (isr
& LE_C0_MISS
) {
443 printf("%s: missed packet\n", device_xname(sc
->sc_dev
));
447 if (isr
& LE_C0_MERR
) {
448 printf("%s: memory error\n", device_xname(sc
->sc_dev
));
454 if ((isr
& LE_C0_RXON
) == 0) {
455 printf("%s: receiver disabled\n", device_xname(sc
->sc_dev
));
460 if ((isr
& LE_C0_TXON
) == 0) {
461 printf("%s: transmitter disabled\n", device_xname(sc
->sc_dev
));
468 * Pretend we have carrier; if we don't this will be cleared
471 sc
->sc_havecarrier
= 1;
473 if (isr
& LE_C0_RINT
)
475 if (isr
& LE_C0_TINT
)
479 rnd_add_uint32(&sc
->rnd_source
, isr
);
488 * Setup output on interface.
489 * Get another datagram to send off of the interface queue, and map it to the
490 * interface before starting the output.
491 * Called only at splnet or interrupt level.
494 am79900_start(struct ifnet
*ifp
)
496 struct lance_softc
*sc
= ifp
->if_softc
;
503 if ((ifp
->if_flags
& (IFF_RUNNING
| IFF_OACTIVE
)) != IFF_RUNNING
)
506 bix
= sc
->sc_last_td
;
509 rp
= LE_TMDADDR(sc
, bix
);
510 (*sc
->sc_copyfromdesc
)(sc
, &tmd
, rp
, sizeof(tmd
));
512 if (tmd
.tmd1
& LE_T1_OWN
) {
513 ifp
->if_flags
|= IFF_OACTIVE
;
514 printf("missing buffer, no_td = %d, last_td = %d\n",
515 sc
->sc_no_td
, sc
->sc_last_td
);
518 IFQ_DEQUEUE(&ifp
->if_snd
, m
);
524 * If BPF is listening on this interface, let it see the packet
525 * before we commit it to the wire.
528 bpf_mtap(ifp
->if_bpf
, m
);
532 * Copy the mbuf chain into the transmit buffer.
534 len
= lance_put(sc
, LE_TBUFADDR(sc
, bix
), m
);
537 if (len
> ETHERMTU
+ sizeof(struct ether_header
))
538 printf("packet length %d\n", len
);
544 * Init transmit registers, and set transmit start flag.
546 tmd
.tmd1
= LE_T1_OWN
| LE_T1_STP
| LE_T1_ENP
| LE_T1_ONES
| (-len
& 0xfff);
550 (*sc
->sc_copytodesc
)(sc
, &tmd
, rp
, sizeof(tmd
));
554 am79900_xmit_print(sc
, sc
->sc_last_td
);
557 (*sc
->sc_wrcsr
)(sc
, LE_CSR0
, LE_C0_INEA
| LE_C0_TDMD
);
559 if (++bix
== sc
->sc_ntbuf
)
562 if (++sc
->sc_no_td
== sc
->sc_ntbuf
) {
563 ifp
->if_flags
|= IFF_OACTIVE
;
569 sc
->sc_last_td
= bix
;
574 am79900_recv_print(struct lance_softc
*sc
, int no
)
578 struct ether_header eh
;
580 (*sc
->sc_copyfromdesc
)(sc
, &rmd
, LE_RMDADDR(sc
, no
), sizeof(rmd
));
581 len
= (rmd
.rmd2
& 0xfff) - 4;
582 printf("%s: receive buffer %d, len = %d\n",
583 device_xname(sc
->sc_dev
), no
, len
);
584 printf("%s: status %04x\n", device_xname(sc
->sc_dev
),
585 (*sc
->sc_rdcsr
)(sc
, LE_CSR0
));
586 printf("%s: adr %08x, flags/blen %08x\n",
587 device_xname(sc
->sc_dev
), rmd
.rmd0
, rmd
.rmd1
);
588 if (len
>= sizeof(eh
)) {
589 (*sc
->sc_copyfrombuf
)(sc
, &eh
, LE_RBUFADDR(sc
, no
), sizeof(eh
));
590 printf("%s: dst %s", device_xname(sc
->sc_dev
),
591 ether_sprintf(eh
.ether_dhost
));
592 printf(" src %s type %04x\n", ether_sprintf(eh
.ether_shost
),
593 ntohs(eh
.ether_type
));
598 am79900_xmit_print(struct lance_softc
*sc
, int no
)
602 struct ether_header eh
;
604 (*sc
->sc_copyfromdesc
)(sc
, &tmd
, LE_TMDADDR(sc
, no
), sizeof(tmd
));
605 len
= -(tmd
.tmd1
& 0xfff);
606 printf("%s: transmit buffer %d, len = %d\n",
607 device_xname(sc
->sc_dev
), no
, len
);
608 printf("%s: status %04x\n", device_xname(sc
->sc_dev
),
609 (*sc
->sc_rdcsr
)(sc
, LE_CSR0
));
610 printf("%s: adr %08x, flags/blen %08x\n",
611 device_xname(sc
->sc_dev
), tmd
.tmd0
, tmd
.tmd1
);
612 if (len
>= sizeof(eh
)) {
613 (*sc
->sc_copyfrombuf
)(sc
, &eh
, LE_TBUFADDR(sc
, no
), sizeof(eh
));
614 printf("%s: dst %s", device_xname(sc
->sc_dev
),
615 ether_sprintf(eh
.ether_dhost
));
616 printf(" src %s type %04x\n", ether_sprintf(eh
.ether_shost
),
617 ntohs(eh
.ether_type
));