📄 at91eth.c
字号:
/* at91Eth.c - AT91RM9200 Ethernet controller driver */#include "vxWorks.h"#include "intLib.h"#include "netLib.h"#include "end.h"#include "endLib.h"#include "cacheLib.h"#include "miiLib.h"#include "errno.h"#include "stdio.h"#include "logLib.h"#include "taskLib.h"#include "config.h"#include "drv/intrCtl/at91Intr.h"#include "at91_ether.h"#define DRV_DEBUG_RX 0x0001#define DRV_DEBUG_TX 0x0002#define END_CACHE_PHYS_TO_VIRT(x) x#undef DEBUG_TRACE#define RX_WAIT_MAX (CPLL_FREQ * 1000) /* Rx completion timeout */#define TX_WAIT_MAX (CPLL_FREQ * 1000) /* Tx completion timeout */#define MII_WAIT_MAX (CPLL_FREQ * 1000) /* max delay for the MII operation */#ifndef NSDELAY#define NSDELAY(nsec) \{ \ volatile int nx; \ volatile int loop = (int)(((CPLL_FREQ * nsec) / 1000) + 1); \ \ for (nx=0; nx<loop; nx++); \}#endif /* NSDELAY *//* External */IMPORT STATUS sysSecEnetAddrGet(int unit, UCHAR* address);static int unit = 0;/* Forward Function Declarations */LOCAL STATUS at91EthAnRestart(ETH_DRV_CTRL *dev);LOCAL void at91EthRxHandler(ETH_DRV_CTRL *dev);LOCAL void at91EthTxHandler(ETH_DRV_CTRL *dev);#ifdef DEBUG_TRACELOCAL void at91EthHexDump(UCHAR *p, ULONG l);#endif /* DEBUG_TRACE */#include "at91_ether.c"LOCAL void at91EthMiiRead(ETH_DRV_CTRL* dev, unsigned char phy_addr, unsigned char address, unsigned short *value){ unsigned int l; read_phy(dev->base_addr, phy_addr,address, &l); *value = (unsigned short) l;}LOCAL void at91EthMiiWrite(ETH_DRV_CTRL* dev, unsigned char phy_addr, unsigned char address, unsigned short value){ unsigned int l=value; write_phy(dev->base_addr, phy_addr,address, l); }/********************************************************************************* at91EthInit - initialize S3C2510 Ethernet controller** RETURNS: OK, or ERROR.*/STATUS at91EthInit( ETH_DRV_CTRL *dev ){ at91ether_probe(dev); /* Initialize flags. */ dev->bPolling = FALSE; dev->bTxBlocked = FALSE; dev->bRxHandler = FALSE; dev->bTxHandler = FALSE; return OK;}/********************************************************************************* at91EthAnRestart - restart auto negotiation** RETURNS: OK, or ERROR.*/STATUS at91EthAnRestart( ETH_DRV_CTRL *dev ){ UINT16 phyAddr = dev->phyInfo.phyAddr; int timeout = MII_WAIT_MAX; /* Perserve selector. */ dev->PHYREGS.phyAds &= MII_ADS_SEL_MASK; /* Set appropriate options. */ dev->PHYREGS.phyAds |=#ifdef ETH_10BT MII_TECH_10BASE_T | /* 10T half-duplex capable */#endif /* ETH_10BT */#ifdef ETH_FULL_DUPLEX MII_TECH_100BASE_TX_FD | /* 100TX-FX full-duplex capable */#ifdef ETH_10BT MII_TECH_10BASE_FD | /* 10T full-duplex capable */#endif /* ETH_10BT */#endif /* ETH_FULL_DUPLEX */ MII_TECH_100BASE_TX; /* 100TX-FX half-duplex capable */ /* Initialize Auto Negotiation Advertisement Register. */ at91EthMiiWrite(dev, phyAddr, MII_AN_ADS_REG, dev->PHYREGS.phyAds); /* Enable and Start Auto Negotiation. */ dev->PHYREGS.phyCtrl |= MII_CR_AUTO_EN | /* Auto-Negotiation Enable */ MII_CR_RESTART; /* Restart Auto Negotiation */ /* Start auto negotiation. */ at91EthMiiWrite(dev, phyAddr, MII_CTRL_REG, dev->PHYREGS.phyCtrl); /* Wait until start auto negotiation. */ while (1) { at91EthMiiRead(dev, phyAddr, MII_CTRL_REG, &dev->PHYREGS.phyCtrl); if (!(dev->PHYREGS.phyCtrl & MII_CR_RESTART)) { break; } } /* Wait until complete auto negotiation. */ while (1) { at91EthMiiRead(dev, phyAddr, MII_STAT_REG, &dev->PHYREGS.phyStatus); if (dev->PHYREGS.phyStatus & MII_SR_AUTO_NEG) { break; } if (--timeout == 0) { printf("eth%d Error: MII auto negotiation timeout\n", dev->unit); return ERROR; } } return OK;}/********************************************************************************* at91EthFlagsSet - set device flags** RETURNS: OK, or ERROR.*/STATUS at91EthFlagsSet( ETH_DRV_CTRL *dev ){ long flags;#ifdef DEBUG_TRACE printf("eth%d FlagsSet, %08X\n", unit, (UINT32)dev->endObj.flags);#endif /* DEBUG_TRACE */ flags = END_FLAGS_GET(&dev->endObj); if (flags & IFF_UP) { /* Config down. */ END_FLAGS_CLR(&dev->endObj, IFF_UP | IFF_RUNNING); } dev->flags = flags; at91ether_set_rx_mode(dev); if (flags & IFF_UP) { /* Config up. */ END_FLAGS_SET(&dev->endObj, IFF_UP | IFF_RUNNING); } return OK;}/********************************************************************************* at91EthLoopSet - set loop mode** RETURNS: OK, or ERROR.*/void at91EthLoopSet( ETH_DRV_CTRL *dev, int mode ){}/********************************************************************************* at91EthMCastAdd - add multicast address** RETURNS: OK, or ERROR.*/ STATUS at91EthMCastAdd( ETH_DRV_CTRL *dev, UCHAR *pAddr ){ unsigned char mc_filter[2]; AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; unsigned int i, bitnr; mc_filter[0] = mc_filter[1] = 0; bitnr = ether_crc(ETH_ALEN, pAddr) >> 26; mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); regs->EMAC_HSH |= mc_filter[1]; regs->EMAC_HSL |= mc_filter[0]; return ERROR;}/********************************************************************************* at91EthMCastDel - remove multicast address** RETURNS: OK, or ERROR.*/STATUS at91EthMCastDel( ETH_DRV_CTRL *dev, /* pointer to driver structure */ UCHAR *pAddr /* pointer to the multicast address */ ){ unsigned char mc_filter[2]; unsigned int i, bitnr;AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; mc_filter[0] = mc_filter[1] = 0; bitnr = ether_crc(ETH_ALEN, pAddr) >> 26; mc_filter[bitnr >> 5] |= 1 << (bitnr & 31); regs->EMAC_HSH &= ~mc_filter[1]; regs->EMAC_HSL &= ~mc_filter[0]; return ERROR;}/********************************************************************************* at91EthStart - start S3C2510 Ethernet controller** RETURNS: OK, or ERROR.*/STATUS at91EthStart( ETH_DRV_CTRL *dev /* pointer to driver structure */ ){ return at91ether_open(dev); return OK;}/********************************************************************************* at91EthStop - stop S3C2510 Ethernet controller** RETURNS: OK, or ERROR.*/STATUS at91EthStop( ETH_DRV_CTRL *dev /* pointer to driver structure */ ){ return at91ether_close(dev); return OK;}/********************************************************************************* at91EthPlllStart - start polling mode** RETURNS: OK, or ERROR.*/STATUS at91EthPollStart( ETH_DRV_CTRL *dev /* pointer to driver structure */ ){ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;#ifdef DEBUG_TRACE printf("eth%d PollStart\n", unit);#endif /* DEBUG_TRACE */ /* Disable interrupt. */ intDisable(dev->irq); regs->EMAC_IDR = AT91C_EMAC_RCOM | AT91C_EMAC_TCOM ; dev->bPolling = TRUE; return OK;}/********************************************************************************* at91EthPollStop - stop polling mode** RETURNS: OK, or ERROR.*/STATUS at91EthPollStop( ETH_DRV_CTRL *dev /* pointer to driver structure */ ){ /* int unit = dev->unit;*/ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr;#ifdef DEBUG_TRACE printf("eth%d PollStop\n", unit);#endif /* DEBUG_TRACE */ regs->EMAC_IER = AT91C_EMAC_RCOM | AT91C_EMAC_TCOM ; dev->bPolling = FALSE; /* Enable interrupt. */ intEnable(dev->irq); return OK;}/********************************************************************************* at91EthRbdFree - free RBD** RETURNS: N/A.*/void at91EthRbdFree( ETH_DRV_CTRL *dev, /* pointer to driver structure */ PETHRBD pRbd /* pointer to the RBD to be freed */ ){ struct at91_private *lp = (struct at91_private *) dev->priv;#ifdef DEBUG_TRACE printf("eth%d RbdFree\n", dev->unit);#endif /* DEBUG_TRACE */ pRbd->descriptors[lp->rxBuffIndex].addr &= ~EMAC_DESC_DONE; /* reset ownership bit */ if (lp->rxBuffIndex == MAX_RX_DESCR-1) /* wrap after last buffer */ lp->rxBuffIndex = 0; else lp->rxBuffIndex++; }/* ** at91EthRbdCheck - check RBD** RETURNS: length of frame received.*/ULONG at91EthRbdCheck( ETH_DRV_CTRL *dev, /* pointer to driver structure */ PETHRBD pRbd /* pointer to the RBD to be checked */ ){ int length = pRbd->descriptors[dev->priv->rxBuffIndex].size & 0x7ff; return (length);}/********************************************************************************* at91EthTbdGet - allocate TBD** RETURNS: pointer to the TBD.*/unsigned char* at91EthTbdGet( ETH_DRV_CTRL *dev /* pointer to driver structure */ ){ AT91PS_EMAC regs = (AT91PS_EMAC) dev->base_addr; char *pBuf=0;#ifdef DEBUG_TRACE printf("eth%d TbdGet\n", dev->unit);#endif /* DEBUG_TRACE */ /* Get the first available TBD. *//* pTbd = (PETHTBD)(dev->tbdBase + dev->tbdFree * SIZE_BD);*//* if (dev->pClPool) */ { if (!(regs->EMAC_TSR & AT91C_EMAC_BNQ)) { return NULL; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -