|
这是我在网上找一些程序,看不懂什么意思
emac的驱动
file:///root/Desktop/%E5%88%B0%20wang%20%E7%9A%84%E9%93%BE%E6%8E%A5/linux%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/EtherNet/ethemac.c
file:///root/Desktop/%E5%88%B0%20wang%20%E7%9A%84%E9%93%BE%E6%8E%A5/linux%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/EtherNet/ethemac.h
ethemac.c
#include "AT91SAM9260.h"
#include "main.h"
#include "ethemac.h"
#include "dm9161.h"
#include "eth.h"
unsigned char Macaddr[6]={0x00, 0x45, 0x56, 0x78, 0x9a, 0xbc};
/* ----- Ethernet Buffer definitions ----- */
/* Receive Transfer descriptor structure */
typedef struct _AT91S_RxTdDescriptor {
unsigned int addr;
union
{
unsigned int status;
struct {
unsigned int Length:12;
unsigned int Rxbuf_off:2;
unsigned int StartOfFrame:1;
unsigned int EndOfFrame:1;
unsigned int Cfi:1;
unsigned int VlanPriority:3;
unsigned int PriorityTag:1;
unsigned int VlanTag:1;
unsigned int TypeID:1;
unsigned int Sa4Match:1;
unsigned int Sa3Match:1;
unsigned int Sa2Match:1;
unsigned int Sa1Match:1;
unsigned int Res0:1;
unsigned int ExternalAdd:1;
unsigned int UniCast:1;
unsigned int MultiCast:1;
unsigned int BroadCast:1;
} S_Status;
} U_Status;
} AT91S_RxTdDescriptor, *AT91PS_RxTdDescriptor;
/* Transmit Transfer descriptor structure */
typedef struct _AT91S_TxTdDescriptor {
unsigned int addr;
union
{
unsigned int status;
struct {
unsigned int Length:11;
unsigned int Res0:4;
unsigned int LastBuff:1;
unsigned int NoCrc:1;
unsigned int Res1:10;
unsigned int BufExhausted:1;
unsigned int TransmitUnderrun:1;
unsigned int TransmitError:1;
unsigned int Wrap:1;
unsigned int BuffUsed:1;
} S_Status;
} U_Status;
} AT91S_TxTdDescriptor, *AT91PS_TxTdDescriptor;
#define RBF_ADDR 0xfffffffc
#define RBF_OWNER (1<<0)
#define RBF_WRAP (1<<1)
#define RBF_BROADCAST (1<<31)
#define RBF_MULTICAST (1<<30)
#define RBF_UNICAST (1<<29)
#define RBF_EXTERNAL (1<<28)
#define RBF_UNKOWN (1<<27)
#define RBF_SIZE 0x07ff
#define RBF_LOCAL4 (1<<26)
#define RBF_LOCAL3 (1<<25)
#define RBF_LOCAL2 (1<<24)
#define RBF_LOCAL1 (1<<23)
#define RBF_EOF (1<<15)
#define RBF_SOF (1<<14)
#define MAX_ETH_FRAME_LEN 0x600 /* 1536 bytes. Max ethernet frame size */
#define RBF_FRAMEMAX 64
#define RBF_FRAMELEN 128
#define TBF_FRAMEMAX 64
#define TBF_FRAMELEN 0x600
/*alignment as per Errata #11 (64 bytes) is insufficient!
AT91S_RxTdDescriptor RxtdList[RBF_FRAMEMAX] __attribute((aligned(512)));
AT91S_TxTdDescriptor TxtdList[TBF_FRAMEMAX] __attribute((aligned(512)));
unsigned char rbf_framebuf[RBF_FRAMEMAX][RBF_FRAMELEN] __attribute((aligned(4)));
unsigned char tbf_framebuf[TBF_FRAMEMAX][TBF_FRAMELEN] __attribute((aligned(4)));*/
__align(512) AT91S_RxTdDescriptor RxtdList[RBF_FRAMEMAX] ;
__align(512) AT91S_TxTdDescriptor TxtdList[TBF_FRAMEMAX] ;
__align(4) unsigned char rbf_framebuf[RBF_FRAMEMAX][RBF_FRAMELEN] ;
__align(4) unsigned char tbf_framebuf[TBF_FRAMEMAX][TBF_FRAMELEN];
unsigned int RxBuffIndex = 0;
unsigned int TxBuffIndex = 0;
//static unsigned char stage_rx_buffer[MAX_ETH_FRAME_LEN];
//volatile unsigned char *rx_pkt_tmp = stage_rx_buffer;
//volatile unsigned char *rx_pkt_tmp = stage_rx_buffer;
/* structure to interface the PHY */
AT91S_PhyOps PhyOps;
AT91PS_EMAC p_mac;
void AT91F_EMAC_Hardware_Init(void)
{
unsigned int periphAEnable, periphBEnable;
p_mac = AT91C_BASE_EMACB;
/* Disable pull-up on:
RXDV (PA17) => PHY normal mode (not Test mode)
ERX0 (PA14) => PHY ADDR0
ERX1 (PA15) => PHY ADDR1
ERX2 (PA25) => PHY ADDR2
ERX3 (PA26) => PHY ADDR3
ECRS (PA28) => PHY ADDR4 => PHYADDR = 0x0
PHY has internal pull-down
*/
AT91C_BASE_PIOA->PIO_PPUDR = AT91C_PA14_ERX0 | AT91C_PA15_ERX1 |
AT91C_PA17_ERXDV | AT91C_PA25_ERX2 |
AT91C_PA26_ERX3 | AT91C_PA28_ECRS;
/* Need to reset PHY -> 500ms reset */
AT91C_BASE_RSTC->RSTC_RMR = (AT91C_RSTC_KEY & ((unsigned int)0xA5<<24)) |
(AT91C_RSTC_ERSTL & (0x0D << 8)) | AT91C_RSTC_URSTEN;
AT91C_BASE_RSTC->RSTC_RCR = (AT91C_RSTC_KEY & ((unsigned int)0xA5<<24)) |
AT91C_RSTC_EXTRST;
/* Wait for end hardware reset */
while (!(AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_NRSTL));
/* Re-enable pull-up */
AT91C_BASE_PIOA->PIO_PPUER = AT91C_PA14_ERX0 | AT91C_PA15_ERX1 |
AT91C_PA17_ERXDV | AT91C_PA25_ERX2 |
AT91C_PA26_ERX3 | AT91C_PA28_ECRS;
#ifdef CONFIG_AT91C_USE_RMII
periphAEnable = ((unsigned int) AT91C_PA21_EMDIO ) |
((unsigned int) AT91C_PA20_EMDC ) |
((unsigned int) AT91C_PA19_ETXCK ) |
((unsigned int) AT91C_PA18_ERXER ) |
((unsigned int) AT91C_PA14_ERX0 ) |
((unsigned int) AT91C_PA17_ERXDV ) |
((unsigned int) AT91C_PA15_ERX1 ) |
((unsigned int) AT91C_PA16_ETXEN ) |
((unsigned int) AT91C_PA12_ETX0 ) |
((unsigned int) AT91C_PA13_ETX1 );
periphBEnable = 0;
#else
periphAEnable = ((unsigned int) AT91C_PA21_EMDIO ) |
((unsigned int) AT91C_PA19_ETXCK ) |
((unsigned int) AT91C_PA20_EMDC ) |
((unsigned int) AT91C_PA18_ERXER ) |
((unsigned int) AT91C_PA14_ERX0 ) |
((unsigned int) AT91C_PA17_ERXDV ) |
((unsigned int) AT91C_PA15_ERX1 ) |
((unsigned int) AT91C_PA16_ETXEN ) |
((unsigned int) AT91C_PA12_ETX0 ) |
((unsigned int) AT91C_PA13_ETX1 );
periphBEnable = ((unsigned int) AT91C_PA27_ERXCK ) |
((unsigned int) AT91C_PA29_ECOL ) |
((unsigned int) AT91C_PA25_ERX2 ) |
((unsigned int) AT91C_PA26_ERX3 ) |
((unsigned int) AT91C_PA22_ETXER ) |
((unsigned int) AT91C_PA10_ETX2 ) |
((unsigned int) AT91C_PA11_ETX3 ) |
((unsigned int) AT91C_PA28_ECRS );
#endif
AT91C_BASE_PIOA->PIO_ASR = periphAEnable;
AT91C_BASE_PIOA->PIO_BSR = periphBEnable;
AT91C_BASE_PIOA->PIO_PDR = (periphAEnable | periphBEnable);
}
/*********** EMAC Phy layer Management functions *************************/
/*
* Name:使能管理断口
* at91_EmacEnableMDIO
* Description:
* Enables the MDIO bit in MAC control register
* Arguments:
* p_mac - pointer to struct AT91S_EMAC
* Return value:
* none
*/
void at91_EmacEnableMDIO (AT91PS_EMAC p_mac)
{
/* Mac CTRL reg set for MDIO enable */
p_mac->EMAC_NCR |= AT91C_EMAC_MPE; /* Management port enable */
}
/*
* Name:MDIO为高 MDC为低
* at91_EmacDisableMDIO
* Description:
* Disables the MDIO bit in MAC control register
* Arguments:
* p_mac - pointer to struct AT91S_EMAC
* Return value:
* none
*/
void at91_EmacDisableMDIO (AT91PS_EMAC p_mac)
{
/* Mac CTRL reg set for MDIO disable */
p_mac->EMAC_NCR &= ~AT91C_EMAC_MPE; /* Management port disable */
}
/*
* Name:读取PHY寄存器的值,在MAN寄存器操作
* at91_EmacReadPhy
* Description:
* Reads data from the PHY register
* Arguments:
* dev - pointer to struct net_device
* RegisterAddress - unsigned char
* pInput - pointer to value read from register
* Return value:
* TRUE - if data read successfully
*/
uchar at91_EmacReadPhy (AT91PS_EMAC p_mac,
unsigned char PhyAddress,
unsigned char RegisterAddress,
unsigned short *pInput)
{
p_mac->EMAC_MAN = (AT91C_EMAC_SOF & (0x01 << 30)) |
(AT91C_EMAC_RW & (0x2 << 28)) |
((PhyAddress & 0x1F) << 23) |
(RegisterAddress << 18) |
(AT91C_EMAC_CODE & (0x2 << 16));
/* Wait until IDLE bit in Network Status register is cleared */
while (!(p_mac->EMAC_NSR & AT91C_EMAC_IDLE));
*pInput = (unsigned short) (p_mac->EMAC_MAN & 0x0000FFFF);
return TRUE;
}
/*
* Name:写取PHY寄存器的值,在MAN寄存器操作
* at91_EmacWritePhy
* Description:
* Writes data to the PHY register
* Arguments:
* dev - pointer to struct net_device
* RegisterAddress - unsigned char
* pOutput - pointer to value to be written in the register
* Return value:
* TRUE - if data read successfully
*/
uchar at91_EmacWritePhy (AT91PS_EMAC p_mac,
unsigned char PhyAddress,
unsigned char RegisterAddress,
unsigned short *pOutput)
{
p_mac->EMAC_MAN = (AT91C_EMAC_SOF & (0x01 << 30)) |
(AT91C_EMAC_RW & (0x1 << 28)) |
((PhyAddress & 0x1F) << 23) |
(RegisterAddress << 18) |
(AT91C_EMAC_CODE & (0x2 << 16)) |
*pOutput;
/* Wait until IDLE bit in Network Status register is cleared */
while (!(p_mac->EMAC_NSR & AT91C_EMAC_IDLE));
return TRUE;
}
/*---------------------------------------------------------------------------- */
/* \fn AT91F_EMACInit */
/* \brief This function initialise the ethernet */
/* \return Status ( Success = 0) */
/*---------------------------------------------------------------------------- */
int AT91F_EMACInit(unsigned int pRxTdList,unsigned int pTxTdList)
{
unsigned int tick = 0;
unsigned short status;
/* Wait for PHY auto negotiation completed
等待PHY自动诊听完成*/
at91_EmacEnableMDIO(p_mac);
do {
at91_EmacReadPhy(p_mac, AT91C_PHY_ADDR, DM9161_BMSR, &status);
at91_EmacReadPhy(p_mac, AT91C_PHY_ADDR, DM9161_BMSR, &status);
tick++;
}
while (!(status & DM9161_AUTONEG_COMP) && (tick < AT91C_ETH_TIMEOUT));
at91_EmacDisableMDIO(p_mac);
if (tick == AT91C_ETH_TIMEOUT)
{
my_printf ("-E- Autonegociation Timeout\n\r");
return 1;
} else
my_printf ("End of Autonegociation\n\r");/**/
/* the sequence write EMAC_SA1L and write EMAC_SA1H must be respected */
p_mac->EMAC_SA1L = (Macaddr[3]<<24) | (Macaddr[2]<<16)| (Macaddr[1]<<8)|Macaddr[0];
p_mac->EMAC_SA1H = (Macaddr[5]<<8)|(Macaddr[4]);
p_mac->EMAC_RBQP = pRxTdList;
p_mac->EMAC_TBQP = pTxTdList;
p_mac->EMAC_NCFGR |= (AT91C_EMAC_CAF | AT91C_EMAC_NBC );
p_mac->EMAC_NCFGR &= ~(AT91C_EMAC_CLK);
p_mac->EMAC_NCR |= (AT91C_EMAC_TE | AT91C_EMAC_RE);
return 0;
}
int board_eth_init ()
{
volatile unsigned int uStatus;
unsigned int val, i;
/* Init PIOs in peripheral mode */
AT91F_EMAC_Hardware_Init();
*AT91C_PMC_PCER = 1 << AT91C_ID_EMAC; /* Peripheral Clock Enable Register */
/* Disable Tx and Rx */
p_mac->EMAC_NCR = 0;
/* Clear statistics */
p_mac->EMAC_NCR = AT91C_EMAC_CLRSTAT;
uStatus = p_mac->EMAC_ISR;
p_mac->EMAC_TSR = 0xFFFFFFFF;
p_mac->EMAC_RSR = 0xFFFFFFFF;
/* We don't use interrupts. disable them */
p_mac->EMAC_IDR = 0xFFFFFFFF;
/* Enable EMAC in MII mode and enable MII Clock (25MHz) */
p_mac->EMAC_USRIO = AT91C_EMAC_CLKEN;
#ifdef CONFIG_AT91C_USE_RMII
p_mac->EMAC_USRIO |= AT91C_EMAC_RMII;
#endif
/* Set MDIO clock */
p_mac->EMAC_NCFGR |= AT91C_EMAC_CLK_HCLK_64;
/* Init Ethernet buffers */
RxBuffIndex = 0;
TxBuffIndex = 0;
/* Initialise RxtdList descriptor */
for (i = 0; i < RBF_FRAMEMAX; ++i) {
val = (unsigned int)(&rbf_framebuf[0]);
RxtdList.addr = val & 0xFFFFFFF8;
RxtdList.U_Status.status = 0;
}
/* Set the WRAP bit at the end of the list descriptor */
RxtdList[RBF_FRAMEMAX-1].addr |= RBF_WRAP;
/* Initialise TxtdList descriptor */
for (i = 0; i < TBF_FRAMEMAX; ++i) {
val = (unsigned int)(&tbf_framebuf[0]);
TxtdList.addr = val & 0xFFFFFFF8;
TxtdList.U_Status.status = 0;
TxtdList.U_Status.S_Status.BuffUsed = 1;
}
TxtdList[0].U_Status.S_Status.BuffUsed = 0;
/* Set the WRAP bit at the end of the list descriptor */
TxtdList[TBF_FRAMEMAX-1].U_Status.S_Status.Wrap = 1;
at91_GetPhyInterface (&PhyOps);
/* Phy Software Reset */
if (!PhyOps.Reset(p_mac))
{
my_printf ("PHY not reset!!\n\r");
return 0;
}
if (!PhyOps.IsPhyConnected (p_mac))
{
my_printf ("PHY not connected!!\n\r");
return 0;
}
/* MII management start from here */
if (!(PhyOps.Init (p_mac)))
{
my_printf ("MAC: error during RMII initialization\n");
return 0;
}
if (AT91F_EMACInit((unsigned int)RxtdList, (unsigned int)TxtdList))
return 0;
// rx_pkt_tmp = stage_rx_buffer;
return 0;
}
// 返回0:成功
// 返回非0:失败
unsigned int txStatusFlag;
unsigned int collisions;
unsigned int tx_exausts;
unsigned int tx_errors;
unsigned int tx_underruns;
unsigned int tx_comp1,tx_comp2;
unsigned int tsr;
int board_eth_send (unsigned char *packet, unsigned int length)
{
int tick=60000;
tsr = p_mac->EMAC_TSR;
if (tsr & AT91C_EMAC_COMP)
{
txStatusFlag = AT91C_EMAC_COMP;
// A frame transmitted
// Check RLE
if (tsr & AT91C_EMAC_RLES) {
txStatusFlag |= AT91C_EMAC_RLES;
tx_errors++;
}
// Check COL
if (tsr & AT91C_EMAC_COL) {
txStatusFlag |= AT91C_EMAC_COL;
collisions++;
}
// Check BEX
if (tsr & AT91C_EMAC_BEX) {
txStatusFlag |= AT91C_EMAC_BEX;
tx_exausts++;
}
// Check UND
if (tsr & AT91C_EMAC_UND) {
txStatusFlag |= AT91C_EMAC_UND;
tx_underruns++;
}
// Clear status
p_mac->EMAC_TSR |= txStatusFlag;
}
tx_comp1 ++;
if ((TxtdList[TxBuffIndex].U_Status.S_Status.BuffUsed == 0))
{
TxtdList[TxBuffIndex].addr = (unsigned int)packet;
TxtdList[TxBuffIndex].U_Status.S_Status.Length = length;
TxtdList[TxBuffIndex].U_Status.S_Status.LastBuff = 1;
}
else
return 2;
p_mac->EMAC_NCR |= AT91C_EMAC_TSTART;
while (!(p_mac->EMAC_TSR & AT91C_EMAC_COMP) && tick--);/*1表示一帧已发送完*/
//while (!(p_mac->EMAC_TSR & AT91C_EMAC_COMP));/*1表示一帧已发送完*/
//tx_comp3 ++;
if(tick!=0)
{
p_mac->EMAC_TSR |= AT91C_EMAC_COMP;/*写1清零该位*/
TxtdList[TxBuffIndex].U_Status.S_Status.Length = 0;
TxtdList[TxBuffIndex].U_Status.S_Status.LastBuff = 0;
if (TxBuffIndex == (TBF_FRAMEMAX - 1))
TxBuffIndex = 0;
else
TxBuffIndex ++;
TxtdList[TxBuffIndex].U_Status.S_Status.BuffUsed = 0;
if (p_mac->EMAC_TSR & AT91C_EMAC_UBR)
p_mac->EMAC_TSR |= AT91C_EMAC_UBR;
return 0;
}
else
{
return 2;
}
}
// 返回0:成功
// 返回1:失败
int board_eth_rcv (unsigned char *pFrame,unsigned int *Rcvsize )
{
int rc = 1;
unsigned char *temp_frame;
//unsigned int ret_len;
int i;
while ((RxtdList[RxBuffIndex].addr & RBF_OWNER)) /*若为零 ,没有数据*/
{
if (RxtdList[RxBuffIndex].U_Status.S_Status.StartOfFrame == 1)/*判断是否是起始帧*/
{
temp_frame = pFrame;
}
memcpy1((uchar *)temp_frame, (uchar *)(RxtdList[RxBuffIndex].addr & RBF_ADDR), RBF_FRAMELEN);
temp_frame += RBF_FRAMELEN;
if (RxtdList[RxBuffIndex].U_Status.S_Status.EndOfFrame == 1)/*最后一帧数据*/
{
*Rcvsize= RxtdList[RxBuffIndex].U_Status.S_Status.Length;
if (p_mac->EMAC_RSR & AT91C_EMAC_REC)/*至少一帧写入到存储器*/
p_mac->EMAC_RSR |= AT91C_EMAC_REC;/*写1清除该位*/
RxtdList[RxBuffIndex].U_Status.status = 0;
RxtdList[RxBuffIndex].addr &= ~RBF_OWNER;
if (RxtdList[RxBuffIndex].addr & RBF_WRAP)
RxBuffIndex = 0;
else
RxBuffIndex++;
rc=0;
for(i=0;i<6000;i++);//若100M通讯,可以适当减小
return rc;
}
for(i=0;i<6000;i++);//若100M通讯,可以适当减小
RxtdList[RxBuffIndex].U_Status.status = 0;
RxtdList[RxBuffIndex].addr &= ~RBF_OWNER;
if (RxtdList[RxBuffIndex].addr & RBF_WRAP)
RxBuffIndex = 0;
else
RxBuffIndex++;
}
return rc;
}
void eth_halt (void)
{
;
}
int board_eth_get_addr(unsigned char *addr)
{
memcpy1(addr, Macaddr, ETH_ALEN);
return 0;
}
int board_eth_lnk_stat(void)
{
return 0;
}
dm9161的驱动
file:///root/Desktop/%E5%88%B0%20wang%20%E7%9A%84%E9%93%BE%E6%8E%A5/linux%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/EtherNet/dm9161.c
file:///root/Desktop/%E5%88%B0%20wang%20%E7%9A%84%E9%93%BE%E6%8E%A5/linux%E7%BD%91%E7%BB%9C%E7%BC%96%E7%A8%8B/EtherNet/dm9161.h
求高手指教 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
|