[haiku-commits] r42391 - in haiku/vendor/freebsd/current: dev dev/dc dev/fxp dev/mii dev/xl ...

  • From: zharik@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 8 Jul 2011 22:06:15 +0200 (CEST)

Author: siarzhuk
Date: 2011-07-08 22:06:13 +0200 (Fri, 08 Jul 2011)
New Revision: 42391
Changeset: https://dev.haiku-os.org/changeset/42391

Added:
   haiku/vendor/freebsd/current/dev/dc/
   haiku/vendor/freebsd/current/dev/dc/dcphy.c
   haiku/vendor/freebsd/current/dev/dc/if_dc.c
   haiku/vendor/freebsd/current/dev/dc/if_dcreg.h
   haiku/vendor/freebsd/current/dev/dc/pnphy.c
   haiku/vendor/freebsd/current/dev/mii/acphy.c
   haiku/vendor/freebsd/current/dev/mii/acphyreg.h
   haiku/vendor/freebsd/current/dev/mii/amphy.c
   haiku/vendor/freebsd/current/dev/mii/amphyreg.h
   haiku/vendor/freebsd/current/dev/xl/
   haiku/vendor/freebsd/current/dev/xl/if_xl.c
   haiku/vendor/freebsd/current/dev/xl/if_xlreg.h
Removed:
   haiku/vendor/freebsd/current/pci/if_xl.c
   haiku/vendor/freebsd/current/pci/if_xlreg.h
Modified:
   haiku/vendor/freebsd/current/dev/fxp/if_fxp.c
   haiku/vendor/freebsd/current/dev/fxp/if_fxpreg.h
   haiku/vendor/freebsd/current/dev/fxp/if_fxpvar.h
   haiku/vendor/freebsd/current/dev/fxp/rcvbundl.h
   haiku/vendor/freebsd/current/dev/mii/bmtphy.c
   haiku/vendor/freebsd/current/dev/mii/bmtphyreg.h
   haiku/vendor/freebsd/current/dev/mii/exphy.c
   haiku/vendor/freebsd/current/dev/mii/inphy.c
   haiku/vendor/freebsd/current/dev/mii/inphyreg.h
   haiku/vendor/freebsd/current/dev/mii/rlphy.c
   haiku/vendor/freebsd/current/dev/mii/ukphy.c
   haiku/vendor/freebsd/current/dev/mii/ukphy_subr.c
   haiku/vendor/freebsd/current/pci/if_rl.c
   haiku/vendor/freebsd/current/pci/if_rlreg.h
Log:
* Porting DEC/21143 "dc" driver to Haiku;
* Updating ipro100 ("fxp"), rtl8139 ("rl"), 3com ("xl") and related mii modules
  to FreeBSD RELEASE_8_2_0.



Added: haiku/vendor/freebsd/current/dev/dc/dcphy.c
===================================================================
--- haiku/vendor/freebsd/current/dev/dc/dcphy.c                         (rev 0)
+++ haiku/vendor/freebsd/current/dev/dc/dcphy.c 2011-07-08 20:06:13 UTC (rev 
42391)
@@ -0,0 +1,421 @@
+/*-
+ * Copyright (c) 1997, 1998, 1999
+ *     Bill Paul <wpaul@xxxxxxxxxxxxxxx>.  All rights reserved.
+ *
+ * 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 Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD
+ * 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/dc/dcphy.c,v 1.35.2.5.2.1 2010/12/21 17:09:25 
kensmith Exp $");
+
+/*
+ * Pseudo-driver for internal NWAY support on DEC 21143 and workalike
+ * controllers.  Technically we're abusing the miibus code to handle
+ * media selection and NWAY support here since there is no MII
+ * interface.  However the logical operations are roughly the same,
+ * and the alternative is to create a fake MII interface in the driver,
+ * which is harder to do.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/bus.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_media.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+#include "miidevs.h"
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+
+#include <dev/pci/pcivar.h>
+
+#include <dev/dc/if_dcreg.h>
+
+#include "miibus_if.h"
+
+#define DC_SETBIT(sc, reg, x)                           \
+        CSR_WRITE_4(sc, reg,                            \
+                CSR_READ_4(sc, reg) | x)
+
+#define DC_CLRBIT(sc, reg, x)                           \
+        CSR_WRITE_4(sc, reg,                            \
+                CSR_READ_4(sc, reg) & ~x)
+
+#define MIIF_AUTOTIMEOUT       0x0004
+
+/*
+ * This is the subsystem ID for the built-in 21143 ethernet
+ * in several Compaq Presario systems.  Apparently these are
+ * 10Mbps only, so we need to treat them specially.
+ */
+#define COMPAQ_PRESARIO_ID     0xb0bb0e11
+
+static int dcphy_probe(device_t);
+static int dcphy_attach(device_t);
+
+static device_method_t dcphy_methods[] = {
+       /* device interface */
+       DEVMETHOD(device_probe,         dcphy_probe),
+       DEVMETHOD(device_attach,        dcphy_attach),
+       DEVMETHOD(device_detach,        mii_phy_detach),
+       DEVMETHOD(device_shutdown,      bus_generic_shutdown),
+       { 0, 0 }
+};
+
+static devclass_t dcphy_devclass;
+
+static driver_t dcphy_driver = {
+       "dcphy",
+       dcphy_methods,
+       sizeof(struct mii_softc)
+};
+
+DRIVER_MODULE(dcphy, miibus, dcphy_driver, dcphy_devclass, 0, 0);
+
+static int     dcphy_service(struct mii_softc *, struct mii_data *, int);
+static void    dcphy_status(struct mii_softc *);
+static void    dcphy_reset(struct mii_softc *);
+static int     dcphy_auto(struct mii_softc *);
+
+static int
+dcphy_probe(device_t dev)
+{
+       struct mii_attach_args *ma;
+
+       ma = device_get_ivars(dev);
+
+       /*
+        * The dc driver will report the 21143 vendor and device
+        * ID to let us know that it wants us to attach.
+        */
+       if (ma->mii_id1 != DC_VENDORID_DEC ||
+           ma->mii_id2 != DC_DEVICEID_21143)
+               return (ENXIO);
+
+       device_set_desc(dev, "Intel 21143 NWAY media interface");
+
+       return (BUS_PROBE_DEFAULT);
+}
+
+static int
+dcphy_attach(device_t dev)
+{
+       struct mii_softc *sc;
+       struct mii_attach_args *ma;
+       struct mii_data *mii;
+       struct dc_softc         *dc_sc;
+       device_t brdev;
+
+       sc = device_get_softc(dev);
+       ma = device_get_ivars(dev);
+       sc->mii_dev = device_get_parent(dev);
+       mii = ma->mii_data;
+       LIST_INSERT_HEAD(&mii->mii_phys, sc, mii_list);
+
+       sc->mii_flags = miibus_get_flags(dev);
+       sc->mii_inst = mii->mii_instance++;
+       sc->mii_phy = ma->mii_phyno;
+       sc->mii_service = dcphy_service;
+       sc->mii_pdata = mii;
+
+       /*
+        * Apparently, we can neither isolate nor do loopback.
+        */
+       sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP;
+
+       /*dcphy_reset(sc);*/
+       dc_sc = mii->mii_ifp->if_softc;
+       CSR_WRITE_4(dc_sc, DC_10BTSTAT, 0);
+       CSR_WRITE_4(dc_sc, DC_10BTCTRL, 0);
+
+       brdev = device_get_parent(sc->mii_dev);
+       switch (pci_get_subdevice(brdev) << 16 | pci_get_subvendor(brdev)) {
+       case COMPAQ_PRESARIO_ID:
+               /* Example of how to only allow 10Mbps modes. */
+               sc->mii_capabilities = BMSR_ANEG | BMSR_10TFDX | BMSR_10THDX;
+               break;
+       default:
+               if (dc_sc->dc_pmode == DC_PMODE_SIA)
+                       sc->mii_capabilities =
+                           BMSR_ANEG | BMSR_10TFDX | BMSR_10THDX;
+               else
+                       sc->mii_capabilities =
+                           BMSR_ANEG | BMSR_100TXFDX | BMSR_100TXHDX |
+                           BMSR_10TFDX | BMSR_10THDX;
+               break;
+       }
+
+       sc->mii_capabilities &= ma->mii_capmask;
+       device_printf(dev, " ");
+       mii_phy_add_media(sc);
+       printf("\n");
+
+       MIIBUS_MEDIAINIT(sc->mii_dev);
+       return (0);
+}
+
+static int
+dcphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
+{
+       struct dc_softc         *dc_sc;
+       struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
+       int reg;
+       u_int32_t               mode;
+
+       dc_sc = mii->mii_ifp->if_softc;
+
+       switch (cmd) {
+       case MII_POLLSTAT:
+               break;
+
+       case MII_MEDIACHG:
+               /*
+                * If the interface is not up, don't do anything.
+                */
+               if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
+                       break;
+
+               mii->mii_media_active = IFM_NONE;
+               mode = CSR_READ_4(dc_sc, DC_NETCFG);
+               mode &= ~(DC_NETCFG_FULLDUPLEX | DC_NETCFG_PORTSEL |
+                   DC_NETCFG_PCS | DC_NETCFG_SCRAMBLER | DC_NETCFG_SPEEDSEL);
+
+               switch (IFM_SUBTYPE(ife->ifm_media)) {
+               case IFM_AUTO:
+                       /*dcphy_reset(sc);*/
+                       (void) dcphy_auto(sc);
+                       break;
+               case IFM_100_T4:
+                       /*
+                        * XXX Not supported as a manual setting right now.
+                        */
+                       return (EINVAL);
+               case IFM_100_TX:
+                       dcphy_reset(sc);
+                       DC_CLRBIT(dc_sc, DC_10BTCTRL, DC_TCTL_AUTONEGENBL);
+                       mode |= DC_NETCFG_PORTSEL | DC_NETCFG_PCS |
+                           DC_NETCFG_SCRAMBLER;
+                       if ((ife->ifm_media & IFM_GMASK) == IFM_FDX)
+                               mode |= DC_NETCFG_FULLDUPLEX;
+                       else
+                               mode &= ~DC_NETCFG_FULLDUPLEX;
+                       CSR_WRITE_4(dc_sc, DC_NETCFG, mode);
+                       break;
+               case IFM_10_T:
+                       DC_CLRBIT(dc_sc, DC_SIARESET, DC_SIA_RESET);
+                       DC_CLRBIT(dc_sc, DC_10BTCTRL, 0xFFFF);
+                       if ((ife->ifm_media & IFM_GMASK) == IFM_FDX)
+                               DC_SETBIT(dc_sc, DC_10BTCTRL, 0x7F3D);
+                       else
+                               DC_SETBIT(dc_sc, DC_10BTCTRL, 0x7F3F);
+                       DC_SETBIT(dc_sc, DC_SIARESET, DC_SIA_RESET);
+                       DC_CLRBIT(dc_sc, DC_10BTCTRL, DC_TCTL_AUTONEGENBL);
+                       mode &= ~DC_NETCFG_PORTSEL;
+                       mode |= DC_NETCFG_SPEEDSEL;
+                       if ((ife->ifm_media & IFM_GMASK) == IFM_FDX)
+                               mode |= DC_NETCFG_FULLDUPLEX;
+                       else
+                               mode &= ~DC_NETCFG_FULLDUPLEX;
+                       CSR_WRITE_4(dc_sc, DC_NETCFG, mode);
+                       break;
+               default:
+                       return (EINVAL);
+               }
+               break;
+
+       case MII_TICK:
+               /*
+                * Is the interface even up?
+                */
+               if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
+                       return (0);
+
+               /*
+                * Only used for autonegotiation.
+                */
+               if (IFM_SUBTYPE(ife->ifm_media) != IFM_AUTO)
+                       break;
+
+               reg = CSR_READ_4(dc_sc, DC_10BTSTAT);
+               if (!(reg & DC_TSTAT_LS10) || !(reg & DC_TSTAT_LS100))
+                       break;
+
+                /*
+                 * Only retry autonegotiation every 5 seconds.
+                *
+                * Otherwise, fall through to calling dcphy_status()
+                * since real Intel 21143 chips don't show valid link
+                * status until autonegotiation is switched off, and
+                * that only happens in dcphy_status().  Without this,
+                * successful autonegotiation is never recognised on
+                * these chips.
+                 */
+                if (++sc->mii_ticks <= 50)
+                       break;
+
+               sc->mii_ticks = 0;
+               dcphy_auto(sc);
+
+               break;
+       }
+
+       /* Update the media status. */
+       dcphy_status(sc);
+
+       /* Callback if something changed. */
+       mii_phy_update(sc, cmd);
+       return (0);
+}
+
+static void
+dcphy_status(struct mii_softc *sc)
+{
+       struct mii_data *mii = sc->mii_pdata;
+       int reg, anlpar, tstat = 0;
+       struct dc_softc         *dc_sc;
+
+       dc_sc = mii->mii_ifp->if_softc;
+
+       mii->mii_media_status = IFM_AVALID;
+       mii->mii_media_active = IFM_ETHER;
+
+       if ((mii->mii_ifp->if_flags & IFF_UP) == 0)
+               return;
+
+       reg = CSR_READ_4(dc_sc, DC_10BTSTAT);
+       if (!(reg & DC_TSTAT_LS10) || !(reg & DC_TSTAT_LS100))
+               mii->mii_media_status |= IFM_ACTIVE;
+
+       if (CSR_READ_4(dc_sc, DC_10BTCTRL) & DC_TCTL_AUTONEGENBL) {
+               /* Erg, still trying, I guess... */
+               tstat = CSR_READ_4(dc_sc, DC_10BTSTAT);
+               if ((tstat & DC_TSTAT_ANEGSTAT) != DC_ASTAT_AUTONEGCMP) {
+                       if ((DC_IS_MACRONIX(dc_sc) || DC_IS_PNICII(dc_sc)) &&
+                           (tstat & DC_TSTAT_ANEGSTAT) == DC_ASTAT_DISABLE)
+                               goto skip;
+                       mii->mii_media_active |= IFM_NONE;
+                       return;
+               }
+
+               if (tstat & DC_TSTAT_LP_CAN_NWAY) {
+                       anlpar = tstat >> 16;
+                       if (anlpar & ANLPAR_TX_FD &&
+                           sc->mii_capabilities & BMSR_100TXFDX)
+                               mii->mii_media_active |= IFM_100_TX | IFM_FDX;
+                       else if (anlpar & ANLPAR_T4 &&
+                           sc->mii_capabilities & BMSR_100T4)
+                               mii->mii_media_active |= IFM_100_T4 | IFM_HDX;
+                       else if (anlpar & ANLPAR_TX &&
+                           sc->mii_capabilities & BMSR_100TXHDX)
+                               mii->mii_media_active |= IFM_100_TX | IFM_HDX;
+                       else if (anlpar & ANLPAR_10_FD)
+                               mii->mii_media_active |= IFM_10_T | IFM_FDX;
+                       else if (anlpar & ANLPAR_10)
+                               mii->mii_media_active |= IFM_10_T | IFM_HDX;
+                       else
+                               mii->mii_media_active |= IFM_NONE;
+                       if (DC_IS_INTEL(dc_sc))
+                               DC_CLRBIT(dc_sc, DC_10BTCTRL,
+                                   DC_TCTL_AUTONEGENBL);
+                       return;
+               }
+
+               /*
+                * If the other side doesn't support NWAY, then the
+                * best we can do is determine if we have a 10Mbps or
+                * 100Mbps link.  There's no way to know if the link
+                * is full or half duplex, so we default to half duplex
+                * and hope that the user is clever enough to manually
+                * change the media settings if we're wrong.
+                */
+               if (!(reg & DC_TSTAT_LS100))
+                       mii->mii_media_active |= IFM_100_TX | IFM_HDX;
+               else if (!(reg & DC_TSTAT_LS10))
+                       mii->mii_media_active |= IFM_10_T | IFM_HDX;
+               else
+                       mii->mii_media_active |= IFM_NONE;
+               if (DC_IS_INTEL(dc_sc))
+                       DC_CLRBIT(dc_sc, DC_10BTCTRL, DC_TCTL_AUTONEGENBL);
+               return;
+       }
+
+skip:
+       if (CSR_READ_4(dc_sc, DC_NETCFG) & DC_NETCFG_SPEEDSEL)
+               mii->mii_media_active |= IFM_10_T;
+       else
+               mii->mii_media_active |= IFM_100_TX;
+       if (CSR_READ_4(dc_sc, DC_NETCFG) & DC_NETCFG_FULLDUPLEX)
+               mii->mii_media_active |= IFM_FDX;
+       else
+               mii->mii_media_active |= IFM_HDX;
+}
+
+static int
+dcphy_auto(struct mii_softc *mii)
+{
+       struct dc_softc         *sc;
+
+       sc = mii->mii_pdata->mii_ifp->if_softc;
+
+       DC_CLRBIT(sc, DC_NETCFG, DC_NETCFG_PORTSEL);
+       DC_SETBIT(sc, DC_NETCFG, DC_NETCFG_FULLDUPLEX);
+       DC_CLRBIT(sc, DC_SIARESET, DC_SIA_RESET);
+       if (mii->mii_capabilities & BMSR_100TXHDX)
+               CSR_WRITE_4(sc, DC_10BTCTRL, 0x3FFFF);
+       else
+               CSR_WRITE_4(sc, DC_10BTCTRL, 0xFFFF);
+       DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
+       DC_SETBIT(sc, DC_10BTCTRL, DC_TCTL_AUTONEGENBL);
+       DC_SETBIT(sc, DC_10BTSTAT, DC_ASTAT_TXDISABLE);
+
+       return (EJUSTRETURN);
+}
+
+static void
+dcphy_reset(struct mii_softc *mii)
+{
+       struct dc_softc         *sc;
+
+       sc = mii->mii_pdata->mii_ifp->if_softc;
+
+       DC_CLRBIT(sc, DC_SIARESET, DC_SIA_RESET);
+       DELAY(1000);
+       DC_SETBIT(sc, DC_SIARESET, DC_SIA_RESET);
+}

Added: haiku/vendor/freebsd/current/dev/dc/if_dc.c
===================================================================
--- haiku/vendor/freebsd/current/dev/dc/if_dc.c                         (rev 0)
+++ haiku/vendor/freebsd/current/dev/dc/if_dc.c 2011-07-08 20:06:13 UTC (rev 
42391)
@@ -0,0 +1,3804 @@
+/*-
+ * Copyright (c) 1997, 1998, 1999
+ *     Bill Paul <wpaul@xxxxxxxxxxxxxxx>.  All rights reserved.
+ *
+ * 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 Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul 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 Bill Paul OR THE VOICES IN HIS HEAD
+ * 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/dc/if_dc.c,v 1.201.2.3.2.1 2010/12/21 17:09:25 
kensmith Exp $");
+
+/*
+ * DEC "tulip" clone ethernet driver. Supports the DEC/Intel 21143
+ * series chips and several workalikes including the following:
+ *
+ * Macronix 98713/98715/98725/98727/98732 PMAC (www.macronix.com)
+ * Macronix/Lite-On 82c115 PNIC II (www.macronix.com)
+ * Lite-On 82c168/82c169 PNIC (www.litecom.com)
+ * ASIX Electronics AX88140A (www.asix.com.tw)
+ * ASIX Electronics AX88141 (www.asix.com.tw)
+ * ADMtek AL981 (www.admtek.com.tw)
+ * ADMtek AN983 (www.admtek.com.tw)
+ * ADMtek cardbus AN985 (www.admtek.com.tw)
+ * Netgear FA511 (www.netgear.com) Appears to be rebadged ADMTek cardbus AN985
+ * Davicom DM9100, DM9102, DM9102A (www.davicom8.com)
+ * Accton EN1217 (www.accton.com)
+ * Xircom X3201 (www.xircom.com)
+ * Abocom FE2500
+ * Conexant LANfinity (www.conexant.com)
+ * 3Com OfficeConnect 10/100B 3CSOHO100B (www.3com.com)
+ *
+ * Datasheets for the 21143 are available at developer.intel.com.
+ * Datasheets for the clone parts can be found at their respective sites.
+ * (Except for the PNIC; see www.freebsd.org/~wpaul/PNIC/pnic.ps.gz.)
+ * The PNIC II is essentially a Macronix 98715A chip; the only difference
+ * worth noting is that its multicast hash table is only 128 bits wide
+ * instead of 512.
+ *
+ * Written by Bill Paul <wpaul@xxxxxxxxxxxxxxx>
+ * Electrical Engineering Department
+ * Columbia University, New York City
+ */
+/*
+ * The Intel 21143 is the successor to the DEC 21140. It is basically
+ * the same as the 21140 but with a few new features. The 21143 supports
+ * three kinds of media attachments:
+ *
+ * o MII port, for 10Mbps and 100Mbps support and NWAY
+ *   autonegotiation provided by an external PHY.
+ * o SYM port, for symbol mode 100Mbps support.
+ * o 10baseT port.
+ * o AUI/BNC port.
+ *
+ * The 100Mbps SYM port and 10baseT port can be used together in
+ * combination with the internal NWAY support to create a 10/100
+ * autosensing configuration.
+ *
+ * Note that not all tulip workalikes are handled in this driver: we only
+ * deal with those which are relatively well behaved. The Winbond is
+ * handled separately due to its different register offsets and the
+ * special handling needed for its various bugs. The PNIC is handled
+ * here, but I'm not thrilled about it.
+ *
+ * All of the workalike chips use some form of MII transceiver support
+ * with the exception of the Macronix chips, which also have a SYM port.
+ * The ASIX AX88140A is also documented to have a SYM port, but all
+ * the cards I've seen use an MII transceiver, probably because the
+ * AX88140A doesn't support internal NWAY.
+ */
+
+#ifdef HAVE_KERNEL_OPTION_HEADERS
+#include "opt_device_polling.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/endian.h>
+#include <sys/systm.h>
+#include <sys/sockio.h>
+#include <sys/mbuf.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+#include <net/if_vlan_var.h>
+
+#include <net/bpf.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#define DC_USEIOSPACE
+
+#include <dev/dc/if_dcreg.h>
+
+#ifdef __sparc64__
+#include <dev/ofw/openfirm.h>
+#include <machine/ofw_machdep.h>
+#endif
+
+MODULE_DEPEND(dc, pci, 1, 1, 1);
+MODULE_DEPEND(dc, ether, 1, 1, 1);
+MODULE_DEPEND(dc, miibus, 1, 1, 1);
+
+/*
+ * "device miibus" is required in kernel config.  See GENERIC if you get
+ * errors here.
+ */
+#include "miibus_if.h"
+
+/*
+ * Various supported device vendors/types and their names.
+ */
+static const struct dc_type dc_devs[] = {
+       { DC_DEVID(DC_VENDORID_DEC, DC_DEVICEID_21143), 0,
+               "Intel 21143 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_DAVICOM, DC_DEVICEID_DM9009), 0,
+               "Davicom DM9009 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_DAVICOM, DC_DEVICEID_DM9100), 0,
+               "Davicom DM9100 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_DAVICOM, DC_DEVICEID_DM9102), 
DC_REVISION_DM9102A,
+               "Davicom DM9102A 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_DAVICOM, DC_DEVICEID_DM9102), 0,
+               "Davicom DM9102 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_AL981), 0,
+               "ADMtek AL981 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_AN983), 0,
+               "ADMtek AN983 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_AN985), 0,
+               "ADMtek AN985 cardBus 10/100BaseTX or clone" },
+       { DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_ADM9511), 0,
+               "ADMtek ADM9511 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_ADMTEK, DC_DEVICEID_ADM9513), 0,
+               "ADMtek ADM9513 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_ASIX, DC_DEVICEID_AX88140A), DC_REVISION_88141,
+               "ASIX AX88141 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_ASIX, DC_DEVICEID_AX88140A), 0,
+               "ASIX AX88140A 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_MX, DC_DEVICEID_98713), DC_REVISION_98713A,
+               "Macronix 98713A 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_MX, DC_DEVICEID_98713), 0,
+               "Macronix 98713 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_CP, DC_DEVICEID_98713_CP), DC_REVISION_98713A,
+               "Compex RL100-TX 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_CP, DC_DEVICEID_98713_CP), 0,
+               "Compex RL100-TX 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_MX, DC_DEVICEID_987x5), DC_REVISION_98725,
+               "Macronix 98725 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_MX, DC_DEVICEID_987x5), DC_REVISION_98715AEC_C,
+               "Macronix 98715AEC-C 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_MX, DC_DEVICEID_987x5), 0,
+               "Macronix 98715/98715A 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_MX, DC_DEVICEID_98727), 0,
+               "Macronix 98727/98732 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_LO, DC_DEVICEID_82C115), 0,
+               "LC82C115 PNIC II 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_LO, DC_DEVICEID_82C168), DC_REVISION_82C169,
+               "82c169 PNIC 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_LO, DC_DEVICEID_82C168), 0,
+               "82c168 PNIC 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_ACCTON, DC_DEVICEID_EN1217), 0,
+               "Accton EN1217 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_ACCTON, DC_DEVICEID_EN2242), 0,
+               "Accton EN2242 MiniPCI 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_XIRCOM, DC_DEVICEID_X3201), 0,
+               "Xircom X3201 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_DLINK, DC_DEVICEID_DRP32TXD), 0,
+               "Neteasy DRP-32TXD Cardbus 10/100" },
+       { DC_DEVID(DC_VENDORID_ABOCOM, DC_DEVICEID_FE2500), 0,
+               "Abocom FE2500 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_ABOCOM, DC_DEVICEID_FE2500MX), 0,
+               "Abocom FE2500MX 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_CONEXANT, DC_DEVICEID_RS7112), 0,
+               "Conexant LANfinity MiniPCI 10/100BaseTX" },
+       { DC_DEVID(DC_VENDORID_HAWKING, DC_DEVICEID_HAWKING_PN672TX), 0,
+               "Hawking CB102 CardBus 10/100" },
+       { DC_DEVID(DC_VENDORID_PLANEX, DC_DEVICEID_FNW3602T), 0,
+               "PlaneX FNW-3602-T CardBus 10/100" },
+       { DC_DEVID(DC_VENDORID_3COM, DC_DEVICEID_3CSOHOB), 0,
+               "3Com OfficeConnect 10/100B" },
+       { DC_DEVID(DC_VENDORID_MICROSOFT, DC_DEVICEID_MSMN120), 0,
+               "Microsoft MN-120 CardBus 10/100" },
+       { DC_DEVID(DC_VENDORID_MICROSOFT, DC_DEVICEID_MSMN130), 0,
+               "Microsoft MN-130 10/100" },
+       { DC_DEVID(DC_VENDORID_LINKSYS, DC_DEVICEID_PCMPC200_AB08), 0,
+               "Linksys PCMPC200 CardBus 10/100" },
+       { DC_DEVID(DC_VENDORID_LINKSYS, DC_DEVICEID_PCMPC200_AB09), 0,
+               "Linksys PCMPC200 CardBus 10/100" },
+       { 0, 0, NULL }
+};
+
+static int dc_probe(device_t);
+static int dc_attach(device_t);
+static int dc_detach(device_t);
+static int dc_suspend(device_t);
+static int dc_resume(device_t);
+static const struct dc_type *dc_devtype(device_t);
+static int dc_newbuf(struct dc_softc *, int, int);
+static int dc_encap(struct dc_softc *, struct mbuf **);
+static void dc_pnic_rx_bug_war(struct dc_softc *, int);
+static int dc_rx_resync(struct dc_softc *);
+static int dc_rxeof(struct dc_softc *);
+static void dc_txeof(struct dc_softc *);
+static void dc_tick(void *);
+static void dc_tx_underrun(struct dc_softc *);
+static void dc_intr(void *);
+static void dc_start(struct ifnet *);
+static void dc_start_locked(struct ifnet *);
+static int dc_ioctl(struct ifnet *, u_long, caddr_t);
+static void dc_init(void *);
+static void dc_init_locked(struct dc_softc *);
+static void dc_stop(struct dc_softc *);
+static void dc_watchdog(void *);
+static int dc_shutdown(device_t);
+static int dc_ifmedia_upd(struct ifnet *);
+static void dc_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+
+static void dc_delay(struct dc_softc *);
+static void dc_eeprom_idle(struct dc_softc *);
+static void dc_eeprom_putbyte(struct dc_softc *, int);
+static void dc_eeprom_getword(struct dc_softc *, int, u_int16_t *);
+static void dc_eeprom_getword_pnic(struct dc_softc *, int, u_int16_t *);
+static void dc_eeprom_getword_xircom(struct dc_softc *, int, u_int16_t *);
+static void dc_eeprom_width(struct dc_softc *);
+static void dc_read_eeprom(struct dc_softc *, caddr_t, int, int, int);
+
+static void dc_mii_writebit(struct dc_softc *, int);
+static int dc_mii_readbit(struct dc_softc *);
+static void dc_mii_sync(struct dc_softc *);
+static void dc_mii_send(struct dc_softc *, u_int32_t, int);
+static int dc_mii_readreg(struct dc_softc *, struct dc_mii_frame *);
+static int dc_mii_writereg(struct dc_softc *, struct dc_mii_frame *);
+static int dc_miibus_readreg(device_t, int, int);
+static int dc_miibus_writereg(device_t, int, int, int);
+static void dc_miibus_statchg(device_t);
+static void dc_miibus_mediainit(device_t);
+
+static void dc_setcfg(struct dc_softc *, int);
+static uint32_t dc_mchash_le(struct dc_softc *, const uint8_t *);
+static uint32_t dc_mchash_be(const uint8_t *);
+static void dc_setfilt_21143(struct dc_softc *);
+static void dc_setfilt_asix(struct dc_softc *);
+static void dc_setfilt_admtek(struct dc_softc *);
+static void dc_setfilt_xircom(struct dc_softc *);
+
+static void dc_setfilt(struct dc_softc *);
+
+static void dc_reset(struct dc_softc *);
+static int dc_list_rx_init(struct dc_softc *);
+static int dc_list_tx_init(struct dc_softc *);
+
+static void dc_read_srom(struct dc_softc *, int);
+static void dc_parse_21143_srom(struct dc_softc *);
+static void dc_decode_leaf_sia(struct dc_softc *, struct dc_eblock_sia *);
+static void dc_decode_leaf_mii(struct dc_softc *, struct dc_eblock_mii *);
+static void dc_decode_leaf_sym(struct dc_softc *, struct dc_eblock_sym *);
+static void dc_apply_fixup(struct dc_softc *, int);
+
+#ifdef DC_USEIOSPACE
+#define DC_RES                 SYS_RES_IOPORT
+#define DC_RID                 DC_PCI_CFBIO
+#else
+#define DC_RES                 SYS_RES_MEMORY
+#define DC_RID                 DC_PCI_CFBMA
+#endif
+
+static device_method_t dc_methods[] = {
+       /* Device interface */
+       DEVMETHOD(device_probe,         dc_probe),
+       DEVMETHOD(device_attach,        dc_attach),
+       DEVMETHOD(device_detach,        dc_detach),
+       DEVMETHOD(device_suspend,       dc_suspend),
+       DEVMETHOD(device_resume,        dc_resume),
+       DEVMETHOD(device_shutdown,      dc_shutdown),
+
+       /* bus interface */
+       DEVMETHOD(bus_print_child,      bus_generic_print_child),
+       DEVMETHOD(bus_driver_added,     bus_generic_driver_added),
+
+       /* MII interface */
+       DEVMETHOD(miibus_readreg,       dc_miibus_readreg),
+       DEVMETHOD(miibus_writereg,      dc_miibus_writereg),
+       DEVMETHOD(miibus_statchg,       dc_miibus_statchg),
+       DEVMETHOD(miibus_mediainit,     dc_miibus_mediainit),
+
+       { 0, 0 }
+};
+
+static driver_t dc_driver = {
+       "dc",
+       dc_methods,
+       sizeof(struct dc_softc)
+};
+
+static devclass_t dc_devclass;
+
+DRIVER_MODULE(dc, pci, dc_driver, dc_devclass, 0, 0);
+DRIVER_MODULE(miibus, dc, miibus_driver, miibus_devclass, 0, 0);
+
+#define DC_SETBIT(sc, reg, x)                          \
+       CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) | (x))
+
+#define DC_CLRBIT(sc, reg, x)                          \
+       CSR_WRITE_4(sc, reg, CSR_READ_4(sc, reg) & ~(x))
+
+#define SIO_SET(x)     DC_SETBIT(sc, DC_SIO, (x))
+#define SIO_CLR(x)     DC_CLRBIT(sc, DC_SIO, (x))
+
+static void
+dc_delay(struct dc_softc *sc)
+{
+       int idx;
+
+       for (idx = (300 / 33) + 1; idx > 0; idx--)
+               CSR_READ_4(sc, DC_BUSCTL);
+}
+
+static void
+dc_eeprom_width(struct dc_softc *sc)
+{
+       int i;
+
+       /* Force EEPROM to idle state. */
+       dc_eeprom_idle(sc);
+
+       /* Enter EEPROM access mode. */
+       CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
+       dc_delay(sc);
+       DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
+       dc_delay(sc);
+       DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+       dc_delay(sc);
+       DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
+       dc_delay(sc);
+
+       for (i = 3; i--;) {
+               if (6 & (1 << i))
+                       DC_SETBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
+               else
+                       DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
+               dc_delay(sc);
+               DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+               dc_delay(sc);
+               DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+               dc_delay(sc);
+       }
+
+       for (i = 1; i <= 12; i++) {
+               DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+               dc_delay(sc);
+               if (!(CSR_READ_4(sc, DC_SIO) & DC_SIO_EE_DATAOUT)) {
+                       DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+                       dc_delay(sc);
+                       break;
+               }
+               DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+               dc_delay(sc);
+       }
+
+       /* Turn off EEPROM access mode. */
+       dc_eeprom_idle(sc);
+
+       if (i < 4 || i > 12)
+               sc->dc_romwidth = 6;
+       else
+               sc->dc_romwidth = i;
+
+       /* Enter EEPROM access mode. */
+       CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
+       dc_delay(sc);
+       DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
+       dc_delay(sc);
+       DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+       dc_delay(sc);
+       DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
+       dc_delay(sc);
+
+       /* Turn off EEPROM access mode. */
+       dc_eeprom_idle(sc);
+}
+
+static void
+dc_eeprom_idle(struct dc_softc *sc)
+{
+       int i;
+
+       CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
+       dc_delay(sc);
+       DC_SETBIT(sc, DC_SIO, DC_SIO_ROMCTL_READ);
+       dc_delay(sc);
+       DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+       dc_delay(sc);
+       DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
+       dc_delay(sc);
+
+       for (i = 0; i < 25; i++) {
+               DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+               dc_delay(sc);
+               DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+               dc_delay(sc);
+       }
+
+       DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+       dc_delay(sc);
+       DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CS);
+       dc_delay(sc);
+       CSR_WRITE_4(sc, DC_SIO, 0x00000000);
+}
+
+/*
+ * Send a read command and address to the EEPROM, check for ACK.
+ */
+static void
+dc_eeprom_putbyte(struct dc_softc *sc, int addr)
+{
+       int d, i;
+
+       d = DC_EECMD_READ >> 6;
+       for (i = 3; i--; ) {
+               if (d & (1 << i))
+                       DC_SETBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
+               else
+                       DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_DATAIN);
+               dc_delay(sc);
+               DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+               dc_delay(sc);
+               DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+               dc_delay(sc);
+       }
+
+       /*
+        * Feed in each bit and strobe the clock.
+        */
+       for (i = sc->dc_romwidth; i--;) {
+               if (addr & (1 << i)) {
+                       SIO_SET(DC_SIO_EE_DATAIN);
+               } else {
+                       SIO_CLR(DC_SIO_EE_DATAIN);
+               }
+               dc_delay(sc);
+               SIO_SET(DC_SIO_EE_CLK);
+               dc_delay(sc);
+               SIO_CLR(DC_SIO_EE_CLK);
+               dc_delay(sc);
+       }
+}
+
+/*
+ * Read a word of data stored in the EEPROM at address 'addr.'
+ * The PNIC 82c168/82c169 has its own non-standard way to read
+ * the EEPROM.
+ */
+static void
+dc_eeprom_getword_pnic(struct dc_softc *sc, int addr, u_int16_t *dest)
+{
+       int i;
+       u_int32_t r;
+
+       CSR_WRITE_4(sc, DC_PN_SIOCTL, DC_PN_EEOPCODE_READ | addr);
+
+       for (i = 0; i < DC_TIMEOUT; i++) {
+               DELAY(1);
+               r = CSR_READ_4(sc, DC_SIO);
+               if (!(r & DC_PN_SIOCTL_BUSY)) {
+                       *dest = (u_int16_t)(r & 0xFFFF);
+                       return;
+               }
+       }
+}
+
+/*
+ * Read a word of data stored in the EEPROM at address 'addr.'
+ * The Xircom X3201 has its own non-standard way to read
+ * the EEPROM, too.
+ */
+static void
+dc_eeprom_getword_xircom(struct dc_softc *sc, int addr, u_int16_t *dest)
+{
+
+       SIO_SET(DC_SIO_ROMSEL | DC_SIO_ROMCTL_READ);
+
+       addr *= 2;
+       CSR_WRITE_4(sc, DC_ROM, addr | 0x160);
+       *dest = (u_int16_t)CSR_READ_4(sc, DC_SIO) & 0xff;
+       addr += 1;
+       CSR_WRITE_4(sc, DC_ROM, addr | 0x160);
+       *dest |= ((u_int16_t)CSR_READ_4(sc, DC_SIO) & 0xff) << 8;
+
+       SIO_CLR(DC_SIO_ROMSEL | DC_SIO_ROMCTL_READ);
+}
+
+/*
+ * Read a word of data stored in the EEPROM at address 'addr.'
+ */
+static void
+dc_eeprom_getword(struct dc_softc *sc, int addr, u_int16_t *dest)
+{
+       int i;
+       u_int16_t word = 0;
+
+       /* Force EEPROM to idle state. */
+       dc_eeprom_idle(sc);
+
+       /* Enter EEPROM access mode. */
+       CSR_WRITE_4(sc, DC_SIO, DC_SIO_EESEL);
+       dc_delay(sc);
+       DC_SETBIT(sc, DC_SIO,  DC_SIO_ROMCTL_READ);
+       dc_delay(sc);
+       DC_CLRBIT(sc, DC_SIO, DC_SIO_EE_CLK);
+       dc_delay(sc);
+       DC_SETBIT(sc, DC_SIO, DC_SIO_EE_CS);
+       dc_delay(sc);
+
+       /*
+        * Send address of word we want to read.
+        */
+       dc_eeprom_putbyte(sc, addr);
+
+       /*
+        * Start reading bits from EEPROM.
+        */
+       for (i = 0x8000; i; i >>= 1) {
+               SIO_SET(DC_SIO_EE_CLK);
+               dc_delay(sc);
+               if (CSR_READ_4(sc, DC_SIO) & DC_SIO_EE_DATAOUT)
+                       word |= i;
+               dc_delay(sc);
+               SIO_CLR(DC_SIO_EE_CLK);
+               dc_delay(sc);
+       }

[... truncated: 16387 lines follow ...]

Other related posts:

  • » [haiku-commits] r42391 - in haiku/vendor/freebsd/current: dev dev/dc dev/fxp dev/mii dev/xl ... - zharik