Index: davinci_emac.c
===================================================================
--- davinci_emac.c	(revision 768)
+++ davinci_emac.c	(revision 3109)
@@ -146,7 +146,7 @@
 #define EMAC_INTERRUPT         13
 #define EMAC_BUS_FREQUENCY     76500000	/* PLL/6 i.e 76.5 MHz */
 #define EMAC_MDIO_FREQUENCY    2200000	/* PHY bus frequency */
-#define EMAC_PHY_MASK          0x2	/* PHY chip is located at address 1 */
+#define EMAC_PHY_MASK          0x3	/* PHY chip is located at address 1 */
 
 /* Note: For DaVinci, Buffer Descriptors are located in Wrapper RAM
  * (4K).  Half of the Wrapper memory is for RX BD's and other half for
@@ -1608,7 +1608,7 @@
 
 static const char emac_ddcversion_string[] = "EMAC DDC version 0.5";
 
-static u32 emac_debug = 0x0;	/* no debug flags by default */
+static u32 emac_debug = 0; /* no debug flags by default */
 static u32 emac_wrapper_ptr = EMAC_WRAPPER_RAM_ADDR;
 
 /* ---------------------------------------------------------------
@@ -2729,7 +2729,9 @@
 		return -EFAULT;
 	}
 
-	copy_from_user(local_buf, buf, count);
+	ret_val = copy_from_user(local_buf, buf, count);
+	if(ret_val)
+		return ret_val;
 	local_buf[count - 1] = '\0';	/* ignoring last \n char */
 	ret_val = count;
 	if (strcmp("0", local_buf) == 0) {
@@ -3344,6 +3346,95 @@
 	dev->net_dev_stats.tx_errors++;
 }
 
+static int
+emac_netdev_set_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	int speed_duplex = 0;
+	unsigned int phy_mode = 0;
+	
+	if (ecmd->autoneg)
+		phy_mode |= SNWAY_AUTO;
+
+	/*             { 10, 100 }   { 0, 1 } */
+	speed_duplex = ecmd->speed + ecmd->duplex;
+	switch (speed_duplex) {
+	case 10:	/* HD10 */
+		phy_mode |= SNWAY_HD10;
+		break;
+	case 11:	/* FD10 */
+		phy_mode |= SNWAY_FD10;
+		break;
+	case 100:	/* HD100 */
+		phy_mode |= SNWAY_HD100;
+		break;
+	case 101:	/* FD100 */
+		phy_mode |= SNWAY_FD100;
+		break;
+	default:
+		return -1;
+	}	
+	emac_mdio_set_phy_mode(phy_mode);
+	return 0;
+}
+
+static int
+emac_netdev_get_ecmd(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	int dplx = emac_mdio_get_duplex();
+
+	/* Hard-coded, but should perhaps be retrieved from davinci_emac_phy */
+	ecmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
+		 SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
+		 SUPPORTED_Autoneg | SUPPORTED_MII;
+	ecmd->advertising = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+		 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
+		 ADVERTISED_Autoneg | ADVERTISED_MII;
+	ecmd->autoneg = emac_mdio_get_autoneg();
+	ecmd->speed = emac_mdio_get_speed();
+	ecmd->transceiver = XCVR_EXTERNAL;
+	ecmd->port = PORT_MII;
+	ecmd->phy_address = emac_mdio_get_phy_num();	
+	ecmd->duplex = (dplx == 3) ? DUPLEX_FULL : DUPLEX_HALF;
+	return 0;
+}
+
+static void emac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, "davinci_emac");
+	strcpy(info->version, EMAC_MODULE_VERSION);
+}
+
+static int emac_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	int ret;
+
+	ret = emac_netdev_get_ecmd(dev, ecmd);
+	return ret;
+}
+
+static int emac_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+	int ret;
+
+	ret = emac_netdev_set_ecmd(dev, ecmd);
+	return ret;
+}
+
+static u32 emac_get_link(struct net_device *dev)
+{
+	u32 ret;
+
+	ret = emac_mdio_is_linked();
+	return ret;
+}
+
+static const struct ethtool_ops ethtool_ops = {
+	.get_drvinfo = emac_get_drvinfo,
+	.get_settings = emac_get_settings,
+	.set_settings = emac_set_settings,
+	.get_link = emac_get_link,
+};
+
 /***************************************************************
  *  emac_dev_init
  *
@@ -3449,6 +3540,7 @@
 	netdev->tx_timeout = emac_tx_timeout;
 	netdev->set_mac_address = emac_dev_set_mac_addr;
 	netdev->poll = emac_poll;
+	SET_ETHTOOL_OPS(netdev, &ethtool_ops);
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	netdev->poll_controller = emac_poll_controller;
 #endif
@@ -3514,7 +3606,7 @@
 		}
 	}
 
-	if (request_irq(dev->init_cfg.intr_line, emac_hal_isr, SA_INTERRUPT,
+	if (request_irq(dev->init_cfg.intr_line, emac_hal_isr, IRQF_DISABLED,
 			"EMAC", dev)) {
 		ERR("Failed to register the irq %d for TI DaVinci EMAC %s.\n",
 		    dev->init_cfg.intr_line, netdev->name);
@@ -3527,7 +3619,7 @@
 		netif_stop_queue(netdev);
 
 	dev->device_stats.start_tick = jiffies;
-	DBG("Started the network queue for %s.\n", netdev->name);
+	/* DBG("Started the network queue for %s.\n", netdev->name); */
 	return (0);
 }
 
@@ -6717,7 +6809,7 @@
 
 	if (ret_code != EMAC_SUCCESS) {
 		if (ret_code == EMAC_ERR_TX_OUT_OF_BD) {
-			ERR("WARN: emac_dev_tx: Out of TX BD's\n");
+			/* ERR("WARN: emac_dev_tx: Out of TX BD's\n"); */
 			netif_stop_queue(dev->owner);
 		}
 		dev->net_dev_stats.tx_dropped++;
@@ -6801,7 +6893,9 @@
 		return -1;
 	}
 
-	driver_create_file(&emac_driver, &driver_attr_version);
+	ret_val = driver_create_file(&emac_driver, &driver_attr_version);
+	if(ret_val)
+		return ret_val;
 	for (unit = 0; unit < instance_count; unit++) {
 		struct net_device *netdev;
 		emac_dev_t *dev;

Index: davinci_emac_phy.c
===================================================================
--- davinci_emac_phy.c	(revision 768)
+++ davinci_emac_phy.c	(revision 3109)
@@ -28,9 +28,20 @@
  *  14Feb2006	Anant Gole 			Re-written for linux
  *  07Dec2006	Paul Bartholomew		Fix half-duplex,
  *           					use PHY_DUPLEX_* constants
+ *
  */
 #include <linux/kernel.h>
 
+#include <linux/module.h>			/* for GPIO */
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/ioctl.h>
+#include <linux/fs.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/arch/gpio.h>
+
 #include "davinci_emac_phy.h"
 
 #define EMAC_PHY_DEBUG
@@ -58,6 +69,8 @@
 #define MII_NWAY_CAPABLE        (1<<3)
 #define MII_PHY_LINKED          (1<<2)
 
+#define PHY_LEDCONFIG_REG	20
+
 #define NWAY_ADVERTIZE_REG    	4
 #define NWAY_REMADVERTISE_REG 	5
 #define MII_NWAY_FD100          (1<<8)
@@ -149,6 +162,8 @@
 	unsigned int phy_mask;	/* phy mask */
 	unsigned int mlink_mask;/* mlink mask */
 	int debug_mode;		/* debug mode */
+
+	int fx_mode;		/* FX (optics) mode detected */
 };
 
 /* Global phy structure instance */
@@ -246,6 +261,12 @@
 	return (emac_phy->phy_addr);
 }
 
+/* Get auto negotiation */
+int emac_mdio_get_autoneg(void)
+{
+	return ((emac_phy->phy_mode & NWAY_AUTO) ? 1 : 0);
+}
+
 /* Check if loopback enabled on phy */
 int emac_mdio_is_loopback(void)
 {
@@ -299,6 +320,7 @@
 void emac_mdio_phy_reset(unsigned int phy_addr)
 {
 	unsigned int control;
+	unsigned int led_config = 0xd00;
 
 	emac_mdio_write(phy_addr, PHY_CONTROL_REG, MII_PHY_RESET);
 
@@ -306,6 +328,11 @@
 		control = emac_mdio_read(phy_addr, PHY_CONTROL_REG);
 	} while (control & MII_PHY_RESET);
 
+	/* LED1 = [orange] display speed status (default)
+	 * LED2 = [green] display link and receive status combined
+	 */
+	emac_mdio_write(phy_addr, PHY_LEDCONFIG_REG, led_config);
+
 	/* CRITICAL: Fix for increasing PHY signal drive strength for
 	 * TX lockup issue. On DaVinci EVM, the Intel LXT971 PHY
   	 * signal strength was low causing  TX to fail randomly. The

Index: davinci_emac_phy.h
===================================================================
--- davinci_emac_phy.h	(revision 768)
+++ davinci_emac_phy.h	(revision 3109)
@@ -87,6 +87,9 @@
 /* Get Phy number/address */
 int emac_mdio_get_phy_num(void);
 
+/* Get autonegotiation status */
+int emac_mdio_get_autoneg(void);
+
 /* Check if loopback enabled on phy */
 int emac_mdio_is_loopback(void);
 
