From 89376b7141edb6f927fb940c27391cda6e67c785 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 19 Feb 2009 19:55:40 +0000 Subject: Initial import. --- bsd_eth_drivers/if_le/Makefile.am | 30 ++ bsd_eth_drivers/if_le/am79900.c | 676 ++++++++++++++++++++++++++++ bsd_eth_drivers/if_le/am79900reg.h | 156 +++++++ bsd_eth_drivers/if_le/am79900var.h | 62 +++ bsd_eth_drivers/if_le/am7990reg.h | 189 ++++++++ bsd_eth_drivers/if_le/am7990var.h | 62 +++ bsd_eth_drivers/if_le/if_le_pci.c | 671 ++++++++++++++++++++++++++++ bsd_eth_drivers/if_le/lance.c | 873 +++++++++++++++++++++++++++++++++++++ bsd_eth_drivers/if_le/lancereg.h | 619 ++++++++++++++++++++++++++ bsd_eth_drivers/if_le/lancevar.h | 216 +++++++++ 10 files changed, 3554 insertions(+) create mode 100644 bsd_eth_drivers/if_le/Makefile.am create mode 100644 bsd_eth_drivers/if_le/am79900.c create mode 100644 bsd_eth_drivers/if_le/am79900reg.h create mode 100644 bsd_eth_drivers/if_le/am79900var.h create mode 100644 bsd_eth_drivers/if_le/am7990reg.h create mode 100644 bsd_eth_drivers/if_le/am7990var.h create mode 100644 bsd_eth_drivers/if_le/if_le_pci.c create mode 100644 bsd_eth_drivers/if_le/lance.c create mode 100644 bsd_eth_drivers/if_le/lancereg.h create mode 100644 bsd_eth_drivers/if_le/lancevar.h (limited to 'bsd_eth_drivers/if_le') diff --git a/bsd_eth_drivers/if_le/Makefile.am b/bsd_eth_drivers/if_le/Makefile.am new file mode 100644 index 0000000..5ae69fd --- /dev/null +++ b/bsd_eth_drivers/if_le/Makefile.am @@ -0,0 +1,30 @@ +# $Id$ +AUTOMAKE_OPTIONS=foreign + +include $(top_srcdir)/rtems-pre.am + +libif_le_a_SOURCES = lance.c am79900.c if_le_pci.c + +libif_le_a_SOURCES += am79900reg.h am79900var.h am7990reg.h +libif_le_a_SOURCES += am7990var.h lancereg.h lancevar.h + +lib_LIBRARIES = libif_le.a + + +AM_CPPFLAGS += -I$(srcdir) +AM_CPPFLAGS += -I$(srcdir)/../libbsdport -I../libbsdport -I../libbsdport/dummyheaders +#AM_CPPFLAGS += -DLEDEBUG + +include $(top_srcdir)/rtems.am + +LINKS = +LINKS +=dev/le/lancereg.h +LINKS +=dev/le/lancevar.h +LINKS +=dev/le/am79900reg.h +LINKS +=dev/le/am79900var.h + +BUILT_SOURCES = + +$(libif_le_a_OBJECTS): $(LINKS) + +include ../links.am diff --git a/bsd_eth_drivers/if_le/am79900.c b/bsd_eth_drivers/if_le/am79900.c new file mode 100644 index 0000000..f6d8072 --- /dev/null +++ b/bsd_eth_drivers/if_le/am79900.c @@ -0,0 +1,676 @@ +/* $NetBSD: am79900.c,v 1.17 2005/12/24 20:27:29 perry Exp $ */ + +/*- + * Copyright (c) 1997 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_le.c 8.2 (Berkeley) 11/16/93 + */ + +/*- + * Copyright (c) 1998 + * Matthias Drochner. All rights reserved. + * Copyright (c) 1995 Charles M. Hannum. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_le.c 8.2 (Berkeley) 11/16/93 + */ + +#ifdef __rtems__ +#include +#endif + +#include +__FBSDID("$FreeBSD: src/sys/dev/le/am79900.c,v 1.4 2006/12/06 02:14:31 marius Exp $"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#ifdef __rtems__ +#include +#endif + +static void am79900_meminit(struct lance_softc *); +static void am79900_rint(struct lance_softc *); +static void am79900_tint(struct lance_softc *); +static void am79900_start_locked(struct lance_softc *sc); + +#ifdef LEDEBUG +static void am79900_recv_print(struct lance_softc *, int); +static void am79900_xmit_print(struct lance_softc *, int); +#endif + +int +am79900_config(struct am79900_softc *sc, const char* name, int unit) +{ + int error, mem; + + sc->lsc.sc_meminit = am79900_meminit; + sc->lsc.sc_start_locked = am79900_start_locked; + + error = lance_config(&sc->lsc, name, unit); + if (error != 0) + return (error); + + mem = 0; + sc->lsc.sc_initaddr = mem; + mem += sizeof(struct leinit); + sc->lsc.sc_rmdaddr = mem; + mem += sizeof(struct lermd) * sc->lsc.sc_nrbuf; + sc->lsc.sc_tmdaddr = mem; + mem += sizeof(struct letmd) * sc->lsc.sc_ntbuf; + sc->lsc.sc_rbufaddr = mem; + mem += LEBLEN * sc->lsc.sc_nrbuf; + sc->lsc.sc_tbufaddr = mem; + mem += LEBLEN * sc->lsc.sc_ntbuf; + + if (mem > sc->lsc.sc_memsize) + panic("%s: memsize", __func__); + + lance_attach(&sc->lsc); + + return (0); +} + +void +am79900_detach(struct am79900_softc *sc) +{ + + lance_detach(&sc->lsc); +} + +/* + * Set up the initialization block and the descriptor rings. + */ +static void +am79900_meminit(struct lance_softc *sc) +{ + struct ifnet *ifp = sc->sc_ifp; + struct leinit init; + struct lermd rmd; + struct letmd tmd; + u_long a; + int bix; + + LE_LOCK_ASSERT(sc, MA_OWNED); + + if (ifp->if_flags & IFF_PROMISC) + init.init_mode = LE_HTOLE32(LE_MODE_NORMAL | LE_MODE_PROM); + else + init.init_mode = LE_HTOLE32(LE_MODE_NORMAL); + + init.init_mode |= LE_HTOLE32(((ffs(sc->sc_ntbuf) - 1) << 28) | + ((ffs(sc->sc_nrbuf) - 1) << 20)); + + init.init_padr[0] = LE_HTOLE32(sc->sc_enaddr[0] | + (sc->sc_enaddr[1] << 8) | (sc->sc_enaddr[2] << 16) | + (sc->sc_enaddr[3] << 24)); + init.init_padr[1] = LE_HTOLE32(sc->sc_enaddr[4] | + (sc->sc_enaddr[5] << 8)); + lance_setladrf(sc, init.init_ladrf); + + sc->sc_last_rd = 0; + sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0; + + a = sc->sc_addr + LE_RMDADDR(sc, 0); + init.init_rdra = LE_HTOLE32(a); + + a = sc->sc_addr + LE_TMDADDR(sc, 0); + init.init_tdra = LE_HTOLE32(a); + + (*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init)); + + /* + * Set up receive ring descriptors. + */ + for (bix = 0; bix < sc->sc_nrbuf; bix++) { + a = sc->sc_addr + LE_RBUFADDR(sc, bix); + rmd.rmd0 = LE_HTOLE32(a); + rmd.rmd1 = LE_HTOLE32(LE_R1_OWN | LE_R1_ONES | + (-LEBLEN & 0xfff)); + rmd.rmd2 = 0; + rmd.rmd3 = 0; + (*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix), + sizeof(rmd)); + } + + /* + * Set up transmit ring descriptors. + */ + for (bix = 0; bix < sc->sc_ntbuf; bix++) { + a = sc->sc_addr + LE_TBUFADDR(sc, bix); + tmd.tmd0 = LE_HTOLE32(a); + tmd.tmd1 = LE_HTOLE32(LE_T1_ONES); + tmd.tmd2 = 0; + tmd.tmd3 = 0; + (*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix), + sizeof(tmd)); + } +} + +static inline void +am79900_rint(struct lance_softc *sc) +{ + struct ifnet *ifp = sc->sc_ifp; + struct mbuf *m; + struct lermd rmd; + uint32_t rmd1; + int bix, rp; +#if defined(__i386__) && !defined(PC98) + struct ether_header *eh; +#endif + + bix = sc->sc_last_rd; + + /* Process all buffers with valid data. */ + for (;;) { + rp = LE_RMDADDR(sc, bix); + (*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd)); + + rmd1 = LE_LE32TOH(rmd.rmd1); + if (rmd1 & LE_R1_OWN) + break; + + m = NULL; + if ((rmd1 & (LE_R1_ERR | LE_R1_STP | LE_R1_ENP)) != + (LE_R1_STP | LE_R1_ENP)){ + if (rmd1 & LE_R1_ERR) { +#ifdef LEDEBUG + if (rmd1 & LE_R1_ENP) { + if ((rmd1 & LE_R1_OFLO) == 0) { + if (rmd1 & LE_R1_FRAM) + if_printf(ifp, + "framing error\n"); + if (rmd1 & LE_R1_CRC) + if_printf(ifp, + "crc mismatch\n"); + } + } else + if (rmd1 & LE_R1_OFLO) + if_printf(ifp, "overflow\n"); +#endif + if (rmd1 & LE_R1_BUFF) + if_printf(ifp, + "receive buffer error\n"); + } else if ((rmd1 & (LE_R1_STP | LE_R1_ENP)) != + (LE_R1_STP | LE_R1_ENP)) + if_printf(ifp, "dropping chained buffer\n"); + } else { +#ifdef LEDEBUG + if (sc->sc_flags & LE_DEBUG) + am79900_recv_print(sc, bix); +#endif + /* Pull the packet off the interface. */ + m = lance_get(sc, LE_RBUFADDR(sc, bix), + (LE_LE32TOH(rmd.rmd2) & 0xfff) - ETHER_CRC_LEN); + } + + rmd.rmd1 = LE_HTOLE32(LE_R1_OWN | LE_R1_ONES | + (-LEBLEN & 0xfff)); + rmd.rmd2 = 0; + rmd.rmd3 = 0; + (*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd)); + + if (++bix == sc->sc_nrbuf) + bix = 0; + + if (m != NULL) { + ifp->if_ipackets++; + +#if defined(__i386__) && !defined(PC98) + /* + * The VMware LANCE does not present IFF_SIMPLEX + * behavior on multicast packets. Thus drop the + * packet if it is from ourselves. + */ + eh = mtod(m, struct ether_header *); + if (!ether_cmp(eh->ether_shost, sc->sc_enaddr)) { + m_freem(m); + continue; + } +#endif + + /* Pass the packet up. */ + LE_UNLOCK(sc); +#ifndef __rtems__ + (*ifp->if_input)(ifp, m); +#else + ether_input_skipping(ifp, m); +#endif + LE_LOCK(sc); + } else + ifp->if_ierrors++; + } + + sc->sc_last_rd = bix; +} + +static inline void +am79900_tint(struct lance_softc *sc) +{ + struct ifnet *ifp = sc->sc_ifp; + struct letmd tmd; + uint32_t tmd1, tmd2; + int bix; + + bix = sc->sc_first_td; + + for (;;) { + if (sc->sc_no_td <= 0) + break; + + (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix), + sizeof(tmd)); + + tmd1 = LE_LE32TOH(tmd.tmd1); + +#ifdef LEDEBUG + if (sc->sc_flags & LE_DEBUG) + if_printf(ifp, "trans tmd: " + "adr %08x, flags/blen %08x\n", + LE_LE32TOH(tmd.tmd0), tmd1); +#endif + + if (tmd1 & LE_T1_OWN) + break; + + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + + if (tmd1 & LE_T1_ERR) { + tmd2 = LE_LE32TOH(tmd.tmd2); + if (tmd2 & LE_T2_BUFF) + if_printf(ifp, "transmit buffer error\n"); + else if (tmd2 & LE_T2_UFLO) + if_printf(ifp, "underflow\n"); + if (tmd2 & (LE_T2_BUFF | LE_T2_UFLO)) { + lance_init_locked(sc); + return; + } + if (tmd2 & LE_T2_LCAR) { + if (sc->sc_flags & LE_CARRIER) + if_link_state_change(ifp, + LINK_STATE_DOWN); + sc->sc_flags &= ~LE_CARRIER; + if (sc->sc_nocarrier) + (*sc->sc_nocarrier)(sc); + else + if_printf(ifp, "lost carrier\n"); + } + if (tmd2 & LE_T2_LCOL) + ifp->if_collisions++; + if (tmd2 & LE_T2_RTRY) { +#ifdef LEDEBUG + if_printf(ifp, "excessive collisions\n"); +#endif + ifp->if_collisions += 16; + } + ifp->if_oerrors++; + } else { + if (tmd1 & LE_T1_ONE) + ifp->if_collisions++; + else if (tmd1 & LE_T1_MORE) + /* Real number is unknown. */ + ifp->if_collisions += 2; + ifp->if_opackets++; + } + + if (++bix == sc->sc_ntbuf) + bix = 0; + + --sc->sc_no_td; + } + + sc->sc_first_td = bix; + + sc->sc_wdog_timer = sc->sc_no_td > 0 ? 5 : 0; +} + +/* + * Controller interrupt + */ +void +am79900_intr(void *arg) +{ + struct lance_softc *sc = arg; + struct ifnet *ifp = sc->sc_ifp; + uint16_t isr; + + LE_LOCK(sc); + + if (sc->sc_hwintr && (*sc->sc_hwintr)(sc) == -1) { + ifp->if_ierrors++; + lance_init_locked(sc); + LE_UNLOCK(sc); + return; + } + + isr = (*sc->sc_rdcsr)(sc, LE_CSR0); +#if defined(LEDEBUG) && LEDEBUG > 1 + if (sc->sc_flags & LE_DEBUG) + if_printf(ifp, "%s: entering with isr=%04x\n", __func__, isr); +#endif + if ((isr & LE_C0_INTR) == 0) { + LE_UNLOCK(sc); + return; + } + + /* + * Clear interrupt source flags and turn off interrupts. If we + * don't clear these flags before processing their sources we + * could completely miss some interrupt events as the NIC can + * change these flags while we're in this handler. We turn off + * interrupts so we don't get another RX interrupt while still + * processing the previous one in ifp->if_input() with the + * driver lock dropped. + */ + (*sc->sc_wrcsr)(sc, LE_CSR0, isr & ~(LE_C0_INEA | LE_C0_TDMD | + LE_C0_STOP | LE_C0_STRT | LE_C0_INIT)); + + if (isr & LE_C0_ERR) { + if (isr & LE_C0_BABL) { +#ifdef LEDEBUG + if_printf(ifp, "babble\n"); +#endif + ifp->if_oerrors++; + } +#if 0 + if (isr & LE_C0_CERR) { + if_printf(ifp, "collision error\n"); + ifp->if_collisions++; + } +#endif + if (isr & LE_C0_MISS) { +#ifdef LEDEBUG + if_printf(ifp, "missed packet\n"); +#endif + ifp->if_ierrors++; + } + if (isr & LE_C0_MERR) { + if_printf(ifp, "memory error\n"); + lance_init_locked(sc); + LE_UNLOCK(sc); + return; + } + } + + if ((isr & LE_C0_RXON) == 0) { + if_printf(ifp, "receiver disabled\n"); + ifp->if_ierrors++; + lance_init_locked(sc); + LE_UNLOCK(sc); + return; + } + if ((isr & LE_C0_TXON) == 0) { + if_printf(ifp, "transmitter disabled\n"); + ifp->if_oerrors++; + lance_init_locked(sc); + LE_UNLOCK(sc); + return; + } + + /* + * Pretend we have carrier; if we don't this will be cleared shortly. + */ + if (!(sc->sc_flags & LE_CARRIER)) + if_link_state_change(ifp, LINK_STATE_UP); + sc->sc_flags |= LE_CARRIER; + + if (isr & LE_C0_RINT) + am79900_rint(sc); + if (isr & LE_C0_TINT) + am79900_tint(sc); + + /* Enable interrupts again. */ + (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA); + + if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) + am79900_start_locked(sc); + + LE_UNLOCK(sc); +} + +/* + * Set up output on interface. + * Get another datagram to send off of the interface queue, and map it to the + * interface before starting the output. + */ +static void +am79900_start_locked(struct lance_softc *sc) +{ + struct ifnet *ifp = sc->sc_ifp; + struct letmd tmd; + struct mbuf *m; + int bix, enq, len, rp; + + LE_LOCK_ASSERT(sc, MA_OWNED); + + if ((ifp->if_drv_flags & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) != + IFF_DRV_RUNNING) + return; + + bix = sc->sc_last_td; + enq = 0; + + for (; sc->sc_no_td < sc->sc_ntbuf && + !IFQ_DRV_IS_EMPTY(&ifp->if_snd);) { + rp = LE_TMDADDR(sc, bix); + (*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd)); + + if (LE_LE32TOH(tmd.tmd1) & LE_T1_OWN) { + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + if_printf(ifp, + "missing buffer, no_td = %d, last_td = %d\n", + sc->sc_no_td, sc->sc_last_td); + } + + IFQ_DRV_DEQUEUE(&ifp->if_snd, m); + if (m == 0) + break; + + /* + * If BPF is listening on this interface, let it see the packet + * before we commit it to the wire. + */ + BPF_MTAP(ifp, m); + + /* + * Copy the mbuf chain into the transmit buffer. + */ + len = lance_put(sc, LE_TBUFADDR(sc, bix), m); + +#ifdef LEDEBUG + if (len > ETHERMTU + ETHER_HDR_LEN) + if_printf(ifp, "packet length %d\n", len); +#endif + + /* + * Init transmit registers, and set transmit start flag. + */ + tmd.tmd1 = LE_HTOLE32(LE_T1_OWN | LE_T1_STP | LE_T1_ENP | + LE_T1_ONES | (-len & 0xfff)); + tmd.tmd2 = 0; + tmd.tmd3 = 0; + + (*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd)); + +#ifdef LEDEBUG + if (sc->sc_flags & LE_DEBUG) + am79900_xmit_print(sc, bix); +#endif + + (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_TDMD); + enq++; + + if (++bix == sc->sc_ntbuf) + bix = 0; + + if (++sc->sc_no_td == sc->sc_ntbuf) { + ifp->if_drv_flags |= IFF_DRV_OACTIVE; + break; + } + } + + sc->sc_last_td = bix; + + if (enq > 0) + sc->sc_wdog_timer = 5; +} + +#ifdef LEDEBUG +static void +am79900_recv_print(struct lance_softc *sc, int no) +{ + struct ifnet *ifp = sc->sc_ifp; + struct ether_header eh; + struct lermd rmd; + uint16_t len; + + (*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd)); + len = LE_LE32TOH(rmd.rmd2) & 0xfff; + if_printf(ifp, "receive buffer %d, len = %d\n", no, len); + if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); + if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(rmd.rmd0), + LE_LE32TOH(rmd.rmd1)); + if (len - ETHER_CRC_LEN >= sizeof(eh)) { + (*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh)); + if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); + printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), + ntohs(eh.ether_type)); + } +} + +static void +am79900_xmit_print(struct lance_softc *sc, int no) +{ + struct ifnet *ifp = sc->sc_ifp; + struct ether_header eh; + struct letmd tmd; + uint16_t len; + + (*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd)); + len = -(LE_LE32TOH(tmd.tmd1) & 0xfff); + if_printf(ifp, "transmit buffer %d, len = %d\n", no, len); + if_printf(ifp, "status %04x\n", (*sc->sc_rdcsr)(sc, LE_CSR0)); + if_printf(ifp, "adr %08x, flags/blen %08x\n", LE_LE32TOH(tmd.tmd0), + LE_LE32TOH(tmd.tmd1)); + if (len >= sizeof(eh)) { + (*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh)); + if_printf(ifp, "dst %s", ether_sprintf(eh.ether_dhost)); + printf(" src %s type %04x\n", ether_sprintf(eh.ether_shost), + ntohs(eh.ether_type)); + } +} +#endif /* LEDEBUG */ diff --git a/bsd_eth_drivers/if_le/am79900reg.h b/bsd_eth_drivers/if_le/am79900reg.h new file mode 100644 index 0000000..1edc0ee --- /dev/null +++ b/bsd_eth_drivers/if_le/am79900reg.h @@ -0,0 +1,156 @@ +/* $NetBSD: am79900reg.h,v 1.8 2005/12/11 12:21:25 christos Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_lereg.h 8.1 (Berkeley) 6/10/93 + */ + +/* $FreeBSD: src/sys/dev/le/am79900reg.h,v 1.1 2006/01/31 14:48:58 marius Exp $ */ + +#ifndef _DEV_LE_AM79900REG_H_ +#define _DEV_LE_AM79900REG_H_ + +/* + * Receive message descriptor + */ +struct lermd { + uint32_t rmd0; + uint32_t rmd1; + uint32_t rmd2; + int32_t rmd3; +}; + +/* + * Transmit message descriptor + */ +struct letmd { + uint32_t tmd0; + uint32_t tmd1; + uint32_t tmd2; + int32_t tmd3; +}; + +/* + * Initialization block + */ +struct leinit { + uint32_t init_mode; /* +0x0000 */ + uint32_t init_padr[2]; /* +0x0002 */ + uint16_t init_ladrf[4]; /* +0x0008 */ + uint32_t init_rdra; /* +0x0010 */ + uint32_t init_tdra; /* +0x0014 */ + int32_t pad; /* Pad to 8 ints. */ +}; + +/* Receive message descriptor 1 (rmd1_bits) */ +#define LE_R1_OWN (1U << 31) /* LANCE owns the packet */ +#define LE_R1_ERR (1U << 30) /* error summary */ +#define LE_R1_FRAM (1U << 29) /* framing error */ +#define LE_R1_OFLO (1U << 28) /* overflow error */ +#define LE_R1_CRC (1U << 27) /* CRC error */ +#define LE_R1_BUFF (1U << 26) /* buffer error */ +#define LE_R1_STP (1U << 25) /* start of packet */ +#define LE_R1_ENP (1U << 24) /* end of packet */ +#define LE_R1_ONES (0xfU << 12) /* must be ones */ +#define LE_R1_BCNT_MASK (0xfff) /* byte count mask */ + +#define LE_R1_BITS \ + "\20\40OWN\37ERR\36FRAM\35OFLO\34CRC\33BUFF\32STP\31ENP" + +/* Transmit message descriptor 1 (tmd1_bits) */ +#define LE_T1_OWN (1U << 31) /* LANCE owns the packet */ +#define LE_T1_ERR (1U << 30) /* error summary */ +#define LE_T1_ADD_FCS (1U << 29) /* add FCS (PCnet-PCI) */ +#define LE_T1_NO_FCS (1U << 29) /* no FCS (ILACC) */ +#define LE_T1_MORE (1U << 28) /* multiple collisions */ +#define LE_T1_LTINT (1U << 28) /* transmit interrupt (if LTINTEN) */ +#define LE_T1_ONE (1U << 27) /* single collision */ +#define LE_T1_DEF (1U << 26) /* deferred transmit */ +#define LE_T1_STP (1U << 25) /* start of packet */ +#define LE_T1_ENP (1U << 24) /* end of packet */ +#define LE_T1_ONES (0xfU << 12) /* must be ones */ +#define LE_T1_BCNT_MASK (0xfff) /* byte count mask */ + +#define LE_T1_BITS \ + "\20\40OWN\37ERR\36RES\35MORE\34ONE\33DEF\32STP\31ENP" + +/* Transmit message descriptor 3 (tmd3) */ +#define LE_T2_BUFF (1U << 31) /* buffer error */ +#define LE_T2_UFLO (1U << 30) /* underflow error */ +#define LE_T2_EXDEF (1U << 29) /* excessive defferral */ +#define LE_T2_LCOL (1U << 28) /* late collision */ +#define LE_T2_LCAR (1U << 27) /* loss of carrier */ +#define LE_T2_RTRY (1U << 26) /* retry error */ +#if 0 +#define LE_T3_TDR_MASK 0x03ff /* time domain reflectometry counter */ +#endif + +#define LE_T3_BITS \ + "\12\40BUFF\37UFLO\35LCOL\34LCAR\33RTRY" + +#endif /* !_DEV_LE_AM7990REG_H_ */ diff --git a/bsd_eth_drivers/if_le/am79900var.h b/bsd_eth_drivers/if_le/am79900var.h new file mode 100644 index 0000000..848d290 --- /dev/null +++ b/bsd_eth_drivers/if_le/am79900var.h @@ -0,0 +1,62 @@ +/* $NetBSD: am79900var.h,v 1.4 2005/12/11 12:21:25 christos Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace + * Simulation Facility, NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* $FreeBSD: src/sys/dev/le/am79900var.h,v 1.1 2006/01/31 14:48:58 marius Exp $ */ + +#ifndef _DEV_LE_AM79900VAR_H_ +#define _DEV_LE_AM79900VAR_H_ + +/* + * Ethernet software status per device. + * + * NOTE: this structure MUST be the first element in machine-dependent + * le_softc structures! This is designed SPECIFICALLY to make it possible + * to simply cast a "void *" to "struct le_softc *" or to + * "struct am79900_softc *". Among other things, this saves a lot of hair + * in the interrupt handlers. + */ +struct am79900_softc { + struct lance_softc lsc; +}; + +int am79900_config(struct am79900_softc *, const char*, int); +void am79900_detach(struct am79900_softc *); +void am79900_intr(void *); + +#endif /* _DEV_LE_AM79900VAR_H_ */ diff --git a/bsd_eth_drivers/if_le/am7990reg.h b/bsd_eth_drivers/if_le/am7990reg.h new file mode 100644 index 0000000..2005e0f --- /dev/null +++ b/bsd_eth_drivers/if_le/am7990reg.h @@ -0,0 +1,189 @@ +/* $NetBSD: am7990reg.h,v 1.11 2005/12/11 12:21:25 christos Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_lereg.h 8.1 (Berkeley) 6/10/93 + */ + +/* $FreeBSD: src/sys/dev/le/am7990reg.h,v 1.1 2006/01/31 14:48:58 marius Exp $ */ + +#ifndef _DEV_LE_AM7990REG_H_ +#define _DEV_LE_AM7990REG_H_ + +/* + * Receive message descriptor + */ +struct lermd { + uint16_t rmd0; +#if BYTE_ORDER == BIG_ENDIAN + uint8_t rmd1_bits; + uint8_t rmd1_hadr; +#else + uint8_t rmd1_hadr; + uint8_t rmd1_bits; +#endif + int16_t rmd2; + uint16_t rmd3; +} __packed; + +/* + * Transmit message descriptor + */ +struct letmd { + uint16_t tmd0; +#if BYTE_ORDER == BIG_ENDIAN + uint8_t tmd1_bits; + uint8_t tmd1_hadr; +#else + uint8_t tmd1_hadr; + uint8_t tmd1_bits; +#endif + int16_t tmd2; + uint16_t tmd3; +} __packed; + +/* + * Initialization block + */ +struct leinit { + uint16_t init_mode; /* +0x0000 */ + uint16_t init_padr[3]; /* +0x0002 */ + uint16_t init_ladrf[4]; /* +0x0008 */ + uint16_t init_rdra; /* +0x0010 */ + uint16_t init_rlen; /* +0x0012 */ + uint16_t init_tdra; /* +0x0014 */ + uint16_t init_tlen; /* +0x0016 */ + int16_t pad0[4]; /* Pad to 16 shorts. */ +} __packed; + +/* Receive message descriptor 1 (rmd1_bits) */ +#define LE_R1_OWN 0x80 /* LANCE owns the packet */ +#define LE_R1_ERR 0x40 /* error summary */ +#define LE_R1_FRAM 0x20 /* framing error */ +#define LE_R1_OFLO 0x10 /* overflow error */ +#define LE_R1_CRC 0x08 /* CRC error */ +#define LE_R1_BUFF 0x04 /* buffer error */ +#define LE_R1_STP 0x02 /* start of packet */ +#define LE_R1_ENP 0x01 /* end of packet */ + +#define LE_R1_BITS \ + "\20\10OWN\7ERR\6FRAM\5OFLO\4CRC\3BUFF\2STP\1ENP" + +/* Transmit message descriptor 1 (tmd1_bits) */ +#define LE_T1_OWN 0x80 /* LANCE owns the packet */ +#define LE_T1_ERR 0x40 /* error summary */ +#define LE_T1_MORE 0x10 /* multiple collisions */ +#define LE_T1_ONE 0x08 /* single collision */ +#define LE_T1_DEF 0x04 /* deferred transmit */ +#define LE_T1_STP 0x02 /* start of packet */ +#define LE_T1_ENP 0x01 /* end of packet */ + +#define LE_T1_BITS \ + "\20\10OWN\7ERR\6RES\5MORE\4ONE\3DEF\2STP\1ENP" + +/* Transmit message descriptor 3 (tmd3) */ +#define LE_T3_BUFF 0x8000 /* buffer error */ +#define LE_T3_UFLO 0x4000 /* underflow error */ +#define LE_T3_LCOL 0x1000 /* late collision */ +#define LE_T3_LCAR 0x0800 /* loss of carrier */ +#define LE_T3_RTRY 0x0400 /* retry error */ +#define LE_T3_TDR_MASK 0x03ff /* time domain reflectometry counter */ + +#define LE_XMD2_ONES 0xf000 + +#define LE_T3_BITS \ + "\20\20BUFF\17UFLO\16RES\15LCOL\14LCAR\13RTRY" + +/* + * PCnet-ISA defines which are not available on LANCE 7990. + */ + +/* (ISA) Bus Configuration Registers */ +#define LE_BCR_MSRDA 0x0000 +#define LE_BCR_MSWRA 0x0001 +#define LE_BCR_MC 0x0002 +#define LE_BCR_LED1 0x0005 +#define LE_BCR_LED2 0x0006 +#define LE_BCR_LED3 0x0007 + +/* Bus configurations bits (MC) */ +#define LE_MC_EADISEL 0x0008 /* EADI selection */ +#define LE_MC_AWAKE 0x0004 /* auto-wake */ +#define LE_MC_ASEL 0x0002 /* auto selection */ +#define LE_MC_XMAUSEL 0x0001 /* external MAU selection */ + +/* LED bis (LED[123]) */ +#define LE_LED_LEDOUT 0x8000 +#define LE_LED_PSE 0x0080 +#define LE_LED_XMTE 0x0010 +#define LE_LED_PVPE 0x0008 +#define LE_LED_PCVE 0x0004 +#define LE_LED_JABE 0x0002 +#define LE_LED_COLE 0x0001 + +#endif /* !_DEV_LE_AM7990REG_H_ */ diff --git a/bsd_eth_drivers/if_le/am7990var.h b/bsd_eth_drivers/if_le/am7990var.h new file mode 100644 index 0000000..0cc5397 --- /dev/null +++ b/bsd_eth_drivers/if_le/am7990var.h @@ -0,0 +1,62 @@ +/* $NetBSD: am7990var.h,v 1.23 2005/12/11 12:21:25 christos Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace + * Simulation Facility, NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* $FreeBSD: src/sys/dev/le/am7990var.h,v 1.1 2006/01/31 14:48:58 marius Exp $ */ + +#ifndef _DEV_LE_AM7990VAR_H_ +#define _DEV_LE_AM7990VAR_H_ + +/* + * Ethernet software status per device. + * + * NOTE: this structure MUST be the first element in machine-dependent + * le_softc structures! This is designed SPECIFICALLY to make it possible + * to simply cast a "void *" to "struct le_softc *" or to + * "struct am7990_softc *". Among other things, this saves a lot of hair + * in the interrupt handlers. + */ +struct am7990_softc { + struct lance_softc lsc; +}; + +int am7990_config(struct am7990_softc *, const char*, int); +void am7990_detach(struct am7990_softc *); +void am7990_intr(void *); + +#endif /* !_DEV_LE_AM7990VAR_H_ */ diff --git a/bsd_eth_drivers/if_le/if_le_pci.c b/bsd_eth_drivers/if_le/if_le_pci.c new file mode 100644 index 0000000..870ddb8 --- /dev/null +++ b/bsd_eth_drivers/if_le/if_le_pci.c @@ -0,0 +1,671 @@ +/* $NetBSD: if_le_pci.c,v 1.43 2005/12/11 12:22:49 christos Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace + * Simulation Facility, NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_le.c 8.2 (Berkeley) 11/16/93 + */ +#ifdef __rtems__ +#include +#endif + +#include +__FBSDID("$FreeBSD: src/sys/dev/le/if_le_pci.c,v 1.7 2007/02/23 12:18:45 piso Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#ifdef __rtems__ +#include /* for memory size calculation */ +#include +#endif + +#define AMD_VENDOR 0x1022 +#define AMD_PCNET_PCI 0x2000 +#define AMD_PCNET_HOME 0x2001 +#define PCNET_MEMSIZE (32*1024) +#define PCNET_PCI_RDP 0x10 +#define PCNET_PCI_RAP 0x12 +#define PCNET_PCI_BDP 0x16 + +struct le_pci_softc { + struct am79900_softc sc_am79900; /* glue to MI code */ + + int sc_rrid; + struct resource *sc_rres; + bus_space_tag_t sc_regt; + bus_space_handle_t sc_regh; + + int sc_irid; + struct resource *sc_ires; + void *sc_ih; + + bus_dma_tag_t sc_pdmat; + bus_dma_tag_t sc_dmat; + bus_dmamap_t sc_dmam; +}; + +device_probe_t le_pci_probe; +device_attach_t le_pci_attach; +static device_detach_t le_pci_detach; +#ifndef __rtems__ +static device_resume_t le_pci_resume; +static device_suspend_t le_pci_suspend; + +static device_method_t le_pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, le_pci_probe), + DEVMETHOD(device_attach, le_pci_attach), + DEVMETHOD(device_detach, le_pci_detach), + /* We can just use the suspend method here. */ + DEVMETHOD(device_shutdown, le_pci_suspend), + DEVMETHOD(device_suspend, le_pci_suspend), + DEVMETHOD(device_resume, le_pci_resume), + + { 0, 0 } +}; + +DEFINE_CLASS_0(le, le_pci_driver, le_pci_methods, sizeof(struct le_pci_softc)); +DRIVER_MODULE(le, pci, le_pci_driver, le_devclass, 0, 0); +MODULE_DEPEND(le, ether, 1, 1, 1); + +#else +static int +le_pci_irq_check_dis(device_t d); + +static void +le_pci_irq_en(device_t d); + +static device_method_t le_pci_methods = { + probe: le_pci_probe, + attach: le_pci_attach, + shutdown: 0, + detach: le_pci_detach, + irq_check_dis: le_pci_irq_check_dis, + irq_en: le_pci_irq_en, +}; + +driver_t libbsdport_le_pci_driver = { + "le", + &le_pci_methods, + DEV_TYPE_PCI, + sizeof(struct le_pci_softc) +}; + +#endif + +static const int le_home_supmedia[] = { + IFM_MAKEWORD(IFM_ETHER, IFM_HPNA_1, 0, 0) +}; + +static const int le_pci_supmedia[] = { + IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0), + IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, IFM_FDX, 0), + IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0), + IFM_MAKEWORD(IFM_ETHER, IFM_10_T, IFM_FDX, 0), + IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, 0), + IFM_MAKEWORD(IFM_ETHER, IFM_10_5, IFM_FDX, 0) +}; + + +static void le_pci_wrbcr(struct lance_softc *, uint16_t, uint16_t); +static uint16_t le_pci_rdbcr(struct lance_softc *, uint16_t); +static void le_pci_wrcsr(struct lance_softc *, uint16_t, uint16_t); +static uint16_t le_pci_rdcsr(struct lance_softc *, uint16_t); +static int le_pci_mediachange(struct lance_softc *); +static void le_pci_hwreset(struct lance_softc *); +static bus_dmamap_callback_t le_pci_dma_callback; + +static void +le_pci_wrbcr(struct lance_softc *sc, uint16_t port, uint16_t val) +{ + struct le_pci_softc *lesc = (struct le_pci_softc *)sc; + + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port); + bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2, + BUS_SPACE_BARRIER_WRITE); + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_BDP, val); +} + +static uint16_t +le_pci_rdbcr(struct lance_softc *sc, uint16_t port) +{ + struct le_pci_softc *lesc = (struct le_pci_softc *)sc; + + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port); + bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2, + BUS_SPACE_BARRIER_WRITE); + return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_BDP)); +} + +static void +le_pci_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val) +{ + struct le_pci_softc *lesc = (struct le_pci_softc *)sc; + + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port); + bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2, + BUS_SPACE_BARRIER_WRITE); + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RDP, val); +} + +static uint16_t +le_pci_rdcsr(struct lance_softc *sc, uint16_t port) +{ + struct le_pci_softc *lesc = (struct le_pci_softc *)sc; + + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, port); + bus_space_barrier(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, 2, + BUS_SPACE_BARRIER_WRITE); + return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RDP)); +} + +static int +le_pci_mediachange(struct lance_softc *sc) +{ + struct ifmedia *ifm = &sc->sc_media; + uint16_t reg; + + if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) + return (EINVAL); + + if (IFM_SUBTYPE(ifm->ifm_media) == IFM_HPNA_1) + le_pci_wrbcr(sc, LE_BCR49, + (le_pci_rdbcr(sc, LE_BCR49) & ~LE_B49_PHYSEL) | 0x1); + else if (IFM_SUBTYPE(ifm->ifm_media) == IFM_AUTO) + le_pci_wrbcr(sc, LE_BCR2, + le_pci_rdbcr(sc, LE_BCR2) | LE_B2_ASEL); + else { + le_pci_wrbcr(sc, LE_BCR2, + le_pci_rdbcr(sc, LE_BCR2) & ~LE_B2_ASEL); + + reg = le_pci_rdcsr(sc, LE_CSR15); + reg &= ~LE_C15_PORTSEL(LE_PORTSEL_MASK); + if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_T) + reg |= LE_C15_PORTSEL(LE_PORTSEL_10T); + else + reg |= LE_C15_PORTSEL(LE_PORTSEL_AUI); + le_pci_wrcsr(sc, LE_CSR15, reg); + } + + reg = le_pci_rdbcr(sc, LE_BCR9); + if (IFM_OPTIONS(ifm->ifm_media) & IFM_FDX) { + reg |= LE_B9_FDEN; + /* + * Allow FDX on AUI only if explicitly chosen, + * not in autoselect mode. + */ + if (IFM_SUBTYPE(ifm->ifm_media) == IFM_10_5) + reg |= LE_B9_AUIFD; + else + reg &= ~LE_B9_AUIFD; + } else + reg &= ~LE_B9_FDEN; + le_pci_wrbcr(sc, LE_BCR9, reg); + + return (0); +} + +static void +le_pci_hwreset(struct lance_softc *sc) +{ + + /* + * Chip is stopped. Set software style to PCnet-PCI (32-bit). + * Actually, am79900.c implements ILACC support (hence its + * name) but unfortunately VMware does not. As far as this + * driver is concerned that should not make a difference + * though, as the settings used have the same meaning for + * both, ILACC and PCnet-PCI (note that there would be a + * difference for the ADD_FCS/NO_FCS bit if used). + */ + le_pci_wrbcr(sc, LE_BCR20, LE_B20_SSTYLE_PCNETPCI2); +} + +static void +le_pci_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error) +{ + struct lance_softc *sc = (struct lance_softc *)xsc; + + if (error != 0) + return; + KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__)); + sc->sc_addr = segs[0].ds_addr; +} + +int +le_pci_probe(device_t dev) +{ + + if (pci_get_vendor(dev) != AMD_VENDOR) + return (ENXIO); + + switch (pci_get_device(dev)) { + case AMD_PCNET_PCI: + device_set_desc(dev, "AMD PCnet-PCI"); + /* Let pcn(4) win. */ + return (BUS_PROBE_LOW_PRIORITY); + case AMD_PCNET_HOME: + device_set_desc(dev, "AMD PCnet-Home"); + /* Let pcn(4) win. */ + return (BUS_PROBE_LOW_PRIORITY); + default: + return (ENXIO); + } +} + +int +le_pci_attach(device_t dev) +{ + struct le_pci_softc *lesc; + struct lance_softc *sc; + int error, i; + + lesc = device_get_softc(dev); + sc = &lesc->sc_am79900.lsc; + + LE_LOCK_INIT(sc, device_get_nameunit(dev)); + + pci_enable_busmaster(dev); + pci_enable_io(dev, PCIM_CMD_PORTEN); + + lesc->sc_rrid = PCIR_BAR(0); + lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_IOPORT, + &lesc->sc_rrid, RF_ACTIVE); + if (lesc->sc_rres == NULL) { + device_printf(dev, "cannot allocate registers\n"); + error = ENXIO; + goto fail_mtx; + } + lesc->sc_regt = rman_get_bustag(lesc->sc_rres); + lesc->sc_regh = rman_get_bushandle(lesc->sc_rres); + + lesc->sc_irid = 0; + if ((lesc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, + &lesc->sc_irid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { + device_printf(dev, "cannot allocate interrupt\n"); + error = ENXIO; + goto fail_rres; + } + + error = bus_dma_tag_create( + bus_get_dma_tag(dev), /* parent */ + 1, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + BUS_SPACE_MAXSIZE_32BIT, /* maxsize */ + 0, /* nsegments */ + BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &lesc->sc_pdmat); + if (error != 0) { + device_printf(dev, "cannot allocate parent DMA tag\n"); + goto fail_ires; + } + + sc->sc_memsize = PCNET_MEMSIZE; + +#ifdef __rtems__ + { + int nbuf = 0; + /* Override ring sizes */ + if ( dev->ifconfig ) { + nbuf += (sc->sc_nrbuf = dev->ifconfig->rbuf_count); + nbuf += (sc->sc_ntbuf = dev->ifconfig->xbuf_count); + } + if ( nbuf ) { + /* at least one of them is set */ + if ( !sc->sc_ntbuf ) { + sc->sc_ntbuf = nbuf/4; /* default proportions as in lance.c */ + /* need at least one */ + if ( !sc->sc_ntbuf ) + sc->sc_ntbuf = 1; + } + if ( !sc->sc_nrbuf ) + sc->sc_nrbuf = nbuf*4; /* default proportions as in lance.c */ + /* It seems the driver assumes ring sizes to be powers of two; + * (look for ffs()-1). + * So we give them what they want. + */ + /* both, nrbuf / ntbuf are > 0 at this point */ + for ( nbuf = 1; nbuf < sc->sc_nrbuf; nbuf<<=1 ) + /* nothing else to do*/; + sc->sc_nrbuf = nbuf; + for ( nbuf = 1; nbuf < sc->sc_ntbuf; nbuf<<=1 ) + /* nothing else to do*/; + sc->sc_ntbuf = nbuf; + + nbuf = sc->sc_ntbuf + sc->sc_nrbuf; + + /* now override memory size; still need to override + * individual ring sizes in 'lance.c' :-( + */ + sc->sc_memsize = nbuf * (LEBLEN + sizeof(struct lermd) + sizeof(struct letmd)) ; + sc->sc_memsize+= sizeof(struct leinit); + } + } +#endif + /* + * For Am79C970A, Am79C971 and Am79C978 the init block must be 2-byte + * aligned and the ring descriptors must be 16-byte aligned when using + * a 32-bit software style. + */ + error = bus_dma_tag_create( + lesc->sc_pdmat, /* parent */ + 16, 0, /* alignment, boundary */ + BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + sc->sc_memsize, /* maxsize */ + 1, /* nsegments */ + sc->sc_memsize, /* maxsegsize */ + 0, /* flags */ + NULL, NULL, /* lockfunc, lockarg */ + &lesc->sc_dmat); + if (error != 0) { + device_printf(dev, "cannot allocate buffer DMA tag\n"); + goto fail_pdtag; + } + + error = bus_dmamem_alloc(lesc->sc_dmat, (void **)&sc->sc_mem, + BUS_DMA_WAITOK | BUS_DMA_COHERENT, &lesc->sc_dmam); + if (error != 0) { + device_printf(dev, "cannot allocate DMA buffer memory\n"); + goto fail_dtag; + } + + sc->sc_addr = 0; + error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem, + sc->sc_memsize, le_pci_dma_callback, sc, 0); + if (error != 0 || sc->sc_addr == 0) { + device_printf(dev, "cannot load DMA buffer map\n"); + goto fail_dmem; + } + + sc->sc_flags = LE_BSWAP; + sc->sc_conf3 = 0; + + sc->sc_mediastatus = NULL; + switch (pci_get_device(dev)) { + case AMD_PCNET_HOME: + sc->sc_mediachange = le_pci_mediachange; + sc->sc_supmedia = le_home_supmedia; + sc->sc_nsupmedia = sizeof(le_home_supmedia) / sizeof(int); + sc->sc_defaultmedia = le_home_supmedia[0]; + break; + default: + sc->sc_mediachange = le_pci_mediachange; + sc->sc_supmedia = le_pci_supmedia; + sc->sc_nsupmedia = sizeof(le_pci_supmedia) / sizeof(int); + sc->sc_defaultmedia = le_pci_supmedia[0]; + } + + /* + * Extract the physical MAC address from the ROM. + */ + for (i = 0; i < sizeof(sc->sc_enaddr); i++) + sc->sc_enaddr[i] = + bus_space_read_1(lesc->sc_regt, lesc->sc_regh, i); + + sc->sc_copytodesc = lance_copytobuf_contig; + sc->sc_copyfromdesc = lance_copyfrombuf_contig; + sc->sc_copytobuf = lance_copytobuf_contig; + sc->sc_copyfrombuf = lance_copyfrombuf_contig; + sc->sc_zerobuf = lance_zerobuf_contig; + + sc->sc_rdcsr = le_pci_rdcsr; + sc->sc_wrcsr = le_pci_wrcsr; + sc->sc_hwreset = le_pci_hwreset; + sc->sc_hwinit = NULL; + sc->sc_hwintr = NULL; + sc->sc_nocarrier = NULL; + + error = am79900_config(&lesc->sc_am79900, device_get_name(dev), + device_get_unit(dev)); + if (error != 0) { + device_printf(dev, "cannot attach Am79900\n"); + goto fail_dmap; + } + + error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE, + NULL, am79900_intr, sc, &lesc->sc_ih); + if (error != 0) { + device_printf(dev, "cannot set up interrupt\n"); + goto fail_am79900; + } + + return (0); + + fail_am79900: + am79900_detach(&lesc->sc_am79900); + fail_dmap: + bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); + fail_dmem: + bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); + fail_dtag: + bus_dma_tag_destroy(lesc->sc_dmat); + fail_pdtag: + bus_dma_tag_destroy(lesc->sc_pdmat); + fail_ires: + bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); + fail_rres: + bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres); + fail_mtx: + LE_LOCK_DESTROY(sc); + return (error); +} + +static int +le_pci_detach(device_t dev) +{ + struct le_pci_softc *lesc; + struct lance_softc *sc; + + lesc = device_get_softc(dev); + sc = &lesc->sc_am79900.lsc; + + bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih); + am79900_detach(&lesc->sc_am79900); + bus_dmamap_unload(lesc->sc_dmat, lesc->sc_dmam); + bus_dmamem_free(lesc->sc_dmat, sc->sc_mem, lesc->sc_dmam); + bus_dma_tag_destroy(lesc->sc_dmat); + bus_dma_tag_destroy(lesc->sc_pdmat); + bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires); + bus_release_resource(dev, SYS_RES_IOPORT, lesc->sc_rrid, lesc->sc_rres); + LE_LOCK_DESTROY(sc); + + return (0); +} + +#ifndef __rtems__ +static int +le_pci_suspend(device_t dev) +{ + struct le_pci_softc *lesc; + + lesc = device_get_softc(dev); + + lance_suspend(&lesc->sc_am79900.lsc); + + return (0); +} + +static int +le_pci_resume(device_t dev) +{ + struct le_pci_softc *lesc; + + lesc = device_get_softc(dev); + + lance_resume(&lesc->sc_am79900.lsc); + + return (0); +} +#else +static int +le_pci_irq_check_dis(device_t d) +{ +struct le_pci_softc *lesc = device_get_softc(d); +/* This can be called from IRQ context -- since all register accesses + * involve RAP we must take care to preserve it across this routine! + */ +u_int16_t rap = bus_space_read_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP); +u_int16_t csr; +int rval; + + csr = le_pci_rdcsr(&lesc->sc_am79900.lsc, LE_CSR0); + if ( LE_C0_INTR & csr ) { + /* must not write 1 to any bit as this might clear things */ + le_pci_wrcsr(&lesc->sc_am79900.lsc, LE_CSR0, LE_C0_INEA & ~(LE_C0_INEA)); + rval = FILTER_HANDLED; + } else { + rval = FILTER_STRAY; + } + /* restore RAP */ + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, rap); + return rval; +} + +static void +le_pci_irq_en(device_t d) +{ +struct le_pci_softc *lesc = device_get_softc(d); +/* This can be called from IRQ context -- since all register accesses + * involve RAP we must take care to preserve it across this routine! + */ +u_int16_t rap = bus_space_read_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP); + /* do NOT |= INTEN because writing 1es in the wrong place may clear flags */ + le_pci_wrcsr(&lesc->sc_am79900.lsc, LE_CSR0, LE_C0_INEA); + /* restore RAP */ + bus_space_write_2(lesc->sc_regt, lesc->sc_regh, PCNET_PCI_RAP, rap); +} + +u_int32_t +le_pci_read_csr(device_t d, int off) +{ +u_int32_t rval; + rtems_bsdnet_semaphore_obtain(); + rval = le_pci_rdcsr(device_get_softc(d), off); + rtems_bsdnet_semaphore_release(); + return rval; +} + +void +le_pci_write_csr(device_t d, int off, u_int16_t v) +{ + rtems_bsdnet_semaphore_obtain(); + le_pci_wrcsr(device_get_softc(d), off, v); + rtems_bsdnet_semaphore_release(); +} + + +u_int32_t +le_pci_read_bcr(device_t d, int off) +{ +u_int32_t rval; + rtems_bsdnet_semaphore_obtain(); + rval = le_pci_rdbcr(device_get_softc(d), off); + rtems_bsdnet_semaphore_release(); + return rval; +} + +void +le_pci_write_bcr(device_t d, int off, u_int16_t v) +{ + rtems_bsdnet_semaphore_obtain(); + le_pci_wrbcr(device_get_softc(d), off, v); + rtems_bsdnet_semaphore_release(); +} + + +#endif diff --git a/bsd_eth_drivers/if_le/lance.c b/bsd_eth_drivers/if_le/lance.c new file mode 100644 index 0000000..24a3713 --- /dev/null +++ b/bsd_eth_drivers/if_le/lance.c @@ -0,0 +1,873 @@ +/* $NetBSD: lance.c,v 1.34 2005/12/24 20:27:30 perry Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace + * Simulation Facility, NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_le.c 8.2 (Berkeley) 11/16/93 + */ + +#ifdef __rtems__ +#include +#include +#endif + +#include +__FBSDID("$FreeBSD: src/sys/dev/le/lance.c,v 1.4 2007/01/20 10:47:16 marius Exp $"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#ifdef __rtems__ +#include +#endif + +devclass_t le_devclass; + +static void lance_start(struct ifnet *); +static void lance_stop(struct lance_softc *); +static void lance_init(void *); +static void lance_watchdog(void *s); +static int lance_mediachange(struct ifnet *); +static void lance_mediastatus(struct ifnet *, struct ifmediareq *); +#ifndef __rtems__ +static int lance_ioctl(struct ifnet *, u_long, caddr_t); +#else +static int lance_ioctl(struct ifnet *, ioctl_command_t, caddr_t); +#endif + +int +lance_config(struct lance_softc *sc, const char* name, int unit) +{ + struct ifnet *ifp; + int i, nbuf; + + if (LE_LOCK_INITIALIZED(sc) == 0) + return (ENXIO); + + ifp = sc->sc_ifp = if_alloc(IFT_ETHER); + if (ifp == NULL) + return (ENOSPC); + + callout_init_mtx(&sc->sc_wdog_ch, &sc->sc_mtx, 0); + + /* Initialize ifnet structure. */ + ifp->if_softc = sc; + if_initname(ifp, name, unit); + ifp->if_start = lance_start; + ifp->if_ioctl = lance_ioctl; + ifp->if_init = lance_init; + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; +#ifdef LANCE_REVC_BUG + ifp->if_flags &= ~IFF_MULTICAST; +#endif + ifp->if_baudrate = IF_Mbps(10); + IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN); + ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN; + IFQ_SET_READY(&ifp->if_snd); + + /* Initialize ifmedia structures. */ + ifmedia_init(&sc->sc_media, 0, lance_mediachange, lance_mediastatus); + if (sc->sc_supmedia != NULL) { + for (i = 0; i < sc->sc_nsupmedia; i++) + ifmedia_add(&sc->sc_media, sc->sc_supmedia[i], 0, NULL); + ifmedia_set(&sc->sc_media, sc->sc_defaultmedia); + } else { + ifmedia_add(&sc->sc_media, + IFM_MAKEWORD(IFM_ETHER, IFM_MANUAL, 0, 0), 0, NULL); + ifmedia_set(&sc->sc_media, + IFM_MAKEWORD(IFM_ETHER, IFM_MANUAL, 0, 0)); + } +#ifdef __rtems__ + assert( (sc->sc_nrbuf == 0) == (sc->sc_ntbuf == 0) ); + assert( sc->sc_memsize >= (sc->sc_nrbuf + sc->sc_ntbuf)*LEBLEN); + /* Only set ring sizes if not defined yet */ + if ( sc->sc_nrbuf == 0 ) +#endif + + switch (sc->sc_memsize) { + case 8192: + sc->sc_nrbuf = 4; + sc->sc_ntbuf = 1; + break; + case 16384: + sc->sc_nrbuf = 8; + sc->sc_ntbuf = 2; + break; + case 32768: + sc->sc_nrbuf = 16; + sc->sc_ntbuf = 4; + break; + case 65536: + sc->sc_nrbuf = 32; + sc->sc_ntbuf = 8; + break; + case 131072: + sc->sc_nrbuf = 64; + sc->sc_ntbuf = 16; + break; + case 262144: + sc->sc_nrbuf = 128; + sc->sc_ntbuf = 32; + break; + default: + /* weird memory size; cope with it */ + nbuf = sc->sc_memsize / LEBLEN; + sc->sc_ntbuf = nbuf / 5; + sc->sc_nrbuf = nbuf - sc->sc_ntbuf; + } + + if_printf(ifp, "%d receive buffers, %d transmit buffers\n", + sc->sc_nrbuf, sc->sc_ntbuf); + + /* Make sure the chip is stopped. */ + LE_LOCK(sc); + lance_stop(sc); + LE_UNLOCK(sc); + + return (0); +} + +void +lance_attach(struct lance_softc *sc) +{ + struct ifnet *ifp = sc->sc_ifp; + + /* Attach the interface. */ + ether_ifattach(ifp, sc->sc_enaddr); + +#ifndef __rtems__ + /* Claim 802.1q capability. */ + ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); + ifp->if_capabilities |= IFCAP_VLAN_MTU; + ifp->if_capenable |= IFCAP_VLAN_MTU; +#endif +} + +void +lance_detach(struct lance_softc *sc) +{ + struct ifnet *ifp = sc->sc_ifp; + + LE_LOCK(sc); + lance_stop(sc); + LE_UNLOCK(sc); + callout_drain(&sc->sc_wdog_ch); + ether_ifdetach(ifp); + if_free(ifp); +} + +void +lance_suspend(struct lance_softc *sc) +{ + + LE_LOCK(sc); + lance_stop(sc); + LE_UNLOCK(sc); +} + +void +lance_resume(struct lance_softc *sc) +{ + + LE_LOCK(sc); + if (sc->sc_ifp->if_flags & IFF_UP) + lance_init_locked(sc); + LE_UNLOCK(sc); +} + +static void +lance_start(struct ifnet *ifp) +{ + struct lance_softc *sc = ifp->if_softc; + + LE_LOCK(sc); + (*sc->sc_start_locked)(sc); + LE_UNLOCK(sc); +} + +static void +lance_stop(struct lance_softc *sc) +{ + struct ifnet *ifp = sc->sc_ifp; + + LE_LOCK_ASSERT(sc, MA_OWNED); + + /* + * Mark the interface down and cancel the watchdog timer. + */ + ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE); + callout_stop(&sc->sc_wdog_ch); + sc->sc_wdog_timer = 0; + + (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP); +} + +static void +lance_init(void *xsc) +{ + struct lance_softc *sc = (struct lance_softc *)xsc; + + LE_LOCK(sc); + lance_init_locked(sc); + LE_UNLOCK(sc); +} + +/* + * Initialization of interface; set up initialization block + * and transmit/receive descriptor rings. + */ +void +lance_init_locked(struct lance_softc *sc) +{ + struct ifnet *ifp = sc->sc_ifp; + u_long a; + int timo; + + LE_LOCK_ASSERT(sc, MA_OWNED); + + (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_STOP); + DELAY(100); + + /* Newer LANCE chips have a reset register. */ + if (sc->sc_hwreset) + (*sc->sc_hwreset)(sc); + + /* Set the correct byte swapping mode, etc. */ + (*sc->sc_wrcsr)(sc, LE_CSR3, sc->sc_conf3); + + /* Set the current media. This may require the chip to be stopped. */ + if (sc->sc_mediachange) + (void)(*sc->sc_mediachange)(sc); + + /* + * Update our private copy of the Ethernet address. + * We NEED the copy so we can ensure its alignment! + */ + memcpy(sc->sc_enaddr, IF_LLADDR(ifp), ETHER_ADDR_LEN); + + /* Set up LANCE init block. */ + (*sc->sc_meminit)(sc); + + /* Give LANCE the physical address of its init block. */ + a = sc->sc_addr + LE_INITADDR(sc); + (*sc->sc_wrcsr)(sc, LE_CSR1, a & 0xffff); + (*sc->sc_wrcsr)(sc, LE_CSR2, a >> 16); + + /* Try to initialize the LANCE. */ + DELAY(100); + (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INIT); + + /* Wait for initialization to finish. */ + for (timo = 100000; timo; timo--) + if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) + break; + + if ((*sc->sc_rdcsr)(sc, LE_CSR0) & LE_C0_IDON) { + /* Start the LANCE. */ + (*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA | LE_C0_STRT); + ifp->if_drv_flags |= IFF_DRV_RUNNING; + ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; + sc->sc_wdog_timer = 0; + callout_reset(&sc->sc_wdog_ch, hz, lance_watchdog, sc); + (*sc->sc_start_locked)(sc); + } else + if_printf(ifp, "controller failed to initialize\n"); + + if (sc->sc_hwinit) + (*sc->sc_hwinit)(sc); +} + +/* + * Routine to copy from mbuf chain to transmit buffer in + * network buffer memory. + */ +int +lance_put(struct lance_softc *sc, int boff, struct mbuf *m) +{ + struct mbuf *n; + int len, tlen = 0; + + LE_LOCK_ASSERT(sc, MA_OWNED); + + for (; m; m = n) { + len = m->m_len; + if (len == 0) { + n = m_free(m); + m = NULL; + continue; + } + (*sc->sc_copytobuf)(sc, mtod(m, caddr_t), boff, len); + boff += len; + tlen += len; + n = m_free(m); + m = NULL; + } + if (tlen < LEMINSIZE) { + (*sc->sc_zerobuf)(sc, boff, LEMINSIZE - tlen); + tlen = LEMINSIZE; + } + return (tlen); +} + +/* + * Pull data off an interface. + * Len is length of data, with local net header stripped. + * We copy the data into mbufs. When full cluster sized units are present + * we copy into clusters. + */ +struct mbuf * +lance_get(struct lance_softc *sc, int boff, int totlen) +{ + struct ifnet *ifp = sc->sc_ifp; + struct mbuf *m, *m0, *newm; + caddr_t newdata; + int len; + + if (totlen <= ETHER_HDR_LEN || totlen > LEBLEN - ETHER_CRC_LEN) { +#ifdef LEDEBUG + if_printf(ifp, "invalid packet size %d; dropping\n", totlen); +#endif + return (NULL); + } + + MGETHDR(m0, M_DONTWAIT, MT_DATA); + if (m0 == NULL) + return (NULL); + m0->m_pkthdr.rcvif = ifp; + m0->m_pkthdr.len = totlen; + len = MHLEN; + m = m0; + + while (totlen > 0) { + if (totlen >= MINCLSIZE) { + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) + goto bad; + len = MCLBYTES; + } + + if (m == m0) { + newdata = (caddr_t) + ALIGN(m->m_data + ETHER_HDR_LEN) - ETHER_HDR_LEN; + len -= newdata - m->m_data; + m->m_data = newdata; + } + + m->m_len = len = min(totlen, len); + (*sc->sc_copyfrombuf)(sc, mtod(m, caddr_t), boff, len); + boff += len; + + totlen -= len; + if (totlen > 0) { + MGET(newm, M_DONTWAIT, MT_DATA); + if (newm == 0) + goto bad; + len = MLEN; + m = m->m_next = newm; + } + } + + return (m0); + + bad: + m_freem(m0); + return (NULL); +} + +static void +lance_watchdog(void *xsc) +{ + struct lance_softc *sc = (struct lance_softc *)xsc; + struct ifnet *ifp = sc->sc_ifp; + + LE_LOCK_ASSERT(sc, MA_OWNED); + + if (sc->sc_wdog_timer == 0 || --sc->sc_wdog_timer != 0) { + callout_reset(&sc->sc_wdog_ch, hz, lance_watchdog, sc); + return; + } + + if_printf(ifp, "device timeout\n"); + ++ifp->if_oerrors; + lance_init_locked(sc); +} + +static int +lance_mediachange(struct ifnet *ifp) +{ + struct lance_softc *sc = ifp->if_softc; + + if (sc->sc_mediachange) { + /* + * For setting the port in LE_CSR15 the PCnet chips must + * be powered down or stopped and unlike documented may + * not take effect without an initialization. So don't + * invoke (*sc_mediachange) directly here but go through + * lance_init_locked(). + */ + LE_LOCK(sc); + lance_stop(sc); + lance_init_locked(sc); + if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd)) + (*sc->sc_start_locked)(sc); + LE_UNLOCK(sc); + } + return (0); +} + +static void +lance_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr) +{ + struct lance_softc *sc = ifp->if_softc; + + LE_LOCK(sc); + if (!(ifp->if_flags & IFF_UP)) { + LE_UNLOCK(sc); + return; + } + + ifmr->ifm_status = IFM_AVALID; + if (sc->sc_flags & LE_CARRIER) + ifmr->ifm_status |= IFM_ACTIVE; + + if (sc->sc_mediastatus) + (*sc->sc_mediastatus)(sc, ifmr); + LE_UNLOCK(sc); +} + +/* + * Process an ioctl request. + */ +static int +#ifndef __rtems__ +lance_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +#else +lance_ioctl(struct ifnet *ifp, ioctl_command_t cmd, caddr_t data) +#endif +{ + struct lance_softc *sc = ifp->if_softc; + struct ifreq *ifr = (struct ifreq *)data; + int error = 0; + + switch (cmd) { + case SIOCSIFFLAGS: + LE_LOCK(sc); + if (ifp->if_flags & IFF_PROMISC) { + if (!(sc->sc_flags & LE_PROMISC)) { + sc->sc_flags |= LE_PROMISC; + lance_init_locked(sc); + } + } else if (sc->sc_flags & LE_PROMISC) { + sc->sc_flags &= ~LE_PROMISC; + lance_init_locked(sc); + } + + if ((ifp->if_flags & IFF_ALLMULTI) && + !(sc->sc_flags & LE_ALLMULTI)) { + sc->sc_flags |= LE_ALLMULTI; + lance_init_locked(sc); + } else if (!(ifp->if_flags & IFF_ALLMULTI) && + (sc->sc_flags & LE_ALLMULTI)) { + sc->sc_flags &= ~LE_ALLMULTI; + lance_init_locked(sc); + } + + if (!(ifp->if_flags & IFF_UP) && + ifp->if_drv_flags & IFF_DRV_RUNNING) { + /* + * If interface is marked down and it is running, then + * stop it. + */ + lance_stop(sc); + } else if (ifp->if_flags & IFF_UP && + !(ifp->if_drv_flags & IFF_DRV_RUNNING)) { + /* + * If interface is marked up and it is stopped, then + * start it. + */ + lance_init_locked(sc); + } +#ifdef LEDEBUG + if (ifp->if_flags & IFF_DEBUG) + sc->sc_flags |= LE_DEBUG; + else + sc->sc_flags &= ~LE_DEBUG; +#endif + LE_UNLOCK(sc); + break; + + case SIOCADDMULTI: + case SIOCDELMULTI: +#ifdef __rtems__ + if ( ETHER_SIOCMULTIFRAG( error, cmd, ifr, ifp ) ) + break; +#endif + /* + * Multicast list has changed; set the hardware filter + * accordingly. + */ + LE_LOCK(sc); + if (ifp->if_drv_flags & IFF_DRV_RUNNING) + lance_init_locked(sc); + LE_UNLOCK(sc); + break; + + case SIOCGIFMEDIA: + case SIOCSIFMEDIA: + error = ifmedia_ioctl(ifp, ifr, &sc->sc_media, cmd); + break; + + default: + error = ether_ioctl(ifp, cmd, data); + break; + } + + return (error); +} + +/* + * Set up the logical address filter. + */ +void +lance_setladrf(struct lance_softc *sc, uint16_t *af) +{ + struct ifnet *ifp = sc->sc_ifp; +#ifndef __rtems__ + struct ifmultiaddr *ifma; +#endif + uint32_t crc; + + /* + * Set up multicast address filter by passing all multicast addresses + * through a crc generator, and then using the high order 6 bits as an + * index into the 64 bit logical address filter. The high order bit + * selects the word, while the rest of the bits select the bit within + * the word. + */ + + if (ifp->if_flags & IFF_PROMISC || sc->sc_flags & LE_ALLMULTI) { + af[0] = af[1] = af[2] = af[3] = 0xffff; + return; + } + + af[0] = af[1] = af[2] = af[3] = 0x0000; +#ifndef __rtems__ + IF_ADDR_LOCK(ifp); + TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + + crc = ether_crc32_le(LLADDR((struct sockaddr_dl *) + ifma->ifma_addr), ETHER_ADDR_LEN); + + /* Just want the 6 most significant bits. */ + crc >>= 26; + + /* Set the corresponding bit in the filter. */ + af[crc >> 4] |= LE_HTOLE16(1 << (crc & 0xf)); + } + IF_ADDR_UNLOCK(ifp); +#else + { + /* UNTESTED */ + struct ether_multi *enm; + struct ether_multistep step; + ETHER_FIRST_MULTI(step, (struct arpcom *)ifp, enm); + while ( enm != NULL ) { + crc = ether_crc32_le(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26; + + /* Just want the 6 most significant bits. */ + crc >>= 26; + + /* Set the corresponding bit in the filter. */ + af[crc >> 4] |= LE_HTOLE16(1 << (crc & 0xf)); + ETHER_NEXT_MULTI( step, enm ); + } + } +#endif +} + +/* + * Routines for accessing the transmit and receive buffers. + * The various CPU and adapter configurations supported by this + * driver require three different access methods for buffers + * and descriptors: + * (1) contig (contiguous data; no padding), + * (2) gap2 (two bytes of data followed by two bytes of padding), + * (3) gap16 (16 bytes of data followed by 16 bytes of padding). + */ + +/* + * contig: contiguous data with no padding. + * + * Buffers may have any alignment. + */ + +void +lance_copytobuf_contig(struct lance_softc *sc, void *from, int boff, int len) +{ + volatile caddr_t buf = sc->sc_mem; + + /* + * Just call memcpy() to do the work. + */ + memcpy(buf + boff, from, len); +} + +void +lance_copyfrombuf_contig(struct lance_softc *sc, void *to, int boff, int len) +{ + volatile caddr_t buf = sc->sc_mem; + + /* + * Just call memcpy() to do the work. + */ + memcpy(to, buf + boff, len); +} + +void +lance_zerobuf_contig(struct lance_softc *sc, int boff, int len) +{ + volatile caddr_t buf = sc->sc_mem; + + /* + * Just let memset() do the work + */ + memset(buf + boff, 0, len); +} + +#if 0 +/* + * Examples only; duplicate these and tweak (if necessary) in + * machine-specific front-ends. + */ + +/* + * gap2: two bytes of data followed by two bytes of pad. + * + * Buffers must be 4-byte aligned. The code doesn't worry about + * doing an extra byte. + */ + +static void +lance_copytobuf_gap2(struct lance_softc *sc, void *fromv, int boff, int len) +{ + volatile caddr_t buf = sc->sc_mem; + caddr_t from = fromv; + volatile uint16_t *bptr; + + if (boff & 0x1) { + /* Handle unaligned first byte. */ + bptr = ((volatile uint16_t *)buf) + (boff - 1); + *bptr = (*from++ << 8) | (*bptr & 0xff); + bptr += 2; + len--; + } else + bptr = ((volatile uint16_t *)buf) + boff; + while (len > 1) { + *bptr = (from[1] << 8) | (from[0] & 0xff); + bptr += 2; + from += 2; + len -= 2; + } + if (len == 1) + *bptr = (uint16_t)*from; +} + +static void +lance_copyfrombuf_gap2(struct lance_softc *sc, void *tov, int boff, int len) +{ + volatile caddr_t buf = sc->sc_mem; + caddr_t to = tov; + volatile uint16_t *bptr; + uint16_t tmp; + + if (boff & 0x1) { + /* Handle unaligned first byte. */ + bptr = ((volatile uint16_t *)buf) + (boff - 1); + *to++ = (*bptr >> 8) & 0xff; + bptr += 2; + len--; + } else + bptr = ((volatile uint16_t *)buf) + boff; + while (len > 1) { + tmp = *bptr; + *to++ = tmp & 0xff; + *to++ = (tmp >> 8) & 0xff; + bptr += 2; + len -= 2; + } + if (len == 1) + *to = *bptr & 0xff; +} + +static void +lance_zerobuf_gap2(struct lance_softc *sc, int boff, int len) +{ + volatile caddr_t buf = sc->sc_mem; + volatile uint16_t *bptr; + + if ((unsigned)boff & 0x1) { + bptr = ((volatile uint16_t *)buf) + (boff - 1); + *bptr &= 0xff; + bptr += 2; + len--; + } else + bptr = ((volatile uint16_t *)buf) + boff; + while (len > 0) { + *bptr = 0; + bptr += 2; + len -= 2; + } +} + +/* + * gap16: 16 bytes of data followed by 16 bytes of pad. + * + * Buffers must be 32-byte aligned. + */ + +static void +lance_copytobuf_gap16(struct lance_softc *sc, void *fromv, int boff, int len) +{ + volatile caddr_t buf = sc->sc_mem; + caddr_t bptr, from = fromv; + int xfer; + + bptr = buf + ((boff << 1) & ~0x1f); + boff &= 0xf; + xfer = min(len, 16 - boff); + while (len > 0) { + memcpy(bptr + boff, from, xfer); + from += xfer; + bptr += 32; + boff = 0; + len -= xfer; + xfer = min(len, 16); + } +} + +static void +lance_copyfrombuf_gap16(struct lance_softc *sc, void *tov, int boff, int len) +{ + volatile caddr_t buf = sc->sc_mem; + caddr_t bptr, to = tov; + int xfer; + + bptr = buf + ((boff << 1) & ~0x1f); + boff &= 0xf; + xfer = min(len, 16 - boff); + while (len > 0) { + memcpy(to, bptr + boff, xfer); + to += xfer; + bptr += 32; + boff = 0; + len -= xfer; + xfer = min(len, 16); + } +} + +static void +lance_zerobuf_gap16(struct lance_softc *sc, int boff, int len) +{ + volatile caddr_t buf = sc->sc_mem; + caddr_t bptr; + int xfer; + + bptr = buf + ((boff << 1) & ~0x1f); + boff &= 0xf; + xfer = min(len, 16 - boff); + while (len > 0) { + memset(bptr + boff, 0, xfer); + bptr += 32; + boff = 0; + len -= xfer; + xfer = min(len, 16); + } +} +#endif /* Example only */ diff --git a/bsd_eth_drivers/if_le/lancereg.h b/bsd_eth_drivers/if_le/lancereg.h new file mode 100644 index 0000000..cbb129e --- /dev/null +++ b/bsd_eth_drivers/if_le/lancereg.h @@ -0,0 +1,619 @@ +/* $NetBSD: lancereg.h,v 1.12 2005/12/11 12:21:27 christos Exp $ */ + +/*- + * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum and Jason R. Thorpe. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Ralph Campbell and Rick Macklem. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)if_lereg.h 8.1 (Berkeley) 6/10/93 + */ + +/* + * Register description for the following Advanced Micro Devices + * Ethernet chips: + * + * - Am7990 Local Area Network Controller for Ethernet (LANCE) + * (and its descendent Am79c90 C-LANCE). + * + * - Am79c900 Integrated Local Area Communications Controller (ILACC) + * + * - Am79c960 PCnet-ISA Single-Chip Ethernet Controller for ISA + * + * - Am79c961 PCnet-ISA+ Jumperless Single-Chip Ethernet Controller + * for ISA + * + * - Am79c961A PCnet-ISA II Jumperless Full-Duplex Single-Chip + * Ethernet Controller for ISA + * + * - Am79c965A PCnet-32 Single-Chip 32-bit Ethernet Controller + * (for VESA and 486 local busses) + * + * - Am79c970 PCnet-PCI Single-Chip Ethernet Controller for PCI + * Local Bus + * + * - Am79c970A PCnet-PCI II Single-Chip Full-Duplex Ethernet Controller + * for PCI Local Bus + * + * - Am79c971 PCnet-FAST Single-Chip Full-Duplex 10/100Mbps + * Ethernet Controller for PCI Local Bus + * + * - Am79c972 PCnet-FAST+ Enhanced 10/100Mbps PCI Ethernet Controller + * with OnNow Support + * + * - Am79c973/Am79c975 PCnet-FAST III Single-Chip 10/100Mbps PCI + * Ethernet Controller with Integrated PHY + * + * - Am79c978 PCnet-Home Single-Chip 1/10 Mbps PCI Home + * Networking Controller. + * + * Initialization block, transmit descriptor, and receive descriptor + * formats are described in two separate files: + * + * 16-bit software model (LANCE) am7990reg.h + * + * 32-bit software model (ILACC) am79900reg.h + * + * Note that the vast majority of the registers described in this file + * belong to follow-on chips to the original LANCE. Only CSR0-CSR3 are + * valid on the LANCE. + */ + +/* $FreeBSD: src/sys/dev/le/lancereg.h,v 1.2 2006/05/16 21:04:01 marius Exp $ */ + +#ifndef _DEV_LE_LANCEREG_H_ +#define _DEV_LE_LANCEREG_H_ + +#define LEBLEN (ETHER_MAX_LEN + ETHER_VLAN_ENCAP_LEN) +/* LEMINSIZE should be ETHER_MIN_LEN when LE_MODE_DTCR is set. */ +#define LEMINSIZE (ETHER_MIN_LEN - ETHER_CRC_LEN) + +#define LE_INITADDR(sc) (sc->sc_initaddr) +#define LE_RMDADDR(sc, bix) (sc->sc_rmdaddr + sizeof(struct lermd) * (bix)) +#define LE_TMDADDR(sc, bix) (sc->sc_tmdaddr + sizeof(struct letmd) * (bix)) +#define LE_RBUFADDR(sc, bix) (sc->sc_rbufaddr + LEBLEN * (bix)) +#define LE_TBUFADDR(sc, bix) (sc->sc_tbufaddr + LEBLEN * (bix)) + +/* + * The byte count fields in descriptors are in two's complement. + * This macro does the conversion for us on unsigned numbers. + */ +#define LE_BCNT(x) (~(x) + 1) + +/* + * Control and Status Register addresses + */ +#define LE_CSR0 0x0000 /* Control and status register */ +#define LE_CSR1 0x0001 /* low address of init block */ +#define LE_CSR2 0x0002 /* high address of init block */ +#define LE_CSR3 0x0003 /* Bus master and control */ +#define LE_CSR4 0x0004 /* Test and features control */ +#define LE_CSR5 0x0005 /* Extended control and Interrupt 1 */ +#define LE_CSR6 0x0006 /* Rx/Tx Descriptor table length */ +#define LE_CSR7 0x0007 /* Extended control and interrupt 2 */ +#define LE_CSR8 0x0008 /* Logical Address Filter 0 */ +#define LE_CSR9 0x0009 /* Logical Address Filter 1 */ +#define LE_CSR10 0x000a /* Logical Address Filter 2 */ +#define LE_CSR11 0x000b /* Logical Address Filter 3 */ +#define LE_CSR12 0x000c /* Physical Address 0 */ +#define LE_CSR13 0x000d /* Physical Address 1 */ +#define LE_CSR14 0x000e /* Physical Address 2 */ +#define LE_CSR15 0x000f /* Mode */ +#define LE_CSR16 0x0010 /* Initialization Block addr lower */ +#define LE_CSR17 0x0011 /* Initialization Block addr upper */ +#define LE_CSR18 0x0012 /* Current Rx Buffer addr lower */ +#define LE_CSR19 0x0013 /* Current Rx Buffer addr upper */ +#define LE_CSR20 0x0014 /* Current Tx Buffer addr lower */ +#define LE_CSR21 0x0015 /* Current Tx Buffer addr upper */ +#define LE_CSR22 0x0016 /* Next Rx Buffer addr lower */ +#define LE_CSR23 0x0017 /* Next Rx Buffer addr upper */ +#define LE_CSR24 0x0018 /* Base addr of Rx ring lower */ +#define LE_CSR25 0x0019 /* Base addr of Rx ring upper */ +#define LE_CSR26 0x001a /* Next Rx Desc addr lower */ +#define LE_CSR27 0x001b /* Next Rx Desc addr upper */ +#define LE_CSR28 0x001c /* Current Rx Desc addr lower */ +#define LE_CSR29 0x001d /* Current Rx Desc addr upper */ +#define LE_CSR30 0x001e /* Base addr of Tx ring lower */ +#define LE_CSR31 0x001f /* Base addr of Tx ring upper */ +#define LE_CSR32 0x0020 /* Next Tx Desc addr lower */ +#define LE_CSR33 0x0021 /* Next Tx Desc addr upper */ +#define LE_CSR34 0x0022 /* Current Tx Desc addr lower */ +#define LE_CSR35 0x0023 /* Current Tx Desc addr upper */ +#define LE_CSR36 0x0024 /* Next Next Rx Desc addr lower */ +#define LE_CSR37 0x0025 /* Next Next Rx Desc addr upper */ +#define LE_CSR38 0x0026 /* Next Next Tx Desc addr lower */ +#define LE_CSR39 0x0027 /* Next Next Tx Desc adddr upper */ +#define LE_CSR40 0x0028 /* Current Rx Byte Count */ +#define LE_CSR41 0x0029 /* Current Rx Status */ +#define LE_CSR42 0x002a /* Current Tx Byte Count */ +#define LE_CSR43 0x002b /* Current Tx Status */ +#define LE_CSR44 0x002c /* Next Rx Byte Count */ +#define LE_CSR45 0x002d /* Next Rx Status */ +#define LE_CSR46 0x002e /* Tx Poll Time Counter */ +#define LE_CSR47 0x002f /* Tx Polling Interval */ +#define LE_CSR48 0x0030 /* Rx Poll Time Counter */ +#define LE_CSR49 0x0031 /* Rx Polling Interval */ +#define LE_CSR58 0x003a /* Software Style */ +#define LE_CSR60 0x003c /* Previous Tx Desc addr lower */ +#define LE_CSR61 0x003d /* Previous Tx Desc addr upper */ +#define LE_CSR62 0x003e /* Previous Tx Byte Count */ +#define LE_CSR63 0x003f /* Previous Tx Status */ +#define LE_CSR64 0x0040 /* Next Tx Buffer addr lower */ +#define LE_CSR65 0x0041 /* Next Tx Buffer addr upper */ +#define LE_CSR66 0x0042 /* Next Tx Byte Count */ +#define LE_CSR67 0x0043 /* Next Tx Status */ +#define LE_CSR72 0x0048 /* Receive Ring Counter */ +#define LE_CSR74 0x004a /* Transmit Ring Counter */ +#define LE_CSR76 0x004c /* Receive Ring Length */ +#define LE_CSR78 0x004e /* Transmit Ring Length */ +#define LE_CSR80 0x0050 /* DMA Transfer Counter and FIFO + Threshold Control */ +#define LE_CSR82 0x0052 /* Tx Desc addr Pointer lower */ +#define LE_CSR84 0x0054 /* DMA addr register lower */ +#define LE_CSR85 0x0055 /* DMA addr register upper */ +#define LE_CSR86 0x0056 /* Buffer Byte Counter */ +#define LE_CSR88 0x0058 /* Chip ID Register lower */ +#define LE_CSR89 0x0059 /* Chip ID Register upper */ +#define LE_CSR92 0x005c /* Ring Length Conversion */ +#define LE_CSR100 0x0064 /* Bus Timeout */ +#define LE_CSR112 0x0070 /* Missed Frame Count */ +#define LE_CSR114 0x0072 /* Receive Collision Count */ +#define LE_CSR116 0x0074 /* OnNow Power Mode Register */ +#define LE_CSR122 0x007a /* Advanced Feature Control */ +#define LE_CSR124 0x007c /* Test Register 1 */ +#define LE_CSR125 0x007d /* MAC Enhanced Configuration Control */ + +/* + * Bus Configuration Register addresses + */ +#define LE_BCR0 0x0000 /* Master Mode Read Active */ +#define LE_BCR1 0x0001 /* Master Mode Write Active */ +#define LE_BCR2 0x0002 /* Misc. Configuration */ +#define LE_BCR4 0x0004 /* LED0 Status */ +#define LE_BCR5 0x0005 /* LED1 Status */ +#define LE_BCR6 0x0006 /* LED2 Status */ +#define LE_BCR7 0x0007 /* LED3 Status */ +#define LE_BCR9 0x0009 /* Full-duplex Control */ +#define LE_BCR16 0x0010 /* I/O Base Address lower */ +#define LE_BCR17 0x0011 /* I/O Base Address upper */ +#define LE_BCR18 0x0012 /* Burst and Bus Control Register */ +#define LE_BCR19 0x0013 /* EEPROM Control and Status */ +#define LE_BCR20 0x0014 /* Software Style */ +#define LE_BCR22 0x0016 /* PCI Latency Register */ +#define LE_BCR23 0x0017 /* PCI Subsystem Vendor ID */ +#define LE_BCR24 0x0018 /* PCI Subsystem ID */ +#define LE_BCR25 0x0019 /* SRAM Size Register */ +#define LE_BCR26 0x001a /* SRAM Boundary Register */ +#define LE_BCR27 0x001b /* SRAM Interface Control Register */ +#define LE_BCR28 0x001c /* Exp. Bus Port Addr lower */ +#define LE_BCR29 0x001d /* Exp. Bus Port Addr upper */ +#define LE_BCR30 0x001e /* Exp. Bus Data Port */ +#define LE_BCR31 0x001f /* Software Timer Register */ +#define LE_BCR32 0x0020 /* PHY Control and Status Register */ +#define LE_BCR33 0x0021 /* PHY Address Register */ +#define LE_BCR34 0x0022 /* PHY Management Data Register */ +#define LE_BCR35 0x0023 /* PCI Vendor ID Register */ +#define LE_BCR36 0x0024 /* PCI Power Management Cap. Alias */ +#define LE_BCR37 0x0025 /* PCI DATA0 Alias */ +#define LE_BCR38 0x0026 /* PCI DATA1 Alias */ +#define LE_BCR39 0x0027 /* PCI DATA2 Alias */ +#define LE_BCR40 0x0028 /* PCI DATA3 Alias */ +#define LE_BCR41 0x0029 /* PCI DATA4 Alias */ +#define LE_BCR42 0x002a /* PCI DATA5 Alias */ +#define LE_BCR43 0x002b /* PCI DATA6 Alias */ +#define LE_BCR44 0x002c /* PCI DATA7 Alias */ +#define LE_BCR45 0x002d /* OnNow Pattern Matching 1 */ +#define LE_BCR46 0x002e /* OnNow Pattern Matching 2 */ +#define LE_BCR47 0x002f /* OnNow Pattern Matching 3 */ +#define LE_BCR48 0x0030 /* LED4 Status */ +#define LE_BCR49 0x0031 /* PHY Select */ + +/* Control and status register 0 (csr0) */ +#define LE_C0_ERR 0x8000 /* error summary */ +#define LE_C0_BABL 0x4000 /* transmitter timeout error */ +#define LE_C0_CERR 0x2000 /* collision */ +#define LE_C0_MISS 0x1000 /* missed a packet */ +#define LE_C0_MERR 0x0800 /* memory error */ +#define LE_C0_RINT 0x0400 /* receiver interrupt */ +#define LE_C0_TINT 0x0200 /* transmitter interrupt */ +#define LE_C0_IDON 0x0100 /* initialization done */ +#define LE_C0_INTR 0x0080 /* interrupt condition */ +#define LE_C0_INEA 0x0040 /* interrupt enable */ +#define LE_C0_RXON 0x0020 /* receiver on */ +#define LE_C0_TXON 0x0010 /* transmitter on */ +#define LE_C0_TDMD 0x0008 /* transmit demand */ +#define LE_C0_STOP 0x0004 /* disable all external activity */ +#define LE_C0_STRT 0x0002 /* enable external activity */ +#define LE_C0_INIT 0x0001 /* begin initialization */ + +#define LE_C0_BITS \ + "\20\20ERR\17BABL\16CERR\15MISS\14MERR\13RINT\ +\12TINT\11IDON\10INTR\07INEA\06RXON\05TXON\04TDMD\03STOP\02STRT\01INIT" + +/* Control and status register 3 (csr3) */ +#define LE_C3_BABLM 0x4000 /* babble mask */ +#define LE_C3_MISSM 0x1000 /* missed frame mask */ +#define LE_C3_MERRM 0x0800 /* memory error mask */ +#define LE_C3_RINTM 0x0400 /* receive interrupt mask */ +#define LE_C3_TINTM 0x0200 /* transmit interrupt mask */ +#define LE_C3_IDONM 0x0100 /* initialization done mask */ +#define LE_C3_DXSUFLO 0x0040 /* disable tx stop on underflow */ +#define LE_C3_LAPPEN 0x0020 /* look ahead packet processing enbl */ +#define LE_C3_DXMT2PD 0x0010 /* disable tx two part deferral */ +#define LE_C3_EMBA 0x0008 /* enable modified backoff algorithm */ +#define LE_C3_BSWP 0x0004 /* byte swap */ +#define LE_C3_ACON 0x0002 /* ALE control, eh? */ +#define LE_C3_BCON 0x0001 /* byte control */ + +/* Control and status register 4 (csr4) */ +#define LE_C4_EN124 0x8000 /* enable CSR124 */ +#define LE_C4_DMAPLUS 0x4000 /* always set (PCnet-PCI) */ +#define LE_C4_TIMER 0x2000 /* enable bus activity timer */ +#define LE_C4_TXDPOLL 0x1000 /* disable transmit polling */ +#define LE_C4_APAD_XMT 0x0800 /* auto pad transmit */ +#define LE_C4_ASTRP_RCV 0x0400 /* auto strip receive */ +#define LE_C4_MFCO 0x0200 /* missed frame counter overflow */ +#define LE_C4_MFCOM 0x0100 /* missed frame coutner overflow mask */ +#define LE_C4_UINTCMD 0x0080 /* user interrupt command */ +#define LE_C4_UINT 0x0040 /* user interrupt */ +#define LE_C4_RCVCCO 0x0020 /* receive collision counter overflow */ +#define LE_C4_RCVCCOM 0x0010 /* receive collision counter overflow + mask */ +#define LE_C4_TXSTRT 0x0008 /* transmit start status */ +#define LE_C4_TXSTRTM 0x0004 /* transmit start mask */ + +/* Control and status register 5 (csr5) */ +#define LE_C5_TOKINTD 0x8000 /* transmit ok interrupt disable */ +#define LE_C5_LTINTEN 0x4000 /* last transmit interrupt enable */ +#define LE_C5_SINT 0x0800 /* system interrupt */ +#define LE_C5_SINTE 0x0400 /* system interrupt enable */ +#define LE_C5_EXDINT 0x0080 /* excessive deferral interrupt */ +#define LE_C5_EXDINTE 0x0040 /* excessive deferral interrupt enbl */ +#define LE_C5_MPPLBA 0x0020 /* magic packet physical logical + broadcast accept */ +#define LE_C5_MPINT 0x0010 /* magic packet interrupt */ +#define LE_C5_MPINTE 0x0008 /* magic packet interrupt enable */ +#define LE_C5_MPEN 0x0004 /* magic packet enable */ +#define LE_C5_MPMODE 0x0002 /* magic packet mode */ +#define LE_C5_SPND 0x0001 /* suspend */ + +/* Control and status register 6 (csr6) */ +#define LE_C6_TLEN 0xf000 /* TLEN from init block */ +#define LE_C6_RLEN 0x0f00 /* RLEN from init block */ + +/* Control and status register 7 (csr7) */ +#define LE_C7_FASTSPNDE 0x8000 /* fast suspend enable */ +#define LE_C7_RDMD 0x2000 /* receive demand */ +#define LE_C7_RDXPOLL 0x1000 /* receive disable polling */ +#define LE_C7_STINT 0x0800 /* software timer interrupt */ +#define LE_C7_STINTE 0x0400 /* software timer interrupt enable */ +#define LE_C7_MREINT 0x0200 /* PHY management read error intr */ +#define LE_C7_MREINTE 0x0100 /* PHY management read error intr + enable */ +#define LE_C7_MAPINT 0x0080 /* PHY management auto-poll intr */ +#define LE_C7_MAPINTE 0x0040 /* PHY management auto-poll intr + enable */ +#define LE_C7_MCCINT 0x0020 /* PHY management command complete + interrupt */ +#define LE_C7_MCCINTE 0x0010 /* PHY management command complete + interrupt enable */ +#define LE_C7_MCCIINT 0x0008 /* PHY management command complete + internal interrupt */ +#define LE_C7_MCCIINTE 0x0004 /* PHY management command complete + internal interrupt enable */ +#define LE_C7_MIIPDTINT 0x0002 /* PHY management detect transition + interrupt */ +#define LE_C7_MIIPDTINTE 0x0001 /* PHY management detect transition + interrupt enable */ + +/* Control and status register 15 (csr15) */ +#define LE_C15_PROM 0x8000 /* promiscuous mode */ +#define LE_C15_DRCVBC 0x4000 /* disable Rx of broadcast */ +#define LE_C15_DRCVPA 0x2000 /* disable Rx of physical address */ +#define LE_C15_DLNKTST 0x1000 /* disable link status */ +#define LE_C15_DAPC 0x0800 /* disable auto-polarity correction */ +#define LE_C15_MENDECL 0x0400 /* MENDEC Loopback mode */ +#define LE_C15_LRT 0x0200 /* low receive threshold (TMAU) */ +#define LE_C15_TSEL 0x0200 /* transmit mode select (AUI) */ +#define LE_C15_PORTSEL(x) ((x) << 7) /* port select */ +#define LE_C15_INTL 0x0040 /* internal loopback */ +#define LE_C15_DRTY 0x0020 /* disable retry */ +#define LE_C15_FCOLL 0x0010 /* force collision */ +#define LE_C15_DXMTFCS 0x0008 /* disable Tx FCS (ADD_FCS overrides) */ +#define LE_C15_LOOP 0x0004 /* loopback enable */ +#define LE_C15_DTX 0x0002 /* disable transmit */ +#define LE_C15_DRX 0x0001 /* disable receiver */ + +#define LE_PORTSEL_AUI 0 +#define LE_PORTSEL_10T 1 +#define LE_PORTSEL_GPSI 2 +#define LE_PORTSEL_MII 3 +#define LE_PORTSEL_MASK 3 + +/* control and status register 80 (csr80) */ +#define LE_C80_RCVFW(x) ((x) << 12) /* Receive FIFO Watermark */ +#define LE_C80_RCVFW_MAX 3 +#define LE_C80_XMTSP(x) ((x) << 10) /* Transmit Start Point */ +#define LE_C80_XMTSP_MAX 3 +#define LE_C80_XMTFW(x) ((x) << 8) /* Transmit FIFO Watermark */ +#define LE_C80_XMTFW_MAX 3 +#define LE_C80_DMATC 0x00ff /* DMA transfer counter */ + +/* control and status register 116 (csr116) */ +#define LE_C116_PME_EN_OVR 0x0400 /* PME_EN overwrite */ +#define LE_C116_LCDET 0x0200 /* link change detected */ +#define LE_C116_LCMODE 0x0100 /* link change wakeup mode */ +#define LE_C116_PMAT 0x0080 /* pattern matched */ +#define LE_C116_EMPPLBA 0x0040 /* magic packet physical logical + broadcast accept */ +#define LE_C116_MPMAT 0x0020 /* magic packet match */ +#define LE_C116_MPPEN 0x0010 /* magic packet pin enable */ +#define LE_C116_RST_POL 0x0001 /* PHY_RST pin polarity */ + +/* control and status register 122 (csr122) */ +#define LE_C122_RCVALGN 0x0001 /* receive packet align */ + +/* control and status register 124 (csr124) */ +#define LE_C124_RPA 0x0008 /* runt packet accept */ + +/* control and status register 125 (csr125) */ +#define LE_C125_IPG 0xff00 /* inter-packet gap */ +#define LE_C125_IFS1 0x00ff /* inter-frame spacing part 1 */ + +/* bus configuration register 0 (bcr0) */ +#define LE_B0_MSRDA 0xffff /* reserved locations */ + +/* bus configuration register 1 (bcr1) */ +#define LE_B1_MSWRA 0xffff /* reserved locations */ + +/* bus configuration register 2 (bcr2) */ +#define LE_B2_PHYSSELEN 0x2000 /* enable writes to BCR18[4:3] */ +#define LE_B2_LEDPE 0x1000 /* LED program enable */ +#define LE_B2_APROMWE 0x0100 /* Address PROM Write Enable */ +#define LE_B2_INTLEVEL 0x0080 /* 1 == edge triggered */ +#define LE_B2_DXCVRCTL 0x0020 /* DXCVR control */ +#define LE_B2_DXCVRPOL 0x0010 /* DXCVR polarity */ +#define LE_B2_EADISEL 0x0008 /* EADI select */ +#define LE_B2_AWAKE 0x0004 /* power saving mode select */ +#define LE_B2_ASEL 0x0002 /* auto-select PORTSEL */ +#define LE_B2_XMAUSEL 0x0001 /* reserved location */ + +/* bus configuration register 4 (bcr4) */ +/* bus configuration register 5 (bcr5) */ +/* bus configuration register 6 (bcr6) */ +/* bus configuration register 7 (bcr7) */ +/* bus configuration register 48 (bcr48) */ +#define LE_B4_LEDOUT 0x8000 /* LED output active */ +#define LE_B4_LEDPOL 0x4000 /* LED polarity */ +#define LE_B4_LEDDIS 0x2000 /* LED disable */ +#define LE_B4_100E 0x1000 /* 100Mb/s enable */ +#define LE_B4_MPSE 0x0200 /* magic packet status enable */ +#define LE_B4_FDLSE 0x0100 /* full-duplex link status enable */ +#define LE_B4_PSE 0x0080 /* pulse stretcher enable */ +#define LE_B4_LNKSE 0x0040 /* link status enable */ +#define LE_B4_RCVME 0x0020 /* receive match status enable */ +#define LE_B4_XMTE 0x0010 /* transmit status enable */ +#define LE_B4_POWER 0x0008 /* power enable */ +#define LE_B4_RCVE 0x0004 /* receive status enable */ +#define LE_B4_SPEED 0x0002 /* high speed enable */ +#define LE_B4_COLE 0x0001 /* collision status enable */ + +/* bus configuration register 9 (bcr9) */ +#define LE_B9_FDRPAD 0x0004 /* full-duplex runt packet accept + disable */ +#define LE_B9_AUIFD 0x0002 /* AUI full-duplex */ +#define LE_B9_FDEN 0x0001 /* full-duplex enable */ + +/* bus configuration register 18 (bcr18) */ +#define LE_B18_ROMTMG 0xf000 /* expansion rom timing */ +#define LE_B18_NOUFLO 0x0800 /* no underflow on transmit */ +#define LE_B18_MEMCMD 0x0200 /* memory read multiple enable */ +#define LE_B18_EXTREQ 0x0100 /* extended request */ +#define LE_B18_DWIO 0x0080 /* double-word I/O */ +#define LE_B18_BREADE 0x0040 /* burst read enable */ +#define LE_B18_BWRITE 0x0020 /* burst write enable */ +#define LE_B18_PHYSEL1 0x0010 /* PHYSEL 1 */ +#define LE_B18_PHYSEL0 0x0008 /* PHYSEL 0 */ + /* 00 ex ROM/Flash */ + /* 01 EADI/MII snoop */ + /* 10 reserved */ + /* 11 reserved */ +#define LE_B18_LINBC 0x0007 /* reserved locations */ + +/* bus configuration register 19 (bcr19) */ +#define LE_B19_PVALID 0x8000 /* EEPROM status valid */ +#define LE_B19_PREAD 0x4000 /* EEPROM read command */ +#define LE_B19_EEDET 0x2000 /* EEPROM detect */ +#define LE_B19_EEN 0x0010 /* EEPROM port enable */ +#define LE_B19_ECS 0x0004 /* EEPROM chip select */ +#define LE_B19_ESK 0x0002 /* EEPROM serial clock */ +#define LE_B19_EDI 0x0001 /* EEPROM data in */ +#define LE_B19_EDO 0x0001 /* EEPROM data out */ + +/* bus configuration register 20 (bcr20) */ +#define LE_B20_APERREN 0x0400 /* Advanced parity error handling */ +#define LE_B20_CSRPCNET 0x0200 /* PCnet-style CSRs (0 = ILACC) */ +#define LE_B20_SSIZE32 0x0100 /* Software Size 32-bit */ +#define LE_B20_SSTYLE 0x0007 /* Software Style */ +#define LE_B20_SSTYLE_LANCE 0 /* LANCE/PCnet-ISA (16-bit) */ +#define LE_B20_SSTYLE_ILACC 1 /* ILACC (32-bit) */ +#define LE_B20_SSTYLE_PCNETPCI2 2 /* PCnet-PCI (32-bit) */ +#define LE_B20_SSTYLE_PCNETPCI3 3 /* PCnet-PCI II (32-bit) */ + +/* bus configuration register 25 (bcr25) */ +#define LE_B25_SRAM_SIZE 0x00ff /* SRAM size */ + +/* bus configuration register 26 (bcr26) */ +#define LE_B26_SRAM_BND 0x00ff /* SRAM boundary */ + +/* bus configuration register 27 (bcr27) */ +#define LE_B27_PTRTST 0x8000 /* reserved for manuf. tests */ +#define LE_B27_LOLATRX 0x4000 /* low latency receive */ +#define LE_B27_EBCS 0x0038 /* expansion bus clock source */ + /* 000 CLK pin */ + /* 001 time base clock */ + /* 010 EBCLK pin */ + /* 011 reserved */ + /* 1xx reserved */ +#define LE_B27_CLK_FAC 0x0007 /* clock factor */ + /* 000 1 */ + /* 001 1/2 */ + /* 010 reserved */ + /* 011 1/4 */ + /* 1xx reserved */ + +/* bus configuration register 28 (bcr28) */ +#define LE_B28_EADDRL 0xffff /* expansion port address lower */ + +/* bus configuration register 29 (bcr29) */ +#define LE_B29_FLASH 0x8000 /* flash access */ +#define LE_B29_LAAINC 0x4000 /* lower address auto increment */ +#define LE_B29_EPADDRU 0x0007 /* expansion port address upper */ + +/* bus configuration register 30 (bcr30) */ +#define LE_B30_EBDATA 0xffff /* expansion bus data port */ + +/* bus configuration register 31 (bcr31) */ +#define LE_B31_STVAL 0xffff /* software timer value */ + +/* bus configuration register 32 (bcr32) */ +#define LE_B32_ANTST 0x8000 /* reserved for manuf. tests */ +#define LE_B32_MIIPD 0x4000 /* MII PHY Detect (manuf. tests) */ +#define LE_B32_FMDC 0x3000 /* fast management data clock */ +#define LE_B32_APEP 0x0800 /* auto-poll PHY */ +#define LE_B32_APDW 0x0700 /* auto-poll dwell time */ +#define LE_B32_DANAS 0x0080 /* disable autonegotiation */ +#define LE_B32_XPHYRST 0x0040 /* PHY reset */ +#define LE_B32_XPHYANE 0x0020 /* PHY autonegotiation enable */ +#define LE_B32_XPHYFD 0x0010 /* PHY full-duplex */ +#define LE_B32_XPHYSP 0x0008 /* PHY speed */ +#define LE_B32_MIIILP 0x0002 /* MII internal loopback */ + +/* bus configuration register 33 (bcr33) */ +#define LE_B33_SHADOW 0x8000 /* shadow enable */ +#define LE_B33_MII_SEL 0x4000 /* MII selected */ +#define LE_B33_ACOMP 0x2000 /* internal PHY autonegotiation comp */ +#define LE_B33_LINK 0x1000 /* link status */ +#define LE_B33_FDX 0x0800 /* full-duplex */ +#define LE_B33_SPEED 0x0400 /* 1 == high speed */ +#define LE_B33_PHYAD 0x03e0 /* PHY address */ +#define PHYAD_SHIFT 5 +#define LE_B33_REGAD 0x001f /* register address */ + +/* bus configuration register 34 (bcr34) */ +#define LE_B34_MIIMD 0xffff /* MII data */ + +/* bus configuration register 49 (bcr49) */ +#define LE_B49_PCNET 0x8000 /* PCnet mode - Must Be One */ +#define LE_B49_PHYSEL_D 0x0300 /* PHY_SEL_Default */ +#define LE_B49_PHYSEL_L 0x0010 /* PHY_SEL_Lock */ +#define LE_B49_PHYSEL 0x0003 /* PHYSEL */ + /* 00 10baseT PHY */ + /* 01 HomePNA PHY */ + /* 10 external PHY */ + /* 11 reserved */ + +/* Initialization block (mode) */ +#define LE_MODE_PROM 0x8000 /* promiscuous mode */ +/* 0x7f80 reserved, must be zero */ +/* 0x4000 - 0x0080 are not available on LANCE 7990. */ +#define LE_MODE_DRCVBC 0x4000 /* disable receive brodcast */ +#define LE_MODE_DRCVPA 0x2000 /* disable physical address detection */ +#define LE_MODE_DLNKTST 0x1000 /* disable link status */ +#define LE_MODE_DAPC 0x0800 /* disable automatic polarity correction */ +#define LE_MODE_MENDECL 0x0400 /* MENDEC loopback mode */ +#define LE_MODE_LRTTSEL 0x0200 /* lower receive threshold / + transmit mode selection */ +#define LE_MODE_PSEL1 0x0100 /* port selection bit1 */ +#define LE_MODE_PSEL0 0x0080 /* port selection bit0 */ +#define LE_MODE_INTL 0x0040 /* internal loopback */ +#define LE_MODE_DRTY 0x0020 /* disable retry */ +#define LE_MODE_COLL 0x0010 /* force a collision */ +#define LE_MODE_DTCR 0x0008 /* disable transmit CRC */ +#define LE_MODE_LOOP 0x0004 /* loopback mode */ +#define LE_MODE_DTX 0x0002 /* disable transmitter */ +#define LE_MODE_DRX 0x0001 /* disable receiver */ +#define LE_MODE_NORMAL 0 /* none of the above */ + +/* + * Chip ID (CSR88 IDL, CSR89 IDU) values for various AMD PCnet parts + */ +#define CHIPID_MANFID(x) (((x) >> 1) & 0x3ff) +#define CHIPID_PARTID(x) (((x) >> 12) & 0xffff) +#define CHIPID_VER(x) (((x) >> 28) & 0x7) + +#define PARTID_Am79c960 0x0003 +#define PARTID_Am79c961 0x2260 +#define PARTID_Am79c961A 0x2261 +#define PARTID_Am79c965 0x2430 /* yes, these... */ +#define PARTID_Am79c970 0x2430 /* ...are the same */ +#define PARTID_Am79c970A 0x2621 +#define PARTID_Am79c971 0x2623 +#define PARTID_Am79c972 0x2624 +#define PARTID_Am79c973 0x2625 +#define PARTID_Am79c978 0x2626 +#define PARTID_Am79c975 0x2627 +#define PARTID_Am79c976 0x2628 + +#endif /* !_DEV_LE_LANCEREG_H_ */ diff --git a/bsd_eth_drivers/if_le/lancevar.h b/bsd_eth_drivers/if_le/lancevar.h new file mode 100644 index 0000000..d107c3b --- /dev/null +++ b/bsd_eth_drivers/if_le/lancevar.h @@ -0,0 +1,216 @@ +/* $NetBSD: lancevar.h,v 1.10 2005/12/11 12:21:27 christos Exp $ */ + +/*- + * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace + * Simulation Facility, NASA Ames Research Center. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* $FreeBSD: src/sys/dev/le/lancevar.h,v 1.3 2006/12/06 02:14:31 marius Exp $ */ + +#ifndef _DEV_LE_LANCEVAR_H_ +#define _DEV_LE_LANCEVAR_H_ + +extern devclass_t le_devclass; + +struct lance_softc { + struct ifnet *sc_ifp; + struct ifmedia sc_media; + struct mtx sc_mtx; + struct callout sc_wdog_ch; + int sc_wdog_timer; + + /* + * Memory functions: + * + * copy to/from descriptor + * copy to/from buffer + * zero bytes in buffer + */ + void (*sc_copytodesc)(struct lance_softc *, void *, int, int); + void (*sc_copyfromdesc)(struct lance_softc *, void *, int, int); + void (*sc_copytobuf)(struct lance_softc *, void *, int, int); + void (*sc_copyfrombuf)(struct lance_softc *, void *, int, int); + void (*sc_zerobuf)(struct lance_softc *, int, int); + + /* + * Machine-dependent functions: + * + * read/write CSR + * hardware reset hook - may be NULL + * hardware init hook - may be NULL + * no carrier hook - may be NULL + * media change hook - may be NULL + */ + uint16_t (*sc_rdcsr)(struct lance_softc *, uint16_t); + void (*sc_wrcsr)(struct lance_softc *, uint16_t, uint16_t); + void (*sc_hwreset)(struct lance_softc *); + void (*sc_hwinit)(struct lance_softc *); + int (*sc_hwintr)(struct lance_softc *); + void (*sc_nocarrier)(struct lance_softc *); + int (*sc_mediachange)(struct lance_softc *); + void (*sc_mediastatus)(struct lance_softc *, struct ifmediareq *); + + /* + * Media-supported by this interface. If this is NULL, + * the only supported media is assumed to be "manual". + */ + const int *sc_supmedia; + int sc_nsupmedia; + int sc_defaultmedia; + + uint16_t sc_conf3; /* CSR3 value */ + + void *sc_mem; /* base address of RAM - CPU's view */ + bus_addr_t sc_addr; /* base address of RAM - LANCE's view */ + + bus_size_t sc_memsize; /* size of RAM */ + + int sc_nrbuf; /* number of receive buffers */ + int sc_ntbuf; /* number of transmit buffers */ + int sc_last_rd; + int sc_first_td; + int sc_last_td; + int sc_no_td; + + int sc_initaddr; + int sc_rmdaddr; + int sc_tmdaddr; + int sc_rbufaddr; + int sc_tbufaddr; + + uint8_t sc_enaddr[ETHER_ADDR_LEN]; + + void (*sc_meminit)(struct lance_softc *); + void (*sc_start_locked)(struct lance_softc *); + + int sc_flags; +#define LE_ALLMULTI (1 << 0) +#define LE_BSWAP (1 << 1) +#define LE_CARRIER (1 << 2) +#define LE_DEBUG (1 << 3) +#define LE_PROMISC (1 << 4) +}; + +#define LE_LOCK_INIT(_sc, _name) \ + mtx_init(&(_sc)->sc_mtx, _name, MTX_NETWORK_LOCK, MTX_DEF) +#define LE_LOCK_INITIALIZED(_sc) mtx_initialized(&(_sc)->sc_mtx) +#define LE_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) +#define LE_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) +#define LE_LOCK_ASSERT(_sc, _what) mtx_assert(&(_sc)->sc_mtx, (_what)) +#define LE_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx) + +/* + * Unfortunately, manual byte swapping is only necessary for the PCnet-PCI + * variants but not for the original LANCE or ILACC so we cannot do this + * with #ifdefs resolved at compile time. + */ +#define LE_HTOLE16(v) (((sc)->sc_flags & LE_BSWAP) ? htole16(v) : (v)) +#define LE_HTOLE32(v) (((sc)->sc_flags & LE_BSWAP) ? htole32(v) : (v)) +#define LE_LE16TOH(v) (((sc)->sc_flags & LE_BSWAP) ? le16toh(v) : (v)) +#define LE_LE32TOH(v) (((sc)->sc_flags & LE_BSWAP) ? le32toh(v) : (v)) + +int lance_config(struct lance_softc *, const char*, int); +void lance_attach(struct lance_softc *); +void lance_detach(struct lance_softc *); +void lance_suspend(struct lance_softc *); +void lance_resume(struct lance_softc *); +void lance_init_locked(struct lance_softc *); +int lance_put(struct lance_softc *, int, struct mbuf *); +struct mbuf *lance_get(struct lance_softc *, int, int); +void lance_setladrf(struct lance_softc *, u_int16_t *); + +/* + * The following functions are only useful on certain CPU/bus + * combinations. They should be written in assembly language for + * maximum efficiency, but machine-independent versions are provided + * for drivers that have not yet been optimized. + */ +void lance_copytobuf_contig(struct lance_softc *, void *, int, int); +void lance_copyfrombuf_contig(struct lance_softc *, void *, int, int); +void lance_zerobuf_contig(struct lance_softc *, int, int); + +#if 0 /* Example only - see lance.c */ +void lance_copytobuf_gap2(struct lance_softc *, void *, int, int); +void lance_copyfrombuf_gap2(struct lance_softc *, void *, int, int); +void lance_zerobuf_gap2(struct lance_softc *, int, int); + +void lance_copytobuf_gap16(struct lance_softc *, void *, int, int); +void lance_copyfrombuf_gap16(struct lance_softc *, void *, int, int); +void lance_zerobuf_gap16(struct lance_softc *, int, int); +#endif /* Example only */ + +/* + * Compare two Ether/802 addresses for equality, inlined and + * unrolled for speed. Use this like memcmp(). + * + * XXX: Add for stuff like this? + * XXX: or maybe add it to libkern.h instead? + * + * "I'd love to have an inline assembler version of this." + * XXX: Who wanted that? mycroft? I wrote one, but this + * version in C is as good as hand-coded assembly. -gwr + * + * Please do NOT tweak this without looking at the actual + * assembly code generated before and after your tweaks! + */ +static inline uint16_t +ether_cmp(void *one, void *two) +{ + uint16_t *a = (u_short *)one; + uint16_t *b = (u_short *)two; + uint16_t diff; + +#ifdef m68k + /* + * The post-increment-pointer form produces the best + * machine code for m68k. This was carefully tuned + * so it compiles to just 8 short (2-byte) op-codes! + */ + diff = *a++ - *b++; + diff |= *a++ - *b++; + diff |= *a++ - *b++; +#else + /* + * Most modern CPUs do better with a single expresion. + * Note that short-cut evaluation is NOT helpful here, + * because it just makes the code longer, not faster! + */ + diff = (a[0] - b[0]) | (a[1] - b[1]) | (a[2] - b[2]); +#endif + + return (diff); +} + +#endif /* _DEV_LE_LANCEVAR_H_ */ -- cgit v1.2.3