diff mbox

Getting the correct asix AX88178 usb gige driver in mainline?

Message ID 201107062209.05794.arnd@arndb.de
State RFC, archived
Delegated to: David Miller
Headers show

Commit Message

Arnd Bergmann July 6, 2011, 8:09 p.m. UTC
On Wednesday 06 July 2011 19:25:38 Marc MERLIN wrote:
> Howdy netdev folks,
> 
> On Tue, Jul 05, 2011 at 08:35:19AM -0700, Greg KH wrote:
> > I looked at this and it seems they took a very old version of the driver
> > (from 2003) and somehow changed it to work for this device.  I can't
> > really tell what they changed unless I were to dig through the original
> > version.
> > 
> > I suggest you post your original message to the 
> > mailing list.  The network developers there should be able to help you
> > out as I can't at the moment due to real-work and travel.
> 
> Here are the details. If somehow their driver could be integrated in
> mainline by putting the relevant bits in the current driver, that would be
> fantastic :)
> (obviously it would have been better if they had done that themselves to
> start with, no idea why they didn't).
> 

Hi Marc,

I've taken a look at the driver you linked to and compared it to the
version that was closest at the time.

This is similar to the patch they must have had at some point. I would guess
that the answer is somewhere in there. It's quite different to the much
cleaner patch 933a27d39e "USB: asix - Add AX88178 support and many other
changes", which was merged later with a similar intention.

	Arnd


--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Marc MERLIN July 6, 2011, 9:08 p.m. UTC | #1
On Wed, Jul 06, 2011 at 10:09:05PM +0200, Arnd Bergmann wrote:
> > Here are the details. If somehow their driver could be integrated in
> > mainline by putting the relevant bits in the current driver, that would be
> > fantastic :)
> > (obviously it would have been better if they had done that themselves to
> > start with, no idea why they didn't).
> > 
> 
> Hi Marc,
> 
> I've taken a look at the driver you linked to and compared it to the
> version that was closest at the time.
> 
> This is similar to the patch they must have had at some point. I would guess
> that the answer is somewhere in there. It's quite different to the much
> cleaner patch 933a27d39e "USB: asix - Add AX88178 support and many other
> changes", which was merged later with a similar intention.

(...)

> The patch I mentioned was merged back in 2006, for 2.6.19. Either that
> patch was never complete and is missing support for your hardware, or
> it broke since then. You should probably try an old kernel to see if it's
> actually a regression.

Thanks for the details Arnd, I'll see if I can boot 2.6.19 on that laptop
and report back.

Marc
Arnd Bergmann July 7, 2011, 12:55 p.m. UTC | #2
On Wednesday 06 July 2011, Marc MERLIN wrote:
> > The patch I mentioned was merged back in 2006, for 2.6.19. Either that
> > patch was never complete and is missing support for your hardware, or
> > it broke since then. You should probably try an old kernel to see if it's
> > actually a regression.
> 
> Thanks for the details Arnd, I'll see if I can boot 2.6.19 on that laptop
> and report back.

I would perhaps try something less ancient first, 2.6.27-longterm would be
a good candidate. If it was working at some point but broken later, chances
are that it wasn't broken until a few years ago, rather than shortly after
it was merged.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Marc MERLIN July 7, 2011, 5:23 p.m. UTC | #3
On Thu, Jul 07, 2011 at 02:55:36PM +0200, Arnd Bergmann wrote:
> On Wednesday 06 July 2011, Marc MERLIN wrote:
> > > The patch I mentioned was merged back in 2006, for 2.6.19. Either that
> > > patch was never complete and is missing support for your hardware, or
> > > it broke since then. You should probably try an old kernel to see if it's
> > > actually a regression.
> > 
> > Thanks for the details Arnd, I'll see if I can boot 2.6.19 on that laptop
> > and report back.
> 
> I would perhaps try something less ancient first, 2.6.27-longterm would be
> a good candidate. If it was working at some point but broken later, chances
> are that it wasn't broken until a few years ago, rather than shortly after
> it was merged.

So, it was problematic to build and boot old kernels for that system, but I
tried my USB adapter in older systems with older kernels.

2.6.20 and 2.6.22.1 both were able to bring the interface up and DHCP.
2.6.24.3 was NOT able to.
Neither was 2.6.34.1.

Mind you, those were not exactly the same kernels with the compile options
on the same machine, but those were the tests I was reasonably able to do
for now.




Linux polgara.svh.merlins.org 2.6.20-16-generic #2 SMP Thu Jun 7 20:19:32 UTC 2007 i686 GNU/Linux
usb 1-5: new high speed USB device using ehci_hcd and address 3
usb 1-5: configuration #1 chosen from 1 choice
eth0: register 'asix' at usb-0000:00:1a.7-5, ASIX AX88178 USB 2.0 Ethernet, 00:0e:c6:88:7c:ae
usbcore: registered new interface driver asix
eth2: link down
ADDRCONF(NETDEV_UP): eth2: link is not ready
ADDRCONF(NETDEV_CHANGE): eth2: link becomes ready
eth2: link up, 1000Mbps, full-duplex, lpa 0xC5E1
eth2: no IPv6 routers present
eth1: no IPv6 routers present
-> OK


2.6.22.1-libata-tj-20070803-p4smp-preempt-1khz-marc4
eth0: register 'asix' at usb-0000:00:1a.7-5, ASIX AX88178 USB 2.0 Ethernet, 00:0e:c6:88:7c:ae
usbcore: registered new interface driver asix
eth2: link down
ADDRCONF(NETDEV_UP): eth2: link is not ready
ADDRCONF(NETDEV_CHANGE): eth2: link becomes ready
eth2: link up, 1000Mbps, full-duplex, lpa 0xC5E1
eth2: no IPv6 routers present
eth1: no IPv6 routers present
-> OK


2.6.24.3-slub-k8up-preempt-noticks-marc1 (different machine)
usb 1-4: new high speed USB device using ehci_hcd and address 4
usb 1-4: configuration #1 chosen from 1 choice
eth1: register 'asix' at usb-0000:00:02.2-4, ASIX AX88178 USB 2.0 Ethernet, 00:0e:c6:88:7c:ae
usbcore: registered new interface driver asix
udev: renamed network interface eth1 to eth3
eth3: link up, 1000Mbps, full-duplex, lpa 0xCDE1
eth3: link up, 1000Mbps, full-duplex, lpa 0xCDE1
eth3: no IPv6 routers present
-> NOT OK
 
Linux polgara.svh.merlins.org 2.6.34.1-core2smp-1khznohz-preempt-notcks-noide-hm64-20100724 #2 SMP Sat Jul 24 16:02:09 PDT 2010 i686 GNU/Linux
usb 1-5: new high speed USB device using ehci_hcd and address 4
usb 1-5: New USB device found, idVendor=0b95, idProduct=1780
usb 1-5: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-5: Product: AX88178 
usb 1-5: Manufacturer: ASIX Elec. Corp.
usb 1-5: SerialNumber: 000002
asix 1-5:1.0: eth1: register 'asix' at usb-0000:00:1a.7-5, ASIX AX88178 USB
2.0 Ethernet, 00:0e:c6:88:7c:ae
usbcore: registered new interface driver asix
eth1: link down
ADDRCONF(NETDEV_UP): eth1: link is not ready
ADDRCONF(NETDEV_CHANGE): eth1: link becomes ready
eth1: link up, 1000Mbps, full-duplex, lpa 0xC5E1
eth1: no IPv6 routers present
->  NOT OK

Marc
Arnd Bergmann July 7, 2011, 5:43 p.m. UTC | #4
On Thursday 07 July 2011 19:23:50 Marc MERLIN wrote:
> On Thu, Jul 07, 2011 at 02:55:36PM +0200, Arnd Bergmann wrote:
> > On Wednesday 06 July 2011, Marc MERLIN wrote:
> > > > The patch I mentioned was merged back in 2006, for 2.6.19. Either that
> > > > patch was never complete and is missing support for your hardware, or
> > > > it broke since then. You should probably try an old kernel to see if it's
> > > > actually a regression.
> > > 
> > > Thanks for the details Arnd, I'll see if I can boot 2.6.19 on that laptop
> > > and report back.
> > 
> > I would perhaps try something less ancient first, 2.6.27-longterm would be
> > a good candidate. If it was working at some point but broken later, chances
> > are that it wasn't broken until a few years ago, rather than shortly after
> > it was merged.
> 
> So, it was problematic to build and boot old kernels for that system, but I
> tried my USB adapter in older systems with older kernels.
> 
> 2.6.20 and 2.6.22.1 both were able to bring the interface up and DHCP.
> 2.6.24.3 was NOT able to.
> Neither was 2.6.34.1.

Not a lot has changed int hat driver between 2.6.22 and 2.6.24, so you could
try

git diff v2.6.22..v2.6.24 drivers/net/usb/asix.c  | patch -Rp1 

on the latest version and see if that helps. There are some rejects, but
those all look harmless.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/usb/net/usbnet.c b/drivers/usb/net/usbnet.c
index 4cbb408..3c1d0ee 100644
--- a/drivers/usb/net/usbnet.c
+++ b/drivers/usb/net/usbnet.c
@@ -739,11 +739,15 @@  static void ax8817x_mdio_write(struct net_device *netdev, int phy_id, int loc, i
 static int ax88172_link_reset(struct usbnet *dev)
 {
 	u16 lpa;
+	u16 adv;
+	u16 res;
 	u8 mode;
 
 	mode = AX_MEDIUM_TX_ABORT_ALLOW | AX_MEDIUM_FLOW_CONTROL_EN;
 	lpa = ax8817x_mdio_read(dev->net, dev->mii.phy_id, MII_LPA);
-	if (lpa & LPA_DUPLEX)
+	adv = ax8817x_mdio_read(dev->net, dev->mii.phy_id, MII_ADVERTISE);
+	res = mii_nway_result(lpa|adv);
+	if (res & LPA_DUPLEX)
 		mode |= AX_MEDIUM_FULL_DUPLEX;
 	ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL);
 
@@ -816,7 +820,7 @@  static int ax8817x_get_eeprom(struct net_device *net,
 			eeprom->offset + i, 0, 2, &ebuf[i]) < 0)
 			return -EINVAL;
 	}
-	return 0;
+	return i * 2;
 }
 
 static void ax8817x_get_drvinfo (struct net_device *net,
@@ -960,6 +964,29 @@  static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 		goto out2;
 
 	msleep(5);
+
+	/* Initialize MII structure */
+	dev->mii.dev = dev->net;
+	dev->mii.mdio_read = ax8817x_mdio_read;
+	dev->mii.mdio_write = ax8817x_mdio_write;
+	dev->mii.phy_id_mask = 0xff;
+	dev->mii.reg_num_mask = 0xff;
+
+	/* Get the PHY id */
+	if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) {
+		dbg("Error reading PHY ID: %02x", ret);
+		goto out2;
+	} else if (ret < 2) {
+		/* this should always return 2 bytes */
+		dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
+		    ret);
+		ret = -EIO;
+		goto out2;
+	}
+	dev->mii.phy_id = *((u8 *)buf + 1);
+
+	if (dev->mii.phy_id == 0x10)
+	{
 	if ((ret = ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0x0001, 0, 0, buf)) < 0) {
 		dbg("Select PHY #1 failed: %d", ret);
 		goto out2;
@@ -984,6 +1011,21 @@  static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 		dbg("Failed to set Internal/External PHY reset control: %d", ret);
 		goto out2;
 	}
+	}
+	else
+	{
+	if ((ret =
+	    ax8817x_write_cmd(dev, AX_CMD_SW_PHY_SELECT, 0x0000, 0, 0, buf)) < 0) {
+		dbg("Select PHY #1 failed: %d", ret);
+		goto out2;
+	}
+
+	if ((ret =
+	     ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_IPPD | AX_SWRESET_PRL, 0, 0, buf)) < 0) {
+		dbg("Failed to power down internal PHY: %d", ret);
+		goto out2;
+	}
+	}
 
 	msleep(150);
 	if ((ret =
@@ -1006,6 +1048,8 @@  static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 		goto out2;
 	}
 
+	if (dev->mii.phy_id == 0x10)
+	{
 	if (((ret =
 	      ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, 0x0010, 2, 2, buf)) < 0)
 	    || (*((u16 *)buf) != 0x003b)) {
@@ -1013,26 +1057,6 @@  static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 		goto out2;
 	}
 
-	/* Initialize MII structure */
-	dev->mii.dev = dev->net;
-	dev->mii.mdio_read = ax8817x_mdio_read;
-	dev->mii.mdio_write = ax8817x_mdio_write;
-	dev->mii.phy_id_mask = 0xff;
-	dev->mii.reg_num_mask = 0xff;
-
-	/* Get the PHY id */
-	if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf)) < 0) {
-		dbg("Error reading PHY ID: %02x", ret);
-		goto out2;
-	} else if (ret < 2) {
-		/* this should always return 2 bytes */
-		dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x",
-		    ret);
-		ret = -EIO;
-		goto out2;
-	}
-	dev->mii.phy_id = *((u8 *)buf + 1);
-
 	if ((ret =
 	     ax8817x_write_cmd(dev, AX_CMD_SW_RESET, AX_SWRESET_PRL, 0, 0, buf)) < 0) {
 		dbg("Set external PHY reset pin level: %d", ret);
@@ -1045,14 +1069,14 @@  static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 		goto out2;
 	}
 	msleep(150);
-
+	}
 
 	dev->net->set_multicast_list = ax8817x_set_multicast;
 	dev->net->ethtool_ops = &ax88772_ethtool_ops;
 
 	ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET);
 	ax8817x_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE,
-			ADVERTISE_ALL | ADVERTISE_CSMA);
+			ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP);
 	mii_nway_restart(&dev->mii);
 
 	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, AX88772_MEDIUM_DEFAULT, 0, 0, buf)) < 0) {
@@ -1060,7 +1084,7 @@  static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 		goto out2;
 	}
 
-	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0, AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,AX88772_IPG2_DEFAULT, 0, buf)) < 0) {
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0, AX88772_IPG0_DEFAULT | (AX88772_IPG1_DEFAULT << 8), AX88772_IPG2_DEFAULT, 0, buf)) < 0) {
 		dbg("Write IPG,IPG1,IPG2 failed: %d", ret);
 		goto out2;
 	}
@@ -1088,6 +1112,663 @@  out1:
 	return ret;
 }
 
+static int mediacheck(struct usbnet *dev)
+{
+	int ret,fullduplex;
+	u16 phylinkstatus1, phylinkstatus2, data16, tempshort = 0;
+	struct ax8817x_data *ax17xdataptr = (struct ax8817x_data *)&dev->data;
+	struct ax88178_data *ax178dataptr = (struct ax88178_data *)ax17xdataptr->ax178dataptr;
+
+
+	if ((ret =ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG,dev->mii.phy_id,
+		GMII_PHY_ANLPAR, REG_LENGTH, &data16)) < 0) {
+		dbg("error on reading MII register 5 failed: %02x", ret);
+		return ret;   //
+	}
+	phylinkstatus1 = le16_to_cpu(data16);
+
+	if ((ret =ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG,dev->mii.phy_id, GMII_PHY_1000BT_STATUS,
+		REG_LENGTH, &data16)) < 0) {
+		dbg("error on reading MII register 0x0a failed: %02x", ret);
+		return ret;   //
+	}
+	phylinkstatus2 = le16_to_cpu(data16);
+
+	if(ax178dataptr->PhyMode == PHY_MODE_MARVELL){ //1st generation Marvel PHY
+		if(ax178dataptr->LedMode == 1){
+			if ((ret = ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG,dev->mii.phy_id, MARVELL_MANUAL_LED,
+				REG_LENGTH, &data16)) < 0) {
+				dbg("error on reading MII register 0x19 failed: %02x", ret);
+				return ret;   //
+			}
+			tempshort = le16_to_cpu(data16);
+			tempshort &=0xfc0f;
+		}
+	}
+
+	fullduplex=1;
+	if(phylinkstatus2 & (GMII_1000_AUX_STATUS_FD_CAPABLE|GMII_1000_AUX_STATUS_HD_CAPABLE)){  /* 1000BT full duplex */
+		ax178dataptr->MediaLink =
+			MEDIUM_GIGA_MODE|MEDIUM_FULL_DUPLEX_MODE|MEDIUM_ENABLE_125MHZ|MEDIUM_ENABLE_RECEIVE;
+			if(ax178dataptr->PhyMode == PHY_MODE_MARVELL){
+				if(ax178dataptr->LedMode == 1){
+					tempshort|=0x3e0;
+				}
+			}
+	}else if(phylinkstatus1 & GMII_ANLPAR_100TXFD){  /* 100BT full duplex */
+		ax178dataptr->MediaLink=MEDIUM_FULL_DUPLEX_MODE|MEDIUM_ENABLE_RECEIVE|MEDIUM_MII_100M_MODE;
+			if(ax178dataptr->PhyMode == PHY_MODE_MARVELL){
+				if(ax178dataptr->LedMode == 1){
+					tempshort|=0x3b0;
+				}
+			}
+	}else if(phylinkstatus1 & GMII_ANLPAR_100TX){   /* 100BT half duplex */
+		ax178dataptr->MediaLink=(MEDIUM_ENABLE_RECEIVE|MEDIUM_MII_100M_MODE);
+		fullduplex=0;
+			if(ax178dataptr->PhyMode == PHY_MODE_MARVELL){
+				if(ax178dataptr->LedMode == 1){
+					tempshort|=0x3b0;
+				}
+		}
+	}else if(phylinkstatus1 & GMII_ANLPAR_10TFD){	/* 10 full duplex */
+		ax178dataptr->MediaLink = (MEDIUM_FULL_DUPLEX_MODE|MEDIUM_ENABLE_RECEIVE);
+		if(ax178dataptr->PhyMode == PHY_MODE_MARVELL){
+			if(ax178dataptr->LedMode == 1){
+				tempshort|=0x02f0;
+			}
+		}
+	}else{
+		/* 10 half duplex*/
+		ax178dataptr->MediaLink = MEDIUM_ENABLE_RECEIVE;
+		fullduplex=0;
+		if(ax178dataptr->PhyMode == PHY_MODE_MARVELL){
+			if(ax178dataptr->LedMode == 1){
+				tempshort|=0x02f0;
+			}
+		}
+	}
+
+	if(ax178dataptr->PhyMode == PHY_MODE_MARVELL){
+		if(ax178dataptr->LedMode == 1){
+			data16 = le16_to_cpu(tempshort);
+		     if ( (ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, (u8)dev->mii.phy_id,
+				 MARVELL_MANUAL_LED, REG_LENGTH, &data16)) < 0){
+			     dbg("error on writing MII register 0x19 failed: %02x", ret);
+			     return ret;
+		     }
+		}
+	}
+	ax178dataptr->MediaLink |= 0x0004;
+	if(ax178dataptr->UseRgmii != 0)
+		ax178dataptr->MediaLink |= 0x0008;
+	if(fullduplex){
+		ax178dataptr->MediaLink |= 0x0020;  //ebable tx flow control as default;
+		ax178dataptr->MediaLink |= 0x0010;  //ebable rx flow control as default;
+	}
+
+	return 0;
+}
+
+static int marevell_init(struct usbnet *dev)
+{
+	struct ax8817x_data *ax17xdataptr = (struct ax8817x_data *)&dev->data;
+	struct ax88178_data *ax178dataptr = (struct ax88178_data *)ax17xdataptr->ax178dataptr;
+	u16 tmp,phyreg,PhyPatch,data16;
+	int ret;
+	void *buf;
+	u8 PhyID = (u8)ax178dataptr->PhyID;
+
+	buf = kmalloc(ETH_ALEN, GFP_KERNEL);
+	if(!buf)
+		return -ENOMEM;
+
+	if(ax178dataptr->UseGpio0)
+	{
+		if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,AXGPIOS_GPO0EN |AXGPIOS_RSE,0, 0,buf)) < 0){
+			dbg("write GPIO failed: %d", ret);
+			return ret;
+		}
+		msleep(25);
+		tmp = AXGPIOS_GPO2 | AXGPIOS_GPO2EN | AXGPIOS_GPO0EN;
+		if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, tmp, 0, 0, buf)) < 0){
+			dbg("write GPIO failed: %d", ret);
+			return ret;
+		}
+		msleep(25);
+		tmp = AXGPIOS_GPO2EN | AXGPIOS_GPO0EN;
+		if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, tmp, 0, 0, buf)) < 0){
+			dbg("write GPIO failed: %d", ret);
+			return ret;
+		}
+		msleep(245);
+		tmp = AXGPIOS_GPO2 | AXGPIOS_GPO2EN | AXGPIOS_GPO0EN;
+		if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, tmp, 0, 0, buf)) < 0){
+			dbg("write GPIO failed: %d", ret);
+			return ret;
+		}	
+		
+	}
+	else /* !UseGpio0 */
+	{
+		tmp = AXGPIOS_GPO1|AXGPIOS_GPO1EN | AXGPIOS_RSE;
+		if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, tmp, 0, 0, buf)) < 0){
+			dbg("write GPIO failed: %d", ret);
+			return ret;
+		}
+		if(ax178dataptr->LedMode != 1) //our new demo board
+		{
+			msleep(25);
+			tmp = AXGPIOS_GPO1|AXGPIOS_GPO1EN | AXGPIOS_GPO2EN | AXGPIOS_GPO2;
+			if ((ret =ax8817x_write_cmd(dev,AX_CMD_WRITE_GPIOS,tmp,0,0,buf)) < 0){
+				dbg("write GPIO failed: %d", ret);
+				return ret;
+			}
+			msleep(25);
+			tmp = AXGPIOS_GPO2EN | AXGPIOS_GPO1|AXGPIOS_GPO1EN;
+			if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, tmp, 0, 0, buf)) < 0){
+				dbg("write GPIO failed: %d", ret);
+				return ret;
+			}
+			msleep(245);
+			tmp = AXGPIOS_GPO1|AXGPIOS_GPO1EN|AXGPIOS_GPO2|AXGPIOS_GPO2EN;
+			if ((ret = ax8817x_write_cmd(dev,AX_CMD_WRITE_GPIOS,tmp,0,0,buf)) < 0){
+				dbg("write GPIO failed: %d", ret);
+				return ret;
+			}
+		}
+		else if(ax178dataptr->LedMode == 1)  //bufflo old card
+		{
+			msleep(350);
+			if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, AXGPIOS_GPO1EN, 0, 0, buf)) < 0){
+				dbg("write GPIO failed: %d", ret);
+				return ret;
+			}
+			msleep(350);
+			if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, AXGPIOS_GPO1|AXGPIOS_GPO1EN, 0, 0, buf)) < 0){
+				dbg("write GPIO failed: %d", ret);
+				return ret;
+			}
+		}		
+	}
+
+
+	if((ret = ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, PhyID, PHY_MARVELL_STATUS, REG_LENGTH, &data16)) < 0){
+	       dbg("read register reg 27 failed: %d", ret);
+	       return ret;
+	}    //read phy register
+
+	phyreg = le16_to_cpu(data16);
+	if(!(phyreg & MARVELL_STATUS_HWCFG)){
+		ax178dataptr->UseRgmii=1;
+		PhyPatch = MARVELL_CTRL_RXDELAY | MARVELL_CTRL_TXDELAY;
+		data16 = cpu_to_le16(PhyPatch);
+		if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, PHY_MARVELL_CTRL, REG_LENGTH, &data16)) < 0)
+			return ret;
+		ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+	}
+
+	if(ax178dataptr->LedMode == 1){
+		if((ret = ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG, PhyID, MARVELL_LED_CTRL, REG_LENGTH, &data16))< 0)
+			return ret;
+		phyreg = le16_to_cpu(data16);
+		phyreg &= 0xf8ff;
+		phyreg |= (1+0x100);
+
+		data16 = le16_to_cpu(phyreg);
+		if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, MARVELL_LED_CTRL, REG_LENGTH,&data16))< 0)
+			return ret;
+		if((ret = ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG, PhyID, MARVELL_LED_CTRL, REG_LENGTH, &data16))< 0)
+			return ret;
+		phyreg = le16_to_cpu(data16);
+		phyreg &=0xfc0f;
+	} else if(ax178dataptr->LedMode == 2){
+
+		if((ret = ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG, PhyID, MARVELL_LED_CTRL, REG_LENGTH, &data16))< 0)
+			return ret;
+
+		phyreg = le16_to_cpu(data16);
+		phyreg &= 0xf886;
+		phyreg |= (1+0x10+0x300);
+		data16 = cpu_to_le16(phyreg);
+		if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, MARVELL_LED_CTRL, REG_LENGTH,&data16))< 0)
+			return ret;
+
+	}else if(ax178dataptr->LedMode == 5){
+		if((ret = ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG, PhyID, MARVELL_LED_CTRL, REG_LENGTH, &data16))< 0)
+			return ret;
+		phyreg = le16_to_cpu(data16);
+		phyreg &= 0xf8be;
+		phyreg |= (1+0x40+0x300);
+		data16 = cpu_to_le16(phyreg);
+		if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, MARVELL_LED_CTRL, REG_LENGTH,&data16))< 0)
+			return ret;
+	}
+	
+	ax178dataptr->phyreg = phyreg;
+	return 0;
+}
+
+static int cicada_init(struct usbnet *dev)
+{
+
+	struct ax8817x_data *ax17xdataptr = (struct ax8817x_data *)&dev->data;
+	struct ax88178_data *ax178dataptr = (struct ax88178_data *)ax17xdataptr->ax178dataptr;
+	u16 tmp, phyreg, i, data16;
+	int ret;
+	void *buf;
+	u8 PhyID = (u8)ax178dataptr->PhyID;
+
+	buf = kmalloc(ETH_ALEN, GFP_KERNEL);
+	if(!buf)
+		return -ENOMEM;
+
+	if(ax178dataptr->UseGpio0)
+	{
+		if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,AXGPIOS_GPO0 | AXGPIOS_GPO0EN | AXGPIOS_RSE,0, 0,buf)) < 0){
+			dbg("write GPIO failed: %d", ret);
+			return ret;
+		}
+	}
+	else
+	{
+		tmp = AXGPIOS_GPO1|AXGPIOS_GPO1EN | AXGPIOS_RSE;
+		if ((ret =ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,tmp,0,0,buf)) < 0){
+			dbg("write GPIO failed: %d", ret);
+			return ret;
+		}
+		if(ax178dataptr->LedMode!= 1) //our new demo board
+		{
+			msleep(25);
+			tmp = AXGPIOS_GPO1|AXGPIOS_GPO1EN | AXGPIOS_GPO2EN | AXGPIOS_GPO2;
+			if ((ret =ax8817x_write_cmd(dev,AX_CMD_WRITE_GPIOS,tmp,0,0,buf)) < 0){
+				dbg("write GPIO failed: %d", ret);
+				return ret;
+			}
+			msleep(25);
+			tmp = AXGPIOS_GPO2EN | AXGPIOS_GPO1|AXGPIOS_GPO1EN;
+			if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, tmp, 0, 0, buf)) < 0){
+				dbg("write GPIO failed: %d", ret);
+				return ret;
+			}
+			msleep(245);
+			tmp = AXGPIOS_GPO1|AXGPIOS_GPO1EN|AXGPIOS_GPO2|AXGPIOS_GPO2EN;
+			if ((ret = ax8817x_write_cmd(dev,AX_CMD_WRITE_GPIOS,tmp,0,0,buf)) < 0){
+				dbg("write GPIO failed: %d", ret);
+				return ret;
+			}
+		}
+		else if(ax178dataptr->LedMode==1)  //bufflo old card
+		{
+			msleep(350);
+			if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, AXGPIOS_GPO1EN, 0, 0, buf)) < 0){
+				dbg("write GPIO failed: %d", ret);
+				return ret;
+			}
+			msleep(350);
+			if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, AXGPIOS_GPO1|AXGPIOS_GPO1EN, 0, 0, buf)) < 0){
+				dbg("write GPIO failed: %d", ret);
+				return ret;
+			}
+		}
+	}
+
+	if(ax178dataptr->PhyMode == PHY_MODE_CICADA_FAMILY){    //CICADA 1st version phy
+		ax178dataptr->UseRgmii=1;
+		ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;// MEDIUM_ENABLE_125MHZ;
+
+		for (i = 0; i < sizeof(CICADA_FAMILY_HWINIT)/sizeof(CICADA_FAMILY_HWINIT[0]); i++) {
+			data16 = cpu_to_le16(CICADA_FAMILY_HWINIT[i].value);
+			ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, CICADA_FAMILY_HWINIT[i].offset, REG_LENGTH, &data16);
+			if(ret < 0) return ret;
+		}
+	}
+	else if(ax178dataptr->PhyMode == PHY_MODE_CICADA_V2){
+		ax178dataptr->UseRgmii=1;
+		ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+
+		for (i = 0; i < ( sizeof(CICADA_V2_HWINIT)/sizeof(CICADA_V2_HWINIT[0]) ); i++) {
+			data16 = cpu_to_le16(CICADA_V2_HWINIT[i].value);
+			ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, CICADA_V2_HWINIT[i].offset, REG_LENGTH, &data16);
+			if(ret < 0) return ret;
+		}
+	}
+	else if(ax178dataptr->PhyMode == PHY_MODE_CICADA_V2_ASIX){
+		ax178dataptr->UseRgmii=1;
+		ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+
+		for (i = 0; i < ( sizeof(CICADA_V2_ASIX_HWINIT)/sizeof(CICADA_V2_ASIX_HWINIT[0]) ); i++) {
+			data16 = cpu_to_le16(CICADA_V2_ASIX_HWINIT[i].value);
+			ret=ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, CICADA_V2_ASIX_HWINIT[i].offset, REG_LENGTH, &data16);
+			if(ret < 0) return ret;
+		}
+	}
+
+	if(ax178dataptr->PhyMode == PHY_MODE_CICADA_FAMILY){
+		if(ax178dataptr->LedMode == 3){
+			if((ret = ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG, PhyID, 27, 2, &data16))< 0)
+				return ret;
+			phyreg = le16_to_cpu(data16);
+			phyreg &= 0xfcff;
+			phyreg |= 0x0100;
+			data16 = cpu_to_le16(phyreg);
+			if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, 27,2,&data16))< 0)
+				return ret;
+		}
+	}
+	return 0;
+}
+
+static int agere_init(struct usbnet *dev)
+{
+	struct ax8817x_data *ax17xdataptr = (struct ax8817x_data *)&dev->data;
+	struct ax88178_data *ax178dataptr = (struct ax88178_data *)ax17xdataptr->ax178dataptr;
+	u16 tmp, phyreg, i;
+	int ret;
+	void *buf;
+	u8 PhyID = (u8)ax178dataptr->PhyID;
+
+	buf = kmalloc(ETH_ALEN, GFP_KERNEL);
+	if(!buf)
+		return -ENOMEM;
+
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS,AXGPIOS_GPO1|AXGPIOS_GPO1EN | AXGPIOS_RSE,0,0,buf)) < 0){
+		dbg("write GPIO failed: %d", ret);
+		return ret;
+	}
+	msleep(25);
+	if ((ret=ax8817x_write_cmd(dev,AX_CMD_WRITE_GPIOS,AXGPIOS_GPO1|AXGPIOS_GPO1EN
+		| AXGPIOS_GPO2EN | AXGPIOS_GPO2,0,0,buf)) < 0){
+		dbg("write GPIO failed: %d", ret);
+		return ret;
+	}
+	msleep(25);
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_GPIOS, AXGPIOS_GPO2EN | AXGPIOS_GPO1
+		| AXGPIOS_GPO1EN, 0, 0, buf)) < 0){
+		dbg("write GPIO failed: %d", ret);
+		return ret;
+	}
+	msleep(245);
+	if ((ret=ax8817x_write_cmd(dev,AX_CMD_WRITE_GPIOS,AXGPIOS_GPO1|AXGPIOS_GPO1EN|AXGPIOS_GPO2
+		| AXGPIOS_GPO2EN,0,0,buf)) < 0){
+		dbg("write GPIO failed: %d", ret);
+		return ret;
+	}
+	
+	ax178dataptr->UseRgmii=1;
+	ax178dataptr->MediaLink |= MEDIUM_ENABLE_125MHZ;
+
+	phyreg = cpu_to_le16(BMCR_RESET);
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, MII_BMCR, REG_LENGTH, &phyreg)) < 0) {
+		dbg("Failed to write MII reg - MII_BMCR: %02x", ret);
+		return ret;
+	} //software reset
+
+	while (1)
+	{
+		phyreg = cpu_to_le16(0x1001);
+		ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, 21, REG_LENGTH, &phyreg);
+		msleep(10);
+		ax8817x_read_cmd(dev, AX_CMD_READ_MII_REG, PhyID, 21, REG_LENGTH, &phyreg);
+		tmp = le16_to_cpu(phyreg);
+		if ((tmp & 0xf00f) == 0x1001)
+			break;
+		msleep(10);
+	}
+
+	if (ax178dataptr->LedMode == 4)
+	{
+		phyreg = cpu_to_le16(0x7417);
+		ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, 28, 2, &phyreg);
+	}
+	else if (ax178dataptr->LedMode == 9)
+	{
+		phyreg = cpu_to_le16(0x7a10);
+		ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, 28, 2, &phyreg);
+	}
+	else if (ax178dataptr->LedMode == 10)
+	{
+		phyreg = cpu_to_le16(0x7a13);
+		ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, PhyID, 28, 2, &phyreg);
+	}
+
+	for (i = 0; i < ( sizeof(AGERE_FAMILY_HWINIT)/sizeof(AGERE_FAMILY_HWINIT[0]) ); i++) {
+		phyreg = cpu_to_le16(AGERE_FAMILY_HWINIT[i].value);
+		ret=ax8817x_write_cmd(dev,AX_CMD_WRITE_MII_REG,PhyID,AGERE_FAMILY_HWINIT[i].offset,REG_LENGTH,&phyreg);
+		if(ret < 0) return ret;
+	}
+
+	return 0;
+}
+
+static int phy_init(struct usbnet *dev)
+{
+	struct ax8817x_data *ax17xdataptr = (struct ax8817x_data *)&dev->data;
+	struct ax88178_data *ax178dataptr = (struct ax88178_data *)ax17xdataptr->ax178dataptr;
+	int ret;
+	u16 tmp, data16, phyanar, phyauxctrl, phyctrl, phyreg = 0;
+	void *buf;
+
+	buf = kmalloc(ETH_ALEN, GFP_KERNEL);
+	if(!buf)
+		return -ENOMEM;
+
+	if(ax178dataptr->PhyMode == PHY_MODE_MARVELL) {
+		if((ret = marevell_init(dev)) < 0) return ret;
+	}else if(ax178dataptr->PhyMode == PHY_MODE_CICADA_FAMILY) {
+		if((ret = cicada_init(dev)) < 0) return ret;
+	}else if(ax178dataptr->PhyMode == PHY_MODE_CICADA_V1) {
+		if((ret = cicada_init(dev)) < 0) return ret;
+	}else if(ax178dataptr->PhyMode == PHY_MODE_CICADA_V2_ASIX) {
+		if((ret = cicada_init(dev)) < 0) return ret;
+	}else if(ax178dataptr->PhyMode == PHY_MODE_AGERE_FAMILY) {
+		if((ret = agere_init(dev)) < 0) return ret;
+	}
+
+	if(ax178dataptr->PhyMode != PHY_MODE_AGERE_FAMILY)
+	{
+		/* reset phy */
+		data16 = cpu_to_le16(BMCR_RESET);
+		if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, dev->mii.phy_id,
+			MII_BMCR, REG_LENGTH, (void *)(&data16))) < 0) {
+			dbg("Failed to write MII reg - MII_BMCR: %02x", ret);
+			return ret;
+		}
+	}
+
+	if  ((ret = ax8817x_read_cmd(dev,AX_CMD_READ_MII_REG, dev->mii.phy_id , MII_BMCR,
+		REG_LENGTH, &data16)) < 0) {
+		dbg("error on read MII reg - MII_BMCR: %02x", ret);
+		return ret;   //could be 0x0000
+	}
+
+	phyctrl = le16_to_cpu(data16);
+	tmp=phyctrl;
+	phyctrl &=~(BMCR_PDOWN|BMCR_ISOLATE);
+	if(phyctrl != tmp){
+		data16 = cpu_to_le16(phyctrl);
+		if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG, dev->mii.phy_id, MII_BMCR,
+			REG_LENGTH, &data16)) < 0) {
+			dbg("Failed to write MII reg - MII_BMCR: %02x", ret);
+			return ret;
+		}
+
+	}
+
+	phyctrl&= ~BMCR_ISOLATE;
+	phyanar=1+(0x0400|ADVERTISE_100FULL|ADVERTISE_100HALF|ADVERTISE_10FULL|ADVERTISE_10HALF);
+	phyauxctrl=0x0200; //1000M and full duplex
+
+	data16 = cpu_to_le16(phyanar);
+	if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG,dev->mii.phy_id,
+		GMII_PHY_ANAR,REG_LENGTH,&data16))< 0) return ret;
+
+	data16 = cpu_to_le16(phyauxctrl);
+	if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG,dev->mii.phy_id,
+		GMII_PHY_1000BT_CONTROL,REG_LENGTH,&data16))< 0) return ret;
+
+	phyctrl |= (BMCR_ANENABLE|BMCR_ANRESTART);
+	data16 = cpu_to_le16(phyctrl);
+	if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG,dev->mii.phy_id,
+		GMII_PHY_CONTROL,REG_LENGTH,&data16))< 0) return ret;
+
+	if(ax178dataptr->PhyMode == PHY_MODE_MARVELL){
+		if(ax178dataptr->LedMode==1) {
+			phyreg |= 0x3f0;
+			data16 = cpu_to_le16(phyreg);
+			if((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MII_REG,dev->mii.phy_id,
+				25,REG_LENGTH,&phyreg))< 0) return ret;
+		}
+	}
+
+	msleep(3000);
+
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_IPG0,
+			(AX88772_IPG0_DEFAULT | (AX88772_IPG1_DEFAULT << 8)),
+			0x000e, 0, buf)) < 0) {
+		dbg("write IPG IPG1 IPG2 reg failed: %d", ret);
+		return ret;
+	}
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, buf)) < 0) {
+		dbg("disable PHY access failed: %d", ret);
+		return ret;
+	}
+
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL,
+			(AX_RX_CTL_MFB | AX_RX_CTL_START | AX_RX_CTL_AB),
+		0, 0, buf)) < 0) {
+		dbg("write RX ctrl reg failed: %d", ret);
+		return ret;
+	}
+
+	return 0;	
+
+}
+
+static int ax88178_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	int ret;
+	void *buf;
+	u16 EepromData,PhyID, temp16;
+	struct ax8817x_data *ax17xdataptr = (struct ax8817x_data *)&dev->data;
+	struct ax88178_data *ax178dataptr;
+
+	get_endpoints(dev,intf);
+
+	buf = kmalloc(6, GFP_KERNEL);
+	if(!buf) {
+		dbg ("Cannot allocate memory for buffer");
+		return -ENOMEM;
+	}
+
+	/* allocate 178 data */
+	if (!(ax178dataptr = kmalloc (sizeof(struct ax88178_data), GFP_KERNEL))) {
+		dbg ("Cannot allocate memory for AX88178 data");
+		return -ENOMEM;
+	}
+	memset (ax178dataptr, 0, sizeof(struct ax88178_data));
+	ax17xdataptr->ax178dataptr = ax178dataptr;
+	/* end of allocate 178 data */
+
+	if ((ret = ax8817x_write_cmd(dev, 0x22, 0x0000, 0, 0, buf)) < 0) {
+		dbg("write S/W reset failed: %d", ret);
+		return ret;
+	}
+	msleep(150);
+
+	if ((ret = ax8817x_write_cmd(dev, 0x20, 0x0048, 0, 0, buf)) < 0) {
+		dbg("write S/W reset failed: %d", ret);
+		return ret;
+	}
+	msleep(150);
+
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_RX_CTL, 0x0000, 0, 0, buf)) < 0) {
+		dbg("send AX_CMD_WRITE_RX_CTL failed: %d", ret);
+		return ret;				//stop rcv
+	}
+
+	msleep(150);
+
+	/* Get the MAC address */
+	memset(buf, 0, ETH_ALEN);
+	if ((ret = ax8817x_read_cmd(dev, AX88772_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf)) < 0) {
+		dbg("read AX_CMD_READ_NODE_ID failed: %d", ret);
+		return ret;
+	}
+	memcpy(dev->net->dev_addr, buf, ETH_ALEN);
+	/* End of get MAC address */
+
+
+	/* Get the EEPROM data*/
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_EEPROM_EN, 0, 0, 0, buf)) < 0) {
+		dbg("enable SROM reading failed: %d", ret);
+		return ret;   // ???
+	}
+
+	if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_EEPROM,
+			0x0017, 0, 2, (void *)(&EepromData))) < 0) {
+		dbg("read SROM address 17h failed: %d", ret);
+		return ret;
+	}
+
+	ax178dataptr->EepromData = le16_to_cpu(EepromData);
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_EEPROM_DIS, 0, 0, 0, buf)) < 0) {
+		dbg("disable SROM reading failed: %d", ret);
+		return ret; // ???
+	}
+	/* End of get EEPROM data */
+
+	/* Get PHY id */
+
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, buf)) < 0) {
+		dbg("enable PHY reg. access capability: %d", ret);
+		return ret;				//enable Phy register access capability
+	}
+
+	if ((ret = ax8817x_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, REG_LENGTH, &temp16)) < 0) {
+		dbg("error on read AX_CMD_READ_PHY_ID: %02x", ret);
+		return ret;
+	} else if (ret < 2) {
+		/* this should always return 2 bytes */
+		dbg("AX_CMD_READ_PHY_ID returned less than 2 bytes: ret=%02x", ret);
+		return -EIO;
+	}
+
+	PhyID = le16_to_cpu(temp16);
+	PhyID = (PhyID >> 8) & PHY_ID_MASK;
+	ax178dataptr->PhyID = PhyID;
+	/* End of get PHY id */
+
+	/* Initialize MII structure */
+	dev->mii.dev = dev->net;
+	dev->mii.mdio_read = ax8817x_mdio_read;
+	dev->mii.mdio_write = ax8817x_mdio_write;
+	dev->mii.phy_id_mask = 0x3f;
+	dev->mii.reg_num_mask = 0x1f;
+	dev->mii.phy_id = (u8)ax178dataptr->PhyID;
+
+	if (ax178dataptr->EepromData == 0xffff)
+	{
+		ax178dataptr->PhyMode  = PHY_MODE_MARVELL;
+		ax178dataptr->LedMode  = 0;
+		ax178dataptr->UseGpio0 = 1; //True
+	}
+	else
+	{
+		ax178dataptr->PhyMode  = (u8)(ax178dataptr->EepromData & EEPROMMASK);
+		ax178dataptr->LedMode  = (u8)(ax178dataptr->EepromData>>8);	
+		if(ax178dataptr->EepromData & 0x80) {
+			ax178dataptr->UseGpio0=0; //MARVEL se and other
+		}
+		else {
+			ax178dataptr->UseGpio0=1; //cameo
+		}
+	}
+
+	if ((ret = phy_init(dev)) < 0)	return ret;
+
+	return 0;
+}
+
 static int ax88772_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
 {
 	u32 *header;
@@ -1199,6 +1880,70 @@  static int ax88772_link_reset(struct usbnet *dev)
 	return 0;
 }
 
+static int set_media(struct usbnet *dev)
+{
+	int	ret;
+	void	*buf;
+	struct ax8817x_data *ax17xdataptr = (struct ax8817x_data *)&dev->data;
+	struct ax88178_data *ax178dataptr = (struct ax88178_data *)ax17xdataptr->ax178dataptr;
+
+	buf = kmalloc(ETH_ALEN, GFP_KERNEL);
+	if(!buf)
+		return -ENOMEM;
+
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, buf)) < 0) {
+		dbg("enable PHY reg. access capability: %d", ret);
+		return ret;				//enable Phy register access capability
+	}
+
+	mediacheck(dev);
+
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE,
+			ax178dataptr->MediaLink, 0, 0, buf)) < 0) {
+		dbg("write mode medium reg failed: %d", ret);
+		return ret;
+	}
+
+	if ((ret = ax8817x_write_cmd(dev, AX_CMD_SET_HW_MII, 0, 0, 0, buf)) < 0) {
+		dbg("disable PHY access failed: %d", ret);
+		return ret;
+	}
+
+	dev->net->set_multicast_list = ax8817x_set_multicast;
+	dev->net->ethtool_ops = &ax8817x_ethtool_ops;
+	return 0;
+}
+
+static int ax88178_link_reset(struct usbnet *dev)
+{
+	int ret;
+
+	if ((ret = set_media(dev)) < 0)	return ret;
+	return 0;
+}
+
+static const struct driver_info ax88178_info = {
+	.description = "ASIX AX88178 USB 2.0 Ethernet",
+	.bind = ax88178_bind,
+	.status = ax8817x_status,
+	.link_reset = ax88178_link_reset,
+	.flags =  FLAG_ETHER|FLAG_FRAMING_AX,
+	.rx_fixup =	ax88772_rx_fixup,
+	.tx_fixup =	ax88772_tx_fixup,
+	.data = 0x00130103,  //useless here
+};
+
+static const struct driver_info belkin178_info = {
+	.description = "Belkin Gigabit USB 2.0 Network Adapter",
+	.bind = ax88178_bind,
+	.status = ax8817x_status,
+	.link_reset = ax88178_link_reset,
+	.flags =  FLAG_ETHER|FLAG_FRAMING_AX,
+	.rx_fixup =	ax88772_rx_fixup,
+	.tx_fixup =	ax88772_tx_fixup,
+	.data = 0x00130103,  //useless here
+};
+
 static const struct driver_info ax8817x_info = {
 	.description = "ASIX AX8817x USB 2.0 Ethernet",
 	.bind = ax8817x_bind,
@@ -1251,6 +1996,18 @@  static const struct driver_info ax88772_info = {
 	.data = 0x00130103,
 };
 
+static const struct driver_info dlink_dub_e100b_info = {
+	.description = "D-Link DUB-E100 USB 2.0 Fast Ethernet Adapter",
+	.bind = ax88772_bind,
+	.status = ax8817x_status,
+	.link_reset = ax88772_link_reset,
+	.reset = ax88772_link_reset,
+	.flags = FLAG_ETHER | FLAG_FRAMING_AX,
+	.rx_fixup = ax88772_rx_fixup,
+	.tx_fixup = ax88772_tx_fixup,
+	.data = 0x00130103,
+};
+
 #endif /* CONFIG_USB_AX8817X */