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