Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 27 Jun 2000 06:48:29 +0200 (CEST)
From:      =?ISO-8859-1?Q?Mikko_Ty=F6l=E4j=E4rvi?= <mikko@dynas.se>
To:        freebsd-mobile@freebsd.org
Subject:   Netgear FA410TX - Some progress (Patch included)
Message-ID:  <Pine.BSF.4.21.0006270644070.304-100000@shiba.smateo1.sfba.home.com>

next in thread | raw e-mail | index | archive | help

Hi,

Having seen this card mentioned in pccard.conf, I bought one. As other
already have discovered, it didn't work.  Probes, attaches, but no
data.

As someone on this list mentioned that Linux already has support for
this chip, I grabbed the Linux source (beware the GPL!), extracted
what seemed to be somewhat relevant parts, and squeezed into
"if_ed.c," with little or no clue as to what I was doing.  It worked.

It looks like newer versions of this card use an updated ethernet
controller (DL10022 instead of DL10019), and that the lack of the
correct incantations is why initializatio fails.

Now, I'd be most grateful if someone more knowledgeable would have a
look at this, and perhaps get hold of specs from wherever the specs on
the old chip (DL10019) came from, and maybe update if_ed.c in a
controlled fashion, to support these new cards.

I haven't tested the hack with any other cards, or in any other setup
than the one on my desk right now, so it may in fact not work for
anyone else, or anywhere else :)

The Linux driver (pcnet_cs) also contains code to disable collision
detection on full duplex duplex links, but it was not obvious where to
put it, so it is not included.

    /Mikko

(Most of this code has been blatantly copied from the Linux driver)

----8<---------------------------------------------------------------

--- if_ed.c.org	Tue Jun 27 05:18:58 2000
+++ if_ed.c	Tue Jun 27 06:35:48 2000
@@ -71,6 +71,13 @@
 #include <dev/ed/if_edreg.h>
 #include <dev/ed/if_edvar.h>
 
+#define LINKSYS_HACK
+#ifdef LINKSYS_HACK
+# define DL10019	19
+# define DL10022	22
+# define dl_type	hpp_options	/* XXX Q&D overloading... */
+#endif
+
 static void	ed_init		__P((void *));
 static int	ed_ioctl	__P((struct ifnet *, u_long, caddr_t));
 static void	ed_start	__P((struct ifnet *));
@@ -902,6 +909,8 @@
 	u_char sum;
 	int i;
 
+	sc->dl_type = 0;
+
 	/*
 	 * Linksys registers(offset from ASIC base)
 	 *
@@ -916,6 +925,10 @@
 	for (i = 0; i < ETHER_ADDR_LEN; i++) {
 		sc->arpcom.ac_enaddr[i] = inb(sc->asic_addr + 0x04 + i);
 	}
+#ifdef LINKSYS_HACK
+	i = inb(sc->asic_addr + 0x0f);
+	sc->dl_type = (i == 0x91 || i == 0x99) ? DL10022 : DL10019;
+#endif
 	return (1);
 }
 
@@ -1674,6 +1687,11 @@
 	else
 		printf("%s ", sc->isa16bit ? "(16 bit)" : "(8 bit)");
 
+#ifdef LINKSYS_HACK
+	if (sc->type == ED_TYPE_NE2000 && sc->dl_type)
+		printf("DL100%d\n", sc->dl_type);
+#endif
+
 	printf("%s\n", (((sc->vendor == ED_VENDOR_3COM) ||
 			 (sc->vendor == ED_VENDOR_HP)) &&
 		(ifp->if_flags & IFF_ALTPHYS)) ? " tranceiver disabled" : "");
@@ -1750,6 +1768,87 @@
 	ed_reset(ifp);
 }
 
+
+#ifdef LINKSYS_HACK
+
+/*======================================================================
+
+    MII interface support for DL10019 and DL10022 based cards
+
+    On the DL10019, the MII IO direction bit is 0x10; on  the DL10022
+    it is 0x20.  Setting both bits seems to work on both card types.
+
+======================================================================*/
+
+#define DLINK_GPIO		0x1c
+#define DLINK_DIAG		0x1d
+#define MDIO_SHIFT_CLK		0x80
+#define MDIO_DATA_OUT		0x40
+#define MDIO_DIR_WRITE		0x30
+#define MDIO_DATA_WRITE0	(MDIO_DIR_WRITE)
+#define MDIO_DATA_WRITE1	(MDIO_DIR_WRITE | MDIO_DATA_OUT)
+#define MDIO_DATA_READ		0x10
+#define MDIO_MASK		0x0f
+
+typedef ushort ioaddr_t;
+
+static void mdio_sync(ioaddr_t addr)
+{
+    int bits, mask = inb(addr) & MDIO_MASK;
+    for (bits = 0; bits < 32; bits++) {
+	outb(addr, mask | MDIO_DATA_WRITE1);
+	outb(addr, mask | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK);
+    }
+}
+
+static int mdio_read(ioaddr_t addr, int phy_id, int loc)
+{
+    u_int cmd = (0x06<<10)|(phy_id<<5)|loc;
+    int i, retval = 0, mask = inb(addr) & MDIO_MASK;
+
+    mdio_sync(addr);
+    for (i = 13; i >= 0; i--) {
+	int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+	outb(addr, mask | dat);
+	outb(addr, mask | dat | MDIO_SHIFT_CLK);
+    }
+    for (i = 19; i > 0; i--) {
+	outb(addr, mask);
+	retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0);
+	outb(addr, mask | MDIO_SHIFT_CLK);
+    }
+    return (retval>>1) & 0xffff;
+}
+
+static void mdio_write(ioaddr_t addr, int phy_id, int loc, int value)
+{
+    u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;
+    int i, mask = inb(addr) & MDIO_MASK;
+
+    mdio_sync(addr);
+    for (i = 31; i >= 0; i--) {
+	int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;
+	outb(addr, mask | dat);
+	outb(addr, mask | dat | MDIO_SHIFT_CLK);
+    }
+    for (i = 1; i >= 0; i--) {
+	outb(addr, mask);
+	outb(addr, mask | MDIO_SHIFT_CLK);
+    }
+}
+
+static void mdio_reset(ioaddr_t addr, int phy_id)
+{
+    outb(addr, 0x08);
+    outb(addr, 0x0c);
+    outb(addr, 0x08);
+    outb(addr, 0x0c);
+    outb(addr, 0x00);
+}
+
+#endif
+
+
 /*
  * Initialize device.
  */
@@ -1891,6 +1990,15 @@
 		}
 	}
 
+#ifdef LINKSYS_HACK
+	if (sc->type == ED_TYPE_NE2000 && sc->dl_type == DL10022) {
+		mdio_reset(sc->nic_addr + DLINK_GPIO, 0);
+		/* Restart MII autonegotiation */
+		mdio_write(sc->nic_addr + DLINK_GPIO, 0, 0, 0x0000);
+		mdio_write(sc->nic_addr + DLINK_GPIO, 0, 0, 0x1200);
+	}
+#endif
+
 	/*
 	 * Set 'running' flag, and clear output active flag.
 	 */
@@ -3302,3 +3410,4 @@
 		af[index >> 3] |= 1 << (index & 7);
 	}
 }
+


 Mikko Työläjärvi_______________________________________mikko@rsasecurity.com
 RSA Security



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-mobile" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.21.0006270644070.304-100000>