1 /* $NetBSD: am7990.c,v 1.68 2005/12/11 12:21:25 christos Exp $ */ 2 3 /*- 4 * SPDX-License-Identifier: BSD-2-Clause 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 67 #include <sys/param.h> 68 #include <sys/bus.h> 69 #include <sys/endian.h> 70 #include <sys/lock.h> 71 #include <sys/mbuf.h> 72 #include <sys/mutex.h> 73 #include <sys/socket.h> 74 75 #include <net/bpf.h> 76 #include <net/ethernet.h> 77 #include <net/if.h> 78 #include <net/if_arp.h> 79 #include <net/if_dl.h> 80 #include <net/if_media.h> 81 #include <net/if_var.h> 82 83 #include <machine/bus.h> 84 85 #include <dev/le/lancereg.h> 86 #include <dev/le/lancevar.h> 87 #include <dev/le/am7990reg.h> 88 #include <dev/le/am7990var.h> 89 90 static void am7990_meminit(struct lance_softc *); 91 static void am7990_rint(struct lance_softc *); 92 static void am7990_tint(struct lance_softc *); 93 static void am7990_start_locked(struct lance_softc *sc); 94 95 #ifdef LEDEBUG 96 static void am7990_recv_print(struct lance_softc *, int); 97 static void am7990_xmit_print(struct lance_softc *, int); 98 #endif 99 100 int 101 am7990_config(struct am7990_softc *sc, const char* name, int unit) 102 { 103 int error, mem; 104 105 sc->lsc.sc_meminit = am7990_meminit; 106 sc->lsc.sc_start_locked = am7990_start_locked; 107 108 error = lance_config(&sc->lsc, name, unit); 109 if (error != 0) 110 return (error); 111 112 mem = 0; 113 sc->lsc.sc_initaddr = mem; 114 mem += sizeof(struct leinit); 115 sc->lsc.sc_rmdaddr = mem; 116 mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf; 117 sc->lsc.sc_tmdaddr = mem; 118 mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf; 119 sc->lsc.sc_rbufaddr = mem; 120 mem += LEBLEN * sc->lsc.sc_nrbuf; 121 sc->lsc.sc_tbufaddr = mem; 122 mem += LEBLEN * sc->lsc.sc_ntbuf; 123 124 if (mem > sc->lsc.sc_memsize) 125 panic("%s: memsize", __func__); 126 127 lance_attach(&sc->lsc); 128 129 return (0); 130 } 131 132 void 133 am7990_detach(struct am7990_softc *sc) 134 { 135 136 lance_detach(&sc->lsc); 137 } 138 139 /* 140 * Set up the initialization block and the descriptor rings. 141 */ 142 static void 143 am7990_meminit(struct lance_softc *sc) 144 { 145 if_t ifp = sc->sc_ifp; 146 struct leinit init; 147 struct lermd rmd; 148 struct letmd tmd; 149 u_long a; 150 int bix; 151 152 LE_LOCK_ASSERT(sc, MA_OWNED); 153 154 if (if_getflags(ifp) & 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 if_t ifp = sc->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 if_inc_counter(ifp, IFCOUNTER_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 (ether_cmp(eh->ether_dhost, sc->sc_enaddr) && 285 ether_cmp(eh->ether_dhost, bcast_enaddr)) { 286 m_freem(m); 287 continue; 288 } 289 #endif 290 291 /* Pass the packet up. */ 292 LE_UNLOCK(sc); 293 if_input(ifp, m); 294 LE_LOCK(sc); 295 } else 296 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 297 } 298 299 sc->sc_last_rd = bix; 300 } 301 302 static void 303 am7990_tint(struct lance_softc *sc) 304 { 305 if_t ifp = sc->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 if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); 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 if_link_state_change(ifp, 344 LINK_STATE_DOWN); 345 sc->sc_flags &= ~LE_CARRIER; 346 if (sc->sc_nocarrier) 347 (*sc->sc_nocarrier)(sc); 348 else 349 if_printf(ifp, "lost carrier\n"); 350 } 351 if (tmd.tmd3 & LE_T3_LCOL) 352 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); 353 if (tmd.tmd3 & LE_T3_RTRY) { 354 #ifdef LEDEBUG 355 if_printf(ifp, "excessive collisions, tdr %d\n", 356 tmd.tmd3 & LE_T3_TDR_MASK); 357 #endif 358 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 16); 359 } 360 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 361 } else { 362 if (tmd.tmd1_bits & LE_T1_ONE) 363 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); 364 else if (tmd.tmd1_bits & LE_T1_MORE) 365 /* Real number is unknown. */ 366 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 2); 367 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 368 } 369 370 if (++bix == sc->sc_ntbuf) 371 bix = 0; 372 373 --sc->sc_no_td; 374 } 375 376 sc->sc_first_td = bix; 377 378 sc->sc_wdog_timer = sc->sc_no_td > 0 ? 5 : 0; 379 } 380 381 /* 382 * Controller interrupt 383 */ 384 void 385 am7990_intr(void *arg) 386 { 387 struct lance_softc *sc = arg; 388 if_t ifp = sc->sc_ifp; 389 uint16_t isr; 390 391 LE_LOCK(sc); 392 393 if (sc->sc_hwintr && (*sc->sc_hwintr)(sc) == -1) { 394 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 395 lance_init_locked(sc); 396 LE_UNLOCK(sc); 397 return; 398 } 399 400 isr = (*sc->sc_rdcsr)(sc, LE_CSR0); 401 #if defined(LEDEBUG) && LEDEBUG > 1 402 if (sc->sc_flags & LE_DEBUG) 403 if_printf(ifp, "%s: entering with isr=%04x\n", __func__, isr); 404 #endif 405 if ((isr & LE_C0_INTR) == 0) { 406 LE_UNLOCK(sc); 407 return; 408 } 409 410 /* 411 * Clear interrupt source flags and turn off interrupts. If we 412 * don't clear these flags before processing their sources we 413 * could completely miss some interrupt events as the NIC can 414 * change these flags while we're in this handler. We toggle 415 * the interrupt enable bit in order to keep receiving them 416 * (some chips work without this, some don't). 417 */ 418 (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~(LE_C0_INEA | LE_C0_TDMD | 419 LE_C0_STOP | LE_C0_STRT | LE_C0_INIT)); 420 421 if (isr & LE_C0_ERR) { 422 if (isr & LE_C0_BABL) { 423 #ifdef LEDEBUG 424 if_printf(ifp, "babble\n"); 425 #endif 426 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 427 } 428 #if 0 429 if (isr & LE_C0_CERR) { 430 if_printf(ifp, "collision error\n"); 431 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); 432 } 433 #endif 434 if (isr & LE_C0_MISS) { 435 #ifdef LEDEBUG 436 if_printf(ifp, "missed packet\n"); 437 #endif 438 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 439 } 440 if (isr & LE_C0_MERR) { 441 if_printf(ifp, "memory error\n"); 442 lance_init_locked(sc); 443 LE_UNLOCK(sc); 444 return; 445 } 446 } 447 448 if ((isr & LE_C0_RXON) == 0) { 449 if_printf(ifp, "receiver disabled\n"); 450 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 451 lance_init_locked(sc); 452 LE_UNLOCK(sc); 453 return; 454 } 455 if ((isr & LE_C0_TXON) == 0) { 456 if_printf(ifp, "transmitter disabled\n"); 457 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 458 lance_init_locked(sc); 459 LE_UNLOCK(sc); 460 return; 461 } 462 463 /* 464 * Pretend we have carrier; if we don't this will be cleared shortly. 465 */ 466 if (!(sc->sc_flags & LE_CARRIER)) 467 if_link_state_change(ifp, LINK_STATE_UP); 468 sc->sc_flags |= LE_CARRIER; 469 470 if (isr & LE_C0_RINT) 471 am7990_rint(sc); 472 if (isr & LE_C0_TINT) 473 am7990_tint(sc); 474 475 /* Enable interrupts again. */ 476 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA); 477 478 if (!if_sendq_empty(ifp)) 479 am7990_start_locked(sc); 480 481 LE_UNLOCK(sc); 482 } 483 484 /* 485 * Set up output on interface. 486 * Get another datagram to send off of the interface queue, and map it to the 487 * interface before starting the output. 488 */ 489 static void 490 am7990_start_locked(struct lance_softc *sc) 491 { 492 if_t ifp = sc->sc_ifp; 493 struct letmd tmd; 494 struct mbuf *m; 495 int bix, enq, len, rp; 496 497 LE_LOCK_ASSERT(sc, MA_OWNED); 498 499 if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 500 IFF_DRV_RUNNING) 501 return; 502 503 bix = sc->sc_last_td; 504 enq = 0; 505 506 for (; sc->sc_no_td < sc->sc_ntbuf && 507 !if_sendq_empty(ifp);) { 508 rp = LE_TMDADDR(sc, bix); 509 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd)); 510 511 if (tmd.tmd1_bits & LE_T1_OWN) { 512 if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); 513 if_printf(ifp, 514 "missing buffer, no_td = %d, last_td = %d\n", 515 sc->sc_no_td, sc->sc_last_td); 516 } 517 518 m = if_dequeue(ifp); 519 if (m == NULL) 520 break; 521 522 /* 523 * If BPF is listening on this interface, let it see the packet 524 * before we commit it to the wire. 525 */ 526 BPF_MTAP(ifp, m); 527 528 /* 529 * Copy the mbuf chain into the transmit buffer. 530 */ 531 len = lance_put(sc, LE_TBUFADDR(sc, bix), m); 532 533 #ifdef LEDEBUG 534 if (len > ETHERMTU + ETHER_HDR_LEN) 535 if_printf(ifp, "packet length %d\n", len); 536 #endif 537 538 /* 539 * Init transmit registers, and set transmit start flag. 540 */ 541 tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP; 542 tmd.tmd2 = -len | LE_XMD2_ONES; 543 tmd.tmd3 = 0; 544 545 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd)); 546 547 #ifdef LEDEBUG 548 if (sc->sc_flags & LE_DEBUG) 549 am7990_xmit_print(sc, bix); 550 #endif 551 552 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD); 553 enq++; 554 555 if (++bix == sc->sc_ntbuf) 556 bix = 0; 557 558 if (++sc->sc_no_td == sc->sc_ntbuf) { 559 if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); 560 break; 561 } 562 } 563 564 sc->sc_last_td = bix; 565 566 if (enq > 0) 567 sc->sc_wdog_timer = 5; 568 } 569 570 #ifdef LEDEBUG 571 static void 572 am7990_recv_print(struct lance_softc *sc, int no) 573 { 574 if_t ifp = sc->sc_ifp; 575 struct ether_header eh; 576 struct lermd rmd; 577 uint16_t len; 578 579 (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd)); 580 len = rmd.rmd3; 581 if_printf(ifp, "receive buffer %d, len = %d\n", no, len); 582 if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); 583 if_printf(ifp, 584 "ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n", 585 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3); 586 if (len - ETHER_CRC_LEN >= sizeof(eh)) { 587 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh)); 588 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); 589 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 590 ntohs(eh.ether_type)); 591 } 592 } 593 594 static void 595 am7990_xmit_print(struct lance_softc *sc, int no) 596 { 597 if_t ifp = sc->sc_ifp; 598 struct ether_header eh; 599 struct letmd tmd; 600 uint16_t len; 601 602 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd)); 603 len = -tmd.tmd2; 604 if_printf(ifp, "transmit buffer %d, len = %d\n", no, len); 605 if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); 606 if_printf(ifp, 607 "ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n", 608 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3); 609 if (len >= sizeof(eh)) { 610 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh)); 611 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); 612 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 613 ntohs(eh.ether_type)); 614 } 615 } 616 #endif /* LEDEBUG */ 617