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