📄 at91emacend.c
字号:
#define EMAC_END_DBG_HASH 0x0080
#define EMAC_END_DBG_ERR 0x8000
int at91EmacEndDebug = EMAC_END_DBG_ERR;
/* interrupt statistics */
int at91EmacEndIntCount = 0; /* amount of interrupts */
int at91EmacEndIntRCOM = 0; /* Receive Complete statistics */
int at91EmacEndIntTCOM = 0; /* Transmit Complete statistics */
int at91EmacEndIntTUND = 0; /* Tx Buffer underrun statistics */
int at91EmacEndIntRTRY = 0; /* Transmit Retry limit statistics */
int at91EmacEndIntRBNA = 0; /* Bufffer Not Avalaible statistics */
int at91EmacEndIntROVR = 0; /* RX overrun statistics */
/* send/receive stats */
int at91EmacEndNumSend = 0; /* Number of packet sent */
int at91EmacEndNumRecv = 0; /* Number of packet received */
int at91EmacEndNumTXRetry = 0; /* number of packet not queued in the driver */
/* watermarks */
int at91EmacEndMaxLoopRecv = 0; /* watermarks in receive loop (at91EmacEndHandleRcvInt()) */
#define EMAC_END_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) \
if (at91EmacEndDebug & FLG) \
logMsg(X0, X1, X2, X3, X4, X5, X6);
#define EMAC_END_LOG_DELAY(FLG) \
if (at91EmacEndDebug & FLG) \
taskDelay(sysClkRateGet()/10);
#define EMAC_END_PRINT(FLG,X) \
if (at91EmacEndDebug & FLG) printf X;
#else /*EMAC_END_DBG*/
#define EMAC_END_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
#define EMAC_END_LOG_DELAY(DBG_SW)
#define EMAC_END_PRINT(DBG_SW,X)
#endif /*EMAC_END_DBG*/
/* LOCALS */
/* forward static functions */
LOCAL void at91EmacEndReset (EMAC_END_DEVICE *pDrvCtrl);
LOCAL void at91EmacEndInt (EMAC_END_DEVICE *pDrvCtrl);
LOCAL void at91EmacEndHandleRcvInt (EMAC_END_DEVICE *pDrvCtrl);
LOCAL STATUS at91EmacEndRecv (EMAC_END_DEVICE *pDrvCtrl, char* pData, int len);
LOCAL void at91EmacEndConfig (EMAC_END_DEVICE *pDrvCtrl);
/* END Specific interfaces. */
/*
* Declare our function table. This is static across all device
* instances.
*/
LOCAL NET_FUNCS at91EmacEndFuncTable =
{
(FUNCPTR) at91EmacEndStart, /* Function to start the device. */
(FUNCPTR) at91EmacEndStop, /* Function to stop the device. */
(FUNCPTR) at91EmacEndUnload, /* Unloading function for the driver. */
(FUNCPTR) at91EmacEndIoctl, /* Ioctl function for the driver. */
(FUNCPTR) at91EmacEndSend, /* Send function for the driver. */
(FUNCPTR) at91EmacEndMCastAdd, /* Multicast add function for the driver. */
(FUNCPTR) at91EmacEndMCastDel, /* Multicast delete function for the driver. */
(FUNCPTR) at91EmacEndMCastGet, /* Multicast retrieve function for the driver. */
(FUNCPTR) at91EmacEndPollSend, /* Polling send function */
(FUNCPTR) at91EmacEndPollRcv, /* Polling receive function */
endEtherAddressForm, /* put address info into a NET_BUFFER */
endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */
endEtherPacketAddrGet /* Get packet addresses. */
};
/*******************************************************************************
*
* at91EmacEndLoad - initialize the driver and device
*
* This routine initializes the driver and the device to the operational state.
* All of the device specific parameters are passed in the initString.
*
* The string contains the target specific parameters like this:
*
* "register addr:int vector:int level:shmem addr:shmem size:shmem width"
*
* This routine can be called in two modes. If it is called with an empty but
* allocated string, it places the name of this device into the <initString>
* and returns 0.
*
* If the string is allocated and not empty, the routine attempts to load
* the driver using the values specified in the string.
*
* RETURNS: An END object pointer, or NULL on error, or 0 and the name of the
* device if the <initString> was empty.
*/
END_OBJ* at91EmacEndLoad
(
char* initString /* String to be parsed by the driver. */
)
{
EMAC_END_DEVICE *pDrvCtrl;
EMAC_END_LOG (EMAC_END_DBG_LOAD, "Loading at91EmacEnd...\n", 1, 2, 3, 4, 5, 6);
if (initString == NULL)
{
EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndLoad: NULL initStr\r\n",
0,0,0,0,0,0);
return NULL;
}
if (initString[0] == EOS)
{
bcopy ((char *)EMAC_END_DEV_NAME, initString, EMAC_END_DEV_LEN);
return NULL;
}
/* else initString is not blank, pass two ... */
/* allocate the device structure */
pDrvCtrl = (EMAC_END_DEVICE *)calloc (sizeof (EMAC_END_DEVICE), 1);
if (pDrvCtrl == NULL)
{
goto errorExit;
}
/* parse the init string, filling in the device structure */
if (at91EmacEndParse (pDrvCtrl, initString) == ERROR)
{
goto errorExit;
}
/* reset the device (ensure that the device is not enable when alloacting memory */
at91EmacEndReset (pDrvCtrl);
/* Perform memory allocation/distribution */
if (at91EmacEndMemInit (pDrvCtrl) == ERROR)
{
goto errorExit;
}
/* Ask the BSP for the ethernet address. */
SYS_ENET_ADDR_GET(pDrvCtrl);
/* set the MAC address - must write the low first */
EMAC_REG(EMAC_SA1L) = (pDrvCtrl->enetAddr[3] << 24) |
(pDrvCtrl->enetAddr[2] << 16) |
(pDrvCtrl->enetAddr[1] << 8) |
pDrvCtrl->enetAddr[0];
EMAC_REG(EMAC_SA1H) = (pDrvCtrl->enetAddr[5] << 8) | pDrvCtrl->enetAddr[4];
/* initialize the END and MIB2 parts of the structure */
if (END_OBJ_INIT (&pDrvCtrl->end, NULL, EMAC_END_DEV_NAME,
pDrvCtrl->unit, &at91EmacEndFuncTable,
"END AT91RM9200 EMAC Driver.") == ERROR
|| END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd,
&pDrvCtrl->enetAddr[0], 6, ETHERMTU,
END_SPEED)
== ERROR)
{
goto errorExit;
}
/* reconfigure the device */
at91EmacEndConfig (pDrvCtrl);
/* set the flags to indicate readiness */
END_OBJ_READY (&pDrvCtrl->end,
IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST);
EMAC_END_LOG (EMAC_END_DBG_LOAD, "Done loading EMAC...", 1, 2, 3, 4, 5, 6);
EMAC_END_LOG_DELAY(EMAC_END_DBG_LOAD);
return (&pDrvCtrl->end);
errorExit:
if (pDrvCtrl != NULL)
{
free ((char *)pDrvCtrl);
}
return NULL;
}
/*******************************************************************************
*
* at91EmacEndParse - parse the init string
*
* Parse the input string. Fill in values in the driver control structure.
*
* The muxLib.o module automatically prepends the unit number to the user's
* initialization string from the BSP (configNet.h).
*
* .IP <unit>
* Device unit number, a small integer.
* .IP <vecNum>
* Interrupt vector number
* .IP <intLvl>
* Interrupt level
* .IP <txNum>
* TX buffers
* .IP <rxNum>
* RX buffers
* .IP <userFlag>
* user flags
* .LP
*
* RETURNS: OK or ERROR for invalid arguments.
*/
LOCAL STATUS at91EmacEndParse
(
EMAC_END_DEVICE * pDrvCtrl, /* device pointer */
char * initString /* information string */
)
{
char* tok;
char* pHolder = NULL;
/* Parse the initString */
/* Unit number. (from muxLib.o) */
tok = strtok_r (initString, ":", &pHolder);
if (tok == NULL)
return ERROR;
pDrvCtrl->unit = atoi (tok);
/* Interrupt vector. */
tok = strtok_r (NULL, ":", &pHolder);
if (tok == NULL)
return ERROR;
pDrvCtrl->ivec = atoi (tok);
/* Interrupt level. */
tok = strtok_r (NULL, ":", &pHolder);
if (tok == NULL)
return ERROR;
/* Transmit buffer descriptor */
pDrvCtrl->ilevel = atoi (tok);
tok = strtok_r (NULL, ":", &pHolder);
if (tok == NULL)
return ERROR;
pDrvCtrl->txNum = atoi (tok);
/* Receive buffer descriptor */
tok = strtok_r (NULL, ":", &pHolder);
if (tok == NULL)
return ERROR;
pDrvCtrl->rxNum = atoi (tok);
/* user flags. */
tok = strtok_r (NULL, ":", &pHolder);
if (tok == NULL)
return ERROR;
pDrvCtrl->flags = strtoul (tok, NULL, 16);
if (!pDrvCtrl->txNum
|| pDrvCtrl->txNum < EMAC_END_TX_MIN || pDrvCtrl->txNum > EMAC_END_TX_MAX)
{
pDrvCtrl->txNum = EMAC_END_TX_DEF_NUM;
}
if (!pDrvCtrl->rxNum
|| pDrvCtrl->rxNum < EMAC_END_RX_MIN || pDrvCtrl->rxNum > EMAC_END_RX_MAX)
{
pDrvCtrl->rxNum = EMAC_END_RX_DEF_NUM;
}
#ifdef EMAC_RX_BUFFER_IN_SRAM
/*
* use internal SRAM for RX buffers and descriptors
* ensures that the receive descriptors start on a 64byte boundary
* (errata #11)
*/
pDrvCtrl->rxNum = NUM_RXBDS;
#endif /* EMAC_RX_BUFFER_IN_SRAM */
EMAC_END_LOG (EMAC_END_DBG_LOAD,
("at91EmacEndParse: unit=%d ivec=%d ilevel=%d txNum=%d rxNum=%d userFlags=0x%x\n"),
pDrvCtrl->unit,
pDrvCtrl->ivec,
pDrvCtrl->ilevel,
pDrvCtrl->txNum,
pDrvCtrl->rxNum,
pDrvCtrl->flags);
EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndParse: Processed all arugments\n", 1, 2, 3, 4, 5, 6);
return OK;
}
/*******************************************************************************
*
* at91EmacEndMemInit - initialize memory for the chip
*
* This routine is highly specific to the device.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS at91EmacEndMemInit
(
EMAC_END_DEVICE * pDrvCtrl /* device to be initialized */
)
{
int i;
if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL)
{
EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndMemInit: Could not allocate pNetPool\n", 1, 2, 3, 4, 5, 6);
return (ERROR);
}
/* number of driver Descriptor/data buffers */
at91EmacEndClDescTbl[0].clNum = pDrvCtrl->rxNum + EMAC_END_LOAN_NUM;
/* Setup mbuf/cluster block pool with more mbufs than clBlks */
at91EmacEndMclBlkConfig.clBlkNum = at91EmacEndClDescTbl[0].clNum;
at91EmacEndMclBlkConfig.mBlkNum = at91EmacEndMclBlkConfig.clBlkNum * 4;
/* Calculate the total memory for all the M-Blks and CL-Blks. */
at91EmacEndMclBlkConfig.memSize = (at91EmacEndMclBlkConfig.mBlkNum *
(MSIZE + sizeof (long))) +
(at91EmacEndMclBlkConfig.clBlkNum *
(CL_BLK_SZ + sizeof(long)));
/* allocate mbuf/Cluster blocks from normal memory */
if ((at91EmacEndMclBlkConfig.memArea = (char *) memalign (sizeof(long), at91EmacEndMclBlkConfig.memSize)) == NULL)
{
EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndMemInit: Could not allocate memArea\n", 1, 2, 3, 4, 5, 6);
return (ERROR);
}
/* Round cluster size up to a multiple of a cache line */
at91EmacEndClDescTbl[0].clSize = ROUND_UP(at91EmacEndClDescTbl[0].clSize,_CACHE_ALIGN_SIZE);
/* Calculate the memory size of all the clusters (including overhead). */
at91EmacEndClDescTbl[0].memSize = (at91EmacEndClDescTbl[0].clNum
* (at91EmacEndClDescTbl[0].clSize + CL_OVERHEAD));
/* Allocate the memory for the clusters from cache safe memory. */
at91EmacEndClDescTbl[0].memArea = (char *) cacheDmaMalloc (at91EmacEndClDescTbl[0].memSize);
/* cacheDmaMalloc memory is assumed to be cache line aligned ! */
/* use cacheDmaFuncs for cacheDmaMalloc memory */
pDrvCtrl->pCacheFuncs = &cacheDmaFuncs;
if (at91EmacEndClDescTbl[0].memArea == NULL)
{
EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndMemInit: system memory unavailable\n", 1, 2, 3, 4, 5, 6);
return (ERROR);
}
/* Initialize the memory pool. */
if (netPoolInit(pDrvCtrl->end.pNetPool, &at91EmacEndMclBlkConfig,
&at91EmacEndClDescTbl[0], at91EmacEndClDescTblNumEnt, NULL) == ERROR)
{
EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndMemInit: Could not init buffering\n", 1, 2, 3, 4, 5, 6);
return (ERROR);
}
if ((pDrvCtrl->pClPoolId = netClPoolIdGet (pDrvCtrl->end.pNetPool, EMAC_END_MAX_CL_LEN, FALSE)) == NULL)
{
EMAC_END_LOG (EMAC_END_DBG_LOAD, "at91EmacEndMemInit: Could not get cluster pool ID\n", 1, 2, 3, 4, 5, 6);
return (ERROR);
}
/*
* Tx buffer and descriptors (virtual descriptor for queuing send request)
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -