1 /* $NetBSD: am79900.c,v 1.17 2005/12/24 20:27:29 perry Exp $ */
2
3 /*-
4 * SPDX-License-Identifier: BSD-2-Clause 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 #include <sys/param.h>
109 #include <sys/bus.h>
110 #include <sys/endian.h>
111 #include <sys/lock.h>
112 #include <sys/mbuf.h>
113 #include <sys/mutex.h>
114 #include <sys/socket.h>
115
116 #include <net/bpf.h>
117 #include <net/ethernet.h>
118 #include <net/if.h>
119 #include <net/if_arp.h>
120 #include <net/if_dl.h>
121 #include <net/if_media.h>
122 #include <net/if_var.h>
123
124 #include <machine/bus.h>
125
126 #include <dev/le/lancereg.h>
127 #include <dev/le/lancevar.h>
128 #include <dev/le/am79900reg.h>
129 #include <dev/le/am79900var.h>
130
131 static void am79900_meminit(struct lance_softc *);
132 static void am79900_rint(struct lance_softc *);
133 static void am79900_tint(struct lance_softc *);
134 static void am79900_start_locked(struct lance_softc *sc);
135
136 #ifdef LEDEBUG
137 static void am79900_recv_print(struct lance_softc *, int);
138 static void am79900_xmit_print(struct lance_softc *, int);
139 #endif
140
141 int
am79900_config(struct am79900_softc * sc,const char * name,int unit)142 am79900_config(struct am79900_softc *sc, const char* name, int unit)
143 {
144 int error, mem;
145
146 sc->lsc.sc_meminit = am79900_meminit;
147 sc->lsc.sc_start_locked = am79900_start_locked;
148
149 error = lance_config(&sc->lsc, name, unit);
150 if (error != 0)
151 return (error);
152
153 mem = 0;
154 sc->lsc.sc_initaddr = mem;
155 mem += sizeof(struct leinit);
156 sc->lsc.sc_rmdaddr = mem;
157 mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf;
158 sc->lsc.sc_tmdaddr = mem;
159 mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf;
160 sc->lsc.sc_rbufaddr = mem;
161 mem += LEBLEN * sc->lsc.sc_nrbuf;
162 sc->lsc.sc_tbufaddr = mem;
163 mem += LEBLEN * sc->lsc.sc_ntbuf;
164
165 if (mem > sc->lsc.sc_memsize)
166 panic("%s: memsize", __func__);
167
168 lance_attach(&sc->lsc);
169
170 return (0);
171 }
172
173 void
am79900_detach(struct am79900_softc * sc)174 am79900_detach(struct am79900_softc *sc)
175 {
176
177 lance_detach(&sc->lsc);
178 }
179
180 /*
181 * Set up the initialization block and the descriptor rings.
182 */
183 static void
am79900_meminit(struct lance_softc * sc)184 am79900_meminit(struct lance_softc *sc)
185 {
186 if_t ifp = sc->sc_ifp;
187 struct leinit init;
188 struct lermd rmd;
189 struct letmd tmd;
190 u_long a;
191 int bix;
192
193 LE_LOCK_ASSERT(sc, MA_OWNED);
194
195 if (if_getflags(ifp) & IFF_PROMISC)
196 init.init_mode = LE_HTOLE32(LE_MODE_NORMAL | LE_MODE_PROM);
197 else
198 init.init_mode = LE_HTOLE32(LE_MODE_NORMAL);
199
200 init.init_mode |= LE_HTOLE32(((ffs(sc->sc_ntbuf) - 1) << 28) |
201 ((ffs(sc->sc_nrbuf) - 1) << 20));
202
203 init.init_padr[0] = LE_HTOLE32(sc->sc_enaddr[0] |
204 (sc->sc_enaddr[1] << 8) | (sc->sc_enaddr[2] << 16) |
205 (sc->sc_enaddr[3] << 24));
206 init.init_padr[1] = LE_HTOLE32(sc->sc_enaddr[4] |
207 (sc->sc_enaddr[5] << 8));
208 lance_setladrf(sc, init.init_ladrf);
209
210 sc->sc_last_rd = 0;
211 sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
212
213 a = sc->sc_addr + LE_RMDADDR(sc, 0);
214 init.init_rdra = LE_HTOLE32(a);
215
216 a = sc->sc_addr + LE_TMDADDR(sc, 0);
217 init.init_tdra = LE_HTOLE32(a);
218
219 (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
220
221 /*
222 * Set up receive ring descriptors.
223 */
224 for (bix = 0; bix < sc->sc_nrbuf; bix++) {
225 a = sc->sc_addr + LE_RBUFADDR(sc, bix);
226 rmd.rmd0 = LE_HTOLE32(a);
227 rmd.rmd1 = LE_HTOLE32(LE_R1_OWN | LE_R1_ONES |
228 (-LEBLEN & 0xfff));
229 rmd.rmd2 = 0;
230 rmd.rmd3 = 0;
231 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
232 sizeof(rmd));
233 }
234
235 /*
236 * Set up transmit ring descriptors.
237 */
238 for (bix = 0; bix < sc->sc_ntbuf; bix++) {
239 a = sc->sc_addr + LE_TBUFADDR(sc, bix);
240 tmd.tmd0 = LE_HTOLE32(a);
241 tmd.tmd1 = LE_HTOLE32(LE_T1_ONES);
242 tmd.tmd2 = 0;
243 tmd.tmd3 = 0;
244 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
245 sizeof(tmd));
246 }
247 }
248
249 static inline void
am79900_rint(struct lance_softc * sc)250 am79900_rint(struct lance_softc *sc)
251 {
252 if_t ifp = sc->sc_ifp;
253 struct mbuf *m;
254 struct lermd rmd;
255 uint32_t rmd1;
256 int bix, rp;
257 #if defined(__i386__)
258 struct ether_header *eh;
259 #endif
260
261 bix = sc->sc_last_rd;
262
263 /* Process all buffers with valid data. */
264 for (;;) {
265 rp = LE_RMDADDR(sc, bix);
266 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
267
268 rmd1 = LE_LE32TOH(rmd.rmd1);
269 if (rmd1 & LE_R1_OWN)
270 break;
271
272 m = NULL;
273 if ((rmd1 & (LE_R1_ERR | LE_R1_STP | LE_R1_ENP)) !=
274 (LE_R1_STP | LE_R1_ENP)){
275 if (rmd1 & LE_R1_ERR) {
276 #ifdef LEDEBUG
277 if (rmd1 & LE_R1_ENP) {
278 if ((rmd1 & LE_R1_OFLO) == 0) {
279 if (rmd1 & LE_R1_FRAM)
280 if_printf(ifp,
281 "framing error\n");
282 if (rmd1 & LE_R1_CRC)
283 if_printf(ifp,
284 "crc mismatch\n");
285 }
286 } else
287 if (rmd1 & LE_R1_OFLO)
288 if_printf(ifp, "overflow\n");
289 #endif
290 if (rmd1 & LE_R1_BUFF)
291 if_printf(ifp,
292 "receive buffer error\n");
293 } else if ((rmd1 & (LE_R1_STP | LE_R1_ENP)) !=
294 (LE_R1_STP | LE_R1_ENP))
295 if_printf(ifp, "dropping chained buffer\n");
296 } else {
297 #ifdef LEDEBUG
298 if (sc->sc_flags & LE_DEBUG)
299 am79900_recv_print(sc, bix);
300 #endif
301 /* Pull the packet off the interface. */
302 m = lance_get(sc, LE_RBUFADDR(sc, bix),
303 (LE_LE32TOH(rmd.rmd2) & 0xfff) - ETHER_CRC_LEN);
304 }
305
306 rmd.rmd1 = LE_HTOLE32(LE_R1_OWN | LE_R1_ONES |
307 (-LEBLEN & 0xfff));
308 rmd.rmd2 = 0;
309 rmd.rmd3 = 0;
310 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
311
312 if (++bix == sc->sc_nrbuf)
313 bix = 0;
314
315 if (m != NULL) {
316 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
317
318 #if defined(__i386__)
319 /*
320 * The VMware LANCE does not present IFF_SIMPLEX
321 * behavior on multicast packets. Thus drop the
322 * packet if it is from ourselves.
323 */
324 eh = mtod(m, struct ether_header *);
325 if (!ether_cmp(eh->ether_shost, sc->sc_enaddr)) {
326 m_freem(m);
327 continue;
328 }
329 #endif
330
331 /* Pass the packet up. */
332 LE_UNLOCK(sc);
333 if_input(ifp, m);
334 LE_LOCK(sc);
335 } else
336 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
337 }
338
339 sc->sc_last_rd = bix;
340 }
341
342 static inline void
am79900_tint(struct lance_softc * sc)343 am79900_tint(struct lance_softc *sc)
344 {
345 if_t ifp = sc->sc_ifp;
346 struct letmd tmd;
347 uint32_t tmd1, tmd2;
348 int bix;
349
350 bix = sc->sc_first_td;
351
352 for (;;) {
353 if (sc->sc_no_td <= 0)
354 break;
355
356 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
357 sizeof(tmd));
358
359 tmd1 = LE_LE32TOH(tmd.tmd1);
360
361 #ifdef LEDEBUG
362 if (sc->sc_flags & LE_DEBUG)
363 if_printf(ifp, "trans tmd: "
364 "adr %08x, flags/blen %08x\n",
365 LE_LE32TOH(tmd.tmd0), tmd1);
366 #endif
367
368 if (tmd1 & LE_T1_OWN)
369 break;
370
371 if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE);
372
373 if (tmd1 & LE_T1_ERR) {
374 tmd2 = LE_LE32TOH(tmd.tmd2);
375 if (tmd2 & LE_T2_BUFF)
376 if_printf(ifp, "transmit buffer error\n");
377 else if (tmd2 & LE_T2_UFLO)
378 if_printf(ifp, "underflow\n");
379 if (tmd2 & (LE_T2_BUFF | LE_T2_UFLO)) {
380 lance_init_locked(sc);
381 return;
382 }
383 if (tmd2 & LE_T2_LCAR) {
384 if (sc->sc_flags & LE_CARRIER)
385 if_link_state_change(ifp,
386 LINK_STATE_DOWN);
387 sc->sc_flags &= ~LE_CARRIER;
388 if (sc->sc_nocarrier)
389 (*sc->sc_nocarrier)(sc);
390 else
391 if_printf(ifp, "lost carrier\n");
392 }
393 if (tmd2 & LE_T2_LCOL)
394 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
395 if (tmd2 & LE_T2_RTRY) {
396 #ifdef LEDEBUG
397 if_printf(ifp, "excessive collisions\n");
398 #endif
399 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 16);
400 }
401 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
402 } else {
403 if (tmd1 & LE_T1_ONE)
404 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
405 else if (tmd1 & LE_T1_MORE)
406 /* Real number is unknown. */
407 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 2);
408 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1);
409 }
410
411 if (++bix == sc->sc_ntbuf)
412 bix = 0;
413
414 --sc->sc_no_td;
415 }
416
417 sc->sc_first_td = bix;
418
419 sc->sc_wdog_timer = sc->sc_no_td > 0 ? 5 : 0;
420 }
421
422 /*
423 * Controller interrupt
424 */
425 void
am79900_intr(void * arg)426 am79900_intr(void *arg)
427 {
428 struct lance_softc *sc = arg;
429 if_t ifp = sc->sc_ifp;
430 uint16_t isr;
431
432 LE_LOCK(sc);
433
434 if (sc->sc_hwintr && (*sc->sc_hwintr)(sc) == -1) {
435 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
436 lance_init_locked(sc);
437 LE_UNLOCK(sc);
438 return;
439 }
440
441 #ifndef __HAIKU__
442 isr = (*sc->sc_rdcsr)(sc, LE_CSR0);
443 #else
444 {
445 HAIKU_INTR_REGISTER_STATE;
446 HAIKU_INTR_REGISTER_ENTER();
447 isr = sc->sc_lastisr;
448 sc->sc_lastisr = 0;
449 HAIKU_INTR_REGISTER_LEAVE();
450 }
451 #endif
452 #if defined(LEDEBUG) && LEDEBUG > 1
453 if (sc->sc_flags & LE_DEBUG)
454 if_printf(ifp, "%s: entering with isr=%04x\n", __func__, isr);
455 #endif
456 if ((isr & LE_C0_INTR) == 0) {
457 LE_UNLOCK(sc);
458 return;
459 }
460
461 /*
462 * Clear interrupt source flags and turn off interrupts. If we
463 * don't clear these flags before processing their sources we
464 * could completely miss some interrupt events as the NIC can
465 * change these flags while we're in this handler. We toggle
466 * the interrupt enable bit in order to keep receiving them
467 * (some chips work without this, some don't).
468 */
469 (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~(LE_C0_INEA | LE_C0_TDMD |
470 LE_C0_STOP | LE_C0_STRT | LE_C0_INIT));
471
472 if (isr & LE_C0_ERR) {
473 if (isr & LE_C0_BABL) {
474 #ifdef LEDEBUG
475 if_printf(ifp, "babble\n");
476 #endif
477 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
478 }
479 #if 0
480 if (isr & LE_C0_CERR) {
481 if_printf(ifp, "collision error\n");
482 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1);
483 }
484 #endif
485 if (isr & LE_C0_MISS) {
486 #ifdef LEDEBUG
487 if_printf(ifp, "missed packet\n");
488 #endif
489 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
490 }
491 if (isr & LE_C0_MERR) {
492 if_printf(ifp, "memory error\n");
493 lance_init_locked(sc);
494 LE_UNLOCK(sc);
495 return;
496 }
497 }
498
499 if ((isr & LE_C0_RXON) == 0) {
500 if_printf(ifp, "receiver disabled\n");
501 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
502 lance_init_locked(sc);
503 LE_UNLOCK(sc);
504 return;
505 }
506 if ((isr & LE_C0_TXON) == 0) {
507 if_printf(ifp, "transmitter disabled\n");
508 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1);
509 lance_init_locked(sc);
510 LE_UNLOCK(sc);
511 return;
512 }
513
514 /*
515 * Pretend we have carrier; if we don't this will be cleared shortly.
516 */
517 if (!(sc->sc_flags & LE_CARRIER))
518 if_link_state_change(ifp, LINK_STATE_UP);
519 sc->sc_flags |= LE_CARRIER;
520
521 if (isr & LE_C0_RINT)
522 am79900_rint(sc);
523 if (isr & LE_C0_TINT)
524 am79900_tint(sc);
525
526 /* Enable interrupts again. */
527 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA);
528
529 if (!if_sendq_empty(ifp))
530 am79900_start_locked(sc);
531
532 LE_UNLOCK(sc);
533 }
534
535 /*
536 * Set up output on interface.
537 * Get another datagram to send off of the interface queue, and map it to the
538 * interface before starting the output.
539 */
540 static void
am79900_start_locked(struct lance_softc * sc)541 am79900_start_locked(struct lance_softc *sc)
542 {
543 if_t ifp = sc->sc_ifp;
544 struct letmd tmd;
545 struct mbuf *m;
546 int bix, enq, len, rp;
547
548 LE_LOCK_ASSERT(sc, MA_OWNED);
549
550 if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
551 IFF_DRV_RUNNING)
552 return;
553
554 bix = sc->sc_last_td;
555 enq = 0;
556
557 for (; sc->sc_no_td < sc->sc_ntbuf &&
558 !if_sendq_empty(ifp);) {
559 rp = LE_TMDADDR(sc, bix);
560 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
561
562 if (LE_LE32TOH(tmd.tmd1) & LE_T1_OWN) {
563 if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0);
564 if_printf(ifp,
565 "missing buffer, no_td = %d, last_td = %d\n",
566 sc->sc_no_td, sc->sc_last_td);
567 }
568
569 m = if_dequeue(ifp);
570 if (m == NULL)
571 break;
572
573 /*
574 * If BPF is listening on this interface, let it see the packet
575 * before we commit it to the wire.
576 */
577 BPF_MTAP(ifp, m);
578
579 /*
580 * Copy the mbuf chain into the transmit buffer.
581 */
582 len = lance_put(sc, LE_TBUFADDR(sc, bix), m);
583
584 #ifdef LEDEBUG
585 if (len > ETHERMTU + ETHER_HDR_LEN)
586 if_printf(ifp, "packet length %d\n", len);
587 #endif
588
589 /*
590 * Init transmit registers, and set transmit start flag.
591 */
592 tmd.tmd1 = LE_HTOLE32(LE_T1_OWN | LE_T1_STP | LE_T1_ENP |
593 LE_T1_ONES | (-len & 0xfff));
594 tmd.tmd2 = 0;
595 tmd.tmd3 = 0;
596
597 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
598
599 #ifdef LEDEBUG
600 if (sc->sc_flags & LE_DEBUG)
601 am79900_xmit_print(sc, bix);
602 #endif
603
604 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD);
605 enq++;
606
607 if (++bix == sc->sc_ntbuf)
608 bix = 0;
609
610 if (++sc->sc_no_td == sc->sc_ntbuf) {
611 if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0);
612 break;
613 }
614 }
615
616 sc->sc_last_td = bix;
617
618 if (enq > 0)
619 sc->sc_wdog_timer = 5;
620 }
621
622 #ifdef LEDEBUG
623 static void
am79900_recv_print(struct lance_softc * sc,int no)624 am79900_recv_print(struct lance_softc *sc, int no)
625 {
626 if_t ifp = sc->sc_ifp;
627 struct ether_header eh;
628 struct lermd rmd;
629 uint16_t len;
630
631 (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
632 len = LE_LE32TOH(rmd.rmd2) & 0xfff;
633 if_printf(ifp, "receive buffer %d, len = %d\n", no, len);
634 if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0));
635 if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(rmd.rmd0),
636 LE_LE32TOH(rmd.rmd1));
637 if (len - ETHER_CRC_LEN >= sizeof(eh)) {
638 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
639 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost));
640 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
641 ntohs(eh.ether_type));
642 }
643 }
644
645 static void
am79900_xmit_print(struct lance_softc * sc,int no)646 am79900_xmit_print(struct lance_softc *sc, int no)
647 {
648 if_t ifp = sc->sc_ifp;
649 struct ether_header eh;
650 struct letmd tmd;
651 uint16_t len;
652
653 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
654 len = -(LE_LE32TOH(tmd.tmd1) & 0xfff);
655 if_printf(ifp, "transmit buffer %d, len = %d\n", no, len);
656 if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0));
657 if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(tmd.tmd0),
658 LE_LE32TOH(tmd.tmd1));
659 if (len >= sizeof(eh)) {
660 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
661 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost));
662 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost),
663 ntohs(eh.ether_type));
664 }
665 }
666 #endif /* LEDEBUG */
667