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