⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mac.c

📁 at91rm9200 bios v1.1 源码
💻 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];

//Buffer descriptor address must be word aligned
#define AT91C_EMAC_TDLIST_BASE	0x20010000		//不能被下载数据冲掉!!!

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;

extern volatile unsigned long StTick;

// ****************************************************************************************************
// ** 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 Wait = StTick + 10;
	unsigned int value = 0x60020000 | (addr << 18);

	pEmac->EMAC_MAN = value;
	delay(100);//while(StTick < Wait);
	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, lnk_stat;
	
	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<<8)|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<<8;
    }
    //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);
	if ( status )
		return status;

	// 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];

	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_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 + -