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