搜索
bottom↓
回复: 1

基于atsam9260处理器linux2.6下的EMAC驱动程序,网卡芯片为DM9161

[复制链接]

出0入0汤圆

发表于 2011-1-8 18:15:13 | 显示全部楼层 |阅读模式
这是我在网上找一些程序,看不懂什么意思
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周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-8-26 02:12

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表