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/cdefs.h> 68 #include <sys/param.h> 69 #include <sys/bus.h> 70 #include <sys/endian.h> 71 #include <sys/lock.h> 72 #include <sys/mbuf.h> 73 #include <sys/mutex.h> 74 #include <sys/socket.h> 75 76 #include <net/bpf.h> 77 #include <net/ethernet.h> 78 #include <net/if.h> 79 #include <net/if_arp.h> 80 #include <net/if_dl.h> 81 #include <net/if_media.h> 82 #include <net/if_var.h> 83 84 #include <machine/bus.h> 85 86 #include <dev/le/lancereg.h> 87 #include <dev/le/lancevar.h> 88 #include <dev/le/am7990reg.h> 89 #include <dev/le/am7990var.h> 90 91 static void am7990_meminit(struct lance_softc *); 92 static void am7990_rint(struct lance_softc *); 93 static void am7990_tint(struct lance_softc *); 94 static void am7990_start_locked(struct lance_softc *sc); 95 96 #ifdef LEDEBUG 97 static void am7990_recv_print(struct lance_softc *, int); 98 static void am7990_xmit_print(struct lance_softc *, int); 99 #endif 100 101 int 102 am7990_config(struct am7990_softc *sc, const char* name, int unit) 103 { 104 int error, mem; 105 106 sc->lsc.sc_meminit = am7990_meminit; 107 sc->lsc.sc_start_locked = am7990_start_locked; 108 109 error = lance_config(&sc->lsc, name, unit); 110 if (error != 0) 111 return (error); 112 113 mem = 0; 114 sc->lsc.sc_initaddr = mem; 115 mem += sizeof(struct leinit); 116 sc->lsc.sc_rmdaddr = mem; 117 mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf; 118 sc->lsc.sc_tmdaddr = mem; 119 mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf; 120 sc->lsc.sc_rbufaddr = mem; 121 mem += LEBLEN * sc->lsc.sc_nrbuf; 122 sc->lsc.sc_tbufaddr = mem; 123 mem += LEBLEN * sc->lsc.sc_ntbuf; 124 125 if (mem > sc->lsc.sc_memsize) 126 panic("%s: memsize", __func__); 127 128 lance_attach(&sc->lsc); 129 130 return (0); 131 } 132 133 void 134 am7990_detach(struct am7990_softc *sc) 135 { 136 137 lance_detach(&sc->lsc); 138 } 139 140 /* 141 * Set up the initialization block and the descriptor rings. 142 */ 143 static void 144 am7990_meminit(struct lance_softc *sc) 145 { 146 if_t ifp = sc->sc_ifp; 147 struct leinit init; 148 struct lermd rmd; 149 struct letmd tmd; 150 u_long a; 151 int bix; 152 153 LE_LOCK_ASSERT(sc, MA_OWNED); 154 155 if (if_getflags(ifp) & IFF_PROMISC) 156 init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM; 157 else 158 init.init_mode = LE_MODE_NORMAL; 159 160 init.init_padr[0] = (sc->sc_enaddr[1] << 8) | sc->sc_enaddr[0]; 161 init.init_padr[1] = (sc->sc_enaddr[3] << 8) | sc->sc_enaddr[2]; 162 init.init_padr[2] = (sc->sc_enaddr[5] << 8) | sc->sc_enaddr[4]; 163 lance_setladrf(sc, init.init_ladrf); 164 165 sc->sc_last_rd = 0; 166 sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0; 167 168 a = sc->sc_addr + LE_RMDADDR(sc, 0); 169 init.init_rdra = a; 170 init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13); 171 172 a = sc->sc_addr + LE_TMDADDR(sc, 0); 173 init.init_tdra = a; 174 init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13); 175 176 (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init)); 177 178 /* 179 * Set up receive ring descriptors. 180 */ 181 for (bix = 0; bix < sc->sc_nrbuf; bix++) { 182 a = sc->sc_addr + LE_RBUFADDR(sc, bix); 183 rmd.rmd0 = a; 184 rmd.rmd1_hadr = a >> 16; 185 rmd.rmd1_bits = LE_R1_OWN; 186 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES; 187 rmd.rmd3 = 0; 188 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix), 189 sizeof(rmd)); 190 } 191 192 /* 193 * Set up transmit ring descriptors. 194 */ 195 for (bix = 0; bix < sc->sc_ntbuf; bix++) { 196 a = sc->sc_addr + LE_TBUFADDR(sc, bix); 197 tmd.tmd0 = a; 198 tmd.tmd1_hadr = a >> 16; 199 tmd.tmd1_bits = 0; 200 tmd.tmd2 = LE_XMD2_ONES; 201 tmd.tmd3 = 0; 202 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix), 203 sizeof(tmd)); 204 } 205 } 206 207 static void 208 am7990_rint(struct lance_softc *sc) 209 { 210 if_t ifp = sc->sc_ifp; 211 struct mbuf *m; 212 struct lermd rmd; 213 int bix, rp; 214 #if defined(LANCE_REVC_BUG) 215 struct ether_header *eh; 216 /* Make sure this is short-aligned, for ether_cmp(). */ 217 static uint16_t bcast_enaddr[3] = { ~0, ~0, ~0 }; 218 #endif 219 220 bix = sc->sc_last_rd; 221 222 /* Process all buffers with valid data. */ 223 for (;;) { 224 rp = LE_RMDADDR(sc, bix); 225 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd)); 226 227 if (rmd.rmd1_bits & LE_R1_OWN) 228 break; 229 230 m = NULL; 231 if ((rmd.rmd1_bits & (LE_R1_ERR | LE_R1_STP | LE_R1_ENP)) != 232 (LE_R1_STP | LE_R1_ENP)) { 233 if (rmd.rmd1_bits & LE_R1_ERR) { 234 #ifdef LEDEBUG 235 if (rmd.rmd1_bits & LE_R1_ENP) { 236 if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) { 237 if (rmd.rmd1_bits & LE_R1_FRAM) 238 if_printf(ifp, 239 "framing error\n"); 240 if (rmd.rmd1_bits & LE_R1_CRC) 241 if_printf(ifp, 242 "crc mismatch\n"); 243 } 244 } else 245 if (rmd.rmd1_bits & LE_R1_OFLO) 246 if_printf(ifp, "overflow\n"); 247 #endif 248 if (rmd.rmd1_bits & LE_R1_BUFF) 249 if_printf(ifp, 250 "receive buffer error\n"); 251 } else if ((rmd.rmd1_bits & (LE_R1_STP | LE_R1_ENP)) != 252 (LE_R1_STP | LE_R1_ENP)) 253 if_printf(ifp, "dropping chained buffer\n"); 254 } else { 255 #ifdef LEDEBUG 256 if (sc->sc_flags & LE_DEBUG) 257 am7990_recv_print(sc, bix); 258 #endif 259 /* Pull the packet off the interface. */ 260 m = lance_get(sc, LE_RBUFADDR(sc, bix), 261 (int)rmd.rmd3 - ETHER_CRC_LEN); 262 } 263 264 rmd.rmd1_bits = LE_R1_OWN; 265 rmd.rmd2 = -LEBLEN | LE_XMD2_ONES; 266 rmd.rmd3 = 0; 267 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd)); 268 269 if (++bix == sc->sc_nrbuf) 270 bix = 0; 271 272 if (m != NULL) { 273 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 274 275 #ifdef LANCE_REVC_BUG 276 /* 277 * The old LANCE (Rev. C) chips have a bug which 278 * causes garbage to be inserted in front of the 279 * received packet. The workaround is to ignore 280 * packets with an invalid destination address 281 * (garbage will usually not match). 282 * Of course, this precludes multicast support... 283 */ 284 eh = mtod(m, struct ether_header *); 285 if (ether_cmp(eh->ether_dhost, sc->sc_enaddr) && 286 ether_cmp(eh->ether_dhost, bcast_enaddr)) { 287 m_freem(m); 288 continue; 289 } 290 #endif 291 292 /* Pass the packet up. */ 293 LE_UNLOCK(sc); 294 if_input(ifp, m); 295 LE_LOCK(sc); 296 } else 297 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 298 } 299 300 sc->sc_last_rd = bix; 301 } 302 303 static void 304 am7990_tint(struct lance_softc *sc) 305 { 306 if_t ifp = sc->sc_ifp; 307 struct letmd tmd; 308 int bix; 309 310 bix = sc->sc_first_td; 311 312 for (;;) { 313 if (sc->sc_no_td <= 0) 314 break; 315 316 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix), 317 sizeof(tmd)); 318 319 #ifdef LEDEBUG 320 if (sc->sc_flags & LE_DEBUG) 321 if_printf(ifp, "trans tmd: " 322 "ladr %04x, hadr %02x, flags %02x, " 323 "bcnt %04x, mcnt %04x\n", 324 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, 325 tmd.tmd2, tmd.tmd3); 326 #endif 327 328 if (tmd.tmd1_bits & LE_T1_OWN) 329 break; 330 331 if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); 332 333 if (tmd.tmd1_bits & LE_T1_ERR) { 334 if (tmd.tmd3 & LE_T3_BUFF) 335 if_printf(ifp, "transmit buffer error\n"); 336 else if (tmd.tmd3 & LE_T3_UFLO) 337 if_printf(ifp, "underflow\n"); 338 if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) { 339 lance_init_locked(sc); 340 return; 341 } 342 if (tmd.tmd3 & LE_T3_LCAR) { 343 if (sc->sc_flags & LE_CARRIER) 344 if_link_state_change(ifp, 345 LINK_STATE_DOWN); 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 if_inc_counter(ifp, IFCOUNTER_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 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 16); 360 } 361 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 362 } else { 363 if (tmd.tmd1_bits & LE_T1_ONE) 364 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); 365 else if (tmd.tmd1_bits & LE_T1_MORE) 366 /* Real number is unknown. */ 367 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 2); 368 if_inc_counter(ifp, IFCOUNTER_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 sc->sc_wdog_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 if_t ifp = sc->sc_ifp; 390 uint16_t isr; 391 392 LE_LOCK(sc); 393 394 if (sc->sc_hwintr && (*sc->sc_hwintr)(sc) == -1) { 395 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 396 lance_init_locked(sc); 397 LE_UNLOCK(sc); 398 return; 399 } 400 401 isr = (*sc->sc_rdcsr)(sc, LE_CSR0); 402 #if defined(LEDEBUG) && LEDEBUG > 1 403 if (sc->sc_flags & LE_DEBUG) 404 if_printf(ifp, "%s: entering with isr=%04x\n", __func__, isr); 405 #endif 406 if ((isr & LE_C0_INTR) == 0) { 407 LE_UNLOCK(sc); 408 return; 409 } 410 411 /* 412 * Clear interrupt source flags and turn off interrupts. If we 413 * don't clear these flags before processing their sources we 414 * could completely miss some interrupt events as the NIC can 415 * change these flags while we're in this handler. We toggle 416 * the interrupt enable bit in order to keep receiving them 417 * (some chips work without this, some don't). 418 */ 419 (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~(LE_C0_INEA | LE_C0_TDMD | 420 LE_C0_STOP | LE_C0_STRT | LE_C0_INIT)); 421 422 if (isr & LE_C0_ERR) { 423 if (isr & LE_C0_BABL) { 424 #ifdef LEDEBUG 425 if_printf(ifp, "babble\n"); 426 #endif 427 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 428 } 429 #if 0 430 if (isr & LE_C0_CERR) { 431 if_printf(ifp, "collision error\n"); 432 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); 433 } 434 #endif 435 if (isr & LE_C0_MISS) { 436 #ifdef LEDEBUG 437 if_printf(ifp, "missed packet\n"); 438 #endif 439 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 440 } 441 if (isr & LE_C0_MERR) { 442 if_printf(ifp, "memory error\n"); 443 lance_init_locked(sc); 444 LE_UNLOCK(sc); 445 return; 446 } 447 } 448 449 if ((isr & LE_C0_RXON) == 0) { 450 if_printf(ifp, "receiver disabled\n"); 451 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 452 lance_init_locked(sc); 453 LE_UNLOCK(sc); 454 return; 455 } 456 if ((isr & LE_C0_TXON) == 0) { 457 if_printf(ifp, "transmitter disabled\n"); 458 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 459 lance_init_locked(sc); 460 LE_UNLOCK(sc); 461 return; 462 } 463 464 /* 465 * Pretend we have carrier; if we don't this will be cleared shortly. 466 */ 467 if (!(sc->sc_flags & LE_CARRIER)) 468 if_link_state_change(ifp, LINK_STATE_UP); 469 sc->sc_flags |= LE_CARRIER; 470 471 if (isr & LE_C0_RINT) 472 am7990_rint(sc); 473 if (isr & LE_C0_TINT) 474 am7990_tint(sc); 475 476 /* Enable interrupts again. */ 477 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA); 478 479 if (!if_sendq_empty(ifp)) 480 am7990_start_locked(sc); 481 482 LE_UNLOCK(sc); 483 } 484 485 /* 486 * Set up output on interface. 487 * Get another datagram to send off of the interface queue, and map it to the 488 * interface before starting the output. 489 */ 490 static void 491 am7990_start_locked(struct lance_softc *sc) 492 { 493 if_t ifp = sc->sc_ifp; 494 struct letmd tmd; 495 struct mbuf *m; 496 int bix, enq, len, rp; 497 498 LE_LOCK_ASSERT(sc, MA_OWNED); 499 500 if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 501 IFF_DRV_RUNNING) 502 return; 503 504 bix = sc->sc_last_td; 505 enq = 0; 506 507 for (; sc->sc_no_td < sc->sc_ntbuf && 508 !if_sendq_empty(ifp);) { 509 rp = LE_TMDADDR(sc, bix); 510 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd)); 511 512 if (tmd.tmd1_bits & LE_T1_OWN) { 513 if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); 514 if_printf(ifp, 515 "missing buffer, no_td = %d, last_td = %d\n", 516 sc->sc_no_td, sc->sc_last_td); 517 } 518 519 m = if_dequeue(ifp); 520 if (m == NULL) 521 break; 522 523 /* 524 * If BPF is listening on this interface, let it see the packet 525 * before we commit it to the wire. 526 */ 527 BPF_MTAP(ifp, m); 528 529 /* 530 * Copy the mbuf chain into the transmit buffer. 531 */ 532 len = lance_put(sc, LE_TBUFADDR(sc, bix), m); 533 534 #ifdef LEDEBUG 535 if (len > ETHERMTU + ETHER_HDR_LEN) 536 if_printf(ifp, "packet length %d\n", len); 537 #endif 538 539 /* 540 * Init transmit registers, and set transmit start flag. 541 */ 542 tmd.tmd1_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP; 543 tmd.tmd2 = -len | LE_XMD2_ONES; 544 tmd.tmd3 = 0; 545 546 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd)); 547 548 #ifdef LEDEBUG 549 if (sc->sc_flags & LE_DEBUG) 550 am7990_xmit_print(sc, bix); 551 #endif 552 553 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD); 554 enq++; 555 556 if (++bix == sc->sc_ntbuf) 557 bix = 0; 558 559 if (++sc->sc_no_td == sc->sc_ntbuf) { 560 if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); 561 break; 562 } 563 } 564 565 sc->sc_last_td = bix; 566 567 if (enq > 0) 568 sc->sc_wdog_timer = 5; 569 } 570 571 #ifdef LEDEBUG 572 static void 573 am7990_recv_print(struct lance_softc *sc, int no) 574 { 575 if_t ifp = sc->sc_ifp; 576 struct ether_header eh; 577 struct lermd rmd; 578 uint16_t len; 579 580 (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd)); 581 len = rmd.rmd3; 582 if_printf(ifp, "receive buffer %d, len = %d\n", no, len); 583 if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); 584 if_printf(ifp, 585 "ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n", 586 rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3); 587 if (len - ETHER_CRC_LEN >= sizeof(eh)) { 588 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh)); 589 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); 590 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 591 ntohs(eh.ether_type)); 592 } 593 } 594 595 static void 596 am7990_xmit_print(struct lance_softc *sc, int no) 597 { 598 if_t ifp = sc->sc_ifp; 599 struct ether_header eh; 600 struct letmd tmd; 601 uint16_t len; 602 603 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd)); 604 len = -tmd.tmd2; 605 if_printf(ifp, "transmit buffer %d, len = %d\n", no, len); 606 if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); 607 if_printf(ifp, 608 "ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n", 609 tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3); 610 if (len >= sizeof(eh)) { 611 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh)); 612 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); 613 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 614 ntohs(eh.ether_type)); 615 } 616 } 617 #endif /* LEDEBUG */ 618