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