Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/ic Driver for Davicom DM9000 ethernet chips.



details:   https://anonhg.NetBSD.org/src/rev/6b739933430a
branches:  trunk
changeset: 757631:6b739933430a
user:      ahoka <ahoka%NetBSD.org@localhost>
date:      Wed Sep 08 22:01:29 2010 +0000

description:
Driver for Davicom DM9000 ethernet chips.

Written by Paul Fleischer, minor modifications by me.

diffstat:

 sys/dev/ic/dm9000.c    |  843 +++++++++++++++++++++++++++++++++++++++++++++++++
 sys/dev/ic/dm9000reg.h |  202 +++++++++++
 sys/dev/ic/dm9000var.h |  146 ++++++++
 3 files changed, 1191 insertions(+), 0 deletions(-)

diffs (truncated from 1203 to 300 lines):

diff -r 3465b34967d0 -r 6b739933430a sys/dev/ic/dm9000.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/ic/dm9000.c       Wed Sep 08 22:01:29 2010 +0000
@@ -0,0 +1,843 @@
+/*     $NetBSD: dm9000.c,v 1.1 2010/09/08 22:01:29 ahoka Exp $ */
+
+/*
+ * Copyright (c) 2009 Paul Fleischer
+ * All rights reserved.
+ *
+ * 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. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ */
+
+/* based on sys/dev/ic/cs89x0.c */
+/*
+ * Copyright (c) 2004 Christopher Gilbert
+ * All rights reserved.
+ *
+ * 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. The name of the company nor the name of the author may be used to
+ *    endorse or promote products derived from this software without specific
+ *    prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 1997
+ * Digital Equipment Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and conditions.
+ * Subject to these conditions, you may download, copy, install,
+ * use, modify and distribute this software in source and/or binary
+ * form. No title or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ *    and retain this copyright notice and list of conditions as
+ *    they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or logo of
+ *    Digital Equipment Corporation. Neither the "Digital Equipment
+ *    Corporation" name nor any trademark or logo of Digital Equipment
+ *    Corporation may be used to endorse or promote products derived
+ *    from this software without the prior written permission of
+ *    Digital Equipment Corporation.
+ *
+ * 3) This software is provided "AS-IS" and any express or implied
+ *    warranties, including but not limited to, any implied warranties
+ *    of merchantability, fitness for a particular purpose, or
+ *    non-infringement are disclaimed. In no event shall DIGITAL be
+ *    liable for any damages whatsoever, and in particular, DIGITAL
+ *    shall not be liable for special, indirect, consequential, or
+ *    incidental damages or damages for lost profits, loss of
+ *    revenue or loss of use, whether such damages arise in contract,
+ *    negligence, tort, under statute, in equity, at law or otherwise,
+ *    even if advised of the possibility of such damage.
+ */
+
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/syslog.h>
+#include <sys/socket.h>
+#include <sys/device.h>
+#include <sys/malloc.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+
+#include <net/if.h>
+#include <net/if_ether.h>
+#include <net/if_media.h>
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_inarp.h>
+#endif
+
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+
+#include <sys/bus.h>
+#include <sys/intr.h>
+
+#include <dev/ic/dm9000var.h>
+#include <dev/ic/dm9000reg.h>
+
+#if 1
+#undef DM9000_DEBUG
+#undef  DM9000_TX_DEBUG
+#undef DM9000_TX_DATA_DEBUG
+#undef DM9000_RX_DEBUG
+#undef  DM9000_RX_DATA_DEBUG
+#else
+#define DM9000_DEBUG
+#define  DM9000_TX_DEBUG
+#define DM9000_TX_DATA_DEBUG
+#define DM9000_RX_DEBUG
+#define  DM9000_RX_DATA_DEBUG
+#endif
+
+#ifdef DM9000_DEBUG
+#define DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0)
+#else
+#define DPRINTF(s) do {} while (/*CONSTCOND*/0)
+#endif
+
+#ifdef DM9000_TX_DEBUG
+#define TX_DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0)
+#else
+#define TX_DPRINTF(s) do {} while (/*CONSTCOND*/0)
+#endif
+
+#ifdef DM9000_RX_DEBUG
+#define RX_DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0)
+#else
+#define RX_DPRINTF(s) do {} while (/*CONSTCOND*/0)
+#endif
+
+#ifdef DM9000_RX_DATA_DEBUG
+#define RX_DATA_DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0)
+#else
+#define RX_DATA_DPRINTF(s) do {} while (/*CONSTCOND*/0)
+#endif
+
+#ifdef DM9000_TX_DATA_DEBUG
+#define TX_DATA_DPRINTF(s) do {printf s; } while (/*CONSTCOND*/0)
+#else
+#define TX_DATA_DPRINTF(s) do {} while (/*CONSTCOND*/0)
+#endif
+
+
+uint16_t dme_phy_read(struct dme_softc *sc, int reg);
+void dme_phy_write(struct dme_softc *sc, int reg, uint16_t value);
+
+/*** Methods registered in struct ifnet ***/
+void   dme_start_output(struct ifnet *ifp);
+int    dme_init(struct ifnet *ifp);
+int    dme_ioctl(struct ifnet *ifp, u_long cmd, void *data);
+void   dme_stop(struct ifnet *ifp, int disable);
+
+int    dme_mediachange(struct ifnet *ifp);
+void   dme_mediastatus(struct ifnet *ufp, struct ifmediareq *ifmr);
+
+/*** Internal methods ***/
+
+/* Prepare data to be transmitted (i.e. dequeue and load it into the DM9000) */
+void    dme_prepare(struct dme_softc *sc, struct ifnet *ifp);
+
+/* Transmit prepared data */
+void    dme_transmit(struct dme_softc *sc);
+
+/* Receive data */
+void    dme_receive(struct dme_softc *sc, struct ifnet *ifp);
+
+/* Software Initialize/Reset of the DM9000 */
+void    dme_reset(struct dme_softc *sc);
+
+uint16_t
+dme_phy_read(struct dme_softc *sc, int reg)
+{
+       uint16_t val;
+       /* Select Register to read*/
+       dme_write(sc, DM9000_EPAR, DM9000_EPAR_INT_PHY +
+           (reg & DM9000_EPAR_EROA_MASK));
+       /* Select read operation (DM9000_EPCR_ERPRR) from the PHY */
+       dme_write(sc, DM9000_EPCR, DM9000_EPCR_ERPRR + DM9000_EPCR_EPOS_PHY);
+
+       /* Wait until access to PHY has completed */
+       while (dme_read(sc, DM9000_EPCR) & DM9000_EPCR_ERRE);
+
+       /* XXX: The delay is probably not necessary as we just busy-waited */
+       delay(200);
+
+       /* Reset ERPRR-bit */
+       dme_write(sc, DM9000_EPCR, DM9000_EPCR_EPOS_PHY);
+
+       val = dme_read(sc, DM9000_EPDRL);
+       val += dme_read(sc, DM9000_EPDRH) << 8;
+
+       return val;
+}
+
+void
+dme_phy_write(struct dme_softc *sc, int reg, uint16_t value)
+{
+       /* Select Register to write*/
+       dme_write(sc, DM9000_EPAR, DM9000_EPAR_INT_PHY +
+           (reg & DM9000_EPAR_EROA_MASK));
+
+       /* Write data to the two data registers */
+       dme_write(sc, DM9000_EPDRL, value & 0xFF);
+       dme_write(sc, DM9000_EPDRH, (value >> 8) & 0xFF);
+
+       /* Select write operation (DM9000_EPCR_ERPRW) from the PHY */
+       dme_write(sc, DM9000_EPCR, DM9000_EPCR_ERPRW + DM9000_EPCR_EPOS_PHY);
+
+       /* Wait until access to PHY has completed */
+       while(dme_read(sc, DM9000_EPCR) & DM9000_EPCR_ERRE);
+
+
+       /* XXX: The delay is probably not necessary as we just busy-waited */
+       delay(200);
+
+       /* Reset ERPRR-bit */
+       dme_write(sc, DM9000_EPCR, DM9000_EPCR_EPOS_PHY);
+}
+
+int
+dme_attach(struct dme_softc *sc, uint8_t *enaddr)
+{
+       struct ifnet *ifp = &sc->sc_ethercom.ec_if;
+       uint8_t b[2];
+
+       dme_read_c(sc, DM9000_VID0, b, 2);
+#if BYTE_ORDER == BIG_ENDIAN
+       sc->sc_vendor_id = (b[0] << 8) | b[1];
+#else
+       sc->sc_vendor_id = b[0] | (b[1] << 8);
+#endif
+       dme_read_c(sc, DM9000_PID0, b, 2);
+#if BYTE_ORDER == BIG_ENDIAN
+       sc->sc_product_id = (b[0] << 8) | b[1];
+#else
+       sc->sc_product_id = b[0] | (b[1] << 8);
+#endif
+       /* TODO: Check the vendor ID as well */
+       if (sc->sc_product_id != 0x9000) {
+               panic("dme_attach: product id mismatch (0x%hx != 0x9000)",
+                   sc->sc_product_id);
+       }
+
+#if 0
+       {
+               /* Force 10Mbps to test dme_phy_write */
+               uint16_t bmcr;
+               bmcr = dme_phy_read(sc, DM9000_PHY_BMCR);
+               bmcr &= ~DM9000_PHY_BMCR_AUTO_NEG_EN;
+               bmcr &= ~DM9000_PHY_BMCR_SPEED_SELECT; /* select 100Mbps */
+               dme_phy_write(sc, DM9000_PHY_BMCR, bmcr);
+       }
+#endif
+       /* Initialize ifnet structure. */
+       strlcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ);
+       ifp->if_softc = sc;
+       ifp->if_start = dme_start_output;
+       ifp->if_init = dme_init;
+       ifp->if_ioctl = dme_ioctl;
+       ifp->if_stop = dme_stop;
+       ifp->if_watchdog = NULL;        /* no watchdog at this stage */
+       ifp->if_flags = IFF_SIMPLEX | IFF_NOTRAILERS |
+               IFF_BROADCAST; /* No multicast support for now */
+       IFQ_SET_READY(&ifp->if_snd);
+
+       /* Initialize ifmedia structures. */
+       ifmedia_init(&sc->sc_media, 0, dme_mediachange, dme_mediastatus);
+       ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_T|IFM_100_TX, 0, NULL);
+       ifmedia_set(&sc->sc_media, IFM_ETHER|IFM_10_T|IFM_100_TX);
+
+       if (enaddr != NULL)
+               memcpy(sc->sc_enaddr, enaddr, sizeof(sc->sc_enaddr));
+
+       /* Configure DM9000 with the MAC address */
+       dme_write_c(sc, DM9000_PAB0, sc->sc_enaddr, 6);
+
+#ifdef DM9000_DEBUG



Home | Main Index | Thread Index | Old Index