am79900.c revision 174986
140090Smsmith/* $NetBSD: am79900.c,v 1.17 2005/12/24 20:27:29 perry Exp $ */ 240090Smsmith 340090Smsmith/*- 440090Smsmith * Copyright (c) 1997 The NetBSD Foundation, Inc. 540090Smsmith * All rights reserved. 640090Smsmith * 740090Smsmith * This code is derived from software contributed to The NetBSD Foundation 840090Smsmith * by Jason R. Thorpe. 940090Smsmith * 1040090Smsmith * Redistribution and use in source and binary forms, with or without 1140090Smsmith * modification, are permitted provided that the following conditions 1240090Smsmith * are met: 1340090Smsmith * 1. Redistributions of source code must retain the above copyright 1440090Smsmith * notice, this list of conditions and the following disclaimer. 1540090Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1640090Smsmith * notice, this list of conditions and the following disclaimer in the 1740090Smsmith * documentation and/or other materials provided with the distribution. 1840090Smsmith * 3. All advertising materials mentioning features or use of this software 1940090Smsmith * must display the following acknowledgement: 2040090Smsmith * This product includes software developed by the NetBSD 2140090Smsmith * Foundation, Inc. and its contributors. 2240090Smsmith * 4. Neither the name of The NetBSD Foundation nor the names of its 2340090Smsmith * contributors may be used to endorse or promote products derived 2440090Smsmith * from this software without specific prior written permission. 2540090Smsmith * 2640116Sjkh * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 2740116Sjkh * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2840090Smsmith * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2940090Smsmith * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 3040090Smsmith * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 3140090Smsmith * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 3240090Smsmith * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 3340090Smsmith * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 3440090Smsmith * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 3540090Smsmith * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3640090Smsmith * POSSIBILITY OF SUCH DAMAGE. 3740090Smsmith */ 3840090Smsmith 3940090Smsmith/*- 4040090Smsmith * Copyright (c) 1992, 1993 4140090Smsmith * The Regents of the University of California. All rights reserved. 4240090Smsmith * 4340090Smsmith * This code is derived from software contributed to Berkeley by 4440090Smsmith * Ralph Campbell and Rick Macklem. 4540090Smsmith * 4640090Smsmith * Redistribution and use in source and binary forms, with or without 4740090Smsmith * modification, are permitted provided that the following conditions 4840090Smsmith * are met: 4940090Smsmith * 1. Redistributions of source code must retain the above copyright 5040090Smsmith * notice, this list of conditions and the following disclaimer. 5140090Smsmith * 2. Redistributions in binary form must reproduce the above copyright 5240090Smsmith * notice, this list of conditions and the following disclaimer in the 5340090Smsmith * documentation and/or other materials provided with the distribution. 5440090Smsmith * 3. Neither the name of the University nor the names of its contributors 5540090Smsmith * may be used to endorse or promote products derived from this software 5640090Smsmith * without specific prior written permission. 5740090Smsmith * 5840090Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 5940090Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 6040090Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 6140090Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 6240090Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 6340090Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 6440090Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 6540090Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 6640090Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 6740090Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 6840090Smsmith * SUCH DAMAGE. 6940090Smsmith * 7040090Smsmith * @(#)if_le.c 8.2 (Berkeley) 11/16/93 7140090Smsmith */ 7240090Smsmith 7340090Smsmith/*- 7440090Smsmith * Copyright (c) 1998 7540090Smsmith * Matthias Drochner. All rights reserved. 7640090Smsmith * Copyright (c) 1995 Charles M. Hannum. All rights reserved. 7740090Smsmith * 7840090Smsmith * This code is derived from software contributed to Berkeley by 7940090Smsmith * Ralph Campbell and Rick Macklem. 8040090Smsmith * 8140090Smsmith * Redistribution and use in source and binary forms, with or without 8240090Smsmith * modification, are permitted provided that the following conditions 8340090Smsmith * are met: 8440090Smsmith * 1. Redistributions of source code must retain the above copyright 8540090Smsmith * notice, this list of conditions and the following disclaimer. 8640090Smsmith * 2. Redistributions in binary form must reproduce the above copyright 8740090Smsmith * notice, this list of conditions and the following disclaimer in the 8840090Smsmith * documentation and/or other materials provided with the distribution. 8940090Smsmith * 3. All advertising materials mentioning features or use of this software 9040090Smsmith * must display the following acknowledgement: 9140090Smsmith * This product includes software developed by the University of 9240090Smsmith * California, Berkeley and its contributors. 9340090Smsmith * 4. Neither the name of the University nor the names of its contributors 9440090Smsmith * may be used to endorse or promote products derived from this software 9540090Smsmith * without specific prior written permission. 9640090Smsmith * 9740090Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 9840090Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 9940090Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 10040090Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 10140090Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 10240090Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 10340090Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 10440090Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 10540090Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 10640090Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 10740090Smsmith * SUCH DAMAGE. 10840090Smsmith * 10940090Smsmith * @(#)if_le.c 8.2 (Berkeley) 11/16/93 11040090Smsmith */ 11140090Smsmith 11240090Smsmith#include <sys/cdefs.h> 11340090Smsmith__FBSDID("$FreeBSD: head/sys/dev/le/am79900.c 174986 2007-12-30 00:23:38Z marius $"); 11440090Smsmith 11540090Smsmith#include <sys/param.h> 11640090Smsmith#include <sys/bus.h> 11740090Smsmith#include <sys/endian.h> 11840090Smsmith#include <sys/lock.h> 11940090Smsmith#include <sys/mbuf.h> 12040090Smsmith#include <sys/mutex.h> 12140090Smsmith#include <sys/socket.h> 12240090Smsmith 12340090Smsmith#include <net/bpf.h> 12440090Smsmith#include <net/ethernet.h> 12540090Smsmith#include <net/if.h> 12640090Smsmith#include <net/if_arp.h> 12740090Smsmith#include <net/if_dl.h> 128#include <net/if_media.h> 129#include <net/if_var.h> 130 131#include <machine/bus.h> 132 133#include <dev/le/lancereg.h> 134#include <dev/le/lancevar.h> 135#include <dev/le/am79900reg.h> 136#include <dev/le/am79900var.h> 137 138static void am79900_meminit(struct lance_softc *); 139static void am79900_rint(struct lance_softc *); 140static void am79900_tint(struct lance_softc *); 141static void am79900_start_locked(struct lance_softc *sc); 142 143#ifdef LEDEBUG 144static void am79900_recv_print(struct lance_softc *, int); 145static void am79900_xmit_print(struct lance_softc *, int); 146#endif 147 148int 149am79900_config(struct am79900_softc *sc, const char* name, int unit) 150{ 151 int error, mem; 152 153 sc->lsc.sc_meminit = am79900_meminit; 154 sc->lsc.sc_start_locked = am79900_start_locked; 155 156 error = lance_config(&sc->lsc, name, unit); 157 if (error != 0) 158 return (error); 159 160 mem = 0; 161 sc->lsc.sc_initaddr = mem; 162 mem += sizeof(struct leinit); 163 sc->lsc.sc_rmdaddr = mem; 164 mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf; 165 sc->lsc.sc_tmdaddr = mem; 166 mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf; 167 sc->lsc.sc_rbufaddr = mem; 168 mem += LEBLEN * sc->lsc.sc_nrbuf; 169 sc->lsc.sc_tbufaddr = mem; 170 mem += LEBLEN * sc->lsc.sc_ntbuf; 171 172 if (mem > sc->lsc.sc_memsize) 173 panic("%s: memsize", __func__); 174 175 lance_attach(&sc->lsc); 176 177 return (0); 178} 179 180void 181am79900_detach(struct am79900_softc *sc) 182{ 183 184 lance_detach(&sc->lsc); 185} 186 187/* 188 * Set up the initialization block and the descriptor rings. 189 */ 190static void 191am79900_meminit(struct lance_softc *sc) 192{ 193 struct ifnet *ifp = sc->sc_ifp; 194 struct leinit init; 195 struct lermd rmd; 196 struct letmd tmd; 197 u_long a; 198 int bix; 199 200 LE_LOCK_ASSERT(sc, MA_OWNED); 201 202 if (ifp->if_flags & IFF_PROMISC) 203 init.init_mode = LE_HTOLE32(LE_MODE_NORMAL | LE_MODE_PROM); 204 else 205 init.init_mode = LE_HTOLE32(LE_MODE_NORMAL); 206 207 init.init_mode |= LE_HTOLE32(((ffs(sc->sc_ntbuf) - 1) << 28) | 208 ((ffs(sc->sc_nrbuf) - 1) << 20)); 209 210 init.init_padr[0] = LE_HTOLE32(sc->sc_enaddr[0] | 211 (sc->sc_enaddr[1] << 8) | (sc->sc_enaddr[2] << 16) | 212 (sc->sc_enaddr[3] << 24)); 213 init.init_padr[1] = LE_HTOLE32(sc->sc_enaddr[4] | 214 (sc->sc_enaddr[5] << 8)); 215 lance_setladrf(sc, init.init_ladrf); 216 217 sc->sc_last_rd = 0; 218 sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0; 219 220 a = sc->sc_addr + LE_RMDADDR(sc, 0); 221 init.init_rdra = LE_HTOLE32(a); 222 223 a = sc->sc_addr + LE_TMDADDR(sc, 0); 224 init.init_tdra = LE_HTOLE32(a); 225 226 (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init)); 227 228 /* 229 * Set up receive ring descriptors. 230 */ 231 for (bix = 0; bix < sc->sc_nrbuf; bix++) { 232 a = sc->sc_addr + LE_RBUFADDR(sc, bix); 233 rmd.rmd0 = LE_HTOLE32(a); 234 rmd.rmd1 = LE_HTOLE32(LE_R1_OWN | LE_R1_ONES | 235 (-LEBLEN & 0xfff)); 236 rmd.rmd2 = 0; 237 rmd.rmd3 = 0; 238 (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix), 239 sizeof(rmd)); 240 } 241 242 /* 243 * Set up transmit ring descriptors. 244 */ 245 for (bix = 0; bix < sc->sc_ntbuf; bix++) { 246 a = sc->sc_addr + LE_TBUFADDR(sc, bix); 247 tmd.tmd0 = LE_HTOLE32(a); 248 tmd.tmd1 = LE_HTOLE32(LE_T1_ONES); 249 tmd.tmd2 = 0; 250 tmd.tmd3 = 0; 251 (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix), 252 sizeof(tmd)); 253 } 254} 255 256static inline void 257am79900_rint(struct lance_softc *sc) 258{ 259 struct ifnet *ifp = sc->sc_ifp; 260 struct mbuf *m; 261 struct lermd rmd; 262 uint32_t rmd1; 263 int bix, rp; 264#if defined(__i386__) && !defined(PC98) 265 struct ether_header *eh; 266#endif 267 268 bix = sc->sc_last_rd; 269 270 /* Process all buffers with valid data. */ 271 for (;;) { 272 rp = LE_RMDADDR(sc, bix); 273 (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd)); 274 275 rmd1 = LE_LE32TOH(rmd.rmd1); 276 if (rmd1 & LE_R1_OWN) 277 break; 278 279 m = NULL; 280 if ((rmd1 & (LE_R1_ERR | LE_R1_STP | LE_R1_ENP)) != 281 (LE_R1_STP | LE_R1_ENP)){ 282 if (rmd1 & LE_R1_ERR) { 283#ifdef LEDEBUG 284 if (rmd1 & LE_R1_ENP) { 285 if ((rmd1 & LE_R1_OFLO) == 0) { 286 if (rmd1 & LE_R1_FRAM) 287 if_printf(ifp, 288 "framing error\n"); 289 if (rmd1 & LE_R1_CRC) 290 if_printf(ifp, 291 "crc mismatch\n"); 292 } 293 } else 294 if (rmd1 & LE_R1_OFLO) 295 if_printf(ifp, "overflow\n"); 296#endif 297 if (rmd1 & LE_R1_BUFF) 298 if_printf(ifp, 299 "receive buffer error\n"); 300 } else if ((rmd1 & (LE_R1_STP | LE_R1_ENP)) != 301 (LE_R1_STP | LE_R1_ENP)) 302 if_printf(ifp, "dropping chained buffer\n"); 303 } else { 304#ifdef LEDEBUG 305 if (sc->sc_flags & LE_DEBUG) 306 am79900_recv_print(sc, bix); 307#endif 308 /* Pull the packet off the interface. */ 309 m = lance_get(sc, LE_RBUFADDR(sc, bix), 310 (LE_LE32TOH(rmd.rmd2) & 0xfff) - ETHER_CRC_LEN); 311 } 312 313 rmd.rmd1 = LE_HTOLE32(LE_R1_OWN | LE_R1_ONES | 314 (-LEBLEN & 0xfff)); 315 rmd.rmd2 = 0; 316 rmd.rmd3 = 0; 317 (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd)); 318 319 if (++bix == sc->sc_nrbuf) 320 bix = 0; 321 322 if (m != NULL) { 323 ifp->if_ipackets++; 324 325#if defined(__i386__) && !defined(PC98) 326 /* 327 * The VMware LANCE does not present IFF_SIMPLEX 328 * behavior on multicast packets. Thus drop the 329 * packet if it is from ourselves. 330 */ 331 eh = mtod(m, struct ether_header *); 332 if (!ether_cmp(eh->ether_shost, sc->sc_enaddr)) { 333 m_freem(m); 334 continue; 335 } 336#endif 337 338 /* Pass the packet up. */ 339 LE_UNLOCK(sc); 340 (*ifp->if_input)(ifp, m); 341 LE_LOCK(sc); 342 } else 343 ifp->if_ierrors++; 344 } 345 346 sc->sc_last_rd = bix; 347} 348 349static inline void 350am79900_tint(struct lance_softc *sc) 351{ 352 struct ifnet *ifp = sc->sc_ifp; 353 struct letmd tmd; 354 uint32_t tmd1, tmd2; 355 int bix; 356 357 bix = sc->sc_first_td; 358 359 for (;;) { 360 if (sc->sc_no_td <= 0) 361 break; 362 363 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix), 364 sizeof(tmd)); 365 366 tmd1 = LE_LE32TOH(tmd.tmd1); 367 368#ifdef LEDEBUG 369 if (sc->sc_flags & LE_DEBUG) 370 if_printf(ifp, "trans tmd: " 371 "adr %08x, flags/blen %08x\n", 372 LE_LE32TOH(tmd.tmd0), tmd1); 373#endif 374 375 if (tmd1 & LE_T1_OWN) 376 break; 377 378 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; 379 380 if (tmd1 & LE_T1_ERR) { 381 tmd2 = LE_LE32TOH(tmd.tmd2); 382 if (tmd2 & LE_T2_BUFF) 383 if_printf(ifp, "transmit buffer error\n"); 384 else if (tmd2 & LE_T2_UFLO) 385 if_printf(ifp, "underflow\n"); 386 if (tmd2 & (LE_T2_BUFF | LE_T2_UFLO)) { 387 lance_init_locked(sc); 388 return; 389 } 390 if (tmd2 & LE_T2_LCAR) { 391 if (sc->sc_flags & LE_CARRIER) 392 if_link_state_change(ifp, 393 LINK_STATE_DOWN); 394 sc->sc_flags &= ~LE_CARRIER; 395 if (sc->sc_nocarrier) 396 (*sc->sc_nocarrier)(sc); 397 else 398 if_printf(ifp, "lost carrier\n"); 399 } 400 if (tmd2 & LE_T2_LCOL) 401 ifp->if_collisions++; 402 if (tmd2 & LE_T2_RTRY) { 403#ifdef LEDEBUG 404 if_printf(ifp, "excessive collisions\n"); 405#endif 406 ifp->if_collisions += 16; 407 } 408 ifp->if_oerrors++; 409 } else { 410 if (tmd1 & LE_T1_ONE) 411 ifp->if_collisions++; 412 else if (tmd1 & LE_T1_MORE) 413 /* Real number is unknown. */ 414 ifp->if_collisions += 2; 415 ifp->if_opackets++; 416 } 417 418 if (++bix == sc->sc_ntbuf) 419 bix = 0; 420 421 --sc->sc_no_td; 422 } 423 424 sc->sc_first_td = bix; 425 426 sc->sc_wdog_timer = sc->sc_no_td > 0 ? 5 : 0; 427} 428 429/* 430 * Controller interrupt 431 */ 432void 433am79900_intr(void *arg) 434{ 435 struct lance_softc *sc = arg; 436 struct ifnet *ifp = sc->sc_ifp; 437 uint16_t isr; 438 439 LE_LOCK(sc); 440 441 if (sc->sc_hwintr && (*sc->sc_hwintr)(sc) == -1) { 442 ifp->if_ierrors++; 443 lance_init_locked(sc); 444 LE_UNLOCK(sc); 445 return; 446 } 447 448 isr = (*sc->sc_rdcsr)(sc, LE_CSR0); 449#if defined(LEDEBUG) && LEDEBUG > 1 450 if (sc->sc_flags & LE_DEBUG) 451 if_printf(ifp, "%s: entering with isr=%04x\n", __func__, isr); 452#endif 453 if ((isr & LE_C0_INTR) == 0) { 454 LE_UNLOCK(sc); 455 return; 456 } 457 458 /* 459 * Clear interrupt source flags and turn off interrupts. If we 460 * don't clear these flags before processing their sources we 461 * could completely miss some interrupt events as the NIC can 462 * change these flags while we're in this handler. We toggle 463 * the interrupt enable bit in order to keep receiving them 464 * (some chips work without this, some don't). 465 */ 466 (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~(LE_C0_INEA | LE_C0_TDMD | 467 LE_C0_STOP | LE_C0_STRT | LE_C0_INIT)); 468 469 if (isr & LE_C0_ERR) { 470 if (isr & LE_C0_BABL) { 471#ifdef LEDEBUG 472 if_printf(ifp, "babble\n"); 473#endif 474 ifp->if_oerrors++; 475 } 476#if 0 477 if (isr & LE_C0_CERR) { 478 if_printf(ifp, "collision error\n"); 479 ifp->if_collisions++; 480 } 481#endif 482 if (isr & LE_C0_MISS) { 483#ifdef LEDEBUG 484 if_printf(ifp, "missed packet\n"); 485#endif 486 ifp->if_ierrors++; 487 } 488 if (isr & LE_C0_MERR) { 489 if_printf(ifp, "memory error\n"); 490 lance_init_locked(sc); 491 LE_UNLOCK(sc); 492 return; 493 } 494 } 495 496 if ((isr & LE_C0_RXON) == 0) { 497 if_printf(ifp, "receiver disabled\n"); 498 ifp->if_ierrors++; 499 lance_init_locked(sc); 500 LE_UNLOCK(sc); 501 return; 502 } 503 if ((isr & LE_C0_TXON) == 0) { 504 if_printf(ifp, "transmitter disabled\n"); 505 ifp->if_oerrors++; 506 lance_init_locked(sc); 507 LE_UNLOCK(sc); 508 return; 509 } 510 511 /* 512 * Pretend we have carrier; if we don't this will be cleared shortly. 513 */ 514 if (!(sc->sc_flags & LE_CARRIER)) 515 if_link_state_change(ifp, LINK_STATE_UP); 516 sc->sc_flags |= LE_CARRIER; 517 518 if (isr & LE_C0_RINT) 519 am79900_rint(sc); 520 if (isr & LE_C0_TINT) 521 am79900_tint(sc); 522 523 /* Enable interrupts again. */ 524 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA); 525 526 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 527 am79900_start_locked(sc); 528 529 LE_UNLOCK(sc); 530} 531 532/* 533 * Set up output on interface. 534 * Get another datagram to send off of the interface queue, and map it to the 535 * interface before starting the output. 536 */ 537static void 538am79900_start_locked(struct lance_softc *sc) 539{ 540 struct ifnet *ifp = sc->sc_ifp; 541 struct letmd tmd; 542 struct mbuf *m; 543 int bix, enq, len, rp; 544 545 LE_LOCK_ASSERT(sc, MA_OWNED); 546 547 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 548 IFF_DRV_RUNNING) 549 return; 550 551 bix = sc->sc_last_td; 552 enq = 0; 553 554 for (; sc->sc_no_td < sc->sc_ntbuf && 555 !IFQ_DRV_IS_EMPTY(&ifp->if_snd);) { 556 rp = LE_TMDADDR(sc, bix); 557 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd)); 558 559 if (LE_LE32TOH(tmd.tmd1) & LE_T1_OWN) { 560 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 561 if_printf(ifp, 562 "missing buffer, no_td = %d, last_td = %d\n", 563 sc->sc_no_td, sc->sc_last_td); 564 } 565 566 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 567 if (m == 0) 568 break; 569 570 /* 571 * If BPF is listening on this interface, let it see the packet 572 * before we commit it to the wire. 573 */ 574 BPF_MTAP(ifp, m); 575 576 /* 577 * Copy the mbuf chain into the transmit buffer. 578 */ 579 len = lance_put(sc, LE_TBUFADDR(sc, bix), m); 580 581#ifdef LEDEBUG 582 if (len > ETHERMTU + ETHER_HDR_LEN) 583 if_printf(ifp, "packet length %d\n", len); 584#endif 585 586 /* 587 * Init transmit registers, and set transmit start flag. 588 */ 589 tmd.tmd1 = LE_HTOLE32(LE_T1_OWN | LE_T1_STP | LE_T1_ENP | 590 LE_T1_ONES | (-len & 0xfff)); 591 tmd.tmd2 = 0; 592 tmd.tmd3 = 0; 593 594 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd)); 595 596#ifdef LEDEBUG 597 if (sc->sc_flags & LE_DEBUG) 598 am79900_xmit_print(sc, bix); 599#endif 600 601 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD); 602 enq++; 603 604 if (++bix == sc->sc_ntbuf) 605 bix = 0; 606 607 if (++sc->sc_no_td == sc->sc_ntbuf) { 608 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 609 break; 610 } 611 } 612 613 sc->sc_last_td = bix; 614 615 if (enq > 0) 616 sc->sc_wdog_timer = 5; 617} 618 619#ifdef LEDEBUG 620static void 621am79900_recv_print(struct lance_softc *sc, int no) 622{ 623 struct ifnet *ifp = sc->sc_ifp; 624 struct ether_header eh; 625 struct lermd rmd; 626 uint16_t len; 627 628 (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd)); 629 len = LE_LE32TOH(rmd.rmd2) & 0xfff; 630 if_printf(ifp, "receive buffer %d, len = %d\n", no, len); 631 if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); 632 if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(rmd.rmd0), 633 LE_LE32TOH(rmd.rmd1)); 634 if (len - ETHER_CRC_LEN >= sizeof(eh)) { 635 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh)); 636 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); 637 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 638 ntohs(eh.ether_type)); 639 } 640} 641 642static void 643am79900_xmit_print(struct lance_softc *sc, int no) 644{ 645 struct ifnet *ifp = sc->sc_ifp; 646 struct ether_header eh; 647 struct letmd tmd; 648 uint16_t len; 649 650 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd)); 651 len = -(LE_LE32TOH(tmd.tmd1) & 0xfff); 652 if_printf(ifp, "transmit buffer %d, len = %d\n", no, len); 653 if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); 654 if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(tmd.tmd0), 655 LE_LE32TOH(tmd.tmd1)); 656 if (len >= sizeof(eh)) { 657 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh)); 658 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); 659 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 660 ntohs(eh.ether_type)); 661 } 662} 663#endif /* LEDEBUG */ 664