qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [5300] ETRAX-FS: Correct ethernet PHY diagnostics register


From: Edgar E. Iglesias
Subject: [Qemu-devel] [5300] ETRAX-FS: Correct ethernet PHY diagnostics register reads.
Date: Mon, 22 Sep 2008 20:34:19 +0000

Revision: 5300
          http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=5300
Author:   edgar_igl
Date:     2008-09-22 20:34:18 +0000 (Mon, 22 Sep 2008)

Log Message:
-----------
ETRAX-FS: Correct ethernet PHY diagnostics register reads.

* Correct ethernet PHY diagnostics register reads.
* Add friendly names for the speed/duplex fields.
* Report duplex mismatches between MAC and PHY.

Modified Paths:
--------------
    trunk/hw/etraxfs_eth.c

Modified: trunk/hw/etraxfs_eth.c
===================================================================
--- trunk/hw/etraxfs_eth.c      2008-09-22 19:50:28 UTC (rev 5299)
+++ trunk/hw/etraxfs_eth.c      2008-09-22 20:34:18 UTC (rev 5300)
@@ -30,6 +30,12 @@
 
 #define D(x)
 
+/* Advertisement control register. */
+#define ADVERTISE_10HALF        0x0020  /* Try for 10mbps half-duplex  */
+#define ADVERTISE_10FULL        0x0040  /* Try for 10mbps full-duplex  */
+#define ADVERTISE_100HALF       0x0080  /* Try for 100mbps half-duplex */
+#define ADVERTISE_100FULL       0x0100  /* Try for 100mbps full-duplex */
+
 /* 
  * The MDIO extensions in the TDK PHY model were reversed engineered from the 
  * linux driver (PHYID and Diagnostics reg).
@@ -78,9 +84,12 @@
                        int speed_100 = 0;
 
                        /* Are we advertising 100 half or 100 duplex ? */
-                       speed_100 = !!(phy->regs[4] & 0x180);
+                       speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF);
+                       speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL);
+
                        /* Are we advertising 10 duplex or 100 duplex ? */
-                       duplex = !!(phy->regs[4] & 0x180);
+                       duplex = !!(phy->regs[4] & ADVERTISE_100FULL);
+                       duplex |= !!(phy->regs[4] & ADVERTISE_10FULL);
                        r = (speed_100 << 10) | (duplex << 11);
                }
                break;
@@ -322,10 +331,40 @@
 
        /* MDIO bus.  */
        struct qemu_mdio mdio_bus;
+       unsigned int phyaddr;
+       int duplex_mismatch;
+
        /* PHY.  */
        struct qemu_phy phy;
 };
 
+static void eth_validate_duplex(struct fs_eth *eth)
+{
+       struct qemu_phy *phy;
+       unsigned int phy_duplex;
+       unsigned int mac_duplex;
+       int new_mm = 0;
+
+       phy = eth->mdio_bus.devs[eth->phyaddr];
+       phy_duplex = !!(phy->read(phy, 18) & (1 << 11));
+       mac_duplex = !!(eth->regs[RW_REC_CTRL] & 128);
+
+       if (mac_duplex != phy_duplex)
+               new_mm = 1;
+
+       if (eth->regs[RW_GEN_CTRL] & 1) {
+               if (new_mm != eth->duplex_mismatch) {
+                       if (new_mm)
+                               printf("HW: WARNING "
+                                      "ETH duplex mismatch MAC=%d PHY=%d\n",
+                                      mac_duplex, phy_duplex);
+                       else
+                               printf("HW: ETH duplex ok.\n");
+               }
+               eth->duplex_mismatch = new_mm;
+       }
+}
+
 static uint32_t eth_rinvalid (void *opaque, target_phys_addr_t addr)
 {
        struct fs_eth *eth = opaque;
@@ -418,11 +457,18 @@
                        /* Attach an MDIO/PHY abstraction.  */
                        if (value & 2)
                                eth->mdio_bus.mdio = value & 1;
-                       if (eth->mdio_bus.mdc != (value & 4))
+                       if (eth->mdio_bus.mdc != (value & 4)) {
                                mdio_cycle(&eth->mdio_bus);
+                               eth_validate_duplex(eth);
+                       }
                        eth->mdio_bus.mdc = !!(value & 4);
                        break;
 
+               case RW_REC_CTRL:
+                       eth->regs[addr] = value;
+                       eth_validate_duplex(eth);
+                       break;
+
                default:
                        eth->regs[addr] = value;
                        D(printf ("%s %x %x\n",
@@ -591,8 +637,9 @@
        eth->dma_in = dma + 1;
 
        /* Connect the phy.  */
+       eth->phyaddr = 1;
        tdk_init(&eth->phy);
-       mdio_attach(&eth->mdio_bus, &eth->phy, 0x1);
+       mdio_attach(&eth->mdio_bus, &eth->phy, eth->phyaddr);
 
        eth->ethregs = cpu_register_io_memory(0, eth_read, eth_write, eth);
        cpu_register_physical_memory (base, 0x5c, eth->ethregs);






reply via email to

[Prev in Thread] Current Thread [Next in Thread]