summaryrefslogtreecommitdiff
path: root/cpu/mpc5xxx/fec.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/mpc5xxx/fec.c')
-rw-r--r--cpu/mpc5xxx/fec.c108
1 files changed, 56 insertions, 52 deletions
diff --git a/cpu/mpc5xxx/fec.c b/cpu/mpc5xxx/fec.c
index b8e2560..16ca0a9 100644
--- a/cpu/mpc5xxx/fec.c
+++ b/cpu/mpc5xxx/fec.c
@@ -14,7 +14,7 @@
#include "sdma.h"
#include "fec.h"
-#define DEBUG 0x8
+/* #define DEBUG 0x28 */
#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
defined(CONFIG_MPC5XXX_FEC)
@@ -28,25 +28,33 @@ static void rfifo_print(mpc5xxx_fec_priv *fec);
static uint32 local_crc32(char *string, unsigned int crc_value, int len);
#endif
+typedef struct {
+ uint8 data[1500]; /* actual data */
+ int length; /* actual length */
+ int used; /* buffer in use or not */
+ uint8 head[16]; /* MAC header(6 + 6 + 2) + 2(aligned) */
+} NBUF;
+
/********************************************************************/
static int mpc5xxx_fec_rbd_init(mpc5xxx_fec_priv *fec)
{
int ix;
char *data;
+ static int once = 0;
- /*
- * the receive ring is located right after the transmit one
- */
for (ix = 0; ix < FEC_RBD_NUM; ix++) {
- data = (char *)malloc(FEC_MAX_PKT_SIZE);
- if (data == NULL) {
- printf ("RBD INIT FAILED\n");
- return -1;
+ if (!once) {
+ data = (char *)malloc(FEC_MAX_PKT_SIZE);
+ if (data == NULL) {
+ printf ("RBD INIT FAILED\n");
+ return -1;
+ }
+ fec->rbdBase[ix].dataPointer = (uint32)data;
}
fec->rbdBase[ix].status = FEC_RBD_EMPTY;
fec->rbdBase[ix].dataLength = 0;
- fec->rbdBase[ix].dataPointer = (uint32)data;
}
+ once ++;
/*
* have the last RBD to close the ring
@@ -336,11 +344,6 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
SDMA_CLEAR_IEVENT(FEC_RECV_TASK_NO);
/*
- * Set SmartDMA intMask register to enable SmartDMA task interrupts
- */
- SDMA_INT_ENABLE(FEC_RECV_TASK_NO);
-
- /*
* Initialize SmartDMA parameters stored in SRAM
*/
*(int *)FEC_TBD_BASE = (int)fec->tbdBase;
@@ -494,8 +497,10 @@ static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
/********************************************************************/
static void mpc5xxx_fec_halt(struct eth_device *dev)
{
- mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
+#if defined(CONFIG_MPC5200)
struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA;
+#endif
+ mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
int counter = 0xffff;
#if (DEBUG & 0x2)
@@ -530,8 +535,6 @@ static void mpc5xxx_fec_halt(struct eth_device *dev)
*/
while ((counter--) && (!(fec->eth->ievent & 0x10000000))) ;
- SDMA_INT_DISABLE (FEC_RECV_TASK_NO);
-
/*
* Disable SmartDMA tasks
*/
@@ -671,7 +674,7 @@ static int mpc5xxx_fec_send(struct eth_device *dev, volatile void *eth_data,
pTbd = &fec->tbdBase[fec->tbdIndex];
pTbd->dataLength = data_length;
pTbd->dataPointer = (uint32)eth_data;
- pTbd->status |= FEC_TBD_READY;
+ pTbd->status |= FEC_TBD_LAST | FEC_TBD_TC | FEC_TBD_READY;
fec->tbdIndex = (fec->tbdIndex + 1) % FEC_TBD_NUM;
#if (DEBUG & 0x100)
@@ -729,8 +732,9 @@ static int mpc5xxx_fec_recv(struct eth_device *dev)
mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
FEC_RBD *pRbd = &fec->rbdBase[fec->rbdIndex];
unsigned long ievent;
- int frame_length;
- char *frame;
+ int frame_length, len = 0;
+ NBUF *frame;
+ char buff[FEC_MAX_PKT_SIZE];
#if (DEBUG & 0x1)
printf ("mpc5xxx_fec_recv %d Start...\n", fec->rbdIndex);
@@ -763,41 +767,40 @@ static int mpc5xxx_fec_recv(struct eth_device *dev)
}
}
- /*
- * Do we have data in Rx FIFO?
- */
- if ((pRbd->status & FEC_RBD_EMPTY) || !(pRbd->status & FEC_RBD_LAST)){
- return 0;
- }
+ if (!(pRbd->status & FEC_RBD_EMPTY)) {
+ if ((pRbd->status & FEC_RBD_LAST) && !(pRbd->status & FEC_RBD_ERR) &&
+ ((pRbd->dataLength - 4) > 14)) {
- /*
- * Pass the packet up only if reception was Ok
- */
- if ((pRbd->dataLength <= 14) || (pRbd->status & FEC_RBD_ERR)) {
- mpc5xxx_fec_rbd_clean(fec, pRbd);
-#if (DEBUG & 0x8)
- printf( "X0" );
+ /*
+ * Get buffer address and size
+ */
+ frame = (NBUF *)pRbd->dataPointer;
+ frame_length = pRbd->dataLength - 4;
+
+#if (DEBUG & 0x20)
+ {
+ int i;
+ printf("recv data hdr:");
+ for (i = 0; i < 14; i++)
+ printf("%x ", *(frame->head + i));
+ printf("\n");
+ }
#endif
- return 0;
+ /*
+ * Fill the buffer and pass it to upper layers
+ */
+ memcpy(buff, frame->head, 14);
+ memcpy(buff + 14, frame->data, frame_length);
+ NetReceive(buff, frame_length);
+ len = frame_length;
+ }
+ /*
+ * Reset buffer descriptor as empty
+ */
+ mpc5xxx_fec_rbd_clean(fec, pRbd);
}
-
- /*
- * Get buffer address and size
- */
- frame = (char *)pRbd->dataPointer;
- frame_length = pRbd->dataLength;
-
- /*
- * Pass the buffer to upper layers
- */
- NetReceive(frame, frame_length);
-
- /*
- * Reset buffer descriptor as empty
- */
- mpc5xxx_fec_rbd_clean(fec, pRbd);
-
- return frame_length;
+ SDMA_CLEAR_IEVENT (FEC_RECV_TASK_NO);
+ return len;
}
@@ -824,6 +827,7 @@ int mpc5xxx_fec_initialize(bd_t * bis)
dev->send = mpc5xxx_fec_send;
dev->recv = mpc5xxx_fec_recv;
+ sprintf(dev->name, "FEC ETHERNET");
eth_register(dev);
return 1;