Added FreeBSD 6.2's PCNET driver (original source, no modifications). It's what i'm using to develop and test the compat. layer right now, since it's one of the possibly devices VMWare emulates. although probe() already works, there's still a lot of work ahead.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21027 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
00212abe1c
commit
3d09a7e4e8
@ -12,7 +12,9 @@ SubInclude HAIKU_TOP src add-ons kernel drivers network via-rhine ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers network vlance ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers network wb840 ;
|
||||
|
||||
# FreeBSD 6.2 drivers
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers network ipro100 ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers network pcnet ;
|
||||
|
||||
SubIncludeGPL HAIKU_TOP src add-ons kernel drivers network bcm440x ;
|
||||
SubIncludeGPL HAIKU_TOP src add-ons kernel drivers network bcm570x ;
|
||||
|
3
src/add-ons/kernel/drivers/network/pcnet/Jamfile
Normal file
3
src/add-ons/kernel/drivers/network/pcnet/Jamfile
Normal file
@ -0,0 +1,3 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel drivers network pcnet ;
|
||||
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers network pcnet dev ;
|
3
src/add-ons/kernel/drivers/network/pcnet/dev/Jamfile
Normal file
3
src/add-ons/kernel/drivers/network/pcnet/dev/Jamfile
Normal file
@ -0,0 +1,3 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel drivers network pcnet dev ;
|
||||
|
||||
SubInclude HAIKU_TOP src add-ons kernel drivers network pcnet dev le ;
|
20
src/add-ons/kernel/drivers/network/pcnet/dev/le/Jamfile
Normal file
20
src/add-ons/kernel/drivers/network/pcnet/dev/le/Jamfile
Normal file
@ -0,0 +1,20 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel drivers network pcnet dev le ;
|
||||
|
||||
SubDirCcFlags -Wall ;
|
||||
|
||||
UsePrivateHeaders kernel net ;
|
||||
|
||||
UseHeaders [ FDirName $(SUBDIR) .. .. ] : true ;
|
||||
UseHeaders [ FDirName $(HAIKU_TOP) src libs compat freebsd_network compat ] : true ;
|
||||
|
||||
SubDirCcFlags [ FDefines _KERNEL=1 ] ;
|
||||
|
||||
KernelAddon pcnet :
|
||||
am7990.c
|
||||
am79900.c
|
||||
if_le_pci.c
|
||||
lance.c
|
||||
glue.c
|
||||
: libfreebsd_network.a
|
||||
;
|
||||
|
627
src/add-ons/kernel/drivers/network/pcnet/dev/le/am7990.c
Normal file
627
src/add-ons/kernel/drivers/network/pcnet/dev/le/am7990.c
Normal file
@ -0,0 +1,627 @@
|
||||
/* $NetBSD: am7990.c,v 1.68 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.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/dev/le/am7990.c,v 1.1.2.3 2006/06/18 15:43:18 marius Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_var.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/le/lancereg.h>
|
||||
#include <dev/le/lancevar.h>
|
||||
#include <dev/le/am7990reg.h>
|
||||
#include <dev/le/am7990var.h>
|
||||
|
||||
static void am7990_meminit(struct lance_softc *);
|
||||
static void am7990_rint(struct lance_softc *);
|
||||
static void am7990_tint(struct lance_softc *);
|
||||
static void am7990_start_locked(struct lance_softc *sc);
|
||||
|
||||
#ifdef LEDEBUG
|
||||
static void am7990_recv_print(struct lance_softc *, int);
|
||||
static void am7990_xmit_print(struct lance_softc *, int);
|
||||
#endif
|
||||
|
||||
int
|
||||
am7990_config(struct am7990_softc *sc, const char* name, int unit)
|
||||
{
|
||||
int error, mem;
|
||||
|
||||
sc->lsc.sc_meminit = am7990_meminit;
|
||||
sc->lsc.sc_start_locked = am7990_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
|
||||
am7990_detach(struct am7990_softc *sc)
|
||||
{
|
||||
|
||||
lance_detach(&sc->lsc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the initialization block and the descriptor rings.
|
||||
*/
|
||||
static void
|
||||
am7990_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_MODE_NORMAL | LE_MODE_PROM;
|
||||
else
|
||||
init.init_mode = LE_MODE_NORMAL;
|
||||
|
||||
init.init_padr[0] = (sc->sc_enaddr[1] << 8) | sc->sc_enaddr[0];
|
||||
init.init_padr[1] = (sc->sc_enaddr[3] << 8) | sc->sc_enaddr[2];
|
||||
init.init_padr[2] = (sc->sc_enaddr[5] << 8) | sc->sc_enaddr[4];
|
||||
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 = a;
|
||||
init.init_rlen = (a >> 16) | ((ffs(sc->sc_nrbuf) - 1) << 13);
|
||||
|
||||
a = sc->sc_addr + LE_TMDADDR(sc, 0);
|
||||
init.init_tdra = a;
|
||||
init.init_tlen = (a >> 16) | ((ffs(sc->sc_ntbuf) - 1) << 13);
|
||||
|
||||
(*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 = a;
|
||||
rmd.rmd1_hadr = a >> 16;
|
||||
rmd.rmd1_bits = LE_R1_OWN;
|
||||
rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
|
||||
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 = a;
|
||||
tmd.tmd1_hadr = a >> 16;
|
||||
tmd.tmd1_bits = 0;
|
||||
tmd.tmd2 = LE_XMD2_ONES;
|
||||
tmd.tmd3 = 0;
|
||||
(*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
|
||||
sizeof(tmd));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
am7990_rint(struct lance_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct mbuf *m;
|
||||
struct lermd rmd;
|
||||
int bix, rp;
|
||||
#if defined(LANCE_REVC_BUG)
|
||||
struct ether_header *eh;
|
||||
/* Make sure this is short-aligned, for ether_cmp(). */
|
||||
static uint16_t bcast_enaddr[3] = { ~0, ~0, ~0 };
|
||||
#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));
|
||||
|
||||
if (rmd.rmd1_bits & LE_R1_OWN)
|
||||
break;
|
||||
|
||||
m = NULL;
|
||||
if ((rmd.rmd1_bits & (LE_R1_ERR | LE_R1_STP | LE_R1_ENP)) !=
|
||||
(LE_R1_STP | LE_R1_ENP)) {
|
||||
if (rmd.rmd1_bits & LE_R1_ERR) {
|
||||
#ifdef LEDEBUG
|
||||
if (rmd.rmd1_bits & LE_R1_ENP) {
|
||||
if ((rmd.rmd1_bits & LE_R1_OFLO) == 0) {
|
||||
if (rmd.rmd1_bits & LE_R1_FRAM)
|
||||
if_printf(ifp,
|
||||
"framing error\n");
|
||||
if (rmd.rmd1_bits & LE_R1_CRC)
|
||||
if_printf(ifp,
|
||||
"crc mismatch\n");
|
||||
}
|
||||
} else
|
||||
if (rmd.rmd1_bits & LE_R1_OFLO)
|
||||
if_printf(ifp, "overflow\n");
|
||||
#endif
|
||||
if (rmd.rmd1_bits & LE_R1_BUFF)
|
||||
if_printf(ifp,
|
||||
"receive buffer error\n");
|
||||
} else if ((rmd.rmd1_bits & (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)
|
||||
am7990_recv_print(sc, bix);
|
||||
#endif
|
||||
/* Pull the packet off the interface. */
|
||||
m = lance_get(sc, LE_RBUFADDR(sc, bix),
|
||||
(int)rmd.rmd3 - ETHER_CRC_LEN);
|
||||
}
|
||||
|
||||
rmd.rmd1_bits = LE_R1_OWN;
|
||||
rmd.rmd2 = -LEBLEN | LE_XMD2_ONES;
|
||||
rmd.rmd3 = 0;
|
||||
(*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
|
||||
|
||||
if (++bix == sc->sc_nrbuf)
|
||||
bix = 0;
|
||||
|
||||
if (m != NULL) {
|
||||
ifp->if_ipackets++;
|
||||
|
||||
#ifdef LANCE_REVC_BUG
|
||||
/*
|
||||
* The old LANCE (Rev. C) chips have a bug which
|
||||
* causes garbage to be inserted in front of the
|
||||
* received packet. The workaround is to ignore
|
||||
* packets with an invalid destination address
|
||||
* (garbage will usually not match).
|
||||
* Of course, this precludes multicast support...
|
||||
*/
|
||||
eh = mtod(m, struct ether_header *);
|
||||
if (ether_cmp(eh->ether_dhost, sc->sc_enaddr) &&
|
||||
ether_cmp(eh->ether_dhost, bcast_enaddr)) {
|
||||
m_freem(m);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Pass the packet up. */
|
||||
LE_UNLOCK(sc);
|
||||
(*ifp->if_input)(ifp, m);
|
||||
LE_LOCK(sc);
|
||||
} else
|
||||
ifp->if_ierrors++;
|
||||
}
|
||||
|
||||
sc->sc_last_rd = bix;
|
||||
}
|
||||
|
||||
static void
|
||||
am7990_tint(struct lance_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct letmd tmd;
|
||||
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));
|
||||
|
||||
#ifdef LEDEBUG
|
||||
if (sc->sc_flags & LE_DEBUG)
|
||||
if_printf(ifp, "trans tmd: "
|
||||
"ladr %04x, hadr %02x, flags %02x, "
|
||||
"bcnt %04x, mcnt %04x\n",
|
||||
tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits,
|
||||
tmd.tmd2, tmd.tmd3);
|
||||
#endif
|
||||
|
||||
if (tmd.tmd1_bits & LE_T1_OWN)
|
||||
break;
|
||||
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
|
||||
if (tmd.tmd1_bits & LE_T1_ERR) {
|
||||
if (tmd.tmd3 & LE_T3_BUFF)
|
||||
if_printf(ifp, "transmit buffer error\n");
|
||||
else if (tmd.tmd3 & LE_T3_UFLO)
|
||||
if_printf(ifp, "underflow\n");
|
||||
if (tmd.tmd3 & (LE_T3_BUFF | LE_T3_UFLO)) {
|
||||
lance_init_locked(sc);
|
||||
return;
|
||||
}
|
||||
if (tmd.tmd3 & LE_T3_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 (tmd.tmd3 & LE_T3_LCOL)
|
||||
ifp->if_collisions++;
|
||||
if (tmd.tmd3 & LE_T3_RTRY) {
|
||||
#ifdef LEDEBUG
|
||||
if_printf(ifp, "excessive collisions, tdr %d\n",
|
||||
tmd.tmd3 & LE_T3_TDR_MASK);
|
||||
#endif
|
||||
ifp->if_collisions += 16;
|
||||
}
|
||||
ifp->if_oerrors++;
|
||||
} else {
|
||||
if (tmd.tmd1_bits & LE_T1_ONE)
|
||||
ifp->if_collisions++;
|
||||
else if (tmd.tmd1_bits & 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;
|
||||
|
||||
ifp->if_timer = sc->sc_no_td > 0 ? 5 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Controller interrupt
|
||||
*/
|
||||
void
|
||||
am7990_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)
|
||||
am7990_rint(sc);
|
||||
if (isr & LE_C0_TINT)
|
||||
am7990_tint(sc);
|
||||
|
||||
/* Enable interrupts again. */
|
||||
(*sc->sc_wrcsr)(sc, LE_CSR0, LE_C0_INEA);
|
||||
|
||||
if (!IFQ_DRV_IS_EMPTY(&ifp->if_snd))
|
||||
am7990_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
|
||||
am7990_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 (tmd.tmd1_bits & 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_bits = LE_T1_OWN | LE_T1_STP | LE_T1_ENP;
|
||||
tmd.tmd2 = -len | LE_XMD2_ONES;
|
||||
tmd.tmd3 = 0;
|
||||
|
||||
(*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
|
||||
|
||||
#ifdef LEDEBUG
|
||||
if (sc->sc_flags & LE_DEBUG)
|
||||
am7990_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)
|
||||
ifp->if_timer = 5;
|
||||
}
|
||||
|
||||
#ifdef LEDEBUG
|
||||
static void
|
||||
am7990_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 = rmd.rmd3;
|
||||
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,
|
||||
"ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
|
||||
rmd.rmd0, rmd.rmd1_hadr, rmd.rmd1_bits, rmd.rmd2, rmd.rmd3);
|
||||
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
|
||||
am7990_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 = -tmd.tmd2;
|
||||
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,
|
||||
"ladr %04x, hadr %02x, flags %02x, bcnt %04x, mcnt %04x\n",
|
||||
tmd.tmd0, tmd.tmd1_hadr, tmd.tmd1_bits, tmd.tmd2, tmd.tmd3);
|
||||
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 */
|
664
src/add-ons/kernel/drivers/network/pcnet/dev/le/am79900.c
Normal file
664
src/add-ons/kernel/drivers/network/pcnet/dev/le/am79900.c
Normal file
@ -0,0 +1,664 @@
|
||||
/* $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
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/dev/le/am79900.c,v 1.1.2.3 2006/06/18 15:43:18 marius Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/bpf.h>
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_var.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/le/lancereg.h>
|
||||
#include <dev/le/lancevar.h>
|
||||
#include <dev/le/am79900reg.h>
|
||||
#include <dev/le/am79900var.h>
|
||||
|
||||
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);
|
||||
(*ifp->if_input)(ifp, m);
|
||||
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;
|
||||
|
||||
ifp->if_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)
|
||||
ifp->if_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 */
|
156
src/add-ons/kernel/drivers/network/pcnet/dev/le/am79900reg.h
Normal file
156
src/add-ons/kernel/drivers/network/pcnet/dev/le/am79900reg.h
Normal file
@ -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.2.1 2006/02/13 11:30:40 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_ */
|
62
src/add-ons/kernel/drivers/network/pcnet/dev/le/am79900var.h
Normal file
62
src/add-ons/kernel/drivers/network/pcnet/dev/le/am79900var.h
Normal file
@ -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.2.1 2006/02/13 11:30:40 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_ */
|
189
src/add-ons/kernel/drivers/network/pcnet/dev/le/am7990reg.h
Normal file
189
src/add-ons/kernel/drivers/network/pcnet/dev/le/am7990reg.h
Normal file
@ -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.2.1 2006/02/13 11:30:40 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_ */
|
62
src/add-ons/kernel/drivers/network/pcnet/dev/le/am7990var.h
Normal file
62
src/add-ons/kernel/drivers/network/pcnet/dev/le/am7990var.h
Normal file
@ -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.2.1 2006/02/13 11:30:40 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_ */
|
3
src/add-ons/kernel/drivers/network/pcnet/dev/le/glue.c
Normal file
3
src/add-ons/kernel/drivers/network/pcnet/dev/le/glue.c
Normal file
@ -0,0 +1,3 @@
|
||||
#include <sys/bus.h>
|
||||
|
||||
HAIKU_FBSD_DRIVER_GLUE(pcnet, le, pci)
|
530
src/add-ons/kernel/drivers/network/pcnet/dev/le/if_le_ledma.c
Normal file
530
src/add-ons/kernel/drivers/network/pcnet/dev/le/if_le_ledma.c
Normal file
@ -0,0 +1,530 @@
|
||||
/* $NetBSD: if_le_ledma.c,v 1.26 2005/12/11 12:23:44 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; Jason R. Thorpe of the Numerical Aerospace
|
||||
* Simulation Facility, NASA Ames Research Center; Paul Kranenburg.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/dev/le/if_le_ledma.c,v 1.1.2.2 2006/06/18 15:43:18 marius Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/ofw_machdep.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <sparc64/sbus/lsi64854reg.h>
|
||||
#include <sparc64/sbus/lsi64854var.h>
|
||||
|
||||
#include <dev/le/lancereg.h>
|
||||
#include <dev/le/lancevar.h>
|
||||
#include <dev/le/am7990var.h>
|
||||
|
||||
#define LEDMA_ALIGNMENT 8 /* ring desc. alignmet for NCR92C990 */
|
||||
#define LEDMA_BOUNDARY (16*1024*1024) /* must not cross 16MB boundary */
|
||||
#define LEDMA_MEMSIZE (16*1024) /* LANCE memory size */
|
||||
#define LEREG1_RDP 0 /* Register Data Port */
|
||||
#define LEREG1_RAP 2 /* Register Address Port */
|
||||
|
||||
struct le_dma_softc {
|
||||
struct am7990_softc sc_am7990; /* 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_dmat;
|
||||
bus_dmamap_t sc_dmam;
|
||||
bus_addr_t sc_laddr; /* LANCE DMA address */
|
||||
|
||||
struct lsi64854_softc *sc_dma; /* pointer to DMA engine */
|
||||
int sc_dodrain;
|
||||
};
|
||||
|
||||
static device_probe_t le_dma_probe;
|
||||
static device_attach_t le_dma_attach;
|
||||
static device_detach_t le_dma_detach;
|
||||
static device_resume_t le_dma_resume;
|
||||
static device_suspend_t le_dma_suspend;
|
||||
|
||||
static device_method_t le_dma_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, le_dma_probe),
|
||||
DEVMETHOD(device_attach, le_dma_attach),
|
||||
DEVMETHOD(device_detach, le_dma_detach),
|
||||
/* We can just use the suspend method here. */
|
||||
DEVMETHOD(device_shutdown, le_dma_suspend),
|
||||
DEVMETHOD(device_suspend, le_dma_suspend),
|
||||
DEVMETHOD(device_resume, le_dma_resume),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
DEFINE_CLASS_0(le, le_dma_driver, le_dma_methods, sizeof(struct le_dma_softc));
|
||||
DRIVER_MODULE(le, dma, le_dma_driver, le_devclass, 0, 0);
|
||||
MODULE_DEPEND(le, ether, 1, 1, 1);
|
||||
|
||||
/*
|
||||
* Media types supported
|
||||
*/
|
||||
static const int le_dma_supmedia[] = {
|
||||
IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, 0),
|
||||
IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0),
|
||||
IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, 0)
|
||||
};
|
||||
|
||||
static void le_dma_wrcsr(struct lance_softc *, uint16_t, uint16_t);
|
||||
static uint16_t le_dma_rdcsr(struct lance_softc *, uint16_t);
|
||||
static void le_dma_setutp(struct lance_softc *);
|
||||
static void le_dma_setaui(struct lance_softc *);
|
||||
static int le_dma_supmediachange(struct lance_softc *);
|
||||
static void le_dma_supmediastatus(struct lance_softc *, struct ifmediareq *);
|
||||
static void le_dma_hwreset(struct lance_softc *);
|
||||
static int le_dma_hwintr(struct lance_softc *);
|
||||
static void le_dma_nocarrier(struct lance_softc *);
|
||||
static bus_dmamap_callback_t le_dma_dma_callback;
|
||||
|
||||
static void
|
||||
le_dma_wrcsr(struct lance_softc *sc, uint16_t port, uint16_t val)
|
||||
{
|
||||
struct le_dma_softc *lesc = (struct le_dma_softc *)sc;
|
||||
|
||||
bus_space_write_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, port);
|
||||
bus_space_barrier(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, 2,
|
||||
BUS_SPACE_BARRIER_WRITE);
|
||||
bus_space_write_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RDP, val);
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
le_dma_rdcsr(struct lance_softc *sc, uint16_t port)
|
||||
{
|
||||
struct le_dma_softc *lesc = (struct le_dma_softc *)sc;
|
||||
|
||||
bus_space_write_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, port);
|
||||
bus_space_barrier(lesc->sc_regt, lesc->sc_regh, LEREG1_RAP, 2,
|
||||
BUS_SPACE_BARRIER_WRITE);
|
||||
return (bus_space_read_2(lesc->sc_regt, lesc->sc_regh, LEREG1_RDP));
|
||||
}
|
||||
|
||||
static void
|
||||
le_dma_setutp(struct lance_softc *sc)
|
||||
{
|
||||
struct lsi64854_softc *dma = ((struct le_dma_softc *)sc)->sc_dma;
|
||||
|
||||
L64854_SCSR(dma, L64854_GCSR(dma) | E_TP_AUI);
|
||||
DELAY(20000); /* We must not touch the LANCE chip for 20ms. */
|
||||
}
|
||||
|
||||
static void
|
||||
le_dma_setaui(struct lance_softc *sc)
|
||||
{
|
||||
struct lsi64854_softc *dma = ((struct le_dma_softc *)sc)->sc_dma;
|
||||
|
||||
L64854_SCSR(dma, L64854_GCSR(dma) & ~E_TP_AUI);
|
||||
DELAY(20000); /* We must not touch the LANCE chip for 20ms. */
|
||||
}
|
||||
|
||||
static int
|
||||
le_dma_supmediachange(struct lance_softc *sc)
|
||||
{
|
||||
struct ifmedia *ifm = &sc->sc_media;
|
||||
|
||||
if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
|
||||
return (EINVAL);
|
||||
|
||||
/*
|
||||
* Switch to the selected media. If autoselect is set, we don't
|
||||
* really have to do anything. We'll switch to the other media
|
||||
* when we detect loss of carrier.
|
||||
*/
|
||||
switch (IFM_SUBTYPE(ifm->ifm_media)) {
|
||||
case IFM_10_T:
|
||||
le_dma_setutp(sc);
|
||||
break;
|
||||
|
||||
case IFM_10_5:
|
||||
le_dma_setaui(sc);
|
||||
break;
|
||||
|
||||
case IFM_AUTO:
|
||||
break;
|
||||
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
le_dma_supmediastatus(struct lance_softc *sc, struct ifmediareq *ifmr)
|
||||
{
|
||||
struct lsi64854_softc *dma = ((struct le_dma_softc *)sc)->sc_dma;
|
||||
|
||||
/*
|
||||
* Notify the world which media we're currently using.
|
||||
*/
|
||||
if (L64854_GCSR(dma) & E_TP_AUI)
|
||||
ifmr->ifm_active = IFM_MAKEWORD(IFM_ETHER, IFM_10_T, 0, 0);
|
||||
else
|
||||
ifmr->ifm_active = IFM_MAKEWORD(IFM_ETHER, IFM_10_5, 0, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
le_dma_hwreset(struct lance_softc *sc)
|
||||
{
|
||||
struct le_dma_softc *lesc = (struct le_dma_softc *)sc;
|
||||
struct lsi64854_softc *dma = lesc->sc_dma;
|
||||
uint32_t aui_bit, csr;
|
||||
|
||||
/*
|
||||
* Reset DMA channel.
|
||||
*/
|
||||
csr = L64854_GCSR(dma);
|
||||
aui_bit = csr & E_TP_AUI;
|
||||
DMA_RESET(dma);
|
||||
|
||||
/* Write bits 24-31 of Lance address. */
|
||||
bus_space_write_4(dma->sc_regt, dma->sc_regh, L64854_REG_ENBAR,
|
||||
lesc->sc_laddr & 0xff000000);
|
||||
|
||||
DMA_ENINTR(dma);
|
||||
|
||||
/*
|
||||
* Disable E-cache invalidates on chip writes.
|
||||
* Retain previous cable selection bit.
|
||||
*/
|
||||
csr = L64854_GCSR(dma);
|
||||
csr |= (E_DSBL_WR_INVAL | aui_bit);
|
||||
L64854_SCSR(dma, csr);
|
||||
DELAY(20000); /* We must not touch the LANCE chip for 20ms. */
|
||||
}
|
||||
|
||||
static int
|
||||
le_dma_hwintr(struct lance_softc *sc)
|
||||
{
|
||||
struct le_dma_softc *lesc = (struct le_dma_softc *)sc;
|
||||
struct lsi64854_softc *dma = lesc->sc_dma;
|
||||
|
||||
#if 0
|
||||
return (DMA_INTR(dma));
|
||||
#else
|
||||
/*
|
||||
* Inlined version of lsi64854_enet_intr() from rev. 1.8 of
|
||||
* sys/sparc64/sbus/lsi64854.c in order to not break the API
|
||||
* of the LSI64854 driver in RELENG_6.
|
||||
*/
|
||||
uint32_t csr;
|
||||
int i, rv;
|
||||
|
||||
csr = L64854_GCSR(dma);
|
||||
|
||||
/* If the DMA logic shows an interrupt, claim it */
|
||||
rv = ((csr & E_INT_PEND) != 0) ? 1 : 0;
|
||||
|
||||
if (csr & (E_ERR_PEND|E_SLAVE_ERR)) {
|
||||
device_printf(dma->sc_dev, "error: csr=%b\n", csr,
|
||||
EDMACSR_BITS);
|
||||
csr &= ~L64854_EN_DMA; /* Stop DMA */
|
||||
/* Invalidate the queue; SLAVE_ERR bit is write-to-clear */
|
||||
csr |= E_INVALIDATE|E_SLAVE_ERR;
|
||||
L64854_SCSR(dma, csr);
|
||||
/* Will be drained with the LE_C0_IDON interrupt. */
|
||||
lesc->sc_dodrain = 1;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* XXX - is this necessary with E_DSBL_WR_INVAL on? */
|
||||
if (lesc->sc_dodrain) {
|
||||
i = 10;
|
||||
csr |= E_DRAIN;
|
||||
L64854_SCSR(dma, csr);
|
||||
while (i-- > 0 && (L64854_GCSR(dma) & E_DRAINING))
|
||||
DELAY(1);
|
||||
lesc->sc_dodrain = 0;
|
||||
}
|
||||
|
||||
return (rv);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
le_dma_nocarrier(struct lance_softc *sc)
|
||||
{
|
||||
struct le_dma_softc *lesc = (struct le_dma_softc *)sc;
|
||||
|
||||
/*
|
||||
* Check if the user has requested a certain cable type, and
|
||||
* if so, honor that request.
|
||||
*/
|
||||
|
||||
if (L64854_GCSR(lesc->sc_dma) & E_TP_AUI) {
|
||||
switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) {
|
||||
case IFM_10_5:
|
||||
case IFM_AUTO:
|
||||
if_printf(sc->sc_ifp, "lost carrier on UTP port, "
|
||||
"switching to AUI port\n");
|
||||
le_dma_setaui(sc);
|
||||
}
|
||||
} else {
|
||||
switch (IFM_SUBTYPE(sc->sc_media.ifm_media)) {
|
||||
case IFM_10_T:
|
||||
case IFM_AUTO:
|
||||
if_printf(sc->sc_ifp, "lost carrier on AUI port, "
|
||||
"switching to UTP port\n");
|
||||
le_dma_setutp(sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
le_dma_dma_callback(void *xsc, bus_dma_segment_t *segs, int nsegs, int error)
|
||||
{
|
||||
struct le_dma_softc *lesc = (struct le_dma_softc *)xsc;
|
||||
|
||||
if (error != 0)
|
||||
return;
|
||||
KASSERT(nsegs == 1, ("%s: bad DMA segment count", __func__));
|
||||
lesc->sc_laddr = segs[0].ds_addr;
|
||||
}
|
||||
|
||||
static int
|
||||
le_dma_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (strcmp(ofw_bus_get_name(dev), "le") == 0) {
|
||||
device_set_desc(dev, "LANCE Ethernet");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
le_dma_attach(device_t dev)
|
||||
{
|
||||
struct le_dma_softc *lesc;
|
||||
struct lsi64854_softc *dma;
|
||||
struct lance_softc *sc;
|
||||
int error;
|
||||
|
||||
lesc = device_get_softc(dev);
|
||||
sc = &lesc->sc_am7990.lsc;
|
||||
|
||||
LE_LOCK_INIT(sc, device_get_nameunit(dev));
|
||||
|
||||
/*
|
||||
* Establish link to `ledma' device.
|
||||
* XXX hackery.
|
||||
*/
|
||||
dma = (struct lsi64854_softc *)device_get_softc(device_get_parent(dev));
|
||||
lesc->sc_dma = dma;
|
||||
lesc->sc_dma->sc_client = lesc;
|
||||
|
||||
lesc->sc_rrid = 0;
|
||||
lesc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&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;
|
||||
}
|
||||
|
||||
sc->sc_memsize = LEDMA_MEMSIZE;
|
||||
error = bus_dma_tag_create(
|
||||
dma->sc_parent_dmat, /* parent */
|
||||
LEDMA_ALIGNMENT, /* alignment */
|
||||
LEDMA_BOUNDARY, /* boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
sc->sc_memsize, /* maxsize */
|
||||
1, /* nsegments */
|
||||
sc->sc_memsize, /* maxsegsize */
|
||||
BUS_DMA_WAITOK, /* flags */
|
||||
NULL, NULL, /* lockfunc, lockarg */
|
||||
&lesc->sc_dmat);
|
||||
if (error != 0) {
|
||||
device_printf(dev, "cannot allocate buffer DMA tag\n");
|
||||
goto fail_ires;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
lesc->sc_laddr = 0;
|
||||
error = bus_dmamap_load(lesc->sc_dmat, lesc->sc_dmam, sc->sc_mem,
|
||||
sc->sc_memsize, le_dma_dma_callback, lesc, 0);
|
||||
if (error != 0 || lesc->sc_laddr == 0) {
|
||||
device_printf(dev, "cannot load DMA buffer map\n");
|
||||
goto fail_dmem;
|
||||
}
|
||||
|
||||
sc->sc_addr = lesc->sc_laddr & 0xffffff;
|
||||
sc->sc_flags = 0;
|
||||
sc->sc_conf3 = LE_C3_BSWP | LE_C3_ACON | LE_C3_BCON;
|
||||
|
||||
sc->sc_mediachange = le_dma_supmediachange;
|
||||
sc->sc_mediastatus = le_dma_supmediastatus;
|
||||
sc->sc_supmedia = le_dma_supmedia;
|
||||
sc->sc_nsupmedia = sizeof(le_dma_supmedia) / sizeof(le_dma_supmedia[0]);
|
||||
sc->sc_defaultmedia = le_dma_supmedia[0];
|
||||
|
||||
OF_getetheraddr(dev, sc->sc_enaddr);
|
||||
|
||||
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_dma_rdcsr;
|
||||
sc->sc_wrcsr = le_dma_wrcsr;
|
||||
sc->sc_hwreset = le_dma_hwreset;
|
||||
sc->sc_hwintr = le_dma_hwintr;
|
||||
sc->sc_nocarrier = le_dma_nocarrier;
|
||||
|
||||
error = am7990_config(&lesc->sc_am7990, device_get_name(dev),
|
||||
device_get_unit(dev));
|
||||
if (error != 0) {
|
||||
device_printf(dev, "cannot attach Am7990\n");
|
||||
goto fail_dmap;
|
||||
}
|
||||
|
||||
error = bus_setup_intr(dev, lesc->sc_ires, INTR_TYPE_NET | INTR_MPSAFE,
|
||||
am7990_intr, sc, &lesc->sc_ih);
|
||||
if (error != 0) {
|
||||
device_printf(dev, "cannot set up interrupt\n");
|
||||
goto fail_am7990;
|
||||
}
|
||||
|
||||
return (0);
|
||||
|
||||
fail_am7990:
|
||||
am7990_detach(&lesc->sc_am7990);
|
||||
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_ires:
|
||||
bus_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires);
|
||||
fail_rres:
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, lesc->sc_rrid, lesc->sc_rres);
|
||||
fail_mtx:
|
||||
LE_LOCK_DESTROY(sc);
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
le_dma_detach(device_t dev)
|
||||
{
|
||||
struct le_dma_softc *lesc;
|
||||
struct lance_softc *sc;
|
||||
|
||||
lesc = device_get_softc(dev);
|
||||
sc = &lesc->sc_am7990.lsc;
|
||||
|
||||
bus_teardown_intr(dev, lesc->sc_ires, lesc->sc_ih);
|
||||
am7990_detach(&lesc->sc_am7990);
|
||||
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_release_resource(dev, SYS_RES_IRQ, lesc->sc_irid, lesc->sc_ires);
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, lesc->sc_rrid, lesc->sc_rres);
|
||||
LE_LOCK_DESTROY(sc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
le_dma_suspend(device_t dev)
|
||||
{
|
||||
struct le_dma_softc *lesc;
|
||||
|
||||
lesc = device_get_softc(dev);
|
||||
|
||||
lance_suspend(&lesc->sc_am7990.lsc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
le_dma_resume(device_t dev)
|
||||
{
|
||||
struct le_dma_softc *lesc;
|
||||
|
||||
lesc = device_get_softc(dev);
|
||||
|
||||
lance_resume(&lesc->sc_am7990.lsc);
|
||||
|
||||
return (0);
|
||||
}
|
516
src/add-ons/kernel/drivers/network/pcnet/dev/le/if_le_pci.c
Normal file
516
src/add-ons/kernel/drivers/network/pcnet/dev/le/if_le_pci.c
Normal file
@ -0,0 +1,516 @@
|
||||
/* $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
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/dev/le/if_le_pci.c,v 1.1.2.2 2006/06/18 15:43:18 marius Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_media.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
|
||||
#include <dev/le/lancereg.h>
|
||||
#include <dev/le/lancevar.h>
|
||||
#include <dev/le/am79900var.h>
|
||||
|
||||
#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;
|
||||
};
|
||||
|
||||
static device_probe_t le_pci_probe;
|
||||
static device_attach_t le_pci_attach;
|
||||
static device_detach_t le_pci_detach;
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static 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 lnc(4) and pcn(4) win. */
|
||||
return (BUS_PROBE_LOW_PRIORITY);
|
||||
case AMD_PCNET_HOME:
|
||||
device_set_desc(dev, "AMD PCnet-Home");
|
||||
/* Let lnc(4) and pcn(4) win. */
|
||||
return (BUS_PROBE_LOW_PRIORITY);
|
||||
default:
|
||||
return (ENXIO);
|
||||
}
|
||||
}
|
||||
|
||||
static 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(
|
||||
NULL, /* 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 */
|
||||
BUS_DMA_WAITOK, /* 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;
|
||||
/*
|
||||
* 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 */
|
||||
BUS_DMA_WAITOK, /* 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,
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
804
src/add-ons/kernel/drivers/network/pcnet/dev/le/lance.c
Normal file
804
src/add-ons/kernel/drivers/network/pcnet/dev/le/lance.c
Normal file
@ -0,0 +1,804 @@
|
||||
/* $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
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/sys/dev/le/lance.c,v 1.1.2.2 2006/06/18 15:43:18 marius Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/mutex.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/sockio.h>
|
||||
|
||||
#include <net/ethernet.h>
|
||||
#include <net/if.h>
|
||||
#include <net/if_arp.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_media.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/if_vlan_var.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <dev/le/lancereg.h>
|
||||
#include <dev/le/lancevar.h>
|
||||
|
||||
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(struct ifnet *);
|
||||
static int lance_mediachange(struct ifnet *);
|
||||
static void lance_mediastatus(struct ifnet *, struct ifmediareq *);
|
||||
static int lance_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
|
||||
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);
|
||||
|
||||
/* Initialize ifnet structure. */
|
||||
ifp->if_softc = sc;
|
||||
if_initname(ifp, name, unit);
|
||||
ifp->if_start = lance_start;
|
||||
ifp->if_ioctl = lance_ioctl;
|
||||
ifp->if_watchdog = lance_watchdog;
|
||||
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));
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
void
|
||||
lance_detach(struct lance_softc *sc)
|
||||
{
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
LE_LOCK(sc);
|
||||
lance_stop(sc);
|
||||
LE_UNLOCK(sc);
|
||||
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);
|
||||
ifp->if_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);
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/* Set the current media. */
|
||||
if (sc->sc_mediachange)
|
||||
(void)(*sc->sc_mediachange)(sc);
|
||||
|
||||
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;
|
||||
ifp->if_timer = 0;
|
||||
(*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(struct ifnet *ifp)
|
||||
{
|
||||
struct lance_softc *sc = ifp->if_softc;
|
||||
|
||||
LE_LOCK(sc);
|
||||
if_printf(ifp, "device timeout\n");
|
||||
++ifp->if_oerrors;
|
||||
lance_init_locked(sc);
|
||||
LE_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
lance_mediachange(struct ifnet *ifp)
|
||||
{
|
||||
struct lance_softc *sc = ifp->if_softc;
|
||||
int error;
|
||||
|
||||
if (sc->sc_mediachange) {
|
||||
LE_LOCK(sc);
|
||||
error = (*sc->sc_mediachange)(sc);
|
||||
LE_UNLOCK(sc);
|
||||
return (error);
|
||||
}
|
||||
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
|
||||
lance_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
|
||||
{
|
||||
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:
|
||||
/*
|
||||
* 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;
|
||||
struct ifmultiaddr *ifma;
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 */
|
619
src/add-ons/kernel/drivers/network/pcnet/dev/le/lancereg.h
Normal file
619
src/add-ons/kernel/drivers/network/pcnet/dev/le/lancereg.h
Normal file
@ -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.1.2.2 2006/06/18 15:43:18 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_ */
|
214
src/add-ons/kernel/drivers/network/pcnet/dev/le/lancevar.h
Normal file
214
src/add-ons/kernel/drivers/network/pcnet/dev/le/lancevar.h
Normal file
@ -0,0 +1,214 @@
|
||||
/* $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.1.2.2 2006/06/18 15:43:18 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;
|
||||
|
||||
/*
|
||||
* 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 <machine/inlines.h> 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_ */
|
Loading…
Reference in New Issue
Block a user