1 /* $NetBSD: am79900.c,v 1.16 2005/12/11 12:21:25 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 1997 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /*- 40 * Copyright (c) 1992, 1993 41 * The Regents of the University of California. All rights reserved. 42 * 43 * This code is derived from software contributed to Berkeley by 44 * Ralph Campbell and Rick Macklem. 45 * 46 * Redistribution and use in source and binary forms, with or without 47 * modification, are permitted provided that the following conditions 48 * are met: 49 * 1. Redistributions of source code must retain the above copyright 50 * notice, this list of conditions and the following disclaimer. 51 * 2. Redistributions in binary form must reproduce the above copyright 52 * notice, this list of conditions and the following disclaimer in the 53 * documentation and/or other materials provided with the distribution. 54 * 3. Neither the name of the University nor the names of its contributors 55 * may be used to endorse or promote products derived from this software 56 * without specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 * SUCH DAMAGE. 69 * 70 * @(#)if_le.c 8.2 (Berkeley) 11/16/93 71 */ 72 73 /*- 74 * Copyright (c) 1998 75 * Matthias Drochner. All rights reserved. 76 * Copyright (c) 1995 Charles M. Hannum. All rights reserved. 77 * 78 * This code is derived from software contributed to Berkeley by 79 * Ralph Campbell and Rick Macklem. 80 * 81 * Redistribution and use in source and binary forms, with or without 82 * modification, are permitted provided that the following conditions 83 * are met: 84 * 1. Redistributions of source code must retain the above copyright 85 * notice, this list of conditions and the following disclaimer. 86 * 2. Redistributions in binary form must reproduce the above copyright 87 * notice, this list of conditions and the following disclaimer in the 88 * documentation and/or other materials provided with the distribution. 89 * 3. All advertising materials mentioning features or use of this software 90 * must display the following acknowledgement: 91 * This product includes software developed by the University of 92 * California, Berkeley and its contributors. 93 * 4. Neither the name of the University nor the names of its contributors 94 * may be used to endorse or promote products derived from this software 95 * without specific prior written permission. 96 * 97 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 98 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 99 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 100 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 101 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 102 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 103 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 104 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 105 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 106 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 107 * SUCH DAMAGE. 108 * 109 * @(#)if_le.c 8.2 (Berkeley) 11/16/93 110 */ 111 112 #include <sys/cdefs.h> 113 __KERNEL_RCSID(0, "$NetBSD: am79900.c,v 1.16 2005/12/11 12:21:25 christos Exp $"); 114 115 #include "bpfilter.h" 116 #include "rnd.h" 117 118 #include <sys/param.h> 119 #include <sys/systm.h> 120 #include <sys/mbuf.h> 121 #include <sys/syslog.h> 122 #include <sys/socket.h> 123 #include <sys/device.h> 124 #include <sys/malloc.h> 125 #include <sys/ioctl.h> 126 #include <sys/errno.h> 127 #if NRND > 0 128 #include <sys/rnd.h> 129 #endif 130 131 #include <net/if.h> 132 #include <net/if_dl.h> 133 #include <net/if_ether.h> 134 #include <net/if_media.h> 135 136 #if NBPFILTER > 0 137 #include <net/bpf.h> 138 #include <net/bpfdesc.h> 139 #endif 140 141 #include <dev/ic/lancereg.h> 142 #include <dev/ic/lancevar.h> 143 #include <dev/ic/am79900reg.h> 144 #include <dev/ic/am79900var.h> 145 146 static void am79900_meminit(struct lance_softc *); 147 static void am79900_start(struct ifnet *); 148 149 #if defined(_KERNEL_OPT) 150 #include "opt_ddb.h" 151 #endif 152 153 #ifdef LEDEBUG 154 static void am79900_recv_print(struct lance_softc *, int); 155 static void am79900_xmit_print(struct lance_softc *, int); 156 #endif 157 158 #define ifp (&sc->sc_ethercom.ec_if) 159 160 void 161 am79900_config(struct am79900_softc *sc) 162 { 163 int mem, i; 164 165 sc->lsc.sc_meminit = am79900_meminit; 166 sc->lsc.sc_start = am79900_start; 167 168 lance_config(&sc->lsc); 169 170 mem = 0; 171 sc->lsc.sc_initaddr = mem; 172 mem += sizeof(struct leinit); 173 sc->lsc.sc_rmdaddr = mem; 174 mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf; 175 sc->lsc.sc_tmdaddr = mem; 176 mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf; 177 for (i = 0; i < sc->lsc.sc_nrbuf; i++, mem += LEBLEN) 178 sc->lsc.sc_rbufaddr[i] = mem; 179 for (i = 0; i < sc->lsc.sc_ntbuf; i++, mem += LEBLEN) 180 sc->lsc.sc_tbufaddr[i] = mem; 181 182 if (mem > sc->lsc.sc_memsize) 183 panic("%s: memsize", sc->lsc.sc_dev.dv_xname); 184 } 185 186 /* 187 * Set up the initialization block and the descriptor rings. 188 */ 189 static void 190 am79900_meminit(struct lance_softc *sc) 191 { 192 u_long a; 193 int bix; 194 struct leinit init; 195 struct lermd rmd; 196 struct letmd tmd; 197 u_int8_t *myaddr; 198 199 #if NBPFILTER > 0 200 if (ifp->if_flags & IFF_PROMISC) 201 init.init_mode = LE_MODE_NORMAL | LE_MODE_PROM; 202 else 203 #endif 204 init.init_mode = LE_MODE_NORMAL; 205 if (sc->sc_initmodemedia == 1) 206 init.init_mode |= LE_MODE_PSEL0; 207 208 init.init_mode |= ((ffs(sc->sc_ntbuf) - 1) << 28) 209 | ((ffs(sc->sc_nrbuf) - 1) << 20); 210 211 /* 212 * Update our private copy of the Ethernet address. 213 * We NEED the copy so we can ensure its alignment! 214 */ 215 memcpy(sc->sc_enaddr, LLADDR(ifp->if_sadl), ETHER_ADDR_LEN); 216 myaddr = sc->sc_enaddr; 217 218 init.init_padr[0] = myaddr[0] | (myaddr[1] << 8) 219 | (myaddr[2] << 16) | (myaddr[3] << 24); 220 init.init_padr[1] = myaddr[4] | (myaddr[5] << 8); 221 lance_setladrf(&sc->sc_ethercom, init.init_ladrf); 222 223 sc->sc_last_rd = 0; 224 sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0; 225 226 a = sc->sc_addr + LE_RMDADDR(sc, 0); 227 init.init_rdra = a; 228 229 a = sc->sc_addr + LE_TMDADDR(sc, 0); 230 init.init_tdra = a; 231 232 (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init)); 233 234 /* 235 * Set up receive ring descriptors. 236 */ 237 for (bix = 0; bix < sc->sc_nrbuf; bix++) { 238 a = sc->sc_addr + LE_RBUFADDR(sc, bix); 239 rmd.rmd0 = a; 240 rmd.rmd1 = LE_R1_OWN | LE_R1_ONES | (-LEBLEN & 0xfff); 241 rmd.rmd2 = 0; 242 rmd.rmd3 = 0; 243 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix), 244 sizeof(rmd)); 245 } 246 247 /* 248 * Set up transmit ring descriptors. 249 */ 250 for (bix = 0; bix < sc->sc_ntbuf; bix++) { 251 a = sc->sc_addr + LE_TBUFADDR(sc, bix); 252 tmd.tmd0 = a; 253 tmd.tmd1 = LE_T1_ONES; 254 tmd.tmd2 = 0; 255 tmd.tmd3 = 0; 256 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix), 257 sizeof(tmd)); 258 } 259 } 260 261 static __inline void 262 am79900_rint(struct lance_softc *sc) 263 { 264 int bix; 265 int rp; 266 struct lermd rmd; 267 268 bix = sc->sc_last_rd; 269 270 /* Process all buffers with valid data. */ 271 for (;;) { 272 rp = LE_RMDADDR(sc, bix); 273 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd)); 274 275 if (rmd.rmd1 & LE_R1_OWN) 276 break; 277 278 if (rmd.rmd1 & LE_R1_ERR) { 279 if (rmd.rmd1 & LE_R1_ENP) { 280 #ifdef LEDEBUG 281 if ((rmd.rmd1 & LE_R1_OFLO) == 0) { 282 if (rmd.rmd1 & LE_R1_FRAM) 283 printf("%s: framing error\n", 284 sc->sc_dev.dv_xname); 285 if (rmd.rmd1 & LE_R1_CRC) 286 printf("%s: crc mismatch\n", 287 sc->sc_dev.dv_xname); 288 } 289 #endif 290 } else { 291 if (rmd.rmd1 & LE_R1_OFLO) 292 printf("%s: overflow\n", 293 sc->sc_dev.dv_xname); 294 } 295 if (rmd.rmd1 & LE_R1_BUFF) 296 printf("%s: receive buffer error\n", 297 sc->sc_dev.dv_xname); 298 ifp->if_ierrors++; 299 } else if ((rmd.rmd1 & (LE_R1_STP | LE_R1_ENP)) != 300 (LE_R1_STP | LE_R1_ENP)) { 301 printf("%s: dropping chained buffer\n", 302 sc->sc_dev.dv_xname); 303 ifp->if_ierrors++; 304 } else { 305 #ifdef LEDEBUG 306 if (sc->sc_debug) 307 am79900_recv_print(sc, sc->sc_last_rd); 308 #endif 309 lance_read(sc, LE_RBUFADDR(sc, bix), 310 (rmd.rmd2 & 0xfff) - 4); 311 } 312 313 rmd.rmd1 = LE_R1_OWN | LE_R1_ONES | (-LEBLEN & 0xfff); 314 rmd.rmd2 = 0; 315 rmd.rmd3 = 0; 316 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd)); 317 318 #ifdef LEDEBUG 319 if (sc->sc_debug) 320 printf("sc->sc_last_rd = %x, rmd: " 321 "adr %08x, flags/blen %08x\n", 322 sc->sc_last_rd, 323 rmd.rmd0, rmd.rmd1); 324 #endif 325 326 if (++bix == sc->sc_nrbuf) 327 bix = 0; 328 } 329 330 sc->sc_last_rd = bix; 331 } 332 333 static __inline void 334 am79900_tint(struct lance_softc *sc) 335 { 336 int bix; 337 struct letmd tmd; 338 339 bix = sc->sc_first_td; 340 341 for (;;) { 342 if (sc->sc_no_td <= 0) 343 break; 344 345 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix), 346 sizeof(tmd)); 347 348 #ifdef LEDEBUG 349 if (sc->sc_debug) 350 printf("trans tmd: " 351 "adr %08x, flags/blen %08x\n", 352 tmd.tmd0, tmd.tmd1); 353 #endif 354 355 if (tmd.tmd1 & LE_T1_OWN) 356 break; 357 358 ifp->if_flags &= ~IFF_OACTIVE; 359 360 if (tmd.tmd1 & LE_T1_ERR) { 361 if (tmd.tmd2 & LE_T2_BUFF) 362 printf("%s: transmit buffer error\n", 363 sc->sc_dev.dv_xname); 364 else if (tmd.tmd2 & LE_T2_UFLO) 365 printf("%s: underflow\n", sc->sc_dev.dv_xname); 366 if (tmd.tmd2 & (LE_T2_BUFF | LE_T2_UFLO)) { 367 lance_reset(sc); 368 return; 369 } 370 if (tmd.tmd2 & LE_T2_LCAR) { 371 sc->sc_havecarrier = 0; 372 if (sc->sc_nocarrier) 373 (*sc->sc_nocarrier)(sc); 374 else 375 printf("%s: lost carrier\n", 376 sc->sc_dev.dv_xname); 377 } 378 if (tmd.tmd2 & LE_T2_LCOL) 379 ifp->if_collisions++; 380 if (tmd.tmd2 & LE_T2_RTRY) { 381 #ifdef LEDEBUG 382 printf("%s: excessive collisions\n", 383 sc->sc_dev.dv_xname); 384 #endif 385 ifp->if_collisions += 16; 386 } 387 ifp->if_oerrors++; 388 } else { 389 if (tmd.tmd1 & LE_T1_ONE) 390 ifp->if_collisions++; 391 else if (tmd.tmd1 & LE_T1_MORE) 392 /* Real number is unknown. */ 393 ifp->if_collisions += 2; 394 ifp->if_opackets++; 395 } 396 397 if (++bix == sc->sc_ntbuf) 398 bix = 0; 399 400 --sc->sc_no_td; 401 } 402 403 sc->sc_first_td = bix; 404 405 am79900_start(ifp); 406 407 if (sc->sc_no_td == 0) 408 ifp->if_timer = 0; 409 } 410 411 /* 412 * Controller interrupt. 413 */ 414 int 415 am79900_intr(void *arg) 416 { 417 struct lance_softc *sc = arg; 418 u_int16_t isr; 419 420 isr = (*sc->sc_rdcsr)(sc, LE_CSR0) | sc->sc_saved_csr0; 421 sc->sc_saved_csr0 = 0; 422 #if defined(LEDEBUG) && LEDEBUG > 1 423 if (sc->sc_debug) 424 printf("%s: am79900_intr entering with isr=%04x\n", 425 sc->sc_dev.dv_xname, isr); 426 #endif 427 if ((isr & LE_C0_INTR) == 0) 428 return (0); 429 430 (*sc->sc_wrcsr)(sc, LE_CSR0, 431 isr & (LE_C0_INEA | LE_C0_BABL | LE_C0_MISS | LE_C0_MERR | 432 LE_C0_RINT | LE_C0_TINT | LE_C0_IDON)); 433 if (isr & LE_C0_ERR) { 434 if (isr & LE_C0_BABL) { 435 #ifdef LEDEBUG 436 printf("%s: babble\n", sc->sc_dev.dv_xname); 437 #endif 438 ifp->if_oerrors++; 439 } 440 #if 0 441 if (isr & LE_C0_CERR) { 442 printf("%s: collision error\n", sc->sc_dev.dv_xname); 443 ifp->if_collisions++; 444 } 445 #endif 446 if (isr & LE_C0_MISS) { 447 #ifdef LEDEBUG 448 printf("%s: missed packet\n", sc->sc_dev.dv_xname); 449 #endif 450 ifp->if_ierrors++; 451 } 452 if (isr & LE_C0_MERR) { 453 printf("%s: memory error\n", sc->sc_dev.dv_xname); 454 lance_reset(sc); 455 return (1); 456 } 457 } 458 459 if ((isr & LE_C0_RXON) == 0) { 460 printf("%s: receiver disabled\n", sc->sc_dev.dv_xname); 461 ifp->if_ierrors++; 462 lance_reset(sc); 463 return (1); 464 } 465 if ((isr & LE_C0_TXON) == 0) { 466 printf("%s: transmitter disabled\n", sc->sc_dev.dv_xname); 467 ifp->if_oerrors++; 468 lance_reset(sc); 469 return (1); 470 } 471 472 /* 473 * Pretend we have carrier; if we don't this will be cleared 474 * shortly. 475 */ 476 sc->sc_havecarrier = 1; 477 478 if (isr & LE_C0_RINT) 479 am79900_rint(sc); 480 if (isr & LE_C0_TINT) 481 am79900_tint(sc); 482 483 #if NRND > 0 484 rnd_add_uint32(&sc->rnd_source, isr); 485 #endif 486 487 return (1); 488 } 489 490 #undef ifp 491 492 /* 493 * Setup output on interface. 494 * Get another datagram to send off of the interface queue, and map it to the 495 * interface before starting the output. 496 * Called only at splnet or interrupt level. 497 */ 498 static void 499 am79900_start(struct ifnet *ifp) 500 { 501 struct lance_softc *sc = ifp->if_softc; 502 int bix; 503 struct mbuf *m; 504 struct letmd tmd; 505 int rp; 506 int len; 507 508 if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) 509 return; 510 511 bix = sc->sc_last_td; 512 513 for (;;) { 514 rp = LE_TMDADDR(sc, bix); 515 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd)); 516 517 if (tmd.tmd1 & LE_T1_OWN) { 518 ifp->if_flags |= IFF_OACTIVE; 519 printf("missing buffer, no_td = %d, last_td = %d\n", 520 sc->sc_no_td, sc->sc_last_td); 521 } 522 523 IFQ_DEQUEUE(&ifp->if_snd, m); 524 if (m == 0) 525 break; 526 527 #if NBPFILTER > 0 528 /* 529 * If BPF is listening on this interface, let it see the packet 530 * before we commit it to the wire. 531 */ 532 if (ifp->if_bpf) 533 bpf_mtap(ifp->if_bpf, m); 534 #endif 535 536 /* 537 * Copy the mbuf chain into the transmit buffer. 538 */ 539 len = lance_put(sc, LE_TBUFADDR(sc, bix), m); 540 541 #ifdef LEDEBUG 542 if (len > ETHERMTU + sizeof(struct ether_header)) 543 printf("packet length %d\n", len); 544 #endif 545 546 ifp->if_timer = 5; 547 548 /* 549 * Init transmit registers, and set transmit start flag. 550 */ 551 tmd.tmd1 = LE_T1_OWN | LE_T1_STP | LE_T1_ENP | LE_T1_ONES | (-len & 0xfff); 552 tmd.tmd2 = 0; 553 tmd.tmd3 = 0; 554 555 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd)); 556 557 #ifdef LEDEBUG 558 if (sc->sc_debug) 559 am79900_xmit_print(sc, sc->sc_last_td); 560 #endif 561 562 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD); 563 564 if (++bix == sc->sc_ntbuf) 565 bix = 0; 566 567 if (++sc->sc_no_td == sc->sc_ntbuf) { 568 ifp->if_flags |= IFF_OACTIVE; 569 break; 570 } 571 572 } 573 574 sc->sc_last_td = bix; 575 } 576 577 #ifdef LEDEBUG 578 static void 579 am79900_recv_print(struct lance_softc *sc, int no) 580 { 581 struct lermd rmd; 582 u_int16_t len; 583 struct ether_header eh; 584 585 (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd)); 586 len = (rmd.rmd2 & 0xfff) - 4; 587 printf("%s: receive buffer %d, len = %d\n", sc->sc_dev.dv_xname, no, 588 len); 589 printf("%s: status %04x\n", sc->sc_dev.dv_xname, 590 (*sc->sc_rdcsr)(sc, LE_CSR0)); 591 printf("%s: adr %08x, flags/blen %08x\n", 592 sc->sc_dev.dv_xname, rmd.rmd0, rmd.rmd1); 593 if (len >= sizeof(eh)) { 594 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh)); 595 printf("%s: dst %s", sc->sc_dev.dv_xname, 596 ether_sprintf(eh.ether_dhost)); 597 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 598 ntohs(eh.ether_type)); 599 } 600 } 601 602 static void 603 am79900_xmit_print(struct lance_softc *sc, int no) 604 { 605 struct letmd tmd; 606 u_int16_t len; 607 struct ether_header eh; 608 609 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd)); 610 len = -(tmd.tmd1 & 0xfff); 611 printf("%s: transmit buffer %d, len = %d\n", sc->sc_dev.dv_xname, no, 612 len); 613 printf("%s: status %04x\n", sc->sc_dev.dv_xname, 614 (*sc->sc_rdcsr)(sc, LE_CSR0)); 615 printf("%s: adr %08x, flags/blen %08x\n", 616 sc->sc_dev.dv_xname, tmd.tmd0, tmd.tmd1); 617 if (len >= sizeof(eh)) { 618 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh)); 619 printf("%s: dst %s", sc->sc_dev.dv_xname, 620 ether_sprintf(eh.ether_dhost)); 621 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 622 ntohs(eh.ether_type)); 623 } 624 } 625 #endif /* LEDEBUG */ 626