This is the mail archive of the ecos-patches@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

dp83816 ethernet: support reading MAC address from EEPROM


Hi,

The attached patch allows the MAC address for a Nation DP83816 ethernet
device to be read from the EEPROM iff CYGHWR_NS_DP83816_USE_EEPROM is
#define'd.

In addition, the patch convert all the _h2le and _le2h calls to
CYG_CPU_TO_LE32 and CYG_LE32_TO_CPU.

David Vrabel
-- 
David Vrabel, Design Engineer

Arcom, Clifton Road           Tel: +44 (0)1223 411200 ext. 3233
Cambridge CB1 7EA, UK         Web: http://www.arcom.com/
%patch
Index: ecos-working/packages/devs/eth/ns/dp83816/current/src/dp83816.h
===================================================================
--- ecos-working.orig/packages/devs/eth/ns/dp83816/current/src/dp83816.h	2005-07-18 15:23:02.000000000 +0100
+++ ecos-working/packages/devs/eth/ns/dp83816/current/src/dp83816.h	2005-07-18 15:23:32.000000000 +0100
@@ -152,6 +152,11 @@
 #define   _CFG_FDUP    (1<<29) // Full duplex
 #define   _CFG_POL     (1<<28) // 10Mb polarity
 #define   _CFG_ANDONE  (1<<27) // Auto-negotiation done
+#define DP_MEAR        0x08  // EEPROM access
+#define   _MEAR_EESEL  (1<<3) // EEPROM chip select
+#define   _MEAR_EECLK  (1<<2) // EEPROM serial clock
+#define   _MEAR_EEDO   (1<<1) // EEPROM data out
+#define   _MEAR_EEDI   (1<<0) // EEPROM data in
 #define DP_ISR         0x10  // Interrupt status
 #define   _ISR_TXRCMP (1<<25) // Tx reset complete
 #define   _ISR_RXRCMP (1<<24) // Rx reset complete
Index: ecos-working/packages/devs/eth/ns/dp83816/current/src/if_dp83816.c
===================================================================
--- ecos-working.orig/packages/devs/eth/ns/dp83816/current/src/if_dp83816.c	2005-07-18 15:23:02.000000000 +0100
+++ ecos-working/packages/devs/eth/ns/dp83816/current/src/if_dp83816.c	2005-07-18 15:23:32.000000000 +0100
@@ -56,6 +56,7 @@
 
 #include <cyg/infra/cyg_type.h>
 #include <cyg/hal/hal_arch.h>
+#include <cyg/hal/hal_endian.h>
 #include <cyg/infra/diag.h>
 #include <cyg/hal/drv_api.h>
 #include <cyg/hal/hal_if.h>
@@ -65,6 +66,10 @@
 #include "dp83816.h"
 #include CYGDAT_DEVS_ETH_NS_DP83816_INL
 
+#ifdef CYGHWR_NS_DP83816_USE_EEPROM
+static cyg_uint16 dp83816_eeprom_read(struct dp83816_priv_data *dp, int location);
+#endif
+
 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
 // This ISR is called when the ethernet interrupt occurs
 static cyg_uint32
@@ -120,24 +125,24 @@
     bdp = dp->rxnext = CYGARC_UNCACHED_ADDRESS(dp->rxd);
     bp = dp->rxbuf;
     for (i = 0; i < dp->rxnum; i++, bdp++) {
-        bdp->next = (dp83816_bd_t *)_h2le(CYGARC_PHYSICAL_ADDRESS(bdp+1));
-        bdp->stat = _h2le(BD_INTR | _DP83816_BUFSIZE);  // Max buffer
-        bdp->buf = (unsigned char *)_h2le(CYGARC_PHYSICAL_ADDRESS(bp));
+        bdp->next = (dp83816_bd_t *)CYG_CPU_TO_LE32(CYGARC_PHYSICAL_ADDRESS(bdp+1));
+        bdp->stat = CYG_CPU_TO_LE32(BD_INTR | _DP83816_BUFSIZE);  // Max buffer
+        bdp->buf = (unsigned char *)CYG_CPU_TO_LE32(CYGARC_PHYSICAL_ADDRESS(bp));
         bp += _DP83816_BUFSIZE;
     }
-    bdp--;  bdp->next = (dp83816_bd_t *)_h2le(CYGARC_PHYSICAL_ADDRESS(dp->rxd));
+    bdp--;  bdp->next = (dp83816_bd_t *)CYG_CPU_TO_LE32(CYGARC_PHYSICAL_ADDRESS(dp->rxd));
     DP_OUT(dp->base, DP_RXCFG, _RXCFG_MXDMA_128 | ((64/32)<<_RXCFG_DRTH_SHIFT));
     DP_OUT(dp->base, DP_RXDP, CYGARC_PHYSICAL_ADDRESS(dp->rxd));
     // Tx ring
     bdp = dp->txfill = dp->txint = CYGARC_UNCACHED_ADDRESS(dp->txd);
     bp = dp->txbuf;
     for (i = 0; i < dp->txnum; i++, bdp++) {
-        bdp->next = (dp83816_bd_t *)_h2le(CYGARC_PHYSICAL_ADDRESS(bdp+1));
+        bdp->next = (dp83816_bd_t *)CYG_CPU_TO_LE32(CYGARC_PHYSICAL_ADDRESS(bdp+1));
         bdp->stat = 0;  // Driver owns buffer for now
-        bdp->buf = (unsigned char *)_h2le(CYGARC_PHYSICAL_ADDRESS(bp));
+        bdp->buf = (unsigned char *)CYG_CPU_TO_LE32(CYGARC_PHYSICAL_ADDRESS(bp));
         bp += _DP83816_BUFSIZE;
     }
-    bdp--;  bdp->next = (dp83816_bd_t *)_h2le(CYGARC_PHYSICAL_ADDRESS(dp->txd));
+    bdp--;  bdp->next = (dp83816_bd_t *)CYG_CPU_TO_LE32(CYGARC_PHYSICAL_ADDRESS(dp->txd));
     DP_OUT(dp->base, DP_TXCFG, _TXCFG_ATP |
                                _TXCFG_MXDMA_128 |
                                ((256/32)<<_TXCFG_FLTH_SHIFT) |
@@ -167,7 +172,33 @@
     bool esa_ok;
     unsigned char enaddr[6];
 
+    DEBUG_FUNCTION();
+
+    CYGHWR_NS_DP83816_PLF_INIT(dp);
+    base = dp->base;
+    if (!base) return false;  // No device found
+
     // Get physical device address
+#ifdef CYGHWR_NS_DP83816_USE_EEPROM
+    {
+        cyg_uint16 t;
+
+        t = (dp83816_eeprom_read(dp, 0x0006) >> 15)
+            | (dp83816_eeprom_read(dp, 0x0007) << 1);
+        enaddr[0] = t & 0xFF;
+        enaddr[1] = t >> 8;
+        t = (dp83816_eeprom_read(dp, 0x0007) >> 15)
+            | (dp83816_eeprom_read(dp, 0x0008) << 1);
+        enaddr[2] = t & 0xFF;
+        enaddr[3] = t >> 8;
+        t = (dp83816_eeprom_read(dp, 0x0008) >> 15)
+            | (dp83816_eeprom_read(dp, 0x0009) << 1);
+        enaddr[4] = t & 0xFF;
+        enaddr[5] = t >> 8;
+        
+        esa_ok =  true;
+    }
+#else
 #ifdef CYGPKG_REDBOOT
 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
     esa_ok = flash_get_config(dp->esa_key, enaddr, CONFIG_ESA);
@@ -178,6 +209,7 @@
     esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,         
                                          dp->esa_key, enaddr, CONFIG_ESA);
 #endif
+#endif
     if (esa_ok) {
         memcpy(dp->enaddr, enaddr, sizeof(enaddr));
     } else {
@@ -185,18 +217,8 @@
         diag_printf("DP83816 - Warning! ESA unknown\n");
     }
 
-    DEBUG_FUNCTION();
-
-    CYGHWR_NS_DP83816_PLF_INIT(dp);
-    base = dp->base;
-    if (!base) return false;  // No device found
-
     if (!dp83816_reset(dp)) return false;
 
-    diag_printf("DP83816 - ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
-                dp->enaddr[0], dp->enaddr[1], dp->enaddr[2],
-                dp->enaddr[3], dp->enaddr[4], dp->enaddr[5] );
-
 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
     cyg_drv_interrupt_create(
         dp->interrupt,
@@ -290,15 +312,15 @@
 
     len = total_len;
     if (len < IEEE_8023_MIN_FRAME) len = IEEE_8023_MIN_FRAME;
-    data = (unsigned char *)CYGARC_VIRTUAL_ADDRESS(_le2h((unsigned long)bdp->buf));
+    data = (unsigned char *)CYGARC_VIRTUAL_ADDRESS(CYG_LE32_TO_CPU((unsigned long)bdp->buf));
     for (i = 0;  i < sg_len;  i++) {
         memcpy(data, (unsigned char *)sg_list[i].buf, sg_list[i].len);
         data += sg_list[i].len;
     }
     bdp->key = key;
-    bdp->stat = _h2le(len | BD_OWN | BD_INTR);
+    bdp->stat = CYG_CPU_TO_LE32(len | BD_OWN | BD_INTR);
     dp->txbusy++;
-    bdp = (dp83816_bd_t *)CYGARC_UNCACHED_ADDRESS(CYGARC_VIRTUAL_ADDRESS(_le2h((unsigned long)bdp->next)));
+    bdp = (dp83816_bd_t *)CYGARC_UNCACHED_ADDRESS(CYGARC_VIRTUAL_ADDRESS(CYG_LE32_TO_CPU((unsigned long)bdp->next)));
     dp->txfill = bdp;
     // Kick the device, in case it went idle
     DP_OUT(dp->base, DP_CR, _CR_TXE);
@@ -311,13 +333,13 @@
     dp83816_bd_t *bdp = dp->txint;
 
     DEBUG_FUNCTION();
-    while ((_le2h(bdp->stat) & (BD_OWN|BD_INTR)) == BD_INTR) {
+    while ((CYG_LE32_TO_CPU(bdp->stat) & (BD_OWN|BD_INTR)) == BD_INTR) {
         // Tell higher level we sent this packet
         (sc->funs->eth_drv->tx_done)(sc, bdp->key, 0);
         bdp->stat = 0;  // retake buffer
         bdp->key = 0;
         dp->txbusy--;
-        bdp = (dp83816_bd_t *)CYGARC_UNCACHED_ADDRESS(CYGARC_VIRTUAL_ADDRESS(_le2h((unsigned long)bdp->next)));
+        bdp = (dp83816_bd_t *)CYGARC_UNCACHED_ADDRESS(CYGARC_VIRTUAL_ADDRESS(CYG_LE32_TO_CPU((unsigned long)bdp->next)));
     }
     dp->txint = bdp;
 }
@@ -340,17 +362,17 @@
     DEBUG_FUNCTION();
 
     while (true) {
-        if ((_le2h(bdp->stat) & BD_OWN) != 0) {
-            err = _le2h(bdp->stat) & (BD_RXA|BD_RXO|BD_LONG|BD_RUNT|BD_ISE|BD_CRCE|BD_FAE|BD_COL);
+        if ((CYG_LE32_TO_CPU(bdp->stat) & BD_OWN) != 0) {
+            err = CYG_LE32_TO_CPU(bdp->stat) & (BD_RXA|BD_RXO|BD_LONG|BD_RUNT|BD_ISE|BD_CRCE|BD_FAE|BD_COL);
             if (err != 0) {
                 diag_printf("RxError: %x\n", err);
             }
-            len = _le2h(bdp->stat) & BD_LENGTH_MASK;
+            len = CYG_LE32_TO_CPU(bdp->stat) & BD_LENGTH_MASK;
             dp->rxnext = bdp;
             (sc->funs->eth_drv->recv)(sc, len);
-            bdp->stat = _h2le(BD_INTR | _DP83816_BUFSIZE);  // Give back buffer
+            bdp->stat = CYG_CPU_TO_LE32(BD_INTR | _DP83816_BUFSIZE);  // Give back buffer
         }
-        bdp = (dp83816_bd_t *)CYGARC_UNCACHED_ADDRESS(CYGARC_VIRTUAL_ADDRESS(_le2h((unsigned long)bdp->next)));
+        bdp = (dp83816_bd_t *)CYGARC_UNCACHED_ADDRESS(CYGARC_VIRTUAL_ADDRESS(CYG_LE32_TO_CPU((unsigned long)bdp->next)));
         if (bdp == bdfirst) {
             break;
         }
@@ -372,7 +394,7 @@
     unsigned char *data;
     int i;
 
-    data = (unsigned char *)CYGARC_VIRTUAL_ADDRESS(_le2h((unsigned long)bdp->buf));
+    data = (unsigned char *)CYGARC_VIRTUAL_ADDRESS(CYG_LE32_TO_CPU((unsigned long)bdp->buf));
     for (i = 0;  i < sg_len;  i++) {
         memcpy((void *)sg_list[i].buf, data, sg_list[i].len);
         data += sg_list[i].len;
@@ -442,3 +464,65 @@
     struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private;
     return dp->interrupt;
 }
+
+/* EEPROM Functions */
+#ifdef CYGHWR_NS_DP83816_USE_EEPROM
+
+#define EEPROM_READ(dp, x)  DP_IN((dp)->base, DP_MEAR, (x))
+#define EEPROM_WRITE(dp, x) DP_OUT((dp)->base, DP_MEAR, (x))
+#define EEPROM_DELAY(dp)    CYG_MACRO_START cyg_uint16 t; EEPROM_READ((dp), t); CYG_MACRO_END
+
+#define DP83816_EEPROM_ADDR_LEN  6
+#define DP83816_EE_READ_CMD     (6 << DP83816_EEPROM_ADDR_LEN)
+
+
+/* EEPROM data is bit-swapped. */
+static cyg_uint16 dp83816_eeprom_fixup_data(cyg_uint16 input)
+{
+    cyg_uint16 output = 0;
+    int i;
+
+    for (i = 0; i < 16; i++) {
+        output = (output << 1) | (input & 0x0001);
+        input >>= 1;
+    }
+    return output;
+}
+
+static cyg_uint16 dp83816_eeprom_command(struct dp83816_priv_data *dp, int cmd, int cmd_len)
+{
+    int d = 0;
+
+    EEPROM_WRITE(dp, _MEAR_EESEL);
+
+    do {
+        cyg_uint32 c = (cmd & (1 << cmd_len)) ? _MEAR_EEDI : 0;
+        cyg_uint8 t;
+
+        EEPROM_WRITE(dp, c | _MEAR_EESEL);
+        EEPROM_DELAY(dp);
+        EEPROM_WRITE(dp, c | _MEAR_EESEL | _MEAR_EECLK);
+        EEPROM_DELAY(dp);
+
+        EEPROM_READ(dp, t);
+        d <<= 1;
+        d |= (t & _MEAR_EEDO) ? 1 : 0;
+    } while (cmd_len--);
+
+    EEPROM_WRITE(dp, _MEAR_EESEL);
+    EEPROM_WRITE(dp, 0);
+
+    return d & 0xffff;
+}
+
+static cyg_uint16 dp83816_eeprom_read(struct dp83816_priv_data *dp, int loc)
+{
+    cyg_uint16 d;
+
+    d = dp83816_eeprom_command(dp, (loc | DP83816_EE_READ_CMD) << 16,
+                               3 + DP83816_EEPROM_ADDR_LEN + 16);
+
+    return dp83816_eeprom_fixup_data(d);
+}
+
+#endif /* CYGHWR_NS_DP83816_USE_EEPROM */
Index: ecos-working/packages/devs/eth/ns/dp83816/current/ChangeLog
===================================================================
--- ecos-working.orig/packages/devs/eth/ns/dp83816/current/ChangeLog	2004-08-24 14:16:18.000000000 +0100
+++ ecos-working/packages/devs/eth/ns/dp83816/current/ChangeLog	2005-07-18 15:33:05.000000000 +0100
@@ -1,3 +1,13 @@
+2005-07-18  David Vrabel  <dvrabel@arcom.com>
+
+	* src/if_dp83816.c: Use CYG_CPU_TO_LE32 and CYG_LE32_TO_CPU macros
+	instead of the _h2le and _le2h functions.
+
+	* src/dp83816.h: #define's for MEAR (EEPROM access) register.
+
+	* src/dp83816.c [CYGHWR_NS_DP83186_USE_EEPROM]: Read MAC address
+	from EEPROM.
+
 2004-08-24  Gary Thomas  <gary@mlbassoc.com>
 
 	* src/if_dp83816.c: Enable start/stop functions (device was always
Index: ecos-working/packages/devs/eth/powerpc/moab/current/ChangeLog
===================================================================
--- ecos-working.orig/packages/devs/eth/powerpc/moab/current/ChangeLog	2003-10-02 21:11:57.000000000 +0100
+++ ecos-working/packages/devs/eth/powerpc/moab/current/ChangeLog	2005-07-18 15:34:36.000000000 +0100
@@ -1,3 +1,8 @@
+2005-07-18  David Vrabel  <dvrabel@arcom.com>
+
+	* include/moab_eth_dp83816.inl: Remove unneeded _h2le and _le2h
+	functions.
+
 2003-10-02  Gary Thomas  <gary@mlbassoc.com>
 
 	* include/moab_eth_dp83816.inl: 
Index: ecos-working/packages/devs/eth/powerpc/moab/current/include/moab_eth_dp83816.inl
===================================================================
--- ecos-working.orig/packages/devs/eth/powerpc/moab/current/include/moab_eth_dp83816.inl	2003-10-02 21:11:58.000000000 +0100
+++ ecos-working/packages/devs/eth/powerpc/moab/current/include/moab_eth_dp83816.inl	2005-07-18 15:33:41.000000000 +0100
@@ -80,26 +80,6 @@
 #undef  CYGHWR_NS_DP83816_PLF_INIT
 #define CYGHWR_NS_DP83816_PLF_INIT(dp) _moab_eth_init(dp)
 
-// Map a 32 bit host quantity to little endian
-unsigned long
-_h2le(unsigned long val)
-{
-    unsigned long res; 
-    unsigned long *addr = &val;
-    __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (res) : "r" (addr), "m" (*addr));
-    return res;
-}
-
-// Map a 32 bit little endian quantity to host representation
-unsigned long
-_le2h(unsigned long val)
-{
-    unsigned long res; 
-    unsigned long *addr = &val;
-    __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (res) : "r" (addr), "m" (*addr));
-    return res;
-}
-
 // Align buffers on a cache boundary
 #define RxBUFSIZE CYGNUM_DEVS_ETH_MOAB_DP83816_RxNUM*_DP83816_BUFSIZE
 #define TxBUFSIZE CYGNUM_DEVS_ETH_MOAB_DP83816_TxNUM*_DP83816_BUFSIZE
%status
pending

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]