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