?? ln97xend.c
字號:
/* ln97xEnd.c - END style AMD Am79C97X PCnet-PCI Ethernet driver *//* Copyright 1984-1998 Wind River Systems, Inc., and Cetia Inc. */#include "copyright_wrs.h"/*modification history--------------------01c,08dec98,snk made architecture independant, by teamF1 Inc. tested with x86 & power Pc architectures.01b,21sep98,dat modified to stand alone01a,01aug98,dmb written from if_lnPci.c, ver 01e*//*DESCRIPTION This module implements the Advanced Micro Devices Am79C971Am79C972 and Am79C973 PCnet-PCI Ethernet 32 bit network interface driver.The PCnet-PCI ethernet controller is inherently little endian becausethe chip is designed to operate on a PCI bus which is a little endianbus. The software interface to the driver is divided into three parts.The first part is the PCI configuration registers and their set up. This part is done at the BSP level in the various BSPs which use thisdriver. The second and third part are dealt in the driver. The secondpart of the 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, operating unmodifiedacross the range of architectures and targets supported by VxWorks. Toachieve this, the driver must be given several target-specific parameters,and some external support routines must be provided. These target-specificvalues and the external support routines are described below.This driver supports multiple units per CPU. The driver can beconfigured to support big-endian or little-endian architectures. Itcontains error recovery code to handle known device errata related to DMAactivity. Big endian processors can be connected to the PCI bus through some controllerswhich take care of hardware byte swapping. In such cases all the registers which the chip DMA s to have to be swapped and written to, so that when thehardware swaps the accesses, the chip would see them correctly. The chip stillhas to be programmed to operated in little endian mode as it is on the PCI bus.If the cpu board hardware automatically swaps all the accesses to and from thePCI bus, then input and output byte stream need not be swapped. BOARD LAYOUTThis device is on-board. No jumpering diagram is necessary.EXTERNAL INTERFACEThe only external interface is the ln97xEndLoad() routine, which expectsthe <initString> parameter as input. This parameter passes in a colon-delimited string of the format:<unit>:<devMemAddr>:<devIoAddr>:<pciMemBase:<vecNum>:<intLvl>:<memAdrs>:<memSize>:<memWidth>:<csr3b>:<offset>:<flags>The ln97xEndLoad() 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 <devMemAddr>This parameter in the memory base address of the device registers in thememory map of the CPU. It indicates to the driver where to find theRDP register.The LANCE presents two registers to the external interface, the RDP (registerdata port) and RAP (register address port) registers. This driver assumes that these two registers occupy two unique addresses in a memory spacethat is directly accessible by the CPU executing this driver. The driverassumes that the RDP register is mapped at a lower address than the RAPregister; the RDP register is therefore derived from the "base address."This parameter should be equal to NONE if memory map is not used..IP <devIoAddr>This parameter in the IO base address of the device registers in theIO map of some CPUs. It indicates to the driver where to find the RDPregister. If both <devIoAddr> and <devMemAddr> are given then the devicechooses <devMemAddr> which is a memory mapped register base address.This parameter should be equal to NONE if IO map is not used..IP <pciMemBase>This parameter is the base address of the CPU memory as seen from thePCI bus. This parameter is zero for most intel architectures..IP <vecNum>This parameter is the vector associated with the device interrupt.This driver configures the LANCE device to generate hardware interruptsfor various events within the device; thus it containsan interrupt handler routine. The driver calls intConnect() to connect its interrupt handler to the interrupt vector generated as a result of the LANCE interrupt..IP <intLvl>Some targets use additional interrupt controller devices to help organizeand service the various interrupt sources. This driver avoids allboard-specific knowledge of such devices. During the driver'sinitialization, the external routine sysLan97xIntEnable() is called toperform any board-specific operations required to allow the servicing of aLANCE interrupt. For a description of sysLan97xIntEnable(), see "ExternalSupport Requirements" below..IP <memAdrs>This parameter gives the driver the memory address to carve out itsbuffers and data structures. If this parameter is specified to beNONE then the driver allocates cache coherent memory for buffersand descriptors from the system pool.The LANCE device is a DMA type of device and typically shares access tosome region of memory with the CPU. This driver is designed for systemsthat directly share memory between the CPU and the LANCE. Itassumes that this shared memory is directly available to itwithout any arbitration or timing concerns..IP <memSize>This parameter can be used to explicitly limit the amount of sharedmemory (bytes) this driver will use. The constant NONE can be used toindicate no specific size limitation. This parameter is used only ifa specific memory region is provided to the driver..IP <memWidth>Some target hardware that restricts the shared memory region to aspecific location also restricts the access width to this region bythe CPU. On these targets, performing an access of an invalid widthwill cause a bus error.This parameter can be used to specify the number of bytes of accesswidth to be used by the driver during access to the shared memory.The constant NONE can be used to indicate no restrictions.Current internal support for this mechanism is not robust; implementation may not work on all targets requiring these restrictions..IP <csr3b>The LANCE control register #3 determines the bus mode of the device,allowing the support of big-endian and little-endian architectures.This parameter, defined as "UINT32 lnCSR_3B", is the value that willbe placed into LANCE control register #3. The default value supportsMotorola-type buses. For information about changing this parameter, see the manual. Normally for devices on the PCI bus this should always belittle endian. This value is zero normally.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 <flags>This is parameter is used for future use, currently its value should bezero.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) sysLan97xIntEnable(pDrvCtrl->intLevel) sysLan97xIntDisable(pDrvCtrl->intLevel) sysLan97xEnetAddrGet(pDrvCtrl, enetAdrs).CEThere are default values in the source code for these macros. They presumememory mapped accesses to the device registers and the normal intConnect(),and intEnable() 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 new features 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 is a dummy routine thatreturns OK.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 sysLan97xIntEnable(). 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 sysLan97xIntDisable(). The macro SYS_ENET_ADDR_GET is used get the ethernet hardware of thechip. This macro calls an external board level routine namelysysLan97xEnetAddrGet() to get the ethernet address.SYSTEM RESOURCE USAGEWhen implemented, this driver requires the following system resources: - one mutual exclusion semaphore - one interrupt vector - 13288 bytes in text for a I80486 target - 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 ln97xEnd.hSEE ALSO: muxLib, endLib, netBufLib.I "Writing and Enhanced Network Driver".I "Advanced Micro Devices PCnet-PCI Ethernet Controller for PCI."*/#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"#include "etherLib.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 "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 "ln97xEnd.h" /* modify by frank *//* local defines *//* * If LN_KICKSTART_TX is TRUE the transmitter is kick-started to force a * read of the transmit descriptors, otherwise the internal polling (1.6msec) * will initiate a read of the descriptors. This should be FALSE is there * is any chance of memory latency or chip accesses detaining the LANCE DMA, * which results in a transmitter UFLO error. This can be changed with the * global lnKickStartTx below. */#define LN_KICKSTART_TX TRUE/* Cache macros */#define LN_CACHE_INVALIDATE(address, len) \ CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))#define LN_CACHE_VIRT_TO_PHYS(address) \ CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, (address))#define LN_CACHE_PHYS_TO_VIRT(address) \ CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->cacheFuncs, (address))/* memory to PCI address translation macros */#define PCI_TO_MEM_PHYS(pciAdrs) \ ((pciAdrs) - (pDrvCtrl->pciMemBase)) #define MEM_TO_PCI_PHYS(memAdrs) \ ((memAdrs) + (pDrvCtrl->pciMemBase)) /* * 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 sysIntConnect(); \ *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) \ { \ *pResult = OK; /* HELP: need a real routine */ \ }#endif /*SYS_INT_DISCONNECT*/#ifndef SYS_INT_ENABLE#define SYS_INT_ENABLE() \ { \ IMPORT STATUS sysLan97xIntEnable(); \ sysLan97xIntEnable (pDrvCtrl->ilevel); \ }#endif /* SYS_INT_ENABLE*//* Macro to disable the appropriate interrupt level */#ifndef SYS_INT_DISABLE# define SYS_INT_DISABLE(pDrvCtrl) \ { \ IMPORT STATUS sysLan97xIntDisable (); \ sysLan97xIntDisable (pDrvCtrl->ilevel); \ }#endif#ifndef SYS_OUT_LONG#define SYS_OUT_LONG(pDrvCtrl,addr,value) \ { \ *((ULONG *)(addr)) = (value); \ }#endif /* SYS_OUT_LONG */#ifndef SYS_IN_LONG#define SYS_IN_LONG(pDrvCtrl,addr,data) \ { \ ((data) = *((ULONG *)(addr))); \ }#endif /* SYS_IN_LONG */#ifndef SYS_OUT_SHORT#define SYS_OUT_SHORT(pDrvCtrl,addr,value) \ { \ *((USHORT *)(addr)) = (value); \ }#endif /* SYS_OUT_SHORT*/#ifndef SYS_IN_SHORT#define SYS_IN_SHORT(pDrvCtrl,addr,data) \ { \ ((data) = *((USHORT *)(addr))); \ } #endif /* SYS_IN_SHORT*/#ifndef SYS_OUT_BYTE#define SYS_OUT_BYTE(pDrvCtrl,addr,value) \ { \ *((UCHAR *)(addr)) = (value); \ }#endif /* SYS_OUT_BYTE */#ifndef SYS_IN_BYTE#define SYS_IN_BYTE(pDrvCtrl,addr,data) \ { \ ((data) = *((UCHAR *)(addr))); \ }#endif /* SYS_IN_BYTE */#ifndef SYS_ENET_ADDR_GET#define SYS_ENET_ADDR_GET(pDrvCtrl, pAddress) \ { \ IMPORT STATUS sysLan97xEnetAddrGet (LN_97X_DRV_CTRL *pDrvCtrl, \ char * enetAdrs); \ sysLan97xEnetAddrGet (pDrvCtrl, pAddress); \ }#endif /* SYS_ENET_ADDR_GET *//* 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 ln97xDebug = DRV_DEBUG_LOAD | DRV_DEBUG_INT | DRV_DEBUG_TX;NET_POOL pLan97xNetPool;#define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) \ if (ln97xDebug & FLG) \ logMsg((char *)X0, (int)X1, (int)X2, (int)X3, (int)X4, \ (int)X5, (int)X6);#define DRV_PRINT(FLG,X) \ if (ln97xDebug & 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 */LOCAL int lnTsize = LN_TMD_TLEN; /* deflt xmit ring size as power of 2 */LOCAL int lnRsize = LN_RMD_RLEN; /* deflt recv ring size as power of 2 */LOCAL BOOL lnKickStartTx = LN_KICKSTART_TX;/* forward static functions */LOCAL int ln97xReset (LN_97X_DRV_CTRL * pDrvCtrl);LOCAL void ln97xInt (LN_97X_DRV_CTRL * pDrvCtrl);LOCAL void ln97xHandleRecvInt (LN_97X_DRV_CTRL * pDrvCtrl);LOCAL STATUS ln97xRecv (LN_97X_DRV_CTRL * pDrvCtrl, LN_RMD *rmd);LOCAL LN_RMD * ln97xFullRMDGet (LN_97X_DRV_CTRL * pDrvCtrl);LOCAL void ln97xCsrWrite (LN_97X_DRV_CTRL * pDrvCtrl, int reg, UINT32 value);LOCAL void ln97xRestart (LN_97X_DRV_CTRL * pDrvCtrl);LOCAL STATUS ln97xRestartSetup (LN_97X_DRV_CTRL * pDrvCtrl);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -