📄 ether_dev.c
字号:
//ether_dev.c
#define ETHER_DEV_GLOBALS
#include "ether_dev.h"
/************************************************************************/
/*ether_dev.c */
/************************************************************************/
extern uint16 *byBuf;
//extern uint16 *RecvbufMalloc(void);
//Register definition
//next receive buffer pointer
uint8 byNextp[2];
//AX88796 work state
uint16 EtherStat[2];
//data send finish flag
uint16 SendFinished[2] = {1,1};
//AX88796 reveice buffer has data
uint16 HasData[2] = {0,0};
//AX88796 receive data information
uint16 RcvDataInfo[2];
//physical addr buffer
uint8 Local_MAC[2][6];
uint8 nichAddr[2][6];
//protocal addr buffer
uint8 nicpAddr[2][4];
//send total data counter
INT32U trnNum[2];
//receive total data counter
INT32U recNum[2];
//error send total data counter
INT32U trnErr[2];
//error data total receive
INT32U recErr[2];
//data overflow counter
INT32U overflowErr[2];
uint8 temp1;
#define IRQ1_INTERRUPT_LEVEL 1
#define IRQ2_INTERRUPT_LEVEL 2
extern void irq1_asm_irq_handler(void);
extern void irq2_asm_irq_handler(void);
//88796 register read and write sub function
void OutportByte(uint16 idx,uint8 addr,uint8 tempData)
{
if(idx)
{
*((uint8*)(addr + 0x200 + Ethernet_Addr_Base1) ) = tempData;
}
else
{
*((uint8*)(addr + 0x200 + Ethernet_Addr_Base0) ) = tempData;
}
}
//Read byte data
uint8 InportByte(uint16 idx,uint8 addr)
{
if(idx)
{
return *((uint8*)(addr + 0x200 + Ethernet_Addr_Base1));
}
else
{
return *((uint8*)(addr + 0x200 + Ethernet_Addr_Base0));
}
}
/************************************************************************/
/*AX88796 initialization sub fuction */
/************************************************************************/
uint16 etherdev_init(uint16 idx)
{
//Software reset
InportByte(idx,NIC_RESET);
//Page 0, stop, no DMA
OutportByte(idx,CR, 0x21);
//8086、WORD-wide DMA mode transfer
OutportByte(idx,DCR, 0x81);
//Brocast,Multicast Package receive
OutportByte(idx,RCR, 0x4c);
//Internal AX88796 loop-back
OutportByte(idx,TCR, 0xc0);
//Clear remote byte count register
OutportByte(idx,RBCR0, 0);
OutportByte(idx,RBCR1, 0);
//Init interrupt mask register
OutportByte(idx,IMR, 0x3f);
//Clear interrupt status register
OutportByte(idx,ISR, 0xFF);
//Init data read boundary page
OutportByte(idx,BNDRY, RX_BUF_Start);
//Init RX_BUF stop page
OutportByte(idx,PSTOP, RX_BUF_Stop);
//Inie RX_BUF start page
OutportByte(idx,PSTART, RX_BUF_Start);
//Page 1, stop, no DMA
OutportByte(idx,CR, 0x61);
temp1 = InportByte(idx,CR);
// Set local MAC address
OutportByte(idx,PAR0, gnitbl[idx].mac[0]);
OutportByte(idx,PAR1, gnitbl[idx].mac[1]);
OutportByte(idx,PAR2, gnitbl[idx].mac[2]);
OutportByte(idx,PAR3, gnitbl[idx].mac[3]);
OutportByte(idx,PAR4, gnitbl[idx].mac[4]);
OutportByte(idx,PAR5, gnitbl[idx].mac[5]);
OutportByte(idx,MAR0, 0);
OutportByte(idx,MAR1, 0);
OutportByte(idx,MAR2, 0);
OutportByte(idx,MAR3, 0x80);
OutportByte(idx,MAR4, 0);
OutportByte(idx,MAR5, 0);
OutportByte(idx,MAR6, 0);
OutportByte(idx,MAR7, 0);
//Init data write pointer
OutportByte(idx,CURR, RX_BUF_Start+1);
//Page 0, start, no DMA
OutportByte(idx,CR, 0x21);
//data receive next pointer
byNextp[idx] = RX_BUF_Start+1;
if(InportByte(idx,GPI) & 2)
{
//Mode 0, full duplex
OutportByte(idx,TCR, 0x80);
}
else
{
OutportByte(idx,TCR, 0x00);
}
//Normal power; internal PHY
OutportByte(idx,GPOC, 0x10);
//transmit page start addr
OutportByte(idx,TPSR, 0x40);
//Remote DMA Active Ax88796
OutportByte(idx,CR, 0x22);
//Ax88796 work state
EtherStat[idx] = 1;
return 1;
}
/************************************************************************/
/* read data */
/************************************************************************/
void readData(uint16 *byBuf,uint16 length,uint16 idx)
{
uint16 i;
if(idx)
{
for(i = 0;i < (length/2);i++)
{
*(byBuf+i) = *((uint16 *)(NIC_DATA +0x200+Ethernet_Addr_Base1));
}
}
else
{
for(i = 0;i < (length/2);i++)
{
*(byBuf+i) = *((uint16*)(NIC_DATA +0x200+Ethernet_Addr_Base0));
}
}
}
/************************************************************************/
/* AX88796 receive data */
/************************************************************************/
uint16 EtherInput(uint8* addr, uint16 max_len,uint8 idx)
{
uint8 RegTemp;
uint16 RcvDataInfo[2];
uint16 length;
//read current page register
RegTemp=InportByte(idx,CPR);
while(byNextp[idx]!=RegTemp)
{
OutportByte(idx,RSAR0,0x00);
OutportByte(idx,RSAR1,byNextp[idx]);
OutportByte(idx,RBCR0, 0x04);
OutportByte(idx,RBCR1, 0x00);
OutportByte(idx,CR, 0x0A);
// get receive data information
readData(RcvDataInfo,0x4,idx);
// data length
length = RcvDataInfo[1] - 4;
if(length > max_len)
{
return(0);
}
OutportByte(idx,RSAR0,0x4);
OutportByte(idx,RSAR1,byNextp[idx]);
//received data length
OutportByte(idx,RBCR0, (uint8)(length& 0x00ff ));
OutportByte(idx,RBCR1, (uint8)(length >> 8));
OutportByte(idx,CR, 0x0A);
//read from AX88796 data register
readData((uint16 *)addr, length,idx);
//set pointer to receive next package
byNextp[idx] = (uint8)(RcvDataInfo[0] >> 8);
//update current page
RegTemp=InportByte(idx,CPR);
}
//update boundry register
RegTemp=byNextp[idx]-1;
if( RegTemp < RX_BUF_Start )
RegTemp=RX_BUF_Stop-1;
OutportByte(idx,BNDRY, RegTemp);
return(length);
}
/************************************************************************/
/* AX88796 data write */
/************************************************************************/
void writeData(uint16 *byBuf ,uint16 length,uint16 idx)
{
INT32U i;
if(idx)
{
for(i = 0;i < ((length+1) >> 1);i++)
{
*((uint16 *)(NIC_DATA + 0x200 + Ethernet_Addr_Base1)) =*(byBuf+i);
}
}
else
{
for(i = 0;i < ((length+1) >>1 ) ;i++)
{
*((uint16 *)(NIC_DATA + 0x200 + Ethernet_Addr_Base0)) = *(byBuf+i);
}
}
}
/************************************************************************/
/* Trigger send of data in output RAM buffer */
/************************************************************************/
uint8 EtherOutput(uint8* addr, uint16 len, uint16 hw_id)
{
uint8 RegTemp;
uint16 i,j,idx;
idx = hw_id;
if(len < 60)
{
len = 60;
}
// Reset remote DMA status
OutportByte(idx,CR, 0x22);
OutportByte(idx,ISR,0x40);
OutportByte(idx,RSAR0,0x0);
OutportByte(idx,RSAR1,0x40);
// Length
OutportByte(idx,RBCR0, (uint8)(len & 0xFF));
OutportByte(idx,RBCR1, (uint8)(len>>8));
OutportByte(idx,CR, 0x12);
//data from cpu to nic
writeData((uint16 * )addr,len,idx);
//renew send pointer
OutportByte(idx,TBCR0, (uint8)(len & 0xFF));
OutportByte(idx,TBCR1, (uint8)(len>>8));
OutportByte(idx,ISR,0x2);
OutportByte(idx,TPSR, TX_BUF_Start );
//Begin to send data
OutportByte(idx,CR,0x26);
for(i=0;i <1000;i++)
{
//ISR register show dasta send complete
RegTemp = InportByte(idx,ISR);
if(RegTemp & 0x02)
{
break;
}
for(j=0;j<100;j++)
{
;
}
}
return SYS_NO_ERR;
}
/************************************************************************/
/*interrupt process handler */
/************************************************************************/
void at91_IRQ1_handler(void)
{
uint8 RegTemp;
static uint8 idx;
idx = 0;
RegTemp = InportByte(idx,ISR); //read interrupt register status
OutportByte(idx,IMR, 0x00); //disable interrupt
OutportByte(idx,ISR, RegTemp); //clear interrupt status
if(RegTemp & 0x01)
{
OSQPost(gpTcpIpMsgQ, &idx);
}
OutportByte(idx,IMR,0x11); //enable interrupt
}
void at91_IRQ2_handler(void)
{
uint8 RegTemp;
static uint8 idx;
idx = 1;
RegTemp = InportByte(idx,ISR); //read interrupt register status
OutportByte(idx,IMR, 0x00); //disable interrupt
OutportByte(idx,ISR, RegTemp); //clear interrupt status
if(RegTemp & 0x01)
{
OSQPost(gpTcpIpMsgQ, &idx);
}
OutportByte(idx,IMR,0x11); //enable interrupt
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -