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