blob: ce03adf5533516bb7a2bf8ed29e7f1746b30c7fa [file] [log] [blame]
/*******************************************************************************
* °æÈ¨ËùÓÐ (C)2011, ÉîÛÚÊÐÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
*
* ÎļþÃû³Æ: net.c
* Îļþ±êʶ:
* ÄÚÈÝÕªÒª: ¸ºÔðCPUºÍPPÄ£¿éÖ®¼äµÄÊý¾Ý½»»¥
* ÆäËü˵Ã÷:
* µ±Ç°°æ±¾: 1.0
* ×÷¡¡¡¡Õß: ±«Ð¡ÔÆ
* Íê³ÉÈÕÆÚ: 2012-1-12 16:22:32
*
* Ð޸ļǼ1
* ÐÞ¸ÄÈÕÆÚ:
* °æ±¾¡¡ºÅ:
* Ð޸ġ¡ÈË:
* ÐÞ¸ÄÄÚÈÝ:
*
*******************************************************************************/
#include <common.h>
#include <asm/errno.h>
#include <malloc.h>
#include <net.h>
#include <asm/arch/gmac.h>
#if 0
#include <tm/io.h>
#include <tm/tm.h>
#include <tm/pon.h>
#include <tm/pp/dma.h>
#include <tm/pp/bmu.h>
#include <tm/pp/red.h>
#include <tm/pp/pp.h>
#include <tm/pp/net.h>
#include <tm/switch/smac.h>
#endif
#ifdef CONFIG_CMD_NET
#define CACHE_ALIGNED(x) ((x)&(~0x1f))
#if 0
typedef struct _queue_ctrl{
u8 *pFirst;
u32 nextToProc;
} NET_QUEUE_CTRL;
#endif
u8 default_mac[6]={0x00,0xd0,0xd0,0x01,0x02,0x03};
/*NET_QUEUE_CTRL queue_ctrl[PP_MAX_QUEUE];
int pp_net_debug=0;*/
void (* volatile net_recv) (u8 * buf, int len) = NULL;
void register_net_recv(void *handle)
{
net_recv = handle;
}
/*
* Get pointer to next RX descriptor to be processed by SW
*/
#if 0
static inline struct pp_desc * pp_get_next_rxdesc(int rxq)
{
struct pp_desc *desc;
NET_QUEUE_CTRL *qc;
qc = &queue_ctrl[rxq];
desc = (struct pp_desc *)(qc->nextToProc * PP_DESC_SIZE + qc->pFirst);
if(unlikely(++qc->nextToProc >= PP_QUEUE_SIZE)){
qc->nextToProc = 0;
}
return desc;
}
static void dump_net_data(u8 *data, u32 len)
{
int i;
len = len > 64?64:len;
for(i=0;i<len;i++){
printf("%.2x ",data[i]);
if((i&0xf) == 0xf)
printf("\n");
}
printf("\n");
}
void dump_desc(struct pp_desc *desc)
{
u32 *data = (u32 *)desc;
printf("%.8x:0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",(u32)desc,data[0],data[1],data[2],data[3]);
printf("bp %u gem %u len %u\n",desc->BP,desc->Gemport_ID,desc->Pkt_Len);
}
static void free_desc(struct pp_desc *desc,int bp)
{
// free desc
#ifdef CONFIG_ZX279112
if(soft_release_rx_desc(desc->Direction, desc->CPU_Queue_ID,desc->Buffer_Type) < 0)
#else
if(soft_release_rx_desc(desc->CPU_Queue_ID,desc->Buffer_Type) < 0)
#endif
printf("failed to rls rx desc1\n");
// free bp
if(pp_bmu_free_bp((u16)bp) < 0)
printf("failed to rls bp\n");
}
static inline int pp_net_rx(struct eth_device* dev,int cnt,int rxq)
{
int i,bp,len;
struct pp_desc *desc ;
u8 *buf;
// receive packet
#ifdef CONFIG_SYS_ARM_CACHE_WRITETHROUGH
invalidate_dcache_all();
#endif
for(i=0;i<cnt;i++){
//get desc, invalid cache, and prefetch
desc = pp_get_next_rxdesc(rxq);
#if !defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) && !defined(CONFIG_SYS_DCACHE_OFF)
invalidate_dcache_range((u32)desc,(u32)desc+16);
#endif
bp = desc->BP;
// check bp
if(unlikely(bp >= BP_NUMBERS)){
printf("invalid bp %u\n",bp);
dump_desc(desc);
//error handle
#ifdef CONFIG_ZX279112
soft_release_rx_desc(desc->Direction, rxq,1);
#else
soft_release_rx_desc(rxq,1);
#endif
continue;
}
buf = (u8 *)(BP_TO_ADDR(bp)) + desc->Offset;
len = desc->Pkt_Len;
#if !defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) && !defined(CONFIG_SYS_DCACHE_OFF)
invalidate_dcache_range((u32)buf,(u32)buf+len);
#endif
if(pp_net_debug>0){
dump_desc(desc);
printf("receive len %u, BP %d ,gem %d,addr %x\n",len,
bp,desc->Gemport_ID,(u32)buf);
dump_net_data(buf,len);
pp_net_debug--;
}
if(net_recv == NULL)
NetReceive(buf, len);
else
net_recv(buf, len);
free_desc(desc,bp);
}
return cnt;
}
/*
* get the count of unprocess packet
*/
static inline int pp_get_rx_cnt(u32 queue)
{
return ZX_REG_READ(PP_DMA_CPU_QUEUE_CNT(queue));
}
#endif
int max_rx_delay=1000;
/*
* pp net poll interface
*/
static int gmac_net_poll(struct eth_device* dev)
{
int i,len=0,trxlen=0;
// unsigned char *rxbuf;
unsigned char rxbuf[256];
//for(i=2;i>0;i--)
for(i=0;i<2;i++)
{
if(zx_gmac_getbd(i)!=0)
{
trxlen=zx_gmac_rx(rxbuf,&len,i);
if(net_recv == NULL)
NetReceive(rxbuf, trxlen);
else
net_recv(rxbuf, trxlen);
if(zx_gmac_getbd(i)!=0)
/* new packet arrived or hardware has update rx cnt, wait for a while */
udelay(1);
}
}
return 0;
}
#if 0
int pp_data_raw_send(u8 *data, u32 len,struct pp_desc *desc)
{
int bp;
u8 *buf;
/* get the tx descriptor */
/* alloc bp to save data */
if((bp = pp_bmu_alloc_bp())<0){
PON_NET_DBG("alloc bp failed\n");
return -1;
}
/* check bp */
if(unlikely(bp >= BP_NUMBERS)){
PON_NET_DBG("invalid bp %d\n",bp);
return -1;
}
/* copy data to bp */
buf = (u8 *)BP_TO_ADDR(bp)+16;
memcpy(buf,data,len);
/* make desc */
desc->BP = bp;
desc->Pkt_Len = len;
desc->Pkt_Len_Changed = len;
desc->Offset = 16;
if(pp_net_debug>0){
printf("send len %u, BP %d ,addr %x\n",len,
bp,(u32)buf);
dump_desc(desc);
dump_net_data(buf,len);
pp_net_debug--;
}
#if !defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH) && !defined(CONFIG_SYS_DCACHE_OFF)
flush_dcache_range((u32)buf,(u32)buf+len);
#endif
/* insert desc */
if(soft_insert_tx_desc((u32 *)desc)<0){
PON_NET_DBG("insert desc failed\n");
return -2;
}
return 0;
}
#endif
/*
* send packet to sw,
*/
static int gmac_net_sw_tx(struct eth_device* dev, volatile void* packet, int length)
{
if(zx_gmac_send((u8 *)packet,length) != 0)
{
printf("gmac send error\n");
return 1;
}
return 0;
}
#if 0
void pp_queue_init(void)
{
int i;
NET_QUEUE_CTRL *qc;
/* init inner rx queue status */
for(i=0;i<PP_MAX_QUEUE;i++){
qc = &queue_ctrl[i];
qc->pFirst = (u8 *)(PP_VA_DESC_BASE + 0x10000 * (PP_RX_QUEUE_OFF+i));
qc->nextToProc = 0;
}
}
#endif
int gmac_eth_init(struct eth_device* dev, bd_t* bd)
{
zx_gmac_init();
return 0;
}
void gmac_eth_halt(struct eth_device* dev)
{
udelay(100); /* wait for send complete */
zx_gmac_stop();
}
/*int pp_net_init(void)
{
tm_set_onu_mac(ONU_MAC1,default_mac);
pp_queue_init();
return 0;
}*/
void gmac_net_register(void)
{
struct eth_device *dev;
dev = malloc(sizeof(*dev));
if (!dev) {
free(dev);
return ;
}
memset(dev, 0, sizeof(*dev));
dev->init = gmac_eth_init;
dev->halt = gmac_eth_halt;
dev->send = gmac_net_sw_tx;
dev->recv = gmac_net_poll;
sprintf(dev->name, "eth0");
/* get mac */
if(!eth_getenv_enetaddr("ethaddr", dev->enetaddr)){
puts("Please set MAC address\n");
}
else{
memcpy(default_mac,dev->enetaddr,6);
}
eth_register(dev);
}
#endif