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 * @(#)if_le.c 8.2 (Berkeley) 11/16/93 66 */ 67 68 /*- 69 * Copyright (c) 1998 70 * Matthias Drochner. All rights reserved. 71 * Copyright (c) 1995 Charles M. Hannum. All rights reserved. 72 * 73 * This code is derived from software contributed to Berkeley by 74 * Ralph Campbell and Rick Macklem. 75 * 76 * Redistribution and use in source and binary forms, with or without 77 * modification, are permitted provided that the following conditions 78 * are met: 79 * 1. Redistributions of source code must retain the above copyright 80 * notice, this list of conditions and the following disclaimer. 81 * 2. Redistributions in binary form must reproduce the above copyright 82 * notice, this list of conditions and the following disclaimer in the 83 * documentation and/or other materials provided with the distribution. 84 * 3. All advertising materials mentioning features or use of this software 85 * must display the following acknowledgement: 86 * This product includes software developed by the University of 87 * California, Berkeley and its contributors. 88 * 4. Neither the name of the University nor the names of its contributors 89 * may be used to endorse or promote products derived from this software 90 * without specific prior written permission. 91 * 92 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 93 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 94 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 95 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 96 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 97 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 98 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 99 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 100 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 101 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 102 * SUCH DAMAGE. 103 * 104 * @(#)if_le.c 8.2 (Berkeley) 11/16/93 105 */ 106 107 #include <sys/cdefs.h> 108 __FBSDID("$FreeBSD$"); 109 110 #include <sys/param.h> 111 #include <sys/bus.h> 112 #include <sys/endian.h> 113 #include <sys/lock.h> 114 #include <sys/mbuf.h> 115 #include <sys/mutex.h> 116 #include <sys/socket.h> 117 118 #include <net/bpf.h> 119 #include <net/ethernet.h> 120 #include <net/if.h> 121 #include <net/if_arp.h> 122 #include <net/if_dl.h> 123 #include <net/if_media.h> 124 #include <net/if_var.h> 125 126 #include <machine/bus.h> 127 128 #include <dev/le/lancereg.h> 129 #include <dev/le/lancevar.h> 130 #include <dev/le/am79900reg.h> 131 #include <dev/le/am79900var.h> 132 133 static void am79900_meminit(struct lance_softc *); 134 static void am79900_rint(struct lance_softc *); 135 static void am79900_tint(struct lance_softc *); 136 static void am79900_start_locked(struct lance_softc *sc); 137 138 #ifdef LEDEBUG 139 static void am79900_recv_print(struct lance_softc *, int); 140 static void am79900_xmit_print(struct lance_softc *, int); 141 #endif 142 143 int 144 am79900_config(struct am79900_softc *sc, const char* name, int unit) 145 { 146 int error, mem; 147 148 sc->lsc.sc_meminit = am79900_meminit; 149 sc->lsc.sc_start_locked = am79900_start_locked; 150 151 error = lance_config(&sc->lsc, name, unit); 152 if (error != 0) 153 return (error); 154 155 mem = 0; 156 sc->lsc.sc_initaddr = mem; 157 mem += sizeof(struct leinit); 158 sc->lsc.sc_rmdaddr = mem; 159 mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf; 160 sc->lsc.sc_tmdaddr = mem; 161 mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf; 162 sc->lsc.sc_rbufaddr = mem; 163 mem += LEBLEN * sc->lsc.sc_nrbuf; 164 sc->lsc.sc_tbufaddr = mem; 165 mem += LEBLEN * sc->lsc.sc_ntbuf; 166 167 if (mem > sc->lsc.sc_memsize) 168 panic("%s: memsize", __func__); 169 170 lance_attach(&sc->lsc); 171 172 return (0); 173 } 174 175 void 176 am79900_detach(struct am79900_softc *sc) 177 { 178 179 lance_detach(&sc->lsc); 180 } 181 182 /* 183 * Set up the initialization block and the descriptor rings. 184 */ 185 static void 186 am79900_meminit(struct lance_softc *sc) 187 { 188 if_t ifp = sc->sc_ifp; 189 struct leinit init; 190 struct lermd rmd; 191 struct letmd tmd; 192 u_long a; 193 int bix; 194 195 LE_LOCK_ASSERT(sc, MA_OWNED); 196 197 if (if_getflags(ifp) & 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 inline void 252 am79900_rint(struct lance_softc *sc) 253 { 254 if_t ifp = sc->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 if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1); 319 320 #if defined(__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 (!ether_cmp(eh->ether_shost, sc->sc_enaddr)) { 328 m_freem(m); 329 continue; 330 } 331 #endif 332 333 /* Pass the packet up. */ 334 LE_UNLOCK(sc); 335 if_input(ifp, m); 336 LE_LOCK(sc); 337 } else 338 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 339 } 340 341 sc->sc_last_rd = bix; 342 } 343 344 static inline void 345 am79900_tint(struct lance_softc *sc) 346 { 347 if_t ifp = sc->sc_ifp; 348 struct letmd tmd; 349 uint32_t tmd1, tmd2; 350 int bix; 351 352 bix = sc->sc_first_td; 353 354 for (;;) { 355 if (sc->sc_no_td <= 0) 356 break; 357 358 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix), 359 sizeof(tmd)); 360 361 tmd1 = LE_LE32TOH(tmd.tmd1); 362 363 #ifdef LEDEBUG 364 if (sc->sc_flags & LE_DEBUG) 365 if_printf(ifp, "trans tmd: " 366 "adr %08x, flags/blen %08x\n", 367 LE_LE32TOH(tmd.tmd0), tmd1); 368 #endif 369 370 if (tmd1 & LE_T1_OWN) 371 break; 372 373 if_setdrvflagbits(ifp, 0, IFF_DRV_OACTIVE); 374 375 if (tmd1 & LE_T1_ERR) { 376 tmd2 = LE_LE32TOH(tmd.tmd2); 377 if (tmd2 & LE_T2_BUFF) 378 if_printf(ifp, "transmit buffer error\n"); 379 else if (tmd2 & LE_T2_UFLO) 380 if_printf(ifp, "underflow\n"); 381 if (tmd2 & (LE_T2_BUFF | LE_T2_UFLO)) { 382 lance_init_locked(sc); 383 return; 384 } 385 if (tmd2 & LE_T2_LCAR) { 386 if (sc->sc_flags & LE_CARRIER) 387 if_link_state_change(ifp, 388 LINK_STATE_DOWN); 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 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); 397 if (tmd2 & LE_T2_RTRY) { 398 #ifdef LEDEBUG 399 if_printf(ifp, "excessive collisions\n"); 400 #endif 401 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 16); 402 } 403 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 404 } else { 405 if (tmd1 & LE_T1_ONE) 406 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); 407 else if (tmd1 & LE_T1_MORE) 408 /* Real number is unknown. */ 409 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 2); 410 if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); 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 sc->sc_wdog_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 if_t ifp = sc->sc_ifp; 432 uint16_t isr; 433 434 LE_LOCK(sc); 435 436 if (sc->sc_hwintr && (*sc->sc_hwintr)(sc) == -1) { 437 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 438 lance_init_locked(sc); 439 LE_UNLOCK(sc); 440 return; 441 } 442 443 isr = (*sc->sc_rdcsr)(sc, LE_CSR0); 444 #if defined(LEDEBUG) && LEDEBUG > 1 445 if (sc->sc_flags & LE_DEBUG) 446 if_printf(ifp, "%s: entering with isr=%04x\n", __func__, isr); 447 #endif 448 if ((isr & LE_C0_INTR) == 0) { 449 LE_UNLOCK(sc); 450 return; 451 } 452 453 /* 454 * Clear interrupt source flags and turn off interrupts. If we 455 * don't clear these flags before processing their sources we 456 * could completely miss some interrupt events as the NIC can 457 * change these flags while we're in this handler. We toggle 458 * the interrupt enable bit in order to keep receiving them 459 * (some chips work without this, some don't). 460 */ 461 (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~(LE_C0_INEA | LE_C0_TDMD | 462 LE_C0_STOP | LE_C0_STRT | LE_C0_INIT)); 463 464 if (isr & LE_C0_ERR) { 465 if (isr & LE_C0_BABL) { 466 #ifdef LEDEBUG 467 if_printf(ifp, "babble\n"); 468 #endif 469 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 470 } 471 #if 0 472 if (isr & LE_C0_CERR) { 473 if_printf(ifp, "collision error\n"); 474 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); 475 } 476 #endif 477 if (isr & LE_C0_MISS) { 478 #ifdef LEDEBUG 479 if_printf(ifp, "missed packet\n"); 480 #endif 481 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 482 } 483 if (isr & LE_C0_MERR) { 484 if_printf(ifp, "memory error\n"); 485 lance_init_locked(sc); 486 LE_UNLOCK(sc); 487 return; 488 } 489 } 490 491 if ((isr & LE_C0_RXON) == 0) { 492 if_printf(ifp, "receiver disabled\n"); 493 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 494 lance_init_locked(sc); 495 LE_UNLOCK(sc); 496 return; 497 } 498 if ((isr & LE_C0_TXON) == 0) { 499 if_printf(ifp, "transmitter disabled\n"); 500 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 501 lance_init_locked(sc); 502 LE_UNLOCK(sc); 503 return; 504 } 505 506 /* 507 * Pretend we have carrier; if we don't this will be cleared shortly. 508 */ 509 if (!(sc->sc_flags & LE_CARRIER)) 510 if_link_state_change(ifp, LINK_STATE_UP); 511 sc->sc_flags |= LE_CARRIER; 512 513 if (isr & LE_C0_RINT) 514 am79900_rint(sc); 515 if (isr & LE_C0_TINT) 516 am79900_tint(sc); 517 518 /* Enable interrupts again. */ 519 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA); 520 521 if (!if_sendq_empty(ifp)) 522 am79900_start_locked(sc); 523 524 LE_UNLOCK(sc); 525 } 526 527 /* 528 * Set up output on interface. 529 * Get another datagram to send off of the interface queue, and map it to the 530 * interface before starting the output. 531 */ 532 static void 533 am79900_start_locked(struct lance_softc *sc) 534 { 535 if_t ifp = sc->sc_ifp; 536 struct letmd tmd; 537 struct mbuf *m; 538 int bix, enq, len, rp; 539 540 LE_LOCK_ASSERT(sc, MA_OWNED); 541 542 if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 543 IFF_DRV_RUNNING) 544 return; 545 546 bix = sc->sc_last_td; 547 enq = 0; 548 549 for (; sc->sc_no_td < sc->sc_ntbuf && 550 !if_sendq_empty(ifp);) { 551 rp = LE_TMDADDR(sc, bix); 552 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd)); 553 554 if (LE_LE32TOH(tmd.tmd1) & LE_T1_OWN) { 555 if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); 556 if_printf(ifp, 557 "missing buffer, no_td = %d, last_td = %d\n", 558 sc->sc_no_td, sc->sc_last_td); 559 } 560 561 m = if_dequeue(ifp); 562 if (m == NULL) 563 break; 564 565 /* 566 * If BPF is listening on this interface, let it see the packet 567 * before we commit it to the wire. 568 */ 569 BPF_MTAP(ifp, m); 570 571 /* 572 * Copy the mbuf chain into the transmit buffer. 573 */ 574 len = lance_put(sc, LE_TBUFADDR(sc, bix), m); 575 576 #ifdef LEDEBUG 577 if (len > ETHERMTU + ETHER_HDR_LEN) 578 if_printf(ifp, "packet length %d\n", len); 579 #endif 580 581 /* 582 * Init transmit registers, and set transmit start flag. 583 */ 584 tmd.tmd1 = LE_HTOLE32(LE_T1_OWN | LE_T1_STP | LE_T1_ENP | 585 LE_T1_ONES | (-len & 0xfff)); 586 tmd.tmd2 = 0; 587 tmd.tmd3 = 0; 588 589 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd)); 590 591 #ifdef LEDEBUG 592 if (sc->sc_flags & LE_DEBUG) 593 am79900_xmit_print(sc, bix); 594 #endif 595 596 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD); 597 enq++; 598 599 if (++bix == sc->sc_ntbuf) 600 bix = 0; 601 602 if (++sc->sc_no_td == sc->sc_ntbuf) { 603 if_setdrvflagbits(ifp, IFF_DRV_OACTIVE, 0); 604 break; 605 } 606 } 607 608 sc->sc_last_td = bix; 609 610 if (enq > 0) 611 sc->sc_wdog_timer = 5; 612 } 613 614 #ifdef LEDEBUG 615 static void 616 am79900_recv_print(struct lance_softc *sc, int no) 617 { 618 if_t ifp = sc->sc_ifp; 619 struct ether_header eh; 620 struct lermd rmd; 621 uint16_t len; 622 623 (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd)); 624 len = LE_LE32TOH(rmd.rmd2) & 0xfff; 625 if_printf(ifp, "receive buffer %d, len = %d\n", no, len); 626 if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); 627 if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(rmd.rmd0), 628 LE_LE32TOH(rmd.rmd1)); 629 if (len - ETHER_CRC_LEN >= sizeof(eh)) { 630 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh)); 631 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); 632 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 633 ntohs(eh.ether_type)); 634 } 635 } 636 637 static void 638 am79900_xmit_print(struct lance_softc *sc, int no) 639 { 640 if_t ifp = sc->sc_ifp; 641 struct ether_header eh; 642 struct letmd tmd; 643 uint16_t len; 644 645 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd)); 646 len = -(LE_LE32TOH(tmd.tmd1) & 0xfff); 647 if_printf(ifp, "transmit buffer %d, len = %d\n", no, len); 648 if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); 649 if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(tmd.tmd0), 650 LE_LE32TOH(tmd.tmd1)); 651 if (len >= sizeof(eh)) { 652 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh)); 653 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); 654 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 655 ntohs(eh.ether_type)); 656 } 657 } 658 #endif /* LEDEBUG */ 659