?? mac.c
字號:
#include "..\config.h"
#include "AT91RM9200.h"
#include "lib_AT91RM9200.h"
#include "Emac.h"
#include "eth.h"
#include "mac.h"
#include "utils.h"
#include "console.h"
#ifdef TFTP_SUPPORT
static U8 OurEmacAddr[ETH_ALEN] = {0x00,0x80,0x48,0x12,0x34,0x56};
//static U8 DstMacID[ETH_ALEN];
#define DRAM_END (DRAM_BASE + DRAM_SIZE)
//Buffer descriptor address must be word aligned
#define AT91C_EMAC_TDLIST_BASE (DRAM_END-SIZE_2M) //非Cache區,不能被下載數據沖掉!!!
static char RxPacket[NB_ETH_RX_PACKETS*ETH_PACKET_SIZE];
static char TxPacket[ETH_PACKET_SIZE];
static AT91PS_TdDescriptor tdList = (AT91PS_TdDescriptor)AT91C_EMAC_TDLIST_BASE;
static U8 lnk_stat;
void Delay(U32 ms)
{
U16 i;
i = AT91C_BASE_TC0->TC_RC>>1; //1000us/2
AT91C_BASE_TC0->TC_CCR = 4; //復位為0,加計數
while(ms--) {
while(AT91C_BASE_TC0->TC_CV<=i);
while(AT91C_BASE_TC0->TC_CV>i);
}
}
// ****************************************************************************************************
// ** EMAC lowlevel functions
// ****************************************************************************************************
//*----------------------------------------------------------------------------
//* \fn AT91F_MII_ReadPhy
//* \brief This function return the MII phy register
//*----------------------------------------------------------------------------
static unsigned short AT91F_MII_ReadPhy(
AT91PS_EMAC pEmac, // \arg Pointer to AT91PS_EMAC service
unsigned char addr)
{
unsigned int value = 0x60020000 | (addr << 18);
pEmac->EMAC_MAN = value;
Delay(10);
return (pEmac->EMAC_MAN & 0x0000ffff);
}
//*----------------------------------------------------------------------------
//* \fn AT91F_MII_GetLinkSpeed
//* \brief This function configure the link speed
//*----------------------------------------------------------------------------
static int MII_GetLinkSpeed(AT91PS_EMAC pEmac) // \arg Pointer to AT91PS_EMAC service
{
unsigned short stat1, stat2;
stat1 = AT91F_MII_ReadPhy(pEmac, MII_STS_REG);
stat1 = AT91F_MII_ReadPhy(pEmac, MII_STS_REG);
if(!(stat1 & 0x4)) //added by hzh
return -1; //no link, see the driver in linux
stat2 = AT91F_MII_ReadPhy(pEmac, MII_STS2_REG);
//set MII for 100BaseTX and Full Duplex
if ((stat1 & 0x4000) && (stat2 & 0x8000) ) {
pEmac->EMAC_CFG |= (AT91C_EMAC_SPD| AT91C_EMAC_FD);
lnk_stat = (1<<1)|1;
}
//set MII for 10BaseT and Full Duplex
else if ((stat1 & 0x1000) && (stat2 & 0x2000)) {
pEmac->EMAC_CFG = (pEmac->EMAC_CFG & ~AT91C_EMAC_SPD) | AT91C_EMAC_FD;
lnk_stat = 1;
}
//set MII for 100BaseTX and Half Duplex
else if ((stat1 & 0x2000) && (stat2 & 0x4000)) {
pEmac->EMAC_CFG = (pEmac->EMAC_CFG | AT91C_EMAC_SPD ) & ~AT91C_EMAC_FD;
lnk_stat = 1<<1;
}
//set MII for 10BaseT and Half Duplex
else if ((stat1 & 0x0800) && (stat2 & 0x1000)) {
pEmac->EMAC_CFG = pEmac->EMAC_CFG & ~AT91C_EMAC_SPD & ~AT91C_EMAC_FD;
lnk_stat = 0;
}
//add by hzh
// printf("Now link status is %s-%s\n", (lnk_stat&(1<<8))?"100M BaseT":"10M BaseT",
// (lnk_stat&1)?"FullDuplex":"HalfDuplex");
return 0;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_MDIO_StartupPhy
//* \brief This function start the phy
//*----------------------------------------------------------------------------
static int AT91F_MDIO_StartupPhy(AT91PS_EMAC pEmac) // \arg Pointer to AT91PS_EMAC service
{
int ret;
if(pEmac->EMAC_SR & AT91C_EMAC_LINK) //this bit has no means, reserved as 0
return 0;
pEmac->EMAC_CTL |= AT91C_EMAC_MPE;
ret = MII_GetLinkSpeed(pEmac);
pEmac->EMAC_CTL &= ~AT91C_EMAC_MPE;
// return 0;
return ret; //modified by hzh
}
//*----------------------------------------------------------------------------
//* \fn AT91F_EMACInit
//* \brief This function initialise the ethernet
//*----------------------------------------------------------------------------
int AT91F_EMACInit( // \return Status ( Success = 0)
AT91PS_EMAC pEmac, // \arg Pointer to AT91PS_EMAC service
unsigned int pTdList)
{
int status;
AT91F_EMAC_CfgPMC();
AT91F_EMAC_CfgPIO();
status = AT91F_MDIO_StartupPhy(pEmac);
// the sequence write EMAC_SA1L and write EMAC_SA1H must be respected
pEmac->EMAC_SA1L = ((int)OurEmacAddr[2] << 24) | ((int)OurEmacAddr[3] << 16) | ((int)OurEmacAddr[4] << 8) | OurEmacAddr[5];
pEmac->EMAC_SA1H = ((int)OurEmacAddr[0] << 8) | OurEmacAddr[1];
if ( status )
return status;
pEmac->EMAC_RBQP = pTdList;
pEmac->EMAC_RSR &= ~(AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
pEmac->EMAC_CFG |= (AT91C_EMAC_CAF | AT91C_EMAC_NBC | AT91C_EMAC_RMII);
pEmac->EMAC_CFG &= ~(AT91C_EMAC_CLK);
pEmac->EMAC_CTL |= (AT91C_EMAC_TE | AT91C_EMAC_RE);
return 0;
}
//*----------------------------------------------------------------------------
//* \fn AT91F_EmacEntry
//* \brief Initialise Emac to receive packets
//*----------------------------------------------------------------------------
static int AT91F_EmacEntry(void)
{
unsigned int i;
char *pRxPacket;
pRxPacket = (char *)RxPacket;
// Initialise tdList descriptor. This descriptor must be WORD aligned
for (i = 0; i < NB_ETH_RX_PACKETS; ++i)
{
tdList[i].addr = ((unsigned int) (pRxPacket + (i * ETH_PACKET_SIZE))) & 0xFFFFFFFC;
tdList[i].size = 0;
}
// Set the WRAP bit at the end of the list descriptor
tdList[NB_ETH_RX_PACKETS-1].addr |= 0x02;
return(AT91F_EMACInit(AT91C_BASE_EMAC, (unsigned int) tdList));
}
int board_eth_init(void)
{
return AT91F_EmacEntry();
}
int board_eth_lnk_stat(void)
{
if(lnk_stat!=-1) {
printf("Now link status is %s-%s\n", (lnk_stat&(1<<1))?"100M BaseT":"10M BaseT",
(lnk_stat&1)?"FullDuplex":"HalfDuplex");
return 0;
}
printf("Link error\n");
return -1;
}
int board_eth_send(unsigned char *data, unsigned int len)
{
if(len<60)
for(; len<60; len++)
data[len] = 0x20; //just for pad, any data
memcpy(TxPacket, data, len);
/* {
int i;
for(i=0; i<len; i++)
printf("%x,", data[i]);
putch('\n');
}*/
if (!(*AT91C_EMAC_TSR & AT91C_EMAC_BNQ))
return -1;
*AT91C_EMAC_TSR |= AT91C_EMAC_COMP;
*AT91C_EMAC_TAR = (unsigned int)TxPacket;
*AT91C_EMAC_TCR = len;
return 0;
}
int board_eth_rcv(unsigned char *data, unsigned int *len)
{
unsigned int i;
// Receive one packet
for (i = 0; i < NB_ETH_RX_PACKETS; ++i) {
if(tdList[i].addr & 0x1) {
if (*AT91C_EMAC_RSR & AT91C_EMAC_REC) //判斷是否接收到
(*AT91C_EMAC_RSR) |= AT91C_EMAC_REC; //清楚標識
break;
}
}
if(i==NB_ETH_RX_PACKETS)
return -1;
// printf("%d\n", i);
memcpy(data, (char *)(tdList[i].addr&~3), tdList[i].size);
// process the packet
tdList[i].addr &= ~0x01;
return 0;
}
int board_eth_get_addr(unsigned char *addr)
{
memcpy(addr, OurEmacAddr, ETH_ALEN);
return 0;
}
#endif
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -