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