This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
AT91 EMAC Patch
- From: John Eigelaar <john at keystone-electronics dot co dot za>
- To: ecos-patches at ecos dot sourceware dot org
- Date: Fri, 23 Mar 2007 15:22:56 +0200
- Subject: AT91 EMAC Patch
Hi,
This patch firstly adds support for the config key to set the MAC address.
It also adds functionality to reset the ownership bits for the most recent
transmitted TX buffers descriptors. Failure to do this leads to a Buffer
Underrun Fault in interrupt mode.
John Eigelaar
? at91_eth.patch
Index: ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/arm/at91/current/ChangeLog,v
retrieving revision 1.1
diff -u -F^f -r1.1 ChangeLog
--- ChangeLog 5 Mar 2007 19:08:10 -0000 1.1
+++ ChangeLog 23 Mar 2007 13:14:49 -0000
@@ -1,3 +1,9 @@
+2007-03-23 John Eigelaar <jeigelaar@mweb.co.za>
+
+ * src/if_at91.c: Added support for the ETH_DRV_SET_MAC_ADDRESS
+ control key. Added functionality to clear the transmit buffer ownershiop
+ bits when the TXCOMP status is detected.
+
2007-01-17 John Eigelaar <jeigelaar@mweb.co.za>
* src/if_at91.c * include/at91_eth.cdl: Working implementation
Index: src/if_at91.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/arm/at91/current/src/if_at91.c,v
retrieving revision 1.1
diff -u -F^f -r1.1 if_at91.c
--- src/if_at91.c 5 Mar 2007 19:08:10 -0000 1.1
+++ src/if_at91.c 23 Mar 2007 13:14:51 -0000
@@ -174,6 +174,7 @@
tbd_t tbd[CYGNUM_DEVS_ETH_ARM_AT91_TX_BUFS];
unsigned long curr_tx_key;
cyg_bool tx_busy;
+ cyg_uint32 last_tbd_idx;
cyg_uint32 curr_tbd_idx;
cyg_uint32 curr_rbd_idx;
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
@@ -660,8 +661,33 @@
at91_eth_control(struct eth_drv_sc *sc, unsigned long key,
void *data, int length)
{
- diag_printf("%s.%d: key %lx\n", __FUNCTION__, __LINE__, key);
- return (1);
+
+ switch (key)
+ {
+ case ETH_DRV_SET_MAC_ADDRESS:
+ {
+ if(length >= ETHER_ADDR_LEN)
+ {
+ at91_eth_stop(sc);
+
+ cyg_uint8 * enaddr = (cyg_uint8 *)data;
+ debug1_printf("AT91_ETH: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ enaddr[0],enaddr[1],enaddr[2],
+ enaddr[3],enaddr[4],enaddr[5]);
+
+ at91_set_mac((at91_eth_priv_t *)sc->driver_private,enaddr,1);
+ at91_eth_start(sc,enaddr,0);
+ return 0;
+ }
+ return 1;
+ }
+ default:
+ {
+ diag_printf("%s.%d: key %lx\n", __FUNCTION__, __LINE__, key);
+ return (1);
+ }
+ }
+
}
// This function is called to see if another packet can be sent.
@@ -700,6 +726,9 @@
cyg_uint32 sr;
priv->tx_busy = true;
+
+ priv->last_tbd_idx = priv->curr_tbd_idx;
+
for(i = 0;i<sg_len;i++)
{
priv->tbd[priv->curr_tbd_idx].addr = sg_list[i].buf;
@@ -730,6 +759,24 @@
at91_start_transmitter(priv);
}
+static void at91_reset_tbd(at91_eth_priv_t *priv)
+{
+ while(priv->curr_tbd_idx != priv->last_tbd_idx)
+ {
+ if(priv->last_tbd_idx == (CYGNUM_DEVS_ETH_ARM_AT91_TX_BUFS-1))
+ {
+ priv->tbd[priv->last_tbd_idx].sr = (AT91_EMAC_TBD_SR_USED|AT91_EMAC_TBD_SR_WRAP);
+ priv->last_tbd_idx = 0;
+ }
+ else
+ {
+ priv->tbd[priv->last_tbd_idx].sr = AT91_EMAC_TBD_SR_USED;
+ priv->last_tbd_idx++;
+ }
+ }
+}
+
+
//======================================================================
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
@@ -810,6 +857,7 @@
/* Check that the last transmission is completed */
if (tsr&AT91_EMAC_TSR_COMP) //5
{
+ at91_reset_tbd(priv);
_eth_drv_tx_done(sc,priv->curr_tx_key,0);
priv->tx_busy = false;
}