1 /* $NetBSD: am7990.c,v 1.70 2008/04/04 12:25:07 tsutsui Exp $ */
4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
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.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
34 * Copyright (c) 1992, 1993
35 * The Regents of the University of California. All rights reserved.
37 * This code is derived from software contributed to Berkeley by
38 * Ralph Campbell and Rick Macklem.
40 * Redistribution and use in source and binary forms, with or without
41 * modification, are permitted provided that the following conditions
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.
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
64 * @(#)if_le.c 8.2 (Berkeley) 11/16/93
67 #include <sys/cdefs.h>
68 __KERNEL_RCSID(0, "$NetBSD: am7990.c,v 1.70 2008/04/04 12:25:07 tsutsui Exp $");
73 #include <sys/param.h>
74 #include <sys/systm.h>
76 #include <sys/syslog.h>
77 #include <sys/socket.h>
78 #include <sys/device.h>
79 #include <sys/malloc.h>
80 #include <sys/ioctl.h>
81 #include <sys/errno.h>
87 #include <net/if_dl.h>
88 #include <net/if_ether.h>
89 #include <net/if_media.h>
93 #include <net/bpfdesc.h>
96 #include <dev/ic/lancereg.h>
97 #include <dev/ic/lancevar.h>
98 #include <dev/ic/am7990reg.h>
99 #include <dev/ic/am7990var.h>
101 static void am7990_meminit(struct lance_softc
*);
102 static void am7990_start(struct ifnet
*);
104 #if defined(_KERNEL_OPT)
109 static void am7990_recv_print(struct lance_softc
*, int);
110 static void am7990_xmit_print(struct lance_softc
*, int);
113 #define ifp (&sc->sc_ethercom.ec_if)
116 am7990_config(struct am7990_softc
*sc
)
120 sc
->lsc
.sc_meminit
= am7990_meminit
;
121 sc
->lsc
.sc_start
= am7990_start
;
123 lance_config(&sc
->lsc
);
126 sc
->lsc
.sc_initaddr
= mem
;
127 mem
+= sizeof(struct leinit
);
128 sc
->lsc
.sc_rmdaddr
= mem
;
129 mem
+= sizeof(struct lermd
) * sc
->lsc
.sc_nrbuf
;
130 sc
->lsc
.sc_tmdaddr
= mem
;
131 mem
+= sizeof(struct letmd
) * sc
->lsc
.sc_ntbuf
;
132 for (i
= 0; i
< sc
->lsc
.sc_nrbuf
; i
++, mem
+= LEBLEN
)
133 sc
->lsc
.sc_rbufaddr
[i
] = mem
;
134 for (i
= 0; i
< sc
->lsc
.sc_ntbuf
; i
++, mem
+= LEBLEN
)
135 sc
->lsc
.sc_tbufaddr
[i
] = mem
;
143 * Set up the initialization block and the descriptor rings.
146 am7990_meminit(struct lance_softc
*sc
)
156 if (ifp
->if_flags
& IFF_PROMISC
)
157 init
.init_mode
= LE_MODE_NORMAL
| LE_MODE_PROM
;
160 init
.init_mode
= LE_MODE_NORMAL
;
161 if (sc
->sc_initmodemedia
== 1)
162 init
.init_mode
|= LE_MODE_PSEL0
;
165 * Update our private copy of the Ethernet address.
166 * We NEED the copy so we can ensure its alignment!
168 memcpy(sc
->sc_enaddr
, CLLADDR(ifp
->if_sadl
), ETHER_ADDR_LEN
);
169 myaddr
= sc
->sc_enaddr
;
171 init
.init_padr
[0] = (myaddr
[1] << 8) | myaddr
[0];
172 init
.init_padr
[1] = (myaddr
[3] << 8) | myaddr
[2];
173 init
.init_padr
[2] = (myaddr
[5] << 8) | myaddr
[4];
174 lance_setladrf(&sc
->sc_ethercom
, init
.init_ladrf
);
177 sc
->sc_first_td
= sc
->sc_last_td
= sc
->sc_no_td
= 0;
179 a
= sc
->sc_addr
+ LE_RMDADDR(sc
, 0);
181 init
.init_rlen
= (a
>> 16) | ((ffs(sc
->sc_nrbuf
) - 1) << 13);
183 a
= sc
->sc_addr
+ LE_TMDADDR(sc
, 0);
185 init
.init_tlen
= (a
>> 16) | ((ffs(sc
->sc_ntbuf
) - 1) << 13);
187 (*sc
->sc_copytodesc
)(sc
, &init
, LE_INITADDR(sc
), sizeof(init
));
190 * Set up receive ring descriptors.
192 for (bix
= 0; bix
< sc
->sc_nrbuf
; bix
++) {
193 a
= sc
->sc_addr
+ LE_RBUFADDR(sc
, bix
);
195 rmd
.rmd1_hadr
= a
>> 16;
196 rmd
.rmd1_bits
= LE_R1_OWN
;
197 rmd
.rmd2
= -LEBLEN
| LE_XMD2_ONES
;
199 (*sc
->sc_copytodesc
)(sc
, &rmd
, LE_RMDADDR(sc
, bix
),
204 * Set up transmit ring descriptors.
206 for (bix
= 0; bix
< sc
->sc_ntbuf
; bix
++) {
207 a
= sc
->sc_addr
+ LE_TBUFADDR(sc
, bix
);
209 tmd
.tmd1_hadr
= a
>> 16;
211 tmd
.tmd2
= 0 | LE_XMD2_ONES
;
213 (*sc
->sc_copytodesc
)(sc
, &tmd
, LE_TMDADDR(sc
, bix
),
219 am7990_rint(struct lance_softc
*sc
)
225 bix
= sc
->sc_last_rd
;
227 /* Process all buffers with valid data. */
229 rp
= LE_RMDADDR(sc
, bix
);
230 (*sc
->sc_copyfromdesc
)(sc
, &rmd
, rp
, sizeof(rmd
));
232 if (rmd
.rmd1_bits
& LE_R1_OWN
)
235 if (rmd
.rmd1_bits
& LE_R1_ERR
) {
236 if (rmd
.rmd1_bits
& LE_R1_ENP
) {
238 if ((rmd
.rmd1_bits
& LE_R1_OFLO
) == 0) {
239 if (rmd
.rmd1_bits
& LE_R1_FRAM
)
240 printf("%s: framing error\n",
241 device_xname(sc
->sc_dev
));
242 if (rmd
.rmd1_bits
& LE_R1_CRC
)
243 printf("%s: crc mismatch\n",
244 device_xname(sc
->sc_dev
));
248 if (rmd
.rmd1_bits
& LE_R1_OFLO
)
249 printf("%s: overflow\n",
250 device_xname(sc
->sc_dev
));
252 if (rmd
.rmd1_bits
& LE_R1_BUFF
)
253 printf("%s: receive buffer error\n",
254 device_xname(sc
->sc_dev
));
256 } else if ((rmd
.rmd1_bits
& (LE_R1_STP
| LE_R1_ENP
)) !=
257 (LE_R1_STP
| LE_R1_ENP
)) {
258 printf("%s: dropping chained buffer\n",
259 device_xname(sc
->sc_dev
));
263 if (sc
->sc_debug
> 1)
264 am7990_recv_print(sc
, sc
->sc_last_rd
);
266 lance_read(sc
, LE_RBUFADDR(sc
, bix
),
270 rmd
.rmd1_bits
= LE_R1_OWN
;
271 rmd
.rmd2
= -LEBLEN
| LE_XMD2_ONES
;
273 (*sc
->sc_copytodesc
)(sc
, &rmd
, rp
, sizeof(rmd
));
277 printf("sc->sc_last_rd = %x, rmd: "
278 "ladr %04x, hadr %02x, flags %02x, "
279 "bcnt %04x, mcnt %04x\n",
281 rmd
.rmd0
, rmd
.rmd1_hadr
, rmd
.rmd1_bits
,
285 if (++bix
== sc
->sc_nrbuf
)
289 sc
->sc_last_rd
= bix
;
293 am7990_tint(struct lance_softc
*sc
)
298 bix
= sc
->sc_first_td
;
301 if (sc
->sc_no_td
<= 0)
304 (*sc
->sc_copyfromdesc
)(sc
, &tmd
, LE_TMDADDR(sc
, bix
),
310 "ladr %04x, hadr %02x, flags %02x, "
311 "bcnt %04x, mcnt %04x\n",
312 tmd
.tmd0
, tmd
.tmd1_hadr
, tmd
.tmd1_bits
,
316 if (tmd
.tmd1_bits
& LE_T1_OWN
)
319 ifp
->if_flags
&= ~IFF_OACTIVE
;
321 if (tmd
.tmd1_bits
& LE_T1_ERR
) {
322 if (tmd
.tmd3
& LE_T3_BUFF
)
323 printf("%s: transmit buffer error\n",
324 device_xname(sc
->sc_dev
));
325 else if (tmd
.tmd3
& LE_T3_UFLO
)
326 printf("%s: underflow\n",
327 device_xname(sc
->sc_dev
));
328 if (tmd
.tmd3
& (LE_T3_BUFF
| LE_T3_UFLO
)) {
332 if (tmd
.tmd3
& LE_T3_LCAR
) {
333 sc
->sc_havecarrier
= 0;
334 if (sc
->sc_nocarrier
)
335 (*sc
->sc_nocarrier
)(sc
);
337 printf("%s: lost carrier\n",
338 device_xname(sc
->sc_dev
));
340 if (tmd
.tmd3
& LE_T3_LCOL
)
341 ifp
->if_collisions
++;
342 if (tmd
.tmd3
& LE_T3_RTRY
) {
344 printf("%s: excessive collisions, tdr %d\n",
345 device_xname(sc
->sc_dev
),
346 tmd
.tmd3
& LE_T3_TDR_MASK
);
348 ifp
->if_collisions
+= 16;
352 if (tmd
.tmd1_bits
& LE_T1_ONE
)
353 ifp
->if_collisions
++;
354 else if (tmd
.tmd1_bits
& LE_T1_MORE
)
355 /* Real number is unknown. */
356 ifp
->if_collisions
+= 2;
360 if (++bix
== sc
->sc_ntbuf
)
366 sc
->sc_first_td
= bix
;
370 if (sc
->sc_no_td
== 0)
375 * Controller interrupt.
378 am7990_intr(void *arg
)
380 struct lance_softc
*sc
= arg
;
383 isr
= (*sc
->sc_rdcsr
)(sc
, LE_CSR0
) | sc
->sc_saved_csr0
;
384 sc
->sc_saved_csr0
= 0;
385 #if defined(LEDEBUG) && LEDEBUG > 1
387 printf("%s: am7990_intr entering with isr=%04x\n",
388 device_xname(sc
->sc_dev
), isr
);
390 if ((isr
& LE_C0_INTR
) == 0)
395 * DEC needs this write order to the registers, don't know
396 * the results on other arch's. Ragge 991029
399 (*sc
->sc_wrcsr
)(sc
, LE_CSR0
, isr
);
400 (*sc
->sc_wrcsr
)(sc
, LE_CSR0
, LE_C0_INEA
);
402 (*sc
->sc_wrcsr
)(sc
, LE_CSR0
,
403 isr
& (LE_C0_INEA
| LE_C0_BABL
| LE_C0_MISS
| LE_C0_MERR
|
404 LE_C0_RINT
| LE_C0_TINT
| LE_C0_IDON
));
406 if (isr
& LE_C0_ERR
) {
407 if (isr
& LE_C0_BABL
) {
409 printf("%s: babble\n", device_xname(sc
->sc_dev
));
414 if (isr
& LE_C0_CERR
) {
415 printf("%s: collision error\n",
416 device_xname(sc
->sc_dev
));
417 ifp
->if_collisions
++;
420 if (isr
& LE_C0_MISS
) {
422 printf("%s: missed packet\n", device_xname(sc
->sc_dev
));
426 if (isr
& LE_C0_MERR
) {
427 printf("%s: memory error\n", device_xname(sc
->sc_dev
));
433 if ((isr
& LE_C0_RXON
) == 0) {
434 printf("%s: receiver disabled\n", device_xname(sc
->sc_dev
));
439 if ((isr
& LE_C0_TXON
) == 0) {
440 printf("%s: transmitter disabled\n", device_xname(sc
->sc_dev
));
447 * Pretend we have carrier; if we don't this will be cleared
450 sc
->sc_havecarrier
= 1;
452 if (isr
& LE_C0_RINT
)
454 if (isr
& LE_C0_TINT
)
458 rnd_add_uint32(&sc
->rnd_source
, isr
);
467 * Setup output on interface.
468 * Get another datagram to send off of the interface queue, and map it to the
469 * interface before starting the output.
470 * Called only at splnet or interrupt level.
473 am7990_start(struct ifnet
*ifp
)
475 struct lance_softc
*sc
= ifp
->if_softc
;
482 if ((ifp
->if_flags
& (IFF_RUNNING
| IFF_OACTIVE
)) != IFF_RUNNING
)
485 bix
= sc
->sc_last_td
;
488 rp
= LE_TMDADDR(sc
, bix
);
489 (*sc
->sc_copyfromdesc
)(sc
, &tmd
, rp
, sizeof(tmd
));
491 if (tmd
.tmd1_bits
& LE_T1_OWN
) {
492 ifp
->if_flags
|= IFF_OACTIVE
;
493 printf("missing buffer, no_td = %d, last_td = %d\n",
494 sc
->sc_no_td
, sc
->sc_last_td
);
497 IFQ_DEQUEUE(&ifp
->if_snd
, m
);
503 * If BPF is listening on this interface, let it see the packet
504 * before we commit it to the wire.
507 bpf_mtap(ifp
->if_bpf
, m
);
511 * Copy the mbuf chain into the transmit buffer.
513 len
= lance_put(sc
, LE_TBUFADDR(sc
, bix
), m
);
516 if (len
> ETHERMTU
+ sizeof(struct ether_header
))
517 printf("packet length %d\n", len
);
523 * Init transmit registers, and set transmit start flag.
525 tmd
.tmd1_bits
= LE_T1_OWN
| LE_T1_STP
| LE_T1_ENP
;
526 tmd
.tmd2
= -len
| LE_XMD2_ONES
;
529 (*sc
->sc_copytodesc
)(sc
, &tmd
, rp
, sizeof(tmd
));
532 if (sc
->sc_debug
> 1)
533 am7990_xmit_print(sc
, sc
->sc_last_td
);
536 (*sc
->sc_wrcsr
)(sc
, LE_CSR0
, LE_C0_INEA
| LE_C0_TDMD
);
538 if (++bix
== sc
->sc_ntbuf
)
541 if (++sc
->sc_no_td
== sc
->sc_ntbuf
) {
542 ifp
->if_flags
|= IFF_OACTIVE
;
548 sc
->sc_last_td
= bix
;
553 am7990_recv_print(struct lance_softc
*sc
, int no
)
557 struct ether_header eh
;
559 (*sc
->sc_copyfromdesc
)(sc
, &rmd
, LE_RMDADDR(sc
, no
), sizeof(rmd
));
561 printf("%s: receive buffer %d, len = %d\n",
562 device_xname(sc
->sc_dev
), no
, len
);
563 printf("%s: status %04x\n", device_xname(sc
->sc_dev
),
564 (*sc
->sc_rdcsr
)(sc
, LE_CSR0
));
565 printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
566 device_xname(sc
->sc_dev
),
567 rmd
.rmd0
, rmd
.rmd1_hadr
, rmd
.rmd1_bits
, rmd
.rmd2
, rmd
.rmd3
);
568 if (len
>= sizeof(eh
)) {
569 (*sc
->sc_copyfrombuf
)(sc
, &eh
, LE_RBUFADDR(sc
, no
), sizeof(eh
));
570 printf("%s: dst %s", device_xname(sc
->sc_dev
),
571 ether_sprintf(eh
.ether_dhost
));
572 printf(" src %s type %04x\n", ether_sprintf(eh
.ether_shost
),
573 ntohs(eh
.ether_type
));
578 am7990_xmit_print(struct lance_softc
*sc
, int no
)
582 struct ether_header eh
;
584 (*sc
->sc_copyfromdesc
)(sc
, &tmd
, LE_TMDADDR(sc
, no
), sizeof(tmd
));
586 printf("%s: transmit buffer %d, len = %d\n",
587 device_xname(sc
->sc_dev
), no
, len
);
588 printf("%s: status %04x\n", device_xname(sc
->sc_dev
),
589 (*sc
->sc_rdcsr
)(sc
, LE_CSR0
));
590 printf("%s: ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
591 device_xname(sc
->sc_dev
),
592 tmd
.tmd0
, tmd
.tmd1_hadr
, tmd
.tmd1_bits
, tmd
.tmd2
, tmd
.tmd3
);
593 if (len
>= sizeof(eh
)) {
594 (*sc
->sc_copyfrombuf
)(sc
, &eh
, LE_TBUFADDR(sc
, no
), sizeof(eh
));
595 printf("%s: dst %s", device_xname(sc
->sc_dev
),
596 ether_sprintf(eh
.ether_dhost
));
597 printf(" src %s type %04x\n", ether_sprintf(eh
.ether_shost
),
598 ntohs(eh
.ether_type
));