📄 at91emacend.c
字号:
/* at91End.c - SNDS END network interface driver for Ethernet */
/* Copyright 1984-1997 Wind River Systems, Inc. */
#include "copyright_wrs.h"
/*
modification history
--------------------
*/
/*
DESCRIPTION
*/
/* includes */
#include "vxWorks.h"
#include "etherMultiLib.h" /* multicast stuff. */
#include "end.h" /* Common END structures. */
#include "endLib.h"
#include "lstLib.h" /* Needed to maintain protocol list. */
#include "cacheLib.h"
#include "stdlib.h"
#include "stdio.h"
#include "intLib.h"
#include "iv.h"
#include "netLib.h"
#include "config.h"
#if defined(CPU_920T)
#include "arch/arm/mmuArmLib.h"
#include "private/vmLibP.h"
/*#include "dllLib.h"*/
#endif /* defined(720T/740T/920T/940T/946ES) */
/* defines */
/* Configuration items */
#define ENET_HDR_REAL_SIZ 14
#define END_BUFSIZ ( ETHERMTU + ENET_HDR_REAL_SIZ + 8 )
#define END_SPEED 10000000
#define AT91END_CL_SIZE ( ETHERMTU + ENET_HDR_REAL_SIZ + 8 )
#define END_MBLK_NUM 256
#define END_CL_NUM (END_MBLK_NUM/2)
#define RX_FD_NUM 32
#define TX_FD_NUM 32
#define LS_POLLING 0x20
#define AT91EMAC_MAX_MULTI 3
/*
* Default macro definitions for BSP interface.
* These macros can be redefined in a wrapper file, to generate
* a new module with an optimized interface.
*/
/* Macro to connect interrupt handler to vector */
/* Macro to get the ethernet address from the BSP */
unsigned char at91EndEnetAddr[6] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
#ifndef SYS_ENET_ADDR_GET
# define SYS_ENET_ADDR_GET(pDevice) \
{ \
bcopy ((char *)at91EndEnetAddr, (char *)(&pDevice->enetAddr), 6); \
}
#endif
/*
* Macros to do a short (UINT16) access to the chip. Default
* assumes a normal memory mapped device.
*/
/*A shortcut for getting the hardware address from the MIB II stuff. */
#define END_HADDR(pEnd) \
((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)
#define END_HADDR_LEN(pEnd) \
((pEnd)->mib2Tbl.ifPhysAddress.addrLength)
/* typedefs */
typedef struct _AT91_END_RECV_FD
{
UINT32 bufaddr;
UINT32 recvstatus;
}AT91_END_RECV_FD;
struct _AT91_END_TRAN_FD;
typedef struct _AT91_END_TRAN_FD
{
char* bufaddr;
UINT32 len;
UINT32 owner;
}AT91_END_TRAN_FD;
typedef struct etherStatistics
{
UINT32 ESTAT_FRA;
UINT32 ESTAT_SCOL;
UINT32 ESTAT_MCOL;
UINT32 ESTAT_OK;
UINT32 ESTAT_SEQE;
UINT32 ESTAT_ALE;
UINT32 ESTAT_DTE;
UINT32 ESTAT_LCOL;
UINT32 ESTAT_ECOL;
UINT32 ESTAT_CSE;
UINT32 ESTAT_TUE;
UINT32 ESTAT_CDE;
UINT32 ESTAT_ELR;
UINT32 ESTAT_RJB;
UINT32 ESTAT_USF;
UINT32 ESTAT_SQEE;
UINT32 ESTAT_DRFC;
} ETHER_STATISTICS;
#define TXFIFOEMPTY 1
#define TXFIFOFULL 2
#define TXFIFONORMAL 3
/* The definition of the driver control structure */
/*
* for addrListLow and addrListHigh:
* ETH addr = E0 E1 E2 E3 E4 E5
* addrListLow( in byte address order ) = E3 E2 E1 E0
* addrListHigh( in byte address order ) = E5 E4
* so we can use htol and htos to convert the ETH address
*/
typedef struct _at91end_device
{
END_OBJ end; /* The class we inherit from. */
int unit; /* unit number */
int level; /* bdmaTx interrupt vector */
long flags; /* Our local flags. */
CL_POOL_ID pClPoolId;
UCHAR* clPointBuf[ RX_FD_NUM ];
UCHAR* TranFifoBuf;
UCHAR* RecvFifoBuf;
UINT32 TranPkgNumber;
UINT32 TranPkgSize;
AT91_END_TRAN_FD pTxBufStart[TX_FD_NUM];
UINT32 TxPtr; /* point to desc sending */
UINT32 TxTailPtr; /* point to desc may writing */
UINT32 TXFifoStat;
UINT32 NetJobDoing;
AT91_END_RECV_FD* RecvBufDesc;
UINT32 rxBufPtr;
UCHAR enetAddr[6]; /* ethernet address */
UCHAR netSpeed; /* 10 or 100 */
UCHAR duplexMode; /* HDX = 0. FDX = 1 */
UCHAR autoNeg; /* 1 = autoneg enabled */
BOOL fdInitialized; /* Set to TRUE after FD allocation */
ETHER_STATISTICS statistics; /* Ethernet statistics counters */
UINT32 addrListHigh[(AT91EMAC_MAX_MULTI+1)]; /* Array for storing addresses Max = 4, i.e. 32 long words */
UINT32 addrListLow[(AT91EMAC_MAX_MULTI+1)]; /* Array for storing addresses Max = 4, i.e. 32 long words */
UINT32 mcastAddrCount; /* Number of valid multicast addresses */
} at91end_device;
/* globals*/
/*
* This will only work if there is only a single unit, for multiple
* unit device drivers these should be integrated into the at91end_device
* structure.
*/
M_CL_CONFIG at91endMclConfig = /* network mbuf configuration table */
{
/*
no. mBlks no. clBlks memArea memSize
----------- ---------- ------- -------
*/
0, 0, NULL, 0
};
CL_DESC at91endClDescTbl [] = /* network cluster pool configuration table */
{
/*
clusterSize num memArea memSize
----------- ---- ------- -------
*/
{AT91END_CL_SIZE, 0, NULL, 0}
};
int endClDescTblNumEnt = (NELEMENTS(at91endClDescTbl));
/* new additions */
/* Definitions for the flags field */
#define END_PROMISCUOUS_FLAG 0x1
#define END_RCV_HANDLING_FLAG 0x2
/* DEBUG MACROS */
#undef END_DEBUG
/*
#define END_DEBUG
*/
#ifdef END_DEBUG
#include "LogLib.h" /* Needed to debug polled mode. */
int endDebug = 1;
#define ENDLOGMSG(x) \
if (endDebug) \
{ \
logMsg x;\
}
#else
#define ENDLOGMSG(x)
#endif /* END_DEBUG */
/* LOCALS */
#ifdef INCLUDE_AT91EMAC_END
/* forward static functions */
LOCAL void at91EmacReset (at91end_device *pDrvCtrl); /**/
LOCAL void at91EndInt (at91end_device *pDrvCtrl); /**/
LOCAL void at91EndMacInitialize (at91end_device *pDevice); /**/
LOCAL STATUS at91EndFdInitialize (at91end_device *pDrvCrtl); /**/
LOCAL void at91EndFdFree (at91end_device *pDrvCtrl); /**/
LOCAL void at91EndHandleRcvInt (at91end_device *pDrvCtrl, UINT32 stat);/**/
LOCAL STATUS at91EndRecv (at91end_device *pDrvCtrl, UINT32 recvdescptr );/**/
LOCAL void at91EndConfig (at91end_device *pDrvCtrl);/**/
LOCAL UINT32 at91EndPhyRead (UINT32 phyRegAddr, UINT32 phyAddr);/**/
LOCAL void at91EndPhyWrite (UINT32 phyRegAddr, UINT32 phyAddr, UINT32 phyData);/**/
LOCAL void at91EndAddrFilterSet (at91end_device *pDrvCtrl);/**/
/* END Specific interfaces. */
/* This is the only externally visible interface. */
END_OBJ* at91EndLoad (char* initString);
LOCAL STATUS at91EndStart (at91end_device* pDrvCtrl);/**/
LOCAL STATUS at91EndStop (at91end_device* pDrvCtrl);/**/
LOCAL STATUS at91EndUnload ();/**/
LOCAL int at91EndIoctl (at91end_device* pDrvCtrl, int cmd, caddr_t data);
LOCAL STATUS at91EndSend (at91end_device* pDrvCtrl, M_BLK_ID pBuf);/**/
LOCAL STATUS at91EndMCastAdd (at91end_device* pDrvCtrl, char* pAddress);/**/
LOCAL STATUS at91EndMCastDel (at91end_device* pDrvCtrl, char* pAddress);/**/
LOCAL STATUS at91EndMCastGet (at91end_device* pDrvCtrl, MULTI_TABLE* pTable);/**/
LOCAL STATUS at91EndPollSend (at91end_device* pDrvCtrl, M_BLK_ID pBuf);/**/
LOCAL STATUS at91EndPollRcv (at91end_device* pDrvCtrl, M_BLK_ID pBuf);/**/
LOCAL STATUS at91EndPollStart (at91end_device* pDrvCtrl);/**/
LOCAL STATUS at91EndPollStop (at91end_device* pDrvCtrl);/**/
LOCAL STATUS at91EndParse ();/*---*/
LOCAL STATUS at91EndMemInit ();/*---*/
LOCAL void FreeEndMemory( at91end_device* pDrvCtrl );
/*
* Declare our function table. This is static across all driver
* instances.
*/
LOCAL NET_FUNCS at91endFuncTable =
{
(STATUS (*) (END_OBJ*))at91EndStart, /* Function to start the device. */
(STATUS (*) (END_OBJ*))at91EndStop, /* Function to stop the device. */
(STATUS (*) (END_OBJ*))at91EndUnload, /* Unloading function for the driver. */
(int (*) (END_OBJ*, int, caddr_t))at91EndIoctl, /* Ioctl function for the driver. */
(STATUS (*) (END_OBJ* , M_BLK_ID))at91EndSend, /* Send function for the driver. */
(STATUS (*) (END_OBJ*, char*))at91EndMCastAdd, /* Multicast address add function for the driver. */
(STATUS (*) (END_OBJ*, char*))at91EndMCastDel, /* Multicast address delete function for the driver. */
(STATUS (*) (END_OBJ*, MULTI_TABLE*))at91EndMCastGet, /* Multicast table retrieve function for the driver. */
(STATUS (*) (END_OBJ*, M_BLK_ID))at91EndPollSend, /* Polling send function for the driver. */
(STATUS (*) (END_OBJ*, M_BLK_ID))at91EndPollRcv, /* Polling receive function for the driver. */
endEtherAddressForm, /* Put address info into a packet. */
endEtherPacketDataGet, /* Get a pointer to packet data. */
endEtherPacketAddrGet /* Get packet addresses. */
};
/*******************************************************************************
*
* at91EndLoad - 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:
*
* "<unit>:<Speed>:<duplex>:<autoneg>"
*
* RETURNS: An END object pointer or NULL on error.
*/
END_OBJ* at91EndLoad
(
char* initString /* String to be parsed by the driver. */
)
{
at91end_device *pDrvCtrl;
ENDLOGMSG (("Loading at91EndEnd...\n", 1, 2, 3, 4, 5, 6));
if ( initString[0] == 0 )
{
strcpy (initString, "atemac");
return (END_OBJ *)NULL;
}
/* allocate the device structure */
pDrvCtrl = (at91end_device *)calloc (sizeof (at91end_device), 1);
if ( pDrvCtrl == NULL )
goto errorExit;
bzero( (void*)pDrvCtrl, sizeof (at91end_device) );
pDrvCtrl ->TXFifoStat = TXFIFOEMPTY;
/* parse the init string, filling in the device structure */
if ( at91EndParse ( pDrvCtrl, initString ) == ERROR )
goto errorExit;
pDrvCtrl->level = INT_LVL_EMAC;
/* Ask the BSP to provide the ethernet address. */
SYS_ENET_ADDR_GET( pDrvCtrl );
/* initialize the END and MIB2 parts of the structure */
strcpy (pDrvCtrl->end.devObject.name, "atemac");
strcpy (pDrvCtrl->end.devObject.description, "AT91RM9200 EMAC END Driver");
/*
* The M2 element must come from m2Lib.h
* This at91End is set up for a DIX type ethernet device.
*/
if ( END_OBJ_INIT ( &pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, "atemac",
pDrvCtrl->unit, &at91endFuncTable,
"AT91RM9200 EMAC END Driver" ) == ERROR
|| END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd,
&pDrvCtrl->enetAddr[0], 6, ETHERMTU,
END_SPEED) == ERROR )
goto errorExit;
/* Perform memory allocation/distribution */
if ( at91EndMemInit (pDrvCtrl) == ERROR )
goto errorExit;
/* reset and reconfigure the device */
at91EndConfig (pDrvCtrl);
/* set the flags to indicate readiness */
END_OBJ_READY ( &pDrvCtrl->end, IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST );
ENDLOGMSG (("Loading at91EndEnd success EXIT...\n", 1, 2, 3, 4, 5, 6));
return ( &pDrvCtrl->end );
errorExit:
if ( pDrvCtrl != NULL )
{
FreeEndMemory( pDrvCtrl );
pDrvCtrl = NULL;
}
ENDLOGMSG (("Loading at91EndEnd Failure EXIT...\n", 1, 2, 3, 4, 5, 6));
return NULL;
}
/*******************************************************************************
*
* at91EndParse - parse the init string
*
* Parse the input string. Fill in values in the driver control structure.
*
* The initialization string format is:
* "<unit>:<Speed>:<duplex>:<autoneg>"
*
* .bS
* unit Device unit number, a small integer.
* Speed 10 (10Mbps) or 100 (100 Mbps)
* duplex 0 (HDX) or 1 (FDX)
* autoneg Autonegotiation disabled (0) or enabled (1)
* .bE
*
* RETURNS: OK or ERROR for invalid arguments.
*/
STATUS at91EndParse
(
at91end_device * pDrvCtrl, /* device pointer */
char * initString /* information string */
)
{
char* tok;
char* pHolder = NULL;
/* Parse the initString */
/* Unit number. */
tok = strtok_r (initString, ":", &pHolder);
if (tok == NULL)
return ERROR;
pDrvCtrl->unit = atoi (tok);
/* netSpeed */
tok = strtok_r (NULL, ":", &pHolder);
if (tok == NULL)
return ERROR;
pDrvCtrl->netSpeed = atoi (tok);
/* DuplexMode */
tok = strtok_r (NULL, ":", &pHolder);
if (tok == NULL)
return ERROR;
pDrvCtrl->duplexMode = atoi (tok);
/* auto Negotiation */
tok = strtok_r (NULL, ":", &pHolder);
if (tok == NULL)
return ERROR;
pDrvCtrl->autoNeg = atoi (tok);
return OK;
}
/*
* format AT91 Special address REG word
*/
LOCAL void FormatETHSpecialAddrWord( UINT32 *wordHigh, UINT32 *wordLow, BYTE *macadd )
{
(*wordLow) = /*htonl( *((UINT32*)( pDevice->enetAddr )) );*/
((UINT32)(macadd[3])<<24) | ((UINT32)(macadd[2])<<16) | ((UINT32)(macadd[1])<<8) | ((UINT32)(macadd[0]));
(*wordHigh) = /*htons( *((UINT16*)( pDevice->enetAddr + 4 )) )*/
((UINT32)(macadd[5])<<8) | ((UINT32)(macadd[4])) ;
}
/*******************************************************************************
*
* at91EndMemInit - initialize memory for the chip
*
* This routine is highly specific to the device.
*
* RETURNS: OK or ERROR.
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -