summaryrefslogtreecommitdiffstats
path: root/sys/dev/ed/if_ed_pccard.c
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2001-03-03 08:31:37 +0000
committerimp <imp@FreeBSD.org>2001-03-03 08:31:37 +0000
commitc2257f6c8a69b4a7cae98128bd89f28f3893f3c5 (patch)
tree6a6e8077b17a02e0d83e4b1fad4660dd6562ccad /sys/dev/ed/if_ed_pccard.c
parent5f89669270bed456c02457eab0709fc74466f733 (diff)
downloadFreeBSD-src-c2257f6c8a69b4a7cae98128bd89f28f3893f3c5.zip
FreeBSD-src-c2257f6c8a69b4a7cae98128bd89f28f3893f3c5.tar.gz
Add support for Dlink DL10022 to the ed driver. This is a mii part
bolted to a ne-2000 chip. This is necessary for the NetGear FA-410TX and other cards. This also requires you add mii to your kernel if you have an ed driver configured. This code will result in a couple of timeout messages for ed on the impacted cards. Additional work will be needed, but this does work right now, and many people need these cards. Submitted by: Ian Dowse <iedowse@maths.tcd.ie>
Diffstat (limited to 'sys/dev/ed/if_ed_pccard.c')
-rw-r--r--sys/dev/ed/if_ed_pccard.c94
1 files changed, 94 insertions, 0 deletions
diff --git a/sys/dev/ed/if_ed_pccard.c b/sys/dev/ed/if_ed_pccard.c
index d579d16..23ef71d 100644
--- a/sys/dev/ed/if_ed_pccard.c
+++ b/sys/dev/ed/if_ed_pccard.c
@@ -44,13 +44,20 @@
#include <net/if.h>
#include <net/if_arp.h>
#include <net/if_mib.h>
+#include <net/if_media.h>
#include <dev/ed/if_edreg.h>
#include <dev/ed/if_edvar.h>
#include <dev/pccard/pccardvar.h>
#include <dev/pccard/pccarddevs.h>
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
#include "card_if.h"
+/* "device miibus" required. See GENERIC if you get errors here. */
+#include "miibus_if.h"
+
+MODULE_DEPEND(ed, miibus, 1, 1, 1);
/*
* PC-Card (PCMCIA) specific code.
@@ -65,6 +72,10 @@ static int ed_pccard_ax88190(device_t dev);
static void ax88190_geteprom(struct ed_softc *);
static int ed_pccard_memwrite(device_t dev, off_t offset, u_char byte);
+static void ed_pccard_dlink_mii_reset(struct ed_softc *sc);
+static u_int ed_pccard_dlink_mii_readbits(struct ed_softc *sc, int nbits);
+static void ed_pccard_dlink_mii_writebits(struct ed_softc *sc, u_int val,
+ int nbits);
static int linksys;
/*
@@ -659,6 +670,13 @@ ed_pccard_Linksys(device_t dev)
sc->isa16bit = 1;
sc->type = ED_TYPE_NE2000;
sc->type_str = "Linksys";
+
+ /* Probe for an MII bus, but continue as normal if there isn't one. */
+ ed_pccard_dlink_mii_reset(sc);
+ sc->mii_readbits = ed_pccard_dlink_mii_readbits;
+ sc->mii_writebits = ed_pccard_dlink_mii_writebits;
+ mii_phy_probe(dev, &sc->miibus, ed_ifmedia_upd, ed_ifmedia_sts);
+
return (1);
}
@@ -694,12 +712,87 @@ ed_pccard_ax88190(device_t dev)
return (error);
}
+/* MII bit-twiddling routines for cards using Dlink chipset */
+#define DLINK_MIISET(sc, x) ed_asic_outb(sc, ED_DLINK_MIIBUS, \
+ ed_asic_inb(sc, ED_DLINK_MIIBUS) | (x))
+#define DLINK_MIICLR(sc, x) ed_asic_outb(sc, ED_DLINK_MIIBUS, \
+ ed_asic_inb(sc, ED_DLINK_MIIBUS) & ~(x))
+
+static void
+ed_pccard_dlink_mii_reset(sc)
+ struct ed_softc *sc;
+{
+ ed_asic_outb(sc, ED_DLINK_MIIBUS, 0);
+ DELAY(10);
+ DLINK_MIISET(sc, ED_DLINK_MII_RESET2);
+ DELAY(10);
+ DLINK_MIISET(sc, ED_DLINK_MII_RESET1);
+ DELAY(10);
+ DLINK_MIICLR(sc, ED_DLINK_MII_RESET1);
+ DELAY(10);
+ DLINK_MIICLR(sc, ED_DLINK_MII_RESET2);
+ DELAY(10);
+}
+
+static void
+ed_pccard_dlink_mii_writebits(sc, val, nbits)
+ struct ed_softc *sc;
+ u_int val;
+ int nbits;
+{
+ int i;
+
+ DLINK_MIISET(sc, ED_DLINK_MII_DIROUT);
+
+ for (i = nbits - 1; i >= 0; i--) {
+ if ((val >> i) & 1)
+ DLINK_MIISET(sc, ED_DLINK_MII_DATAOUT);
+ else
+ DLINK_MIICLR(sc, ED_DLINK_MII_DATAOUT);
+ DELAY(10);
+ DLINK_MIISET(sc, ED_DLINK_MII_CLK);
+ DELAY(10);
+ DLINK_MIICLR(sc, ED_DLINK_MII_CLK);
+ DELAY(10);
+ }
+}
+
+static u_int
+ed_pccard_dlink_mii_readbits(sc, nbits)
+ struct ed_softc *sc;
+ int nbits;
+{
+ int i;
+ u_int val = 0;
+
+ DLINK_MIICLR(sc, ED_DLINK_MII_DIROUT);
+
+ for (i = nbits - 1; i >= 0; i--) {
+ DLINK_MIISET(sc, ED_DLINK_MII_CLK);
+ DELAY(10);
+ val <<= 1;
+ if (ed_asic_inb(sc, ED_DLINK_MIIBUS) & ED_DLINK_MII_DATATIN)
+ val++;
+ DLINK_MIICLR(sc, ED_DLINK_MII_CLK);
+ DELAY(10);
+ }
+
+ return val;
+}
+
static device_method_t ed_pccard_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, pccard_compat_probe),
DEVMETHOD(device_attach, pccard_compat_attach),
DEVMETHOD(device_detach, ed_pccard_detach),
+ /* Bus interface */
+ DEVMETHOD(bus_child_detached, ed_child_detached),
+
+ /* MII interface */
+ DEVMETHOD(miibus_readreg, ed_miibus_readreg),
+ DEVMETHOD(miibus_writereg, ed_miibus_writereg),
+
/* Card interface */
DEVMETHOD(card_compat_match, ed_pccard_match),
DEVMETHOD(card_compat_probe, ed_pccard_probe),
@@ -714,3 +807,4 @@ static driver_t ed_pccard_driver = {
};
DRIVER_MODULE(if_ed, pccard, ed_pccard_driver, ed_devclass, 0, 0);
+DRIVER_MODULE(miibus, ed, miibus_driver, miibus_devclass, 0, 0);
OpenPOWER on IntegriCloud