1 /* $NetBSD: am79900.c,v 1.17 2005/12/24 20:27:29 perry 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 __FBSDID("$FreeBSD$"); 114 115 #include <sys/param.h> 116 #include <sys/bus.h> 117 #include <sys/endian.h> 118 #include <sys/lock.h> 119 #include <sys/mbuf.h> 120 #include <sys/mutex.h> 121 #include <sys/socket.h> 122 123 #include <net/bpf.h> 124 #include <net/ethernet.h> 125 #include <net/if.h> 126 #include <net/if_arp.h> 127 #include <net/if_dl.h> 128 #include <net/if_media.h> 129 #include <net/if_var.h> 130 131 #include <dev/le/lancereg.h> 132 #include <dev/le/lancevar.h> 133 #include <dev/le/am79900reg.h> 134 #include <dev/le/am79900var.h> 135 136 static void am79900_meminit(struct lance_softc *); 137 static void am79900_rint(struct lance_softc *); 138 static void am79900_tint(struct lance_softc *); 139 static void am79900_start_locked(struct lance_softc *sc); 140 141 #ifdef LEDEBUG 142 static void am79900_recv_print(struct lance_softc *, int); 143 static void am79900_xmit_print(struct lance_softc *, int); 144 #endif 145 146 int 147 am79900_config(struct am79900_softc *sc, const char* name, int unit) 148 { 149 int error, mem; 150 151 sc->lsc.sc_meminit = am79900_meminit; 152 sc->lsc.sc_start_locked = am79900_start_locked; 153 154 error = lance_config(&sc->lsc, name, unit); 155 if (error != 0) 156 return (error); 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 sc->lsc.sc_rbufaddr = mem; 166 mem += LEBLEN * sc->lsc.sc_nrbuf; 167 sc->lsc.sc_tbufaddr = mem; 168 mem += LEBLEN * sc->lsc.sc_ntbuf; 169 170 if (mem > sc->lsc.sc_memsize) 171 panic("%s: memsize", __func__); 172 173 lance_attach(&sc->lsc); 174 175 return (0); 176 } 177 178 void 179 am79900_detach(struct am79900_softc *sc) 180 { 181 182 lance_detach(&sc->lsc); 183 } 184 185 /* 186 * Set up the initialization block and the descriptor rings. 187 */ 188 static void 189 am79900_meminit(struct lance_softc *sc) 190 { 191 struct ifnet *ifp = sc->sc_ifp; 192 struct leinit init; 193 struct lermd rmd; 194 struct letmd tmd; 195 u_long a; 196 int bix; 197 198 LE_LOCK_ASSERT(sc, MA_OWNED); 199 200 if (ifp->if_flags & IFF_PROMISC) 201 init.init_mode = LE_HTOLE32(LE_MODE_NORMAL | LE_MODE_PROM); 202 else 203 init.init_mode = LE_HTOLE32(LE_MODE_NORMAL); 204 205 init.init_mode |= LE_HTOLE32(((ffs(sc->sc_ntbuf) - 1) << 28) | 206 ((ffs(sc->sc_nrbuf) - 1) << 20)); 207 208 init.init_padr[0] = LE_HTOLE32(sc->sc_enaddr[0] | 209 (sc->sc_enaddr[1] << 8) | (sc->sc_enaddr[2] << 16) | 210 (sc->sc_enaddr[3] << 24)); 211 init.init_padr[1] = LE_HTOLE32(sc->sc_enaddr[4] | 212 (sc->sc_enaddr[5] << 8)); 213 lance_setladrf(sc, init.init_ladrf); 214 215 sc->sc_last_rd = 0; 216 sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0; 217 218 a = sc->sc_addr + LE_RMDADDR(sc, 0); 219 init.init_rdra = LE_HTOLE32(a); 220 221 a = sc->sc_addr + LE_TMDADDR(sc, 0); 222 init.init_tdra = LE_HTOLE32(a); 223 224 (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init)); 225 226 /* 227 * Set up receive ring descriptors. 228 */ 229 for (bix = 0; bix < sc->sc_nrbuf; bix++) { 230 a = sc->sc_addr + LE_RBUFADDR(sc, bix); 231 rmd.rmd0 = LE_HTOLE32(a); 232 rmd.rmd1 = LE_HTOLE32(LE_R1_OWN | LE_R1_ONES | 233 (-LEBLEN & 0xfff)); 234 rmd.rmd2 = 0; 235 rmd.rmd3 = 0; 236 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix), 237 sizeof(rmd)); 238 } 239 240 /* 241 * Set up transmit ring descriptors. 242 */ 243 for (bix = 0; bix < sc->sc_ntbuf; bix++) { 244 a = sc->sc_addr + LE_TBUFADDR(sc, bix); 245 tmd.tmd0 = LE_HTOLE32(a); 246 tmd.tmd1 = LE_HTOLE32(LE_T1_ONES); 247 tmd.tmd2 = 0; 248 tmd.tmd3 = 0; 249 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix), 250 sizeof(tmd)); 251 } 252 } 253 254 static inline void 255 am79900_rint(struct lance_softc *sc) 256 { 257 struct ifnet *ifp = sc->sc_ifp; 258 struct lermd rmd; 259 uint32_t rmd1; 260 int bix, rp; 261 262 bix = sc->sc_last_rd; 263 264 /* Process all buffers with valid data. */ 265 for (;;) { 266 rp = LE_RMDADDR(sc, bix); 267 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd)); 268 269 rmd1 = LE_LE32TOH(rmd.rmd1); 270 if (rmd1 & LE_R1_OWN) 271 break; 272 273 if (rmd1 & LE_R1_ERR) { 274 if (rmd1 & LE_R1_ENP) { 275 #ifdef LEDEBUG 276 if ((rmd1 & LE_R1_OFLO) == 0) { 277 if (rmd1 & LE_R1_FRAM) 278 if_printf(ifp, 279 "framing error\n"); 280 if (rmd1 & LE_R1_CRC) 281 if_printf(ifp, 282 "crc mismatch\n"); 283 } 284 #endif 285 } else { 286 if (rmd1 & LE_R1_OFLO) 287 if_printf(ifp, "overflow\n"); 288 } 289 if (rmd1 & LE_R1_BUFF) 290 if_printf(ifp, "receive buffer error\n"); 291 ifp->if_ierrors++; 292 } else if ((rmd1 & (LE_R1_STP | LE_R1_ENP)) != 293 (LE_R1_STP | LE_R1_ENP)) { 294 if_printf(ifp, "dropping chained buffer\n"); 295 ifp->if_ierrors++; 296 } else { 297 #ifdef LEDEBUG 298 if (sc->sc_flags & LE_DEBUG) 299 am79900_recv_print(sc, sc->sc_last_rd); 300 #endif 301 lance_read(sc, LE_RBUFADDR(sc, bix), 302 (LE_LE32TOH(rmd.rmd2) & 0xfff) - ETHER_CRC_LEN); 303 } 304 305 rmd.rmd1 = LE_HTOLE32(LE_R1_OWN | LE_R1_ONES | 306 (-LEBLEN & 0xfff)); 307 rmd.rmd2 = 0; 308 rmd.rmd3 = 0; 309 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd)); 310 311 #ifdef LEDEBUG 312 if (sc->sc_flags & LE_DEBUG) 313 if_printf(ifp, "sc->sc_last_rd = %x, rmd: " 314 "adr %08x, flags/blen %08x\n", 315 sc->sc_last_rd, LE_LE32TOH(rmd.rmd0), 316 LE_LE32TOH(rmd.rmd1)); 317 #endif 318 319 if (++bix == sc->sc_nrbuf) 320 bix = 0; 321 } 322 323 sc->sc_last_rd = bix; 324 } 325 326 static inline void 327 am79900_tint(struct lance_softc *sc) 328 { 329 struct ifnet *ifp = sc->sc_ifp; 330 struct letmd tmd; 331 uint32_t tmd1, tmd2; 332 int bix; 333 334 bix = sc->sc_first_td; 335 336 for (;;) { 337 if (sc->sc_no_td <= 0) 338 break; 339 340 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix), 341 sizeof(tmd)); 342 343 #ifdef LEDEBUG 344 if (sc->sc_flags & LE_DEBUG) 345 if_printf(ifp, "trans tmd: " 346 "adr %08x, flags/blen %08x\n", 347 LE_LE32TOH(tmd.tmd0), LE_LE32TOH(tmd.tmd1)); 348 #endif 349 350 tmd1 = LE_LE32TOH(tmd.tmd1); 351 if (tmd1 & LE_T1_OWN) 352 break; 353 354 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 355 356 tmd2 = LE_LE32TOH(tmd.tmd2); 357 if (tmd1 & LE_T1_ERR) { 358 if (tmd2 & LE_T2_BUFF) 359 if_printf(ifp, "transmit buffer error\n"); 360 else if (tmd2 & LE_T2_UFLO) 361 if_printf(ifp, "underflow\n"); 362 if (tmd2 & (LE_T2_BUFF | LE_T2_UFLO)) { 363 lance_init_locked(sc); 364 return; 365 } 366 if (tmd2 & LE_T2_LCAR) { 367 if (sc->sc_flags & LE_CARRIER) 368 if_link_state_change(ifp, 369 LINK_STATE_DOWN); 370 sc->sc_flags &= ~LE_CARRIER; 371 if (sc->sc_nocarrier) 372 (*sc->sc_nocarrier)(sc); 373 else 374 if_printf(ifp, "lost carrier\n"); 375 } 376 if (tmd2 & LE_T2_LCOL) 377 ifp->if_collisions++; 378 if (tmd2 & LE_T2_RTRY) { 379 #ifdef LEDEBUG 380 if_printf(ifp, "excessive collisions\n"); 381 #endif 382 ifp->if_collisions += 16; 383 } 384 ifp->if_oerrors++; 385 } else { 386 if (tmd1 & LE_T1_ONE) 387 ifp->if_collisions++; 388 else if (tmd1 & LE_T1_MORE) 389 /* Real number is unknown. */ 390 ifp->if_collisions += 2; 391 ifp->if_opackets++; 392 } 393 394 if (++bix == sc->sc_ntbuf) 395 bix = 0; 396 397 --sc->sc_no_td; 398 } 399 400 sc->sc_first_td = bix; 401 402 ifp->if_timer = sc->sc_no_td > 0 ? 5 : 0; 403 } 404 405 /* 406 * Controller interrupt 407 */ 408 void 409 am79900_intr(void *arg) 410 { 411 struct lance_softc *sc = arg; 412 struct ifnet *ifp = sc->sc_ifp; 413 uint16_t isr; 414 415 LE_LOCK(sc); 416 417 if (sc->sc_hwintr && (*sc->sc_hwintr)(sc) == -1) { 418 ifp->if_ierrors++; 419 lance_init_locked(sc); 420 LE_UNLOCK(sc); 421 return; 422 } 423 424 isr = (*sc->sc_rdcsr)(sc, LE_CSR0); 425 #if defined(LEDEBUG) && LEDEBUG > 1 426 if (sc->sc_flags & LE_DEBUG) 427 if_printf(ifp, "%s: entering with isr=%04x\n", __func__, isr); 428 #endif 429 if ((isr & LE_C0_INTR) == 0) { 430 LE_UNLOCK(sc); 431 return; 432 } 433 434 /* 435 * Clear interrupt source flags and turn off interrupts. If we 436 * don't clear these flags before processing their sources we 437 * could completely miss some interrupt events as the the NIC 438 * can change these flags while we're in this handler. We turn 439 * of interrupts while processing them so we don't get another 440 * one while we still process the previous one in ifp->if_input() 441 * with the driver lock dropped. 442 */ 443 (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~(LE_C0_INEA | LE_C0_TDMD | 444 LE_C0_STOP | LE_C0_STRT | LE_C0_INIT)); 445 446 if (isr & LE_C0_ERR) { 447 if (isr & LE_C0_BABL) { 448 #ifdef LEDEBUG 449 if_printf(ifp, "babble\n"); 450 #endif 451 ifp->if_oerrors++; 452 } 453 #if 0 454 if (isr & LE_C0_CERR) { 455 if_printf(ifp, "collision error\n"); 456 ifp->if_collisions++; 457 } 458 #endif 459 if (isr & LE_C0_MISS) { 460 #ifdef LEDEBUG 461 if_printf(ifp, "missed packet\n"); 462 #endif 463 ifp->if_ierrors++; 464 } 465 if (isr & LE_C0_MERR) { 466 if_printf(ifp, "memory error\n"); 467 lance_init_locked(sc); 468 LE_UNLOCK(sc); 469 return; 470 } 471 } 472 473 if ((isr & LE_C0_RXON) == 0) { 474 if_printf(ifp, "receiver disabled\n"); 475 ifp->if_ierrors++; 476 lance_init_locked(sc); 477 LE_UNLOCK(sc); 478 return; 479 } 480 if ((isr & LE_C0_TXON) == 0) { 481 if_printf(ifp, "transmitter disabled\n"); 482 ifp->if_oerrors++; 483 lance_init_locked(sc); 484 LE_UNLOCK(sc); 485 return; 486 } 487 488 /* 489 * Pretend we have carrier; if we don't this will be cleared shortly. 490 */ 491 if (!(sc->sc_flags & LE_CARRIER)) 492 if_link_state_change(ifp, LINK_STATE_UP); 493 sc->sc_flags |= LE_CARRIER; 494 495 if (isr & LE_C0_RINT) 496 am79900_rint(sc); 497 if (isr & LE_C0_TINT) 498 am79900_tint(sc); 499 500 /* Enable interrupts again. */ 501 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA); 502 503 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 504 am79900_start_locked(sc); 505 506 LE_UNLOCK(sc); 507 } 508 509 /* 510 * Set up output on interface. 511 * Get another datagram to send off of the interface queue, and map it to the 512 * interface before starting the output. 513 */ 514 static void 515 am79900_start_locked(struct lance_softc *sc) 516 { 517 struct ifnet *ifp = sc->sc_ifp; 518 struct letmd tmd; 519 struct mbuf *m; 520 int bix, enq, len, rp; 521 522 LE_LOCK_ASSERT(sc, MA_OWNED); 523 524 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 525 IFF_DRV_RUNNING) 526 return; 527 528 bix = sc->sc_last_td; 529 enq = 0; 530 531 for (; sc->sc_no_td < sc->sc_ntbuf && 532 !IFQ_DRV_IS_EMPTY(&ifp->if_snd);) { 533 rp = LE_TMDADDR(sc, bix); 534 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd)); 535 536 if (LE_LE32TOH(tmd.tmd1) & LE_T1_OWN) { 537 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 538 if_printf(ifp, 539 "missing buffer, no_td = %d, last_td = %d\n", 540 sc->sc_no_td, sc->sc_last_td); 541 } 542 543 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 544 if (m == 0) 545 break; 546 547 /* 548 * If BPF is listening on this interface, let it see the packet 549 * before we commit it to the wire. 550 */ 551 BPF_MTAP(ifp, m); 552 553 /* 554 * Copy the mbuf chain into the transmit buffer. 555 */ 556 len = lance_put(sc, LE_TBUFADDR(sc, bix), m); 557 558 #ifdef LEDEBUG 559 if (len > ETHERMTU + ETHER_HDR_LEN) 560 if_printf(ifp, "packet length %d\n", len); 561 #endif 562 563 /* 564 * Init transmit registers, and set transmit start flag. 565 */ 566 tmd.tmd1 = LE_HTOLE32(LE_T1_OWN | LE_T1_STP | LE_T1_ENP | 567 LE_T1_ONES | (-len & 0xfff)); 568 tmd.tmd2 = 0; 569 tmd.tmd3 = 0; 570 571 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd)); 572 573 #ifdef LEDEBUG 574 if (sc->sc_flags & LE_DEBUG) 575 am79900_xmit_print(sc, sc->sc_last_td); 576 #endif 577 578 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD); 579 enq++; 580 581 if (++bix == sc->sc_ntbuf) 582 bix = 0; 583 584 if (++sc->sc_no_td == sc->sc_ntbuf) { 585 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 586 break; 587 } 588 } 589 590 sc->sc_last_td = bix; 591 592 if (enq > 0) 593 ifp->if_timer = 5; 594 } 595 596 #ifdef LEDEBUG 597 static void 598 am79900_recv_print(struct lance_softc *sc, int no) 599 { 600 struct ifnet *ifp = sc->sc_ifp; 601 struct ether_header eh; 602 struct lermd rmd; 603 uint16_t len; 604 605 (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd)); 606 len = LE_LE32TOH(rmd.rmd2) & 0xfff; 607 if_printf(ifp, "receive buffer %d, len = %d\n", no, len); 608 if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); 609 if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(rmd.rmd0), 610 LE_LE32TOH(rmd.rmd1)); 611 if (len - ETHER_CRC_LEN >= sizeof(eh)) { 612 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh)); 613 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); 614 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 615 ntohs(eh.ether_type)); 616 } 617 } 618 619 static void 620 am79900_xmit_print(struct lance_softc *sc, int no) 621 { 622 struct ifnet *ifp = sc->sc_ifp; 623 struct ether_header eh; 624 struct letmd tmd; 625 uint16_t len; 626 627 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd)); 628 len = -(LE_LE32TOH(tmd.tmd1) & 0xfff); 629 if_printf(ifp, "transmit buffer %d, len = %d\n", no, len); 630 if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); 631 if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(tmd.tmd0), 632 LE_LE32TOH(tmd.tmd1)); 633 if (len >= sizeof(eh)) { 634 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh)); 635 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); 636 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 637 ntohs(eh.ether_type)); 638 } 639 } 640 #endif /* LEDEBUG */ 641