📄 auend.c
字号:
/* auEnd.c - END style Au MAC Ethernet driver */
/* Copyright 1984-2002 Wind River Systems, Inc., and Cetia Inc. */
#include "copyright_wrs.h"
/*
* This file has been developed or significantly modified by the
* MIPS Center of Excellence Dedicated Engineering Staff.
* This notice is as per the MIPS Center of Excellence Master Partner
* Agreement, do not remove this notice without checking first with
* WR/Platforms MIPS Center of Excellence engineering management.
*/
/*
modification history
--------------------
01h,30mar05,fhc adopted for V100R001CPE, non-critical comment and debug info
change.
01k,24jun02,zmm Removed kernel calls from polling routines, Fix SPR 75773.
01j,14may02,zmm Global au1000 name changes. SPR 77333.
01i,18apr02,zmm Add muxError calls, if mBlkGet, netClBlkGet, or netClusterGet
fails. Fix SPR 73756.
01h,04apr02,zmm Move enabling the receiver from Reset to Config routine.
Fix SPR 75126.
01g,15nov01,zmm Supported auto-negotiation and cache coherency,
plus general cleanups. SPR 71884.
01f,11oct01,tlc Change register names according to new revision of Au1000
Databook. General cleanup.
01e,21sep01,agf add cluster alloc and MAC enable address to LOAD string
generalize driver to work on MAC 0 or 1
01d,20sep01,agf increase pCluster allocation, check Done bit prior to Tx load
01c,19jul01,zmm Supported polling driver mode, and few interrupt mode fixes.
01b,19jun01,zmm Fix race condition and Tx handling.
01a,17may01,mem written.
*/
/*
DESCRIPTION
This module implements the Alchemey Semiconductor au on-chip
ethernet MACs.
The software interface to the driver is divided into three parts.
The first part is the interrupt registers and their setup. This part
is done at the BSP level in the various BSPs which use this driver.
The second and third part are addressed in the driver. The second part of
the interface comprises of the I/O control registers and their
programming. The third part of the interface comprises of the descriptors
and the buffers.
This driver is designed to be moderately generic. Though it currently is
implemented on one processor, in the future it may be added to other
Alchemey product offerings. Thus, it would be desirable to use the same
driver with no source level changes. To achieve this, the driver must be
given several target-specific parameters, and some external support
routines must be provided. These target-specific values and the external
support routines are described below.
This driver supports multiple units per CPU. The driver can be
configured to support big-endian or little-endian architectures.
BOARD LAYOUT
This device is on-board. No jumpering diagram is necessary.
EXTERNAL INTERFACE
The only external interface is the auEndLoad() routine, which expects
the <initString> parameter as input. This parameter passes in a
colon-delimited string of the format:
<unit>:<devMemAddr>:<devIoAddr>:<enableAddr>:<vecNum>:<intLvl>:<offset>
:<qtyCluster>:<flags>
The auEndLoad() function uses strtok() to parse the string.
TARGET-SPECIFIC PARAMETERS
.IP <unit>
A convenient holdover from the former model. This parameter is used only
in the string name for the driver.
.IP <devAddr>
This parameter is the memory base address of the device registers in the
memory map of the CPU. It indicates to the driver where to find the
base MAC register.
.IP <devIoAddr>
This parameter in the base address of the device registers for the
dedicated DMA channel for the MAC device. It indicates to the driver
where to find the DMA registers.
.IP <enableAddr>
This parameter is the address MAC enable register. It is necessary to
specify selection between MAC 0 and MAC 1.
.IP <vecNum>
This parameter is the vector associated with the device interrupt.
This driver configures the MAC device to generate hardware interrupts
for various events within the device; thus it contains an interrupt handler
routine. The driver calls intConnect() via the macro SYS_INT_CONNECT()
to connect its interrupt handler to the interrupt vector generated as a
result of the MAC interrupt.
.IP <intLvl>
Some targets use additional interrupt controller devices to help organize
and service the various interrupt sources. This driver avoids all board-
specific knowledge of such devices. During the driver's initialization,
the external routine sysLanAuIntEnable() is called to perform any
board-specific operations required to allow the servicing of an interrupt.
For a description of sysLanAuIntEnable(), see "External Support
Requirements" below.
.IP <offset>
This parameter specifies the offset from which the packet has to be
loaded from the begining of the device buffer. Normally this parameter is
zero except for architectures which access long words only on aligned
addresses. For these architectures the value of this offset should be 2.
.IP <qtyCluster>
This parameter is used to explicitly allocate the number of clusters that
will be allocated. This allows the user to suit the stack to the amount of
physical memory on the board.
.IP <flags>
This is parameter is reserved for future use. Its value should be zero.
EXTERNAL SUPPORT REQUIREMENTS
This driver requires several external support functions, defined as macros:
.CS
SYS_INT_CONNECT(pDrvCtrl, routine, arg)
SYS_INT_DISCONNECT (pDrvCtrl, routine, arg)
SYS_INT_ENABLE(pDrvCtrl)
SYS_INT_DISABLE(pDrvCtrl)
SYS_OUT_BYTE(pDrvCtrl, reg, data)
SYS_IN_BYTE(pDrvCtrl, reg, data)
SYS_OUT_WORD(pDrvCtrl, reg, data)
SYS_IN_WORD(pDrvCtrl, reg, data)
SYS_OUT_LONG(pDrvCtrl, reg, data)
SYS_IN_LONG(pDrvCtrl, reg, data)
SYS_ENET_ADDR_GET(pDrvCtrl, pAddress)
sysLanAuIntEnable(pDrvCtrl->intLevel)
sysLanAuIntDisable(pDrvCtrl->intLevel)
sysLanAuEnetAddrGet(pDrvCtrl, enetAdrs)
.CE
There are default values in the source code for these macros. They presume
memory mapped accesses to the device registers and the intConnect(), and
intEnable() BSP functions. The first argument to each is the device
controller structure. Thus, each has access back to all the device-specific
information. Having the pointer in the macro facilitates the addition of new
features to this driver.
The macros SYS_INT_CONNECT, SYS_INT_DISCONNECT, SYS_INT_ENABLE and
SYS_INT_DISABLE allow the driver to be customized for BSPs that use special
versions of these routines.
The macro SYS_INT_CONNECT is used to connect the interrupt handler to
the appropriate vector. By default it is the routine intConnect().
The macro SYS_INT_DISCONNECT is used to disconnect the interrupt handler prior
to unloading the module. By default this routine is not implemented.
The macro SYS_INT_ENABLE is used to enable the interrupt level for the
end device. It is called once during initialization. It calls an
external board level routine sysLanAuIntEnable().
The macro SYS_INT_DISABLE is used to disable the interrupt level for the
end device. It is called during stop. It calls an
external board level routine sysLanAuIntDisable().
The macro SYS_ENET_ADDR_GET is used get the ethernet hardware of the
chip. This macro calls an external board level routine namely
sysLanAuEnetAddrGet() to get the ethernet address.
SYSTEM RESOURCE USAGE
When implemented, this driver requires the following system resources:
- one mutual exclusion semaphore
- one interrupt vector
- 64 bytes in the initialized data section (data)
- 0 bytes in the uninitialized data section (BSS)
The driver allocates clusters of size 1520 bytes for receive frames and
and transmit frames.
INCLUDES:
end.h endLib.h etherMultiLib.h auEnd.h
SEE ALSO: muxLib, endLib, netBufLib
.I "Writing and Enhanced Network Driver"
*/
#include "vxWorks.h"
#include "wdLib.h"
#include "stdlib.h"
#include "taskLib.h"
#include "logLib.h"
#include "intLib.h"
#include "netLib.h"
#include "stdio.h"
#include "stdlib.h"
#include "sysLib.h"
#include "iv.h"
#include "memLib.h"
#include "semLib.h"
#include "cacheLib.h"
#include "sys/ioctl.h"
#ifndef DOC /* don't include when building documentation */
#include "net/mbuf.h"
#endif /* DOC */
#include "net/protosw.h"
#include "sys/socket.h"
#include "errno.h"
#include "net/if.h"
#include "net/route.h"
#include "netinet/in.h"
#include "netinet/in_systm.h"
#include "netinet/in_var.h"
#include "netinet/ip.h"
#include "netinet/if_ether.h"
#include "net/if_subr.h"
#include "m2Lib.h"
#include "miiLib.h"
#include "etherMultiLib.h" /* multicast stuff. */
#include "end.h" /* Common END structures. */
#include "netBufLib.h"
#include "muxLib.h"
#undef END_MACROS
#include "endLib.h"
#include "lstLib.h" /* Needed to maintain protocol list. */
#include "logLib.h"
#include "auEnd.h"
#include "drv/multi/auLib.h"
#include "memPrint.h"
/* MII macro */
#define DRV_PHY_FLAGS_ISSET(setBits) \
(pDrvCtrl->miiPhyFlags & (setBits))
/* Cache macros */
#define AU_CACHE_VIRT_TO_PHYS(address) \
CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (address))
#define AU_CACHE_PHYS_TO_VIRT(address) \
CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->cacheFuncs, (address))
/*
* Default macro definitions for BSP interface.
* These macros can be redefined in a wrapper file, to generate
* a new module with an optimized interface.
*/
#ifndef SYS_INT_CONNECT
#define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult) \
{ \
IMPORT STATUS intConnect(); \
*pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec),\
(rtn), (int)(arg)); \
}
#endif /*SYS_INT_CONNECT*/
#ifndef SYS_INT_DISCONNECT
#define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult) \
{ \
}
#endif /*SYS_INT_DISCONNECT*/
#ifndef SYS_INT_ENABLE
#define SYS_INT_ENABLE(pDrvCtrl) \
{ \
IMPORT STATUS sysLanAuIntEnable(); \
sysLanAuIntEnable (pDrvCtrl->ilevel); \
}
#endif /* SYS_INT_ENABLE*/
/* Macro to disable the appropriate interrupt level */
#ifndef SYS_INT_DISABLE
#define SYS_INT_DISABLE(pDrvCtrl) \
{ \
IMPORT STATUS sysLanAuIntDisable (); \
sysLanAuIntDisable (pDrvCtrl->ilevel); \
}
#endif /* SYS_INT_DISABLE */
#ifndef SYS_ENET_ADDR_GET
#define SYS_ENET_ADDR_GET(pDrvCtrl, pAddress) \
{ \
IMPORT STATUS sysLanAuEnetAddrGet (AU_DRV_CTRL *pDrvCtrl, \
char * enetAdrs); \
sysLanAuEnetAddrGet (pDrvCtrl, pAddress); \
}
#endif /* SYS_ENET_ADDR_GET */
#ifndef SYS_WB_FLUSH
#define SYS_WB_FLUSH() \
{ \
IMPORT void sysWbFlush (void); \
sysWbFlush(); \
}
#endif/* SYS_WB_FLUSH */
/* 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)
#define END_FLAGS_ISSET(pEnd, setBits) \
((pEnd)->flags & (setBits))
/* externs */
IMPORT int endMultiLstCnt (END_OBJ *);
/* debug */
#define DRV_DEBUG
#undef DRV_DEBUG
#if 0
# define DRV_DEBUG
#endif
#ifdef DRV_DEBUG
# if 0
# define DEBUG_PRINT_TO_MEM
# endif
#endif
/* define the various levels of debugging if the DRV_DEBUG is defined */
#ifdef DRV_DEBUG
# define DRV_DEBUG_OFF 0x0000
# define DRV_DEBUG_RX 0x0001
# define DRV_DEBUG_TX 0x0002
# define DRV_DEBUG_INT 0x0004
# define DRV_DEBUG_POLL (DRV_DEBUG_POLL_RX | DRV_DEBUG_POLL_TX)
# define DRV_DEBUG_POLL_RX 0x0008
# define DRV_DEBUG_POLL_TX 0x0010
# define DRV_DEBUG_LOAD 0x0020
# define DRV_DEBUG_LOAD2 0x0040
# define DRV_DEBUG_IOCTL 0x0080
# define DRV_DEBUG_RESET 0x0100
# define DRV_DEBUG_MCAST 0x0200
# define DRV_DEBUG_CSR 0x0400
# define DRV_DEBUG_RX_PKT 0x0800
# define DRV_DEBUG_POLL_REDIR 0x10000
# define DRV_DEBUG_LOG_NVRAM 0x20000
# define DRV_DEBUG_MII 0x40000
# define DRV_DEBUG_ALL 0xfffff
#endif /* DRV_DEBUG */
#ifdef DRV_DEBUG
# if defined(DEBUG_PRINT_TO_MEM)
int auDebug = DRV_DEBUG_ALL;
# define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) \
if (auDebug & FLG) \
memPrintf((char *)X0, (int)X1, (int)X2, (int)X3, (int)X4, \
(int)X5, (int)X6);
# define DRV_PRINT(FLG,X) \
if(auDebug & FLG) memPrintf X;
# else /* DEBUG_PRINT_TO_MEM */
int auDebug = DRV_DEBUG_ALL; /* (DRV_DEBUG_LOAD | DRV_DEBUG_TX | DRV_DEBUG_RX
| DRV_DEBUG_MII | DRV_DEBUG_INT); */
# define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) \
if (auDebug & FLG) \
logMsg((char *)X0, (int)X1, (int)X2, (int)X3, (int)X4, \
(int)X5, (int)X6);
# define DRV_PRINT(FLG,X) \
if (auDebug & FLG) printf X;
# endif /* DEBUG_PRINT_TO_MEM */
#else /*DRV_DEBUG*/
# define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
# define DRV_PRINT(DBG_SW,X)
#endif /*DRV_DEBUG*/
/* locals */
#ifdef DRV_DEBUG
AU_DRV_CTRL * dbgDrvCtrl[2];
#endif
/* forward static functions */
LOCAL int auReset (AU_DRV_CTRL * pDrvCtrl);
LOCAL void auInt (AU_DRV_CTRL * pDrvCtrl);
LOCAL void auHandleInt (AU_DRV_CTRL * pDrvCtrl);
LOCAL STATUS auRecv (AU_DRV_CTRL * pDrvCtrl);
LOCAL void auRestart (AU_DRV_CTRL * pDrvCtrl);
LOCAL STATUS auRestartSetup (AU_DRV_CTRL * pDrvCtrl);
LOCAL void auAddrFilterSet (AU_DRV_CTRL * pDrvCtrl);
LOCAL void auConfig (AU_DRV_CTRL * pDrvCtrl);
LOCAL STATUS auMemInit (AU_DRV_CTRL * pDrvCtrl);
LOCAL void auTRingScrub (AU_DRV_CTRL * pDrvCtrl);
LOCAL STATUS auPhyPreInit (AU_DRV_CTRL *pDrvCtrl);
LOCAL STATUS auMiiInit (AU_DRV_CTRL *pDrvCtrl);
LOCAL STATUS auMiiRead (AU_DRV_CTRL *pDrvCtrl, UINT8 phyAdrs,
UINT8 phyReg, UINT16 *pRetVal);
LOCAL STATUS auMiiWrite (AU_DRV_CTRL *pDrvCtrl, UINT8 phyAdrs,
UINT8 phyReg, USHORT data);
LOCAL UINT8 auPhyFind (AU_DRV_CTRL *pDrvCtrl);
/* END Specific interfaces. */
LOCAL STATUS auStart (AU_DRV_CTRL * pDrvCtrl);
LOCAL STATUS auStop (AU_DRV_CTRL * pDrvCtrl);
LOCAL STATUS auUnload (AU_DRV_CTRL * pDrvCtrl);
LOCAL int auIoctl (AU_DRV_CTRL * pDrvCtrl, int cmd, caddr_t data);
LOCAL STATUS auSend (AU_DRV_CTRL * pDrvCtrl, M_BLK_ID pBuf);
LOCAL STATUS auMCastAddrAdd (AU_DRV_CTRL* pDrvCtrl, char * pAddress);
LOCAL STATUS auMCastAddrDel (AU_DRV_CTRL * pDrvCtrl,
char * pAddress);
LOCAL STATUS auMCastAddrGet (AU_DRV_CTRL * pDrvCtrl,
MULTI_TABLE * pTable);
LOCAL STATUS auPollSend (AU_DRV_CTRL * pDrvCtrl, M_BLK_ID pBuf);
LOCAL STATUS auPollReceive (AU_DRV_CTRL * pDrvCtrl, M_BLK_ID pBuf);
LOCAL STATUS auPollStart (AU_DRV_CTRL * pDrvCtrl);
LOCAL STATUS auPollStop (AU_DRV_CTRL * pDrvCtrl);
void auDump(int unit);
/*
* Declare our function table. This is static across all driver
* instances.
*/
LOCAL NET_FUNCS auFuncTable =
{
(FUNCPTR) auStart, /* Function to start the device. */
(FUNCPTR) auStop, /* Function to stop the device. */
(FUNCPTR) auUnload, /* Unloading function for the driver. */
(FUNCPTR) auIoctl, /* Ioctl function for the driver. */
(FUNCPTR) auSend, /* Send function for the driver. */
(FUNCPTR) auMCastAddrAdd, /* Multicast address add */
(FUNCPTR) auMCastAddrDel, /* Multicast address delete */
(FUNCPTR) auMCastAddrGet, /* Multicast table retrieve */
(FUNCPTR) auPollSend, /* Polling send function */
(FUNCPTR) auPollReceive, /* Polling receive function */
endEtherAddressForm, /* Put address info into a packet. */
(FUNCPTR) endEtherPacketDataGet, /* Get a pointer to packet data. */
(FUNCPTR) endEtherPacketAddrGet /* Get packet addresses. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -