This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
dp83816 ethernet: support reading MAC address from EEPROM
- From: David Vrabel <dvrabel at arcom dot com>
- To: eCos Patches <ecos-patches at ecos dot sourceware dot org>
- Date: Mon, 18 Jul 2005 15:46:29 +0100
- Subject: 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