]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/le/am79900.c
arm: Let the GDB stub write to SP, LR and GP registers
[FreeBSD/FreeBSD.git] / sys / dev / le / am79900.c
1 /*      $NetBSD: am79900.c,v 1.17 2005/12/24 20:27:29 perry Exp $       */
2
3 /*-
4  * SPDX-License-Identifier: BSD-2-Clause-NetBSD AND BSD-3-Clause
5  *
6  * Copyright (c) 1997 The NetBSD Foundation, Inc.
7  * All rights reserved.
8  *
9  * This code is derived from software contributed to The NetBSD Foundation
10  * by Jason R. Thorpe.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 /*-
35  * Copyright (c) 1992, 1993
36  *      The Regents of the University of California.  All rights reserved.
37  *
38  * This code is derived from software contributed to Berkeley by
39  * Ralph Campbell and Rick Macklem.
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  * 1. Redistributions of source code must retain the above copyright
45  *    notice, this list of conditions and the following disclaimer.
46  * 2. Redistributions in binary form must reproduce the above copyright
47  *    notice, this list of conditions and the following disclaimer in the
48  *    documentation and/or other materials provided with the distribution.
49  * 3. Neither the name of the University nor the names of its contributors
50  *    may be used to endorse or promote products derived from this software
51  *    without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63  * SUCH DAMAGE.
64  *
65  *      @(#)if_le.c     8.2 (Berkeley) 11/16/93
66  */
67
68 /*-
69  * Copyright (c) 1998
70  *      Matthias Drochner.  All rights reserved.
71  * Copyright (c) 1995 Charles M. Hannum.  All rights reserved.
72  *
73  * This code is derived from software contributed to Berkeley by
74  * Ralph Campbell and Rick Macklem.
75  *
76  * Redistribution and use in source and binary forms, with or without
77  * modification, are permitted provided that the following conditions
78  * are met:
79  * 1. Redistributions of source code must retain the above copyright
80  *    notice, this list of conditions and the following disclaimer.
81  * 2. Redistributions in binary form must reproduce the above copyright
82  *    notice, this list of conditions and the following disclaimer in the
83  *    documentation and/or other materials provided with the distribution.
84  * 3. All advertising materials mentioning features or use of this software
85  *    must display the following acknowledgement:
86  *      This product includes software developed by the University of
87  *      California, Berkeley and its contributors.
88  * 4. Neither the name of the University nor the names of its contributors
89  *    may be used to endorse or promote products derived from this software
90  *    without specific prior written permission.
91  *
92  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
93  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
95  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
96  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
97  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
98  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
99  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
100  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
101  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
102  * SUCH DAMAGE.
103  *
104  *      @(#)if_le.c     8.2 (Berkeley) 11/16/93
105  */
106
107 #include <sys/cdefs.h>
108 __FBSDID("$FreeBSD$");
109
110 #include <sys/param.h>
111 #include <sys/bus.h>
112 #include <sys/endian.h>
113 #include <sys/lock.h>
114 #include <sys/mbuf.h>
115 #include <sys/mutex.h>
116 #include <sys/socket.h>
117
118 #include <net/bpf.h>
119 #include <net/ethernet.h>
120 #include <net/if.h>
121 #include <net/if_arp.h>
122 #include <net/if_dl.h>
123 #include <net/if_media.h>
124 #include <net/if_var.h>
125
126 #include <machine/bus.h>
127
128 #include <dev/le/lancereg.h>
129 #include <dev/le/lancevar.h>
130 #include <dev/le/am79900reg.h>
131 #include <dev/le/am79900var.h>
132
133 static void     am79900_meminit(struct lance_softc *);
134 static void     am79900_rint(struct lance_softc *);
135 static void     am79900_tint(struct lance_softc *);
136 static void     am79900_start_locked(struct lance_softc *sc);
137
138 #ifdef LEDEBUG
139 static void     am79900_recv_print(struct lance_softc *, int);
140 static void     am79900_xmit_print(struct lance_softc *, int);
141 #endif
142
143 int
144 am79900_config(struct am79900_softc *sc, const char* name, int unit)
145 {
146         int error, mem;
147
148         sc->lsc.sc_meminit = am79900_meminit;
149         sc->lsc.sc_start_locked = am79900_start_locked;
150
151         error = lance_config(&sc->lsc, name, unit);
152         if (error != 0)
153                 return (error);
154
155         mem = 0;
156         sc->lsc.sc_initaddr = mem;
157         mem += sizeof(struct leinit);
158         sc->lsc.sc_rmdaddr = mem;
159         mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf;
160         sc->lsc.sc_tmdaddr = mem;
161         mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf;
162         sc->lsc.sc_rbufaddr = mem;
163         mem += LEBLEN * sc->lsc.sc_nrbuf;
164         sc->lsc.sc_tbufaddr = mem;
165         mem += LEBLEN * sc->lsc.sc_ntbuf;
166
167         if (mem > sc->lsc.sc_memsize)
168                 panic("%s: memsize", __func__);
169
170         lance_attach(&sc->lsc);
171
172         return (0);
173 }
174
175 void
176 am79900_detach(struct am79900_softc *sc)
177 {
178
179         lance_detach(&sc->lsc);
180 }
181
182 /*
183  * Set up the initialization block and the descriptor rings.
184  */
185 static void
186 am79900_meminit(struct lance_softc *sc)
187 {
188         struct ifnet *ifp = sc->sc_ifp;
189         struct leinit init;
190         struct lermd rmd;
191         struct letmd tmd;
192         u_long a;
193         int bix;
194
195         LE_LOCK_ASSERT(sc, MA_OWNED);
196
197         if (ifp->if_flags & IFF_PROMISC)
198                 init.init_mode = LE_HTOLE32(LE_MODE_NORMAL | LE_MODE_PROM);
199         else
200                 init.init_mode = LE_HTOLE32(LE_MODE_NORMAL);
201
202         init.init_mode |= LE_HTOLE32(((ffs(sc->sc_ntbuf) - 1) << 28) |
203             ((ffs(sc->sc_nrbuf) - 1) << 20));
204
205         init.init_padr[0] = LE_HTOLE32(sc->sc_enaddr[0] |
206             (sc->sc_enaddr[1] << 8) | (sc->sc_enaddr[2] << 16) |
207             (sc->sc_enaddr[3] << 24));
208         init.init_padr[1] = LE_HTOLE32(sc->sc_enaddr[4] |
209             (sc->sc_enaddr[5] << 8));
210         lance_setladrf(sc, init.init_ladrf);
211
212         sc->sc_last_rd = 0;
213         sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
214
215         a = sc->sc_addr + LE_RMDADDR(sc, 0);
216         init.init_rdra = LE_HTOLE32(a);
217
218         a = sc->sc_addr + LE_TMDADDR(sc, 0);
219         init.init_tdra = LE_HTOLE32(a);
220
221         (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
222
223         /*
224          * Set up receive ring descriptors.
225          */
226         for (bix = 0; bix < sc->sc_nrbuf; bix++) {
227                 a = sc->sc_addr + LE_RBUFADDR(sc, bix);
228                 rmd.rmd0 = LE_HTOLE32(a);
229                 rmd.rmd1 = LE_HTOLE32(LE_R1_OWN | LE_R1_ONES |
230                     (-LEBLEN & 0xfff));
231                 rmd.rmd2 = 0;
232                 rmd.rmd3 = 0;
233                 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
234                     sizeof(rmd));
235         }
236
237         /*
238          * Set up transmit ring descriptors.
239          */
240         for (bix = 0; bix < sc->sc_ntbuf; bix++) {
241                 a = sc->sc_addr + LE_TBUFADDR(sc, bix);
242                 tmd.tmd0 = LE_HTOLE32(a);
243                 tmd.tmd1 = LE_HTOLE32(LE_T1_ONES);
244                 tmd.tmd2 = 0;
245                 tmd.tmd3 = 0;
246                 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
247                     sizeof(tmd));
248         }
249 }
250
251 static inline void
252 am79900_rint(struct lance_softc *sc)
253 {
254         struct ifnet *ifp = sc->sc_ifp;
255         struct mbuf *m;
256         struct lermd rmd;
257         uint32_t rmd1;
258         int bix, rp;
259 #if defined(__i386__)
260         struct ether_header *eh;
261 #endif
262
263         bix = sc->sc_last_rd;
264
265         /* Process all buffers with valid data. */
266         for (;;) {
267                 rp = LE_RMDADDR(sc, bix);
268                 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
269
270                 rmd1 = LE_LE32TOH(rmd.rmd1);
271                 if (rmd1 & LE_R1_OWN)
272                         break;
273
274                 m = NULL;
275                 if ((rmd1 & (LE_R1_ERR | LE_R1_STP | LE_R1_ENP)) !=
276                     (LE_R1_STP | LE_R1_ENP)){
277                         if (rmd1 & LE_R1_ERR) {
278 #ifdef LEDEBUG
279                                 if (rmd1 & LE_R1_ENP) {
280                                         if ((rmd1 & LE_R1_OFLO) == 0) {
281                                                 if (rmd1 & LE_R1_FRAM)
282                                                         if_printf(ifp,
283                                                             "framing error\n");
284                                                 if (rmd1 & LE_R1_CRC)
285                                                         if_printf(ifp,
286                                                             "crc mismatch\n");
287                                         }
288                                 } else
289                                         if (rmd1 & LE_R1_OFLO)
290                                                 if_printf(ifp, "overflow\n");
291 #endif
292                                 if (rmd1 & LE_R1_BUFF)
293                                         if_printf(ifp,
294                                             "receive buffer error\n");
295                         } else if ((rmd1 & (LE_R1_STP | LE_R1_ENP)) !=
296                             (LE_R1_STP | LE_R1_ENP))
297                                 if_printf(ifp, "dropping chained buffer\n");
298                 } else {
299 #ifdef LEDEBUG
300                         if (sc->sc_flags & LE_DEBUG)
301                                 am79900_recv_print(sc, bix);
302 #endif
303                         /* Pull the packet off the interface. */
304                         m = lance_get(sc, LE_RBUFADDR(sc, bix),
305                             (LE_LE32TOH(rmd.rmd2) & 0xfff) - ETHER_CRC_LEN);
306                 }
307
308                 rmd.rmd1 = LE_HTOLE32(LE_R1_OWN | LE_R1_ONES |
309                     (-LEBLEN & 0xfff));
310                 rmd.rmd2 = 0;
311                 rmd.rmd3 = 0;
312                 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
313
314                 if (++bix == sc->sc_nrbuf)
315                         bix = 0;
316
317                 if (m != NULL) {
318                         if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
319
320 #if defined(__i386__)
321                         /*
322                          * The VMware LANCE does not present IFF_SIMPLEX
323                          * behavior on multicast packets. Thus drop the
324                          * packet if it is from ourselves.
325                          */
326                         eh = mtod(m, struct ether_header *);
327                         if (!ether_cmp(eh->ether_shost, sc->sc_enaddr)) {
328                                 m_freem(m);
329                                 continue;
330                         }
331 #endif
332
333                         /* Pass the packet up. */
334                         LE_UNLOCK(sc);
335                         (*ifp->if_input)(ifp, m);
336                         LE_LOCK(sc);
337                 } else
338                         if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
339         }
340
341         sc->sc_last_rd = bix;
342 }
343
344 static inline void
345 am79900_tint(struct lance_softc *sc)
346 {
347         struct ifnet *ifp = sc->sc_ifp;
348         struct letmd tmd;
349         uint32_t tmd1, tmd2;
350         int bix;
351
352         bix = sc->sc_first_td;
353
354         for (;;) {
355                 if (sc->sc_no_td <= 0)
356                         break;
357
358                 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
359                     sizeof(tmd));
360
361                 tmd1 = LE_LE32TOH(tmd.tmd1);
362
363 #ifdef LEDEBUG
364                 if (sc->sc_flags & LE_DEBUG)
365                         if_printf(ifp, "trans tmd: "
366                             "adr %08x, flags/blen %08x\n",
367                             LE_LE32TOH(tmd.tmd0), tmd1);
368 #endif
369
370                 if (tmd1 & LE_T1_OWN)
371                         break;
372
373                 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
374
375                 if (tmd1 & LE_T1_ERR) {
376                         tmd2 = LE_LE32TOH(tmd.tmd2);
377                         if (tmd2 & LE_T2_BUFF)
378                                 if_printf(ifp, "transmit buffer error\n");
379                         else if (tmd2 & LE_T2_UFLO)
380                                 if_printf(ifp, "underflow\n");
381                         if (tmd2 & (LE_T2_BUFF | LE_T2_UFLO)) {
382                                 lance_init_locked(sc);
383                                 return;
384                         }
385                         if (tmd2 & LE_T2_LCAR) {
386                                 if (sc->sc_flags & LE_CARRIER)
387                                         if_link_state_change(ifp,
388                                             LINK_STATE_DOWN);
389                                 sc->sc_flags &= ~LE_CARRIER;
390                                 if (sc->sc_nocarrier)
391                                         (*sc->sc_nocarrier)(sc);
392                                 else
393                                         if_printf(ifp, "lost carrier\n");
394                         }
395                         if (tmd2 & LE_T2_LCOL)
396                                 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
397                         if (tmd2 & LE_T2_RTRY) {
398 #ifdef LEDEBUG
399                                 if_printf(ifp, "excessive collisions\n");
400 #endif
401                                 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 16);
402                         }
403                         if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
404                 } else {
405                         if (tmd1 & LE_T1_ONE)
406                                 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
407                         else if (tmd1 & LE_T1_MORE)
408                                 /* Real number is unknown. */
409                                 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 2);
410                         if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
411                 }
412
413                 if (++bix == sc->sc_ntbuf)
414                         bix = 0;
415
416                 --sc->sc_no_td;
417         }
418
419         sc->sc_first_td = bix;
420
421         sc->sc_wdog_timer = sc->sc_no_td > 0 ? 5 : 0;
422 }
423
424 /*
425  * Controller interrupt
426  */
427 void
428 am79900_intr(void *arg)
429 {
430         struct lance_softc *sc = arg;
431         struct ifnet *ifp = sc->sc_ifp;
432         uint16_t isr;
433
434         LE_LOCK(sc);
435
436         if (sc->sc_hwintr && (*sc->sc_hwintr)(sc) == -1) {
437                 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
438                 lance_init_locked(sc);
439                 LE_UNLOCK(sc);
440                 return;
441         }
442
443         isr = (*sc->sc_rdcsr)(sc, LE_CSR0);
444 #if defined(LEDEBUG) && LEDEBUG > 1
445         if (sc->sc_flags & LE_DEBUG)
446                 if_printf(ifp, "%s: entering with isr=%04x\n", __func__, isr);
447 #endif
448         if ((isr & LE_C0_INTR) == 0) {
449                 LE_UNLOCK(sc);
450                 return;
451         }
452
453         /*
454          * Clear interrupt source flags and turn off interrupts. If we
455          * don't clear these flags before processing their sources we
456          * could completely miss some interrupt events as the NIC can
457          * change these flags while we're in this handler. We toggle
458          * the interrupt enable bit in order to keep receiving them
459          * (some chips work without this, some don't).
460          */
461         (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~(LE_C0_INEA | LE_C0_TDMD |
462             LE_C0_STOP | LE_C0_STRT | LE_C0_INIT));
463
464         if (isr & LE_C0_ERR) {
465                 if (isr & LE_C0_BABL) {
466 #ifdef LEDEBUG
467                         if_printf(ifp, "babble\n");
468 #endif
469                         if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
470                 }
471 #if 0
472                 if (isr & LE_C0_CERR) {
473                         if_printf(ifp, "collision error\n");
474                         if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
475                 }
476 #endif
477                 if (isr & LE_C0_MISS) {
478 #ifdef LEDEBUG
479                         if_printf(ifp, "missed packet\n");
480 #endif
481                         if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
482                 }
483                 if (isr & LE_C0_MERR) {
484                         if_printf(ifp, "memory error\n");
485                         lance_init_locked(sc);
486                         LE_UNLOCK(sc);
487                         return;
488                 }
489         }
490
491         if ((isr & LE_C0_RXON) == 0) {
492                 if_printf(ifp, "receiver disabled\n");
493                 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
494                 lance_init_locked(sc);
495                 LE_UNLOCK(sc);
496                 return;
497         }
498         if ((isr & LE_C0_TXON) == 0) {
499                 if_printf(ifp, "transmitter disabled\n");
500                 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
501                 lance_init_locked(sc);
502                 LE_UNLOCK(sc);
503                 return;
504         }
505
506         /*
507          * Pretend we have carrier; if we don't this will be cleared shortly.
508          */
509         if (!(sc->sc_flags & LE_CARRIER))
510                 if_link_state_change(ifp, LINK_STATE_UP);
511         sc->sc_flags |= LE_CARRIER;
512
513         if (isr & LE_C0_RINT)
514                 am79900_rint(sc);
515         if (isr & LE_C0_TINT)
516                 am79900_tint(sc);
517
518         /* Enable interrupts again. */
519         (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA);
520
521         if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
522                 am79900_start_locked(sc);
523
524         LE_UNLOCK(sc);
525 }
526
527 /*
528  * Set up output on interface.
529  * Get another datagram to send off of the interface queue, and map it to the
530  * interface before starting the output.
531  */
532 static void
533 am79900_start_locked(struct lance_softc *sc)
534 {
535         struct ifnet *ifp = sc->sc_ifp;
536         struct letmd tmd;
537         struct mbuf *m;
538         int bix, enq, len, rp;
539
540         LE_LOCK_ASSERT(sc, MA_OWNED);
541
542         if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
543             IFF_DRV_RUNNING)
544                 return;
545
546         bix = sc->sc_last_td;
547         enq = 0;
548
549         for (; sc->sc_no_td < sc->sc_ntbuf &&
550             !IFQ_DRV_IS_EMPTY(&ifp->if_snd);) {
551                 rp = LE_TMDADDR(sc, bix);
552                 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
553
554                 if (LE_LE32TOH(tmd.tmd1) & LE_T1_OWN) {
555                         ifp->if_drv_flags |= IFF_DRV_OACTIVE;
556                         if_printf(ifp,
557                             "missing buffer, no_td = %d, last_td = %d\n",
558                             sc->sc_no_td, sc->sc_last_td);
559                 }
560
561                 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
562                 if (m == NULL)
563                         break;
564
565                 /*
566                  * If BPF is listening on this interface, let it see the packet
567                  * before we commit it to the wire.
568                  */
569                 BPF_MTAP(ifp, m);
570
571                 /*
572                  * Copy the mbuf chain into the transmit buffer.
573                  */
574                 len = lance_put(sc, LE_TBUFADDR(sc, bix), m);
575
576 #ifdef LEDEBUG
577                 if (len > ETHERMTU + ETHER_HDR_LEN)
578                         if_printf(ifp, "packet length %d\n", len);
579 #endif
580
581                 /*
582                  * Init transmit registers, and set transmit start flag.
583                  */
584                 tmd.tmd1 = LE_HTOLE32(LE_T1_OWN | LE_T1_STP | LE_T1_ENP |
585                     LE_T1_ONES | (-len & 0xfff));
586                 tmd.tmd2 = 0;
587                 tmd.tmd3 = 0;
588
589                 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
590
591 #ifdef LEDEBUG
592                 if (sc->sc_flags & LE_DEBUG)
593                         am79900_xmit_print(sc, bix);
594 #endif
595
596                 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
597                 enq++;
598
599                 if (++bix == sc->sc_ntbuf)
600                         bix = 0;
601
602                 if (++sc->sc_no_td == sc->sc_ntbuf) {
603                         ifp->if_drv_flags |= IFF_DRV_OACTIVE;
604                         break;
605                 }
606         }
607
608         sc->sc_last_td = bix;
609
610         if (enq > 0)
611                 sc->sc_wdog_timer = 5;
612 }
613
614 #ifdef LEDEBUG
615 static void
616 am79900_recv_print(struct lance_softc *sc, int no)
617 {
618         struct ifnet *ifp = sc->sc_ifp;
619         struct ether_header eh;
620         struct lermd rmd;
621         uint16_t len;
622
623         (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
624         len = LE_LE32TOH(rmd.rmd2) & 0xfff;
625         if_printf(ifp, "receive buffer %d, len = %d\n", no, len);
626         if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0));
627         if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(rmd.rmd0),
628             LE_LE32TOH(rmd.rmd1));
629         if (len - ETHER_CRC_LEN >= sizeof(eh)) {
630                 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
631                 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost));
632                 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
633                     ntohs(eh.ether_type));
634         }
635 }
636
637 static void
638 am79900_xmit_print(struct lance_softc *sc, int no)
639 {
640         struct ifnet *ifp = sc->sc_ifp;
641         struct ether_header eh;
642         struct letmd tmd;
643         uint16_t len;
644
645         (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
646         len = -(LE_LE32TOH(tmd.tmd1) & 0xfff);
647         if_printf(ifp, "transmit buffer %d, len = %d\n", no, len);
648         if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0));
649         if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(tmd.tmd0),
650             LE_LE32TOH(tmd.tmd1));
651         if (len >= sizeof(eh)) {
652                 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
653                 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost));
654                 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
655                     ntohs(eh.ether_type));
656         }
657 }
658 #endif /* LEDEBUG */