📄 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--------------------01l,30jan03,m_h IPv6 Support01m,16jan03,agf make phyMaxDelay in units of phyDelayParm (SPR 83803)01l,13jan03,agf fix timing parameters used by miiLib (SPR 83803)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 101d,20sep01,agf increase pCluster allocation, check Done bit prior to Tx load01c,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-chipethernet MACs.The software interface to the driver is divided into three parts.The first part is the interrupt registers and their setup. This partis 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 ofthe interface comprises of the I/O control registers and theirprogramming. The third part of the interface comprises of the descriptorsand the buffers. This driver is designed to be moderately generic. Though it currently isimplemented on one processor, in the future it may be added to otherAlchemey product offerings. Thus, it would be desirable to use the samedriver with no source level changes. To achieve this, the driver must begiven several target-specific parameters, and some external supportroutines must be provided. These target-specific values and the externalsupport routines are described below.This driver supports multiple units per CPU. The driver can beconfigured to support big-endian or little-endian architectures.BOARD LAYOUTThis device is on-board. No jumpering diagram is necessary.EXTERNAL INTERFACEThe only external interface is the auEndLoad() routine, which expectsthe <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 onlyin the string name for the driver..IP <devAddr>This parameter is the memory base address of the device registers in thememory map of the CPU. It indicates to the driver where to find thebase MAC register..IP <devIoAddr>This parameter in the base address of the device registers for thededicated DMA channel for the MAC device. It indicates to the driverwhere 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 interruptsfor various events within the device; thus it contains an interrupt handlerroutine. The driver calls intConnect() via the macro SYS_INT_CONNECT()to connect its interrupt handler to the interrupt vector generated as aresult of the MAC interrupt..IP <intLvl>Some targets use additional interrupt controller devices to help organizeand 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 anyboard-specific operations required to allow the servicing of an interrupt.For a description of sysLanAuIntEnable(), see "External SupportRequirements" below..IP <offset>This parameter specifies the offset from which the packet has to beloaded from the begining of the device buffer. Normally this parameter iszero except for architectures which access long words only on alignedaddresses. For these architectures the value of this offset should be 2..IP <qtyCluster>This parameter is used to explicitly allocate the number of clusters thatwill be allocated. This allows the user to suit the stack to the amount ofphysical memory on the board..IP <flags>This is parameter is reserved for future use. Its value should be zero.EXTERNAL SUPPORT REQUIREMENTSThis 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).CEThere are default values in the source code for these macros. They presumememory mapped accesses to the device registers and the intConnect(), andintEnable() BSP functions. The first argument to each is the devicecontroller structure. Thus, each has access back to all the device-specificinformation. Having the pointer in the macro facilitates the addition of newfeatures to this driver.The macros SYS_INT_CONNECT, SYS_INT_DISCONNECT, SYS_INT_ENABLE andSYS_INT_DISABLE allow the driver to be customized for BSPs that use specialversions of these routines.The macro SYS_INT_CONNECT is used to connect the interrupt handler tothe appropriate vector. By default it is the routine intConnect().The macro SYS_INT_DISCONNECT is used to disconnect the interrupt handler priorto unloading the module. By default this routine is not implemented.The macro SYS_INT_ENABLE is used to enable the interrupt level for theend device. It is called once during initialization. It calls anexternal board level routine sysLanAuIntEnable(). The macro SYS_INT_DISABLE is used to disable the interrupt level for theend device. It is called during stop. It calls anexternal board level routine sysLanAuIntDisable(). The macro SYS_ENET_ADDR_GET is used get the ethernet hardware of thechip. This macro calls an external board level routine namelysysLanAuEnetAddrGet() to get the ethernet address.SYSTEM RESOURCE USAGEWhen 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 andand transmit frames.INCLUDES:end.h endLib.h etherMultiLib.h auEnd.hSEE ALSO: muxLib, endLib, netBufLib.I "Writing and Enhanced Network Driver"*/#include "vxWorks.h"#include "wdLib.h"#include "stdlib.h"#include "taskLib.h"#include "lstLib.h" /* Needed to maintain protocol list. */#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"#ifdef WR_IPV6#include "adv_net.h"#endif /*WR_IPV6*/#undef END_MACROS#include "endLib.h"#include "logLib.h"#include "drv/end/auEnd.h"#include "drv/multi/auLib.h"/* local defines */#define DRV_DEBUG /* temporary should be taken out */#undef DRV_DEBUG/* 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 *//* 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 *);#ifdef DRV_DEBUG /* if debugging driver */int auDebug = (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;#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_DEBUGAU_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);/* * 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. */ endEtherPacketDataGet, /* Get a pointer to packet data. */ endEtherPacketAddrGet /* Get packet addresses. */ };/******************************************************************************** auEndLoad - 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 <initString>, which* expects a string of the following format:** <unit>:<devMemAddr>:<devIoAddr>:<enableAddr>:<vecNum>:<intLvl>:<offset>* :<qtyCluster>:<flags>** 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 (that is, "au") 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 NULL.*/END_OBJ * auEndLoad ( char * initString /* string to be parse by the driver */ )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -