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