1/* $NetBSD: am79900.c,v 1.17 2005/12/24 20:27:29 perry Exp $ */ 2 3/*- 4 * SPDX-License-Identifier: BSD-2-Clause-NetBSD 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: releng/12.0/sys/dev/le/am79900.c 326255 2017-11-27 14:52:40Z pfg $"); 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 133static void am79900_meminit(struct lance_softc *); 134static void am79900_rint(struct lance_softc *); 135static void am79900_tint(struct lance_softc *); 136static void am79900_start_locked(struct lance_softc *sc); 137 138#ifdef LEDEBUG 139static void am79900_recv_print(struct lance_softc *, int); 140static void am79900_xmit_print(struct lance_softc *, int); 141#endif 142 143int 144am79900_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 175void 176am79900_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 */ 185static void 186am79900_meminit(struct lance_softc *sc) 187{ 188 struct ifnet *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 (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 251static inline void 252am79900_rint(struct lance_softc *sc) 253{ 254 struct ifnet *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 (*ifp->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 344static inline void 345am79900_tint(struct lance_softc *sc) 346{ 347 struct ifnet *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 ifp->if_drv_flags &= ~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 */ 427void 428am79900_intr(void *arg) 429{ 430 struct lance_softc *sc = arg; 431 struct ifnet *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#ifndef __HAIKU__ 444 isr = (*sc->sc_rdcsr)(sc, LE_CSR0); 445#else 446 { 447 HAIKU_INTR_REGISTER_STATE; 448 HAIKU_INTR_REGISTER_ENTER(); 449 isr = sc->sc_lastisr; 450 sc->sc_lastisr = 0; 451 HAIKU_INTR_REGISTER_LEAVE(); 452 } 453#endif 454#if defined(LEDEBUG) && LEDEBUG > 1 455 if (sc->sc_flags & LE_DEBUG) 456 if_printf(ifp, "%s: entering with isr=%04x\n", __func__, isr); 457#endif 458 if ((isr & LE_C0_INTR) == 0) { 459 LE_UNLOCK(sc); 460 return; 461 } 462 463 /* 464 * Clear interrupt source flags and turn off interrupts. If we 465 * don't clear these flags before processing their sources we 466 * could completely miss some interrupt events as the NIC can 467 * change these flags while we're in this handler. We toggle 468 * the interrupt enable bit in order to keep receiving them 469 * (some chips work without this, some don't). 470 */ 471 (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~(LE_C0_INEA | LE_C0_TDMD | 472 LE_C0_STOP | LE_C0_STRT | LE_C0_INIT)); 473 474 if (isr & LE_C0_ERR) { 475 if (isr & LE_C0_BABL) { 476#ifdef LEDEBUG 477 if_printf(ifp, "babble\n"); 478#endif 479 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 480 } 481#if 0 482 if (isr & LE_C0_CERR) { 483 if_printf(ifp, "collision error\n"); 484 if_inc_counter(ifp, IFCOUNTER_COLLISIONS, 1); 485 } 486#endif 487 if (isr & LE_C0_MISS) { 488#ifdef LEDEBUG 489 if_printf(ifp, "missed packet\n"); 490#endif 491 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 492 } 493 if (isr & LE_C0_MERR) { 494 if_printf(ifp, "memory error\n"); 495 lance_init_locked(sc); 496 LE_UNLOCK(sc); 497 return; 498 } 499 } 500 501 if ((isr & LE_C0_RXON) == 0) { 502 if_printf(ifp, "receiver disabled\n"); 503 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 504 lance_init_locked(sc); 505 LE_UNLOCK(sc); 506 return; 507 } 508 if ((isr & LE_C0_TXON) == 0) { 509 if_printf(ifp, "transmitter disabled\n"); 510 if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); 511 lance_init_locked(sc); 512 LE_UNLOCK(sc); 513 return; 514 } 515 516 /* 517 * Pretend we have carrier; if we don't this will be cleared shortly. 518 */ 519 if (!(sc->sc_flags & LE_CARRIER)) 520 if_link_state_change(ifp, LINK_STATE_UP); 521 sc->sc_flags |= LE_CARRIER; 522 523 if (isr & LE_C0_RINT) 524 am79900_rint(sc); 525 if (isr & LE_C0_TINT) 526 am79900_tint(sc); 527 528 /* Enable interrupts again. */ 529 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA); 530 531 if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) 532 am79900_start_locked(sc); 533 534 LE_UNLOCK(sc); 535} 536 537/* 538 * Set up output on interface. 539 * Get another datagram to send off of the interface queue, and map it to the 540 * interface before starting the output. 541 */ 542static void 543am79900_start_locked(struct lance_softc *sc) 544{ 545 struct ifnet *ifp = sc->sc_ifp; 546 struct letmd tmd; 547 struct mbuf *m; 548 int bix, enq, len, rp; 549 550 LE_LOCK_ASSERT(sc, MA_OWNED); 551 552 if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != 553 IFF_DRV_RUNNING) 554 return; 555 556 bix = sc->sc_last_td; 557 enq = 0; 558 559 for (; sc->sc_no_td < sc->sc_ntbuf && 560 !IFQ_DRV_IS_EMPTY(&ifp->if_snd);) { 561 rp = LE_TMDADDR(sc, bix); 562 (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd)); 563 564 if (LE_LE32TOH(tmd.tmd1) & LE_T1_OWN) { 565 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 566 if_printf(ifp, 567 "missing buffer, no_td = %d, last_td = %d\n", 568 sc->sc_no_td, sc->sc_last_td); 569 } 570 571 IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 572 if (m == NULL) 573 break; 574 575 /* 576 * If BPF is listening on this interface, let it see the packet 577 * before we commit it to the wire. 578 */ 579 BPF_MTAP(ifp, m); 580 581 /* 582 * Copy the mbuf chain into the transmit buffer. 583 */ 584 len = lance_put(sc, LE_TBUFADDR(sc, bix), m); 585 586#ifdef LEDEBUG 587 if (len > ETHERMTU + ETHER_HDR_LEN) 588 if_printf(ifp, "packet length %d\n", len); 589#endif 590 591 /* 592 * Init transmit registers, and set transmit start flag. 593 */ 594 tmd.tmd1 = LE_HTOLE32(LE_T1_OWN | LE_T1_STP | LE_T1_ENP | 595 LE_T1_ONES | (-len & 0xfff)); 596 tmd.tmd2 = 0; 597 tmd.tmd3 = 0; 598 599 (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd)); 600 601#ifdef LEDEBUG 602 if (sc->sc_flags & LE_DEBUG) 603 am79900_xmit_print(sc, bix); 604#endif 605 606 (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD); 607 enq++; 608 609 if (++bix == sc->sc_ntbuf) 610 bix = 0; 611 612 if (++sc->sc_no_td == sc->sc_ntbuf) { 613 ifp->if_drv_flags |= IFF_DRV_OACTIVE; 614 break; 615 } 616 } 617 618 sc->sc_last_td = bix; 619 620 if (enq > 0) 621 sc->sc_wdog_timer = 5; 622} 623 624#ifdef LEDEBUG 625static void 626am79900_recv_print(struct lance_softc *sc, int no) 627{ 628 struct ifnet *ifp = sc->sc_ifp; 629 struct ether_header eh; 630 struct lermd rmd; 631 uint16_t len; 632 633 (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd)); 634 len = LE_LE32TOH(rmd.rmd2) & 0xfff; 635 if_printf(ifp, "receive buffer %d, len = %d\n", no, len); 636 if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); 637 if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(rmd.rmd0), 638 LE_LE32TOH(rmd.rmd1)); 639 if (len - ETHER_CRC_LEN >= sizeof(eh)) { 640 (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh)); 641 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); 642 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 643 ntohs(eh.ether_type)); 644 } 645} 646 647static void 648am79900_xmit_print(struct lance_softc *sc, int no) 649{ 650 struct ifnet *ifp = sc->sc_ifp; 651 struct ether_header eh; 652 struct letmd tmd; 653 uint16_t len; 654 655 (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd)); 656 len = -(LE_LE32TOH(tmd.tmd1) & 0xfff); 657 if_printf(ifp, "transmit buffer %d, len = %d\n", no, len); 658 if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); 659 if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(tmd.tmd0), 660 LE_LE32TOH(tmd.tmd1)); 661 if (len >= sizeof(eh)) { 662 (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh)); 663 if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); 664 printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), 665 ntohs(eh.ether_type)); 666 } 667} 668#endif /* LEDEBUG */ 669