📄 hisilicon-sf.c
字号:
#include <linux-adapter.h>#include <command.h>#include "hisilicon-sf.h"#include "SF_Reg.h"#include "SF_RegStruct.h"#include "SF_TypeDef.h"#include <net.h>#define sf_print_mac(mac) do{ int i;\ printk(KERN_INFO "MAC: ");\ for (i = 0; i < ETH_ALEN; i++)\ printk("%c%02X", i ? '-' : ' ', *(((unsigned char*)mac)+i));\ printk("\n");\ }while(0)static struct net_device *sf_devs[2]={NULL, NULL};#define sf_port_dev(n) sf_devs[(n)==0 ? 1:0]void *sf_rxtxbuf = NULL;static void eth_reset(void){ SF_SoftReset(); udelay(1000);}void string_to_mac(unsigned char *mac, char* s){ int i; char *e; for (i=0; i<ETH_ALEN; ++i) { mac[i] = s ? simple_strtoul(s, &e, 16) : 0; if (s) { s = (*e) ? e+1 : e; } }}static void sf_get_mac(unsigned char * p){ unsigned int tmac; unsigned char* pt; pt=(unsigned char*)&tmac; tmac=*(UINT32 *) SF_GLB_DIO(5); p[0]=pt[1]; p[1]=pt[0]; tmac=*(UINT32 *) SF_GLB_DIO(4); p[2]=pt[3]; p[3]=pt[2]; p[4]=pt[1]; p[5]=pt[0];}static void sf_set_mac(struct net_device *dev, const unsigned char* mac){ unsigned char t[4]={0}; if(dev) memcpy(dev->dev_addr,mac,ETH_ALEN); sf_lock(lp); t[0]=mac[1]; t[1]=mac[0]; *SF_GLB_DIO(5) = *((UINT32*)t); t[0]=mac[5]; t[1]=mac[4]; t[2]=mac[3]; t[3]=mac[2]; *SF_GLB_DIO(4) = *((UINT32*)t); sf_unlock(lp);}void init_sf_mac_env(void){ unsigned char mac[ETH_ALEN]; char* s=getenv("ethaddr"); if(s==NULL) return; eth_reset(); string_to_mac(mac,s); sf_set_mac(sf_port_dev(0), mac); sf_set_mac(sf_port_dev(1), mac); sf_print_mac(mac);}#define cmp_mac(ma,mb) (\ (*((unsigned int*))ma==*((unsigned int*)mb)) && \ (((*((unsigned int*)((unsigned char*)ma+4)))&0x0000FFFF)==\ ((*((unsigned int*)((unsigned char*)mb+4)))&0x0000FFFF))\ )static int net_port = 1; /* 0 is down-link,1 is up-link */static int adaptive_type = 0; /* 0 is adaptive,1 is non-adaptive */void get_eth_env(void){ char* s=getenv("netport"); if (s != NULL) { if(strcmp("eth0", s) == 0) { net_port = 1; } if(strcmp("eth1", s) == 0) { net_port = 0; } } if(net_port == 1) printf("Using Up port.\n"); else if(net_port == 0) printf("Using Down port.\n"); else { net_port = 1; printf("Net port number error!\n"); } s = getenv("adaptive"); if (s != NULL) { if(strcmp("auto", s) == 0) { adaptive_type = 0; }else { adaptive_type = 1; } }else { adaptive_type =1; }}static int sf_dev_init(int unit){ struct net_device *dev; struct sf_local* lp; unsigned char _sf_mac[ETH_ALEN]; const char *init_stat; if(unit>1 || unit<0) return -ENODEV; dev = alloc_etherdev(sizeof(struct sf_local)); if(dev == NULL) return -ENOMEM;#if 0 SET_MODULE_OWNER(dev); dev->base_addr = SF_REG_BASE; dev->irq = HISILICON_SF_IRQ; dev->open = sf_open; dev->stop = sf_close; dev->tx_timeout = sf_tx_timeout; dev->watchdog_timeo = 5*HZ; dev->hard_start_xmit = sf_hard_start_xmit; dev->get_stats = sf_get_stats; dev->set_mac_address = sf_set_mac_address; dev->set_config = sf_set_config;#endif lp = netdev_priv(dev); lp->port = (unit==0 ? 1:0); spin_lock_init(&lp->lock); sf_get_mac(_sf_mac); sf_set_mac(dev,_sf_mac); if(lp->port) { lp->phy = hisilicon_phy_connect(SF_UPP_PHY_NAME, SF_UPP_PHY_ID); init_stat = SF_UPP_INIT_STAT; } else { lp->phy = hisilicon_phy_connect(SF_DNP_PHY_NAME, SF_DNP_PHY_ID); init_stat = SF_DNP_INIT_STAT; } lp->auto_conf = init_stat[0]-'0'; lp->fetch_mod = init_stat[1]-'0'; lp->link_stat = init_stat[2]-'0'; lp->duplex_stat = init_stat[3]-'0'; lp->speed_stat = init_stat[4]-'0'; lp->orig_fetch_mod = lp->fetch_mod; lp->phy->probe(lp->port); sf_port_dev(lp->port) = dev; netif_carrier_off(dev); return register_netdev(dev);}static void _sf_stat_static_set(struct net_device *dev){ struct sf_local *lp = netdev_priv(dev); sf_lock(lp); SF_SetPortStatusFetchMode(lp->port, lp->fetch_mod==0?2:0); SF_SetSpeedLinkDuplexMode(lp->port, lp->speed_stat, lp->enabled, lp->duplex_stat); lp->phy->set_static_mod(lp->port,LP2PHY_STAT(lp)); SF_SetFrameConfiguration(lp->port, 0x03*lp->speed_stat, 90, 0x1FFF); sf_unlock(lp);}static void _sf_stat_auto_set(struct net_device *dev){ struct sf_local *lp = netdev_priv(dev); sf_lock(lp); lp->orig_fetch_mod = lp->fetch_mod; lp->fetch_mod = 1; SF_SetPortStatusFetchMode(lp->port, 0); lp->phy->set_auto_mod(lp->port); sf_unlock(lp);}static int sf_port_startup(struct net_device *dev){ struct sf_local *lp = netdev_priv(dev); lp->enabled = 1; lp->phy->init(lp->port); if(lp->auto_conf) { _sf_stat_auto_set(dev); } else { lp->link_stat = 1; _sf_stat_static_set(dev); netif_carrier_on(dev); } return 0;}static int sf_open(struct net_device *dev){ struct sf_local *lp = netdev_priv(dev); int ret=0; if(lp->isopen) return -EPERM; lp->isopen = 1; ret = sf_port_startup(dev); netif_start_queue(dev); return ret;}static int sf_buffer_init(void){ unsigned long __sf_rxtx_buffer = HISILICON_SF_RXTXBUF_ALIGN(_bss_end); sf_rxtxbuf = (void*)HISILICON_SF_RXTXBUF_ALIGN(__sf_rxtx_buffer); memset(sf_rxtxbuf, 0, HISILICON_SF_RXTXBUF_LEN + HISILICON_SF_NATBUF_LEN); SF_SetExternSdramBufferAddress((unsigned long)sf_rxtxbuf); SF_NATSetExternFormAddress((unsigned long)sf_rxtxbuf + HISILICON_SF_RXTXBUF_LEN); printf("SFBuf: 0x%08X - 0x%08X\n", (unsigned int)sf_rxtxbuf, (unsigned int)sf_rxtxbuf + HISILICON_SF_RXTXBUF_LEN + HISILICON_SF_NATBUF_LEN - 1);}int eth_init(bd_t * bd){ unsigned long t, n; struct net_device *dev = NULL; struct sf_local *lp = NULL; get_eth_env(); sf_buffer_init(); init_sf_mac_env(); sf_hdw_startup(); sf_dev_init(0); sf_dev_init(1); dev = sf_port_dev(net_port); lp = netdev_priv(dev); sf_open(sf_port_dev(net_port)); if(!lp->auto_conf) { printf("Configuring network: "); for(t=0, n=0; t<20 && n<3; t++) { unsigned long stat; udelay(300000); stat = lp->phy->get_states(net_port); if(stat == LP2PHY_STAT(lp)) { printf("+"); if(t==0) t = 100; n++; } else { n = 0; printf(">"); } } udelay(500000); printf("\n"); } return 0;}/* Get a data block via Ethernet */extern int eth_rx (void){ static int rx_idx=0; UINT16 rxlen=0; int ret; int i; for(i=1; i<=4; i++) { rxlen=0; ret = SF_FrameReceive(i, (UINT32 *)NetRxPackets[rx_idx], &rxlen); if(rxlen < 60 || net_port!=(ret&0x01)) continue; NetReceive(NetRxPackets[rx_idx], rxlen); rx_idx=(rx_idx + 1)%PKTBUFSRX; } return rxlen;}static void mem_dump(unsigned char *mem, int len){ int i; for(i=0; i<len; i++) { if(!(i%16)) printf("\n0x%04X:",i); if(!(i%8)) printf(" "); printf("%02X",mem[i]); } putc('\n');}extern int eth_send (volatile void *packet, int length){ if(SF_FrameTransmit(1,net_port, 0,0,(unsigned int)length,0,0,(UINT8 *)packet) != 1) { printf("Send packet faild, length = %d!\n", length); mem_dump((unsigned char *)packet, length); } return 0;}static int sf_close(struct net_device *dev){ struct sf_local *lp = netdev_priv(dev); netif_carrier_off(dev); lp->enabled = 0; lp->isopen = 0; lp->link_stat = 0; _sf_stat_static_set(dev); lp->phy->exit(lp->port); return 0;}void eth_halt (void){ int i; for(i=0; i<2; i++) { if(sf_port_dev(i)==NULL) continue; sf_close(sf_port_dev(i)); free_netdev(sf_port_dev(i)); sf_port_dev(i) = NULL; } eth_reset(); SF_SetExternSdramBufferAddress(0); SF_NATSetExternFormAddress(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -