网卡DM9000E的底层驱动函数
0赞
发表于 2012/1/7 15:28:39
阅读(2788)
#define __DEBUG #include#include "dm_types.h" #include "dm_bf5xx.h" #include "dm_lan_dm9000e.h" #define CONFIG_DRIVER_DM9000 #define CONFIG_COMMANDS 1 #define CFG_CMD_NET 1 #ifdef CONFIG_DRIVER_DM9000 #if (CONFIG_COMMANDS & CFG_CMD_NET) #define PKTALIGN 32 #define PKTSIZE_ALIGN 1536 #define CFG_HZ 1000 /* 1 kHz */ static void phy_write( int_t reg, uint16_t value); #define DM9000_VID_L 0x28 #define DM9000_VID_H 0x29 #define DM9000_PID_L 0x2A #define DM9000_PID_H 0x2B #define DM9000_ID 0x90000A46 #define DM9000_int32_MII 0x00 #define DM9000_10MHD 0x1 #define DM9000_10MFD 0x2 #define DM9000_100MHD 0x3 #define DM9000_100MFD 0x4 #define LOOP_MAC 0x1 #define LOOP_PHY100M 0x2 static uint8_t ior(int_t reg); uint16_t NetRxPackets[PKTSIZE_ALIGN+PKTALIGN]; uint8_t env_enetaddr[6]; /**************************************************************************** * 名称 : GetDM9000ID * 功能 : 读取DM9000E ID并打印 * 入口参数 :无 * 出口参数 :id_val ID值 ****************************************************************************/ uint32_t GetDM9000ID(void) { uint32_t id_val; id_val = ior(DM9000_PID_H); printf("DM9000E ID is %x",id_val); id_val = ior(DM9000_PID_L); printf("%x",id_val); id_val = ior(DM9000_VID_H); printf("%x",id_val); id_val = ior(DM9000_VID_L); printf(" %x\n\r",id_val); return id_val; } /**************************************************************************** * 名称 : iow * 功能 : 将值写入指定的寄存器 * 入口参数 :reg,value * 出口参数 :无 ****************************************************************************/ static void iow(int_t reg, uint8_t value) { DM9000_PPTR = reg; asm("ssync;"); asm("ssync;"); asm("ssync;"); DM9000_PDATA = value & 0xff; asm("ssync;"); asm("ssync;"); asm("ssync;"); } /**************************************************************************** * 名称 : ior * 功能 : 送入要读取的寄存器地址返回当前寄存器值 * 入口参数 :reg * 出口参数 :DM9000_PDATA & 0xff ****************************************************************************/ static uint8_t ior(int_t reg) { DM9000_PPTR = reg; asm("ssync;"); asm("ssync;"); asm("ssync;"); return DM9000_PDATA & 0xff; } /**************************************************************************** * 名称 : eth_reset * 功能 : 复位,初始化dm9000E并打印相关设置 * 入口参数 :无 * 出口参数 :无 ****************************************************************************/ void eth_reset (void) { int_t IoMode; uint8_t tmp; iow(0, 1); // 复位 mdelay(50); // delay 100us IoMode = ior(0xfe) >> 6; //读取io模式 if(!IoMode) printf("DM9000 work in 16 bus width\r\n"); else if(IoMode == 2) printf("DM9000 work in 8 bus width\r\n"); else if(IoMode == 1) printf("DM9000 work in 32 bus width\r\n"); else printf("DM9000 work in wrong bus width, error\r\n"); iow(0x1e, 0x01); iow(0x1f, 0x00); // 使能 PHY iow(0xff, 0x80); iow(0x01, 0xc); // 清除 TX 状态 iow(0x5, 0x33); // 使能 RX ior(0x6); iow(0x2, 1); // 使能TX mdelay(100); IoMode = ior(0x01); if(IoMode & 0x40) printf("Link on ethernet at:%d Mbps\r\n", (IoMode & 0x80) ? 10:100); } /**************************************************************************** * 名称 : eth_rx * 功能 : 读取网络传输数据 * 入口参数 :addr * 出口参数 :rxlen ****************************************************************************/ int_t eth_rx (uint16_t *addr) { int_t i; uint16_t rxlen; uint16_t status; uint8_t RxRead; uint8_t *tmp; RxRead = ior(0xf0); RxRead = (DM9000_PDATA) & 0xff; RxRead = (DM9000_PDATA) & 0xff; if (RxRead != 1) return 0; status = ior(0xf2);//获得状态 rxlen = DM9000_PDATA; //获得长度 asm("ssync;"); if (rxlen > PKTSIZE_ALIGN + PKTALIGN) printf ("packet too big! %d %d\r\n", rxlen, PKTSIZE_ALIGN + PKTALIGN); for ( i =0; i >1; int_t IoMode; TxStatus = ior(0x01); TxStatus = TxStatus & 0xc; DM9000_PPTR = 0xf8; // data copy ready set for(i=0;i<2;i++) //延时匹配时序。 asm("ssync;"); for (addr = packet; length1 > 0; length1 --) { DM9000_PDATA = *addr++; for(i=0;i<3;i++) //延时匹配84nS延时时序。 asm("ssync;"); // delay(1000); } iow(0xfd, (length >> 8) & 0xff); //set transmit leng iow(0xfc, length & 0xff); /* start transmit */ iow(0x02, txCmd|0x1); /// while(!(ior(0x01)&0x40)); return 0; } /**************************************************************************** * 名称 : phy_read * 功能 : 读取DM9000E物理寄存器 * 入口参数 :reg * 出口参数 :( ior( 0xe) << 8 ) | ior( 0xd) ****************************************************************************/ static uint16_t phy_read(int_t reg) { /* Fill the phyxcer register into REG_0C */ iow( 0xc, DM9000_PHY | reg); iow( 0xb, 0xc); /* Issue phyxcer read command */ mdelay(100); /* Wait read complete */ iow(0xb, 0x0); /* Clear phyxcer read command */ /* The read data keeps on REG_0D & REG_0E */ return ( ior( 0xe) << 8 ) | ior( 0xd); } /**************************************************************************** * 名称 : phy_write * 功能 : 写DM9000E物理寄存器 * 入口参数 :reg,value * 出口参数 :无 ****************************************************************************/ static void phy_write( int_t reg, uint16_t value) { /* Fill the phyxcer register into REG_0C */ iow( 0xc, DM9000_PHY | reg); /* Fill the written data into REG_0D & REG_0E */ iow( 0xd, (value & 0xff)); iow(0xe, ( (value >> 8) & 0xff)); iow(0xb, 0xa); /* Issue phyxcer write command */ mdelay(100); /* Wait write complete */ iow(0xb, 0x0); /* Clear phyxcer write command */ } /**************************************************************************** * 名称 : set_PHY_mode * 功能 : 设置网卡工作模式 10M:100M * 入口参数 :op_mode * 出口参数 :无 ****************************************************************************/ static void set_PHY_mode(op_mode) { int_t phy_reg4,phy_reg0; switch(op_mode) { case DM9000_10MHD: phy_reg4 = 0x21; asm("ssync;"); phy_reg0 = 0x0000; asm("ssync;"); break; case DM9000_10MFD: phy_reg4 = 0x41; asm("ssync;"); phy_reg0 = 0x1100; asm("ssync;"); break; case DM9000_100MHD: phy_reg4 = 0x81; asm("ssync;"); phy_reg0 = 0x2000; asm("ssync;"); break; case DM9000_100MFD: phy_reg4 = 0x101; asm("ssync;"); phy_reg0 = 0x3100; asm("ssync;"); break; } // end of switch phy_write( 0, phy_reg0); // delay(100); phy_write( 4, 0x0400|phy_reg4); } /**************************************************************************** * 名称 : loopback * 功能 : 网卡环路测试,设置网卡工作于何种环路测试模式 * 入口参数 :mode * 出口参数 :无 ****************************************************************************/ void loopback(int_t mode) { switch(mode) { case LOOP_MAC: iow(DM9000_NCR, 0x02); phy_write( 0, 0x40); break; case LOOP_PHY100M: iow(DM9000_NCR, 0x04); phy_write( 0, 0x40); break; } } #endif /* COMMANDS & CFG_NET */ #endif /* CONFIG_DRIVER_DM9000 */ uint16_t pack[1024]; uint16_t packLen=0; //#define PHY_LOOPBACK_TEST 1 void main() { int_t i; Set_PLL(22,5); Init_EBIU(); Init_SDRAM(); set_PHY_mode(DM9000_100MHD); eth_reset(); #if PHY_LOOPBACK_TEST // loopback(LOOP_MAC); // loopback(LOOP_PHY100M); #endif mdelay(100); GetDM9000ID(); for(i=0;i<1024;i++) pack[i] = i; while(1) { for(i=0;i<1000000;i++) { packLen = 512; eth_send(pack,packLen); } eth_rx(NetRxPackets); //接收数据包 } }