📄 dm_lan_dm9000e.c
字号:
/**************************************************************************
文件名称: dm_lan_dm9000e.c
作者: Andy
版本: 0.1
创建时间 : 2007-04
描述:
文件实现了网卡DM9000E的底层驱动函数
修改历史:
****************************************************************************/
#define __DEBUG
#include <string.h>
#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<rxlen/2;i++)
addr[i] = DM9000_PDATA;
asm("ssync;");
return rxlen;
}
unsigned char txCmd;
/****************************************************************************
* 名称 : eth_send
* 功能 : 向网络发送数据包
* 入口参数 :packet,length
* 出口参数 :0
****************************************************************************/
void eth_send (volatile void *packet, int_t length)
{
int_t i;
volatile uint16_t *addr;
int_t tmo;
uint8_t TxStatus;
int_t length1 = length>>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;
int_t j;
int_t k;
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;
j=10;
while(j--)
{
for(i=0;i<100;i++)
{
packLen=eth_rx(pack);
for(k=0;k<packLen;k++) printf("%x/n",pack[k]);
//packLen = 256;
//eth_send(pack,packLen);
}
eth_rx(NetRxPackets); //接收数据包
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -