📄 el3c90xend.c
字号:
/* el3c90xEnd.c - END network interface driver for 3COM 3C90xB XL *//* Copyright 1984-1999 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01b,11jan99,mtl big endian fix to eprm read rtn.01a,11jan99,mtl written by teamF1 Inc.*//*DESCRIPTION This module implements the device driver for the 3COM EtherLink Xl andFast EtherLink XL PCI network interface cards.The 3c90x 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.The 3c90x series chips use a bus-master DMA interface for transferingpackets to and from the controller chip. Some of the old 3c59x cardsalso supported a bus master mode, however for those chipsyou could only DMA packets to and from a contiguous memory buffer. Fortransmission this would mean copying the contents of the queued M_BLKchain into a an M_BLK cluster and then DMAing the cluster. This extracopy would sort of defeat the purpose of the bus master support forany packet that doesn't fit into a single M_BLK. By contrast, the 3c90x cardssupport a fragment-based bus master mode where M_BLK chains can beencapsulated using TX descriptors. This is also called the gather technique,where the fragments in an mBlk chain are directly incorporated into thedownload transmit descriptor. This avoids any copying of data from themBlk chain. NETWORK CARDS SUPPORTED: - 3Com 3c900-TPO 10Mbps/RJ-45 - 3Com 3c900-COMBO 10Mbps/RJ-45,AUI,BNC - 3Com 3c905-TX 10/100Mbps/RJ-45 - 3Com 3c905-T4 10/100Mbps/RJ-45 - 3Com 3c900B-TPO 10Mbps/RJ-45 - 3Com 3c900B-COMBO 10Mbps/RJ-45,AUI,BNC - 3Com 3c905B-TX 10/100Mbps/RJ-45 - 3Com 3c905B-FL/FX 10/100Mbps/Fiber-optic - 3Com 3c980-TX 10/100Mbps server adapter - Dell Optiplex GX1 on-board 3c918 10/100Mbps/RJ-45 BOARD LAYOUTThis device is on-board. No jumpering diagram is necessary.EXTERNAL INTERFACEThe only external interface is the el3c90xEndLoad() 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>:<flags>:<buffMultiplier>The el3c90xEndLoad() 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 theregister set. < This parameter should be equal to NONE if the devicedoes not support memory mapped registers..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 the device does not support IO mapped registers.. <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 sysEl3c90xIntEnable() is called toperform any board-specific operations required to allow the servicing of aNIC interrupt. For a description of sysEl3c90xIntEnable(), 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 3C90x NIC 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 NIC. 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 <flags>This is parameter is used for future use, currently its value should bezero..IP <buffMultiplier>This parameter is used increase the number of buffers allocated in thedriver pool. If this parameter is -1 then a default multiplier of 2 ischoosen. With a multiplier of 2 the total number of clusters allocatedis 64 which is twice the cumulative number of upload and download descriptors.The device has 16 upload and 16 download descriptors. For example on choosingthe buffer multiplier of 3, the total number of clusters allocated will be96 ((16 + 16)*3). There are as many clBlks as the number of clusters.The number of mBlks allocated are twice the number of clBlks.By default there are 64 clusters, 64 clBlks and 128 mBlks allocated in thepool for the device. Depending on the load of the system increase thenumber of clusters allocated by incrementing the buffer multiplier.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_DELAY (delay) sysEl3c90xIntEnable(pDrvCtrl->intLevel) sysEl3c90xIntDisable(pDrvCtrl->intLevel) sysDelay (delay).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 sysEl3c90xIntEnable(). 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 sysEl3c90xIntDisable().The macro SYS_DELAY is used for a delay loop. It calls an external boardlevel routine sysDelay(delay). The granularity of delay is one microsecond.SYSTEM RESOURCE USAGEWhen implemented, this driver requires the following system resources: - one mutual exclusion semaphore - one interrupt vector - 24072 bytes in text for a I80486 target - 112 bytes in the initialized data section (data) - 0 bytes in the uninitialized data section (BSS)The driver allocates clusters of size 1536 bytes for receive frames andand transmit frames. There are 16 descriptors in the upload ringand 16 descriptors in the download ring. The buffer multiplier by defaultis 2, which means that the total number of clusters allocated by defaultare 64 ((upload descriptors + download descriptors)*2). There are as manyclBlks as the number of clusters. The number of mBlks allocated are twicethe number of clBlks. By default there are 64 clusters, 64 clBlks and 128mBlks allocated in the pool for the device. Depending on the load of thesystem increase the number of clusters allocated by incrementing the buffermultiplier.INCLUDES:end.h endLib.h etherMultiLib.h el3c90xEnd.hSEE ALSO: muxLib, endLib, netBufLib.pG "Writing and Enhanced Network Driver".SH "BIBLIOGRAPHY".iB "3COM 3c90x and 3c90xB NICs Technical reference."*/#include "vxWorks.h"#include "wdLib.h"#include "stdlib.h"#include "taskLib.h"#include "tickLib.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"#include "etherMultiLib.h" /* multicast stuff. */#include "end.h" /* Common END structures. */#include "endLib.h"#include "lstLib.h" /* Needed to maintain protocol list. */#include "netBufLib.h"#include "muxLib.h"#include "m2Lib.h"#include "drv/end/el3c90xEnd.h"#ifndef EL3C90X_CACHE_INVALIDATE#define EL3C90X_CACHE_INVALIDATE(address, len) \ CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))#endif /* EL3C90X_CACHE_INVALIDATE */ #ifndef EL3C90X_CACHE_VIRT_TO_PHYS#define EL3C90X_CACHE_VIRT_TO_PHYS(address) \ (MEM_TO_PCI_PHYS((UINT32)(CACHE_DRV_VIRT_TO_PHYS \ (&pDrvCtrl->cacheFuncs,(address)))))#endif /* EL3C90X_CACHE_VIRT_TO_PHYS *//* memory to PCI address translation macro */#ifndef MEM_TO_PCI_PHYS#define MEM_TO_PCI_PHYS(memAdrs) \ ((memAdrs) + (pDrvCtrl->pciMemBase))#endif /* * 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 */#ifndef SYS_INT_CONNECT#define SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult) \ { \ *pResult = intConnect ((VOIDFUNCPTR *)INUM_TO_IVEC (pDrvCtrl->ivec), \ rtn, (int)arg); \ }#endif/* Macro to disconnect interrupt handler from vector */#ifndef SYS_INT_DISCONNECT#define SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult) \ { \ *pResult = OK; \ }#endif/* Macro to enable the appropriate interrupt level */#ifndef SYS_INT_ENABLE#define SYS_INT_ENABLE(pDrvCtrl) \ { \ IMPORT STATUS sysEl3c90xIntEnable(); \ sysEl3c90xIntEnable ((pDrvCtrl)->intLevel); \ }#endif /* SYS_INT_ENABLE*//* Macro to disable the appropriate interrupt level */#ifndef SYS_INT_DISABLE#define SYS_INT_DISABLE(pDrvCtrl) \ { \ IMPORT void sysEl3c90xIntDisable (); \ sysEl3c90xIntDisable ((pDrvCtrl)->intLevel); \ }#endif#ifndef SYS_OUT_LONG#define SYS_OUT_LONG(pDrvCtrl,addr,value) \ { \ *((ULONG *)(addr)) = PCI_SWAP((value)); \ }#endif /* SYS_OUT_LONG */#ifndef SYS_IN_LONG#define SYS_IN_LONG(pDrvCtrl,addr,data) \ { \ ((data) = PCI_SWAP(*((ULONG *)(addr)))); \ }#endif /* SYS_IN_LONG */#ifndef SYS_OUT_SHORT#define SYS_OUT_SHORT(pDrvCtrl,addr,value) \ { \ *((USHORT *)(addr)) = PCI_WORD_SWAP((value)); \ }#endif /* SYS_OUT_SHORT*/#ifndef SYS_IN_SHORT#define SYS_IN_SHORT(pDrvCtrl,addr,data) \ { \ ((data) = PCI_WORD_SWAP(*((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_DELAY #define SYS_DELAY(x) \ { \ int loop; \ loop = (x); \ loop = ((loop * 3) >> 1); \ while (loop--) \ sysDelay(); \ }#endif /* SYS_DELAY *//* 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))#define VOID_TO_DRVCTRL(pVoid,pDrvCtrl) ((pDrvCtrl)=(EL3C90X_DEVICE *)(pVoid))/* externs */IMPORT int endMultiLstCnt (END_OBJ *);IMPORT void sysDelay(); /* x86 bSP implements around 720 ns delay *//* DEBUG MACROS */#ifdef DRV_DEBUG /* if debugging driver */int el3c90xDebug = DRV_DEBUG_LOAD| DRV_DEBUG_INT | DRV_DEBUG_TX;NET_POOL * pElXlPool;#define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) \ if (el3c90xDebug & FLG) \ logMsg((char *)X0, (int)X1, (int)X2, (int)X3, (int)X4, \ (int)X5, (int)X6);#define ENDLOGMSG(x) \ if (el3c90xDebug) \ { \ logMsg x; \ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -