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