📄 ks8695end.c
字号:
/* ks8695End.c - ks8695 Enhanced Network Driver (END) for KS8695/P BSP *//* * Author: LIQUN RUAN (RLQ) * 09/18/2003 * Created based on WindRiver's templateEnd.c for Micrel Semiconductor's KS8695/P SOHO router chip * *//* Copyright 1984-2001 Wind River Systems, Inc. *//*TODO - Remove the ks8695 modification history and begin a new history starting with version 01a and growing the history upward with each revision.modification history--------------------01y,14jun02,dat Fixing diab warnings01x,15may02,dat Update comments about polled entry points01w,03nov01,dat buffer/cache updates01v,24sep01,pai merge from sustaining branch to Veloce (SPR# 70553).01u,06jun01,pai ks8695EndLoad corrected for two-pass algorithm (SPR# 67836)01t,09mar01,dat 64473, MuxLib was free'ing the END_OBJ structure. Fixed the load function for driver name response.01s,29sep00,dat removing PHYS_TO_VIRT translation01r,20sep00,dat SPR 32058, allow for alternate intConnect rtn01q,28aug00,stv corrected the handling of EIOCSFLAGS ioctl (SPR# 29423).01p,02aug00,stv removed netMblkClChainFree() in Pollsend routine (SPR# 32885).01o,11jun00,ham removed reference to etherLib.01n,27jan00,dat fixed use of NULL01m,12dec00,pai fixed KS8695_SYS_ENET_ADDR_GET and KS8695_SYS_INT_ENABLE definitions (SPR #62969).01l,12dec00,pai fixed various build errors (SPR #62962).01k,12dec00,pai merged in changes from HIT August Drivers Release.01j,12oct99,dat SPR 28492, fixed ks8695EndSend.01i,29mar99,dat documentation, SPR 26119. fixed .bS/.bE usage01h,28feb99,pul changed the prototype for END NET functions, to have END_OBJ reference as the first argument rather than device object, fix for SPR#2428501g,17feb99,dat documentation, removed beta warning01f,29sep98,dat Fixed problem in PollRx relating to SPR 22325.01e,28sep98,dat SPR 22325, system mode transition, plus fixed warnings and ks8695 is now compilable (SPR 22204).01d,17jul98,db changed "holder" in ks8695EndParse from char** to char *. fixed references to "holder" in ks8695EndParse(spr #21464).01c,15oct97,gnn revised to reflect the latest API changes.01b,05may97,dat added TODO's for documentation and macros.01a,04feb97,gnn written.*//*DESCRIPTIONTODO - Describe the chip being used completely, even if it provides morefeatures than ethernet.TODO - Describe the device's full ethernet capabilities, even if this driverdoesn't or can't utilize all of them. Describe the features that the driverdoes implement and any restrictions on their use.TODO - Describe all macros that can be used to customize this driver. Allaccesses to chip registers should be done through redefineable macros.In this example driver the macros KS8695_OUT_SHORT and KS8695_IN_SHORTare sample macros to read/write data to a mock device. If a devicecommunicates through formatted control blocks in shared memory, theaccesses to those control blocks should also be through redefinablemacros.TODO - The following information describes the procedure an end user wouldfollow to integrate this new END device into a new BSP. The procedure needs to be well documented.This driver is easily customized for a BSP by modifying global pointersto routines. The routine pointers are declared below. The code belowindicates the default values for each routine as well. By modifyingthese global pointer values, the BSP can change the behaviour of the driver..CS IMPORT STATUS (*ks8695IntConnectRtn) \ (int level, FUNCTPR pFunc, int arg); IMPORT STATUS (*ks8695IntDisconnectRtn) \ (int level, FUNCTPR pFunc, int arg); IMPORT STATUS (*ks8695IntEnableRtn) (int level); IMPORT STATUS (*ks8695EnetAddrGetRtn)(int unit, char *pResult); IMPORT STATUS (*ks8695OutShortRtn)(UINT addr, UINT value); IMPORT STATUS (*ks8695InShortRtn)(UINT addr, USHORT *pData); ks8695IntConnectRtn = intConnect; /@ must not be NULL @/ ks8695IntDisconnectRtn = NULL; ks8695IntEnableRtn = NULL; ks8695EndAddrGetRtn = NULL; ks8695OutShortRtn = NULL; ks8695InShortRtn = NULL;.CEExcecpt for ks8695IntConnectRtn and ks8695IntEnableRtn, a NULL valuewill result in the driver taking a default action. For the int disconnectfunction the default action is to do nothing at all. For the short in and outroutines, the default is to assume memory mapped device registers and toaccess them directly. The default ethernet address get routineprovides an invalid ethernet address of all zeros (0:0:0:0:0:0).If the BSP is willing to accept these default values no action at allis needed. To change the default value, the BSP should create an appropriateroutine and set the address into the global value before first use. Thiswould normally be done at function sysHwInit2() time.For Tornado 3.0 you need to pay attention to virtual physical addresstranslations which are important. Use the cache lib macros to toproper VIRT_TO_PHYS translation as part of generating the physical DMAaddress for the device. Avoid the use of PHYS_TO_VIRT translation asit can be very time consuming. If at all possible, the driver shouldcache the virtual address of each data buffer used for DMA.Prior to VxWorks AE 1.1, the muxLib function muxDevUnload() did a freeof the actual END_OBJ structure that was malloc'd during the driverload routine. Starting with VxWorks AE 1.1, this behaviour can bechanged. If the second argument to END_OBJ_INIT points to the END_OBJthen muxLib will free it during muxDevUnload. If not, then muxDevUnloadwill not free the allocated space. Under this situation, it is assumedthat the driver unload routine has free'd the space itself. This preservesbackward compatibility with older drivers that always specified the secondargument to END_OBJ_INIT() as a pointer to the END_OBJ structure. Thisks8695 has been changed to use the new behaviour instead.INCLUDES:end.h endLib.h etherMultiLib.hSEE ALSO: muxLib, endLib.I "Writing and Enhanced Network Driver"*//* includes */#include "vxWorks.h"#include "stdlib.h"#include "cacheLib.h"#include "intLib.h"#include "end.h" /* Common END structures. */#include "endLib.h"#include "lstLib.h" /* Needed to maintain protocol list. */#include "iv.h"#include "semLib.h"#include "logLib.h"#include "netLib.h"#include "stdio.h"#include "sysLib.h"#include "errno.h"#include "errnoLib.h"#include "memLib.h"#include "iosLib.h"#include "tickLib.h"#undef ETHER_MAP_IP_MULTICAST#include "etherMultiLib.h" /* multicast stuff. */#include "net/mbuf.h"#include "net/unixLib.h"#include "net/protosw.h"#include "net/systm.h"#include "net/if_subr.h"#include "net/route.h"#include "netinet/if_ether.h"#include "sys/socket.h"#include "sys/ioctl.h"#include "sys/times.h"#include "wdLib.h"#include "ks8695End.h" /* KS8695/P specific defines. */IMPORT int endMultiLstCnt (END_OBJ* pEnd);IMPORT POOL_FUNC *_pEndNetPoolFuncTbl; /* defines */#define DEBUG#define DEBUG_THIS#define PACKET_DUMP/*#define NO_RX*/ /* no rx, for debug only */#define USE_PERF_COUNTER#define TEST_RX#define KS8695_DRV_NAME "ks" /* max 8 bytes */#define KS8695_DRV_NAME_LEN (strlen(KS8695_DRV_NAME) + 1)char ks8695_driver_version[] = "1.0.0";char ks8695_copyright[] = "Copyright (c) 2003 Micrel Semiconductor Corp.";#define STAT_NET(x) (pDrvCtrl->stats.x)/*#define NO_TASK_DELAY*/#ifndef NO_TASK_DELAY#define SW_WRITE_DELAY() taskDelay(4) /* enough delay for cpu 166/125 MHz */#else#define SW_WRITE_DELAY() delayEx(400000)#endif/* Configuration items */#define END_BUFSIZ (ETHERMTU + SIZEOF_ETHERHEADER + 6)#define END_SPEED_10M 10000000 /* 10Mbs full duplex */#define END_SPEED_100M 100000000 /* 100Mbs full duplex, default */#define END_SPEED_10M_H 10000000 /* 10Mbs half duplex */#define END_SPEED_100M_H 100000000 /* 100Mbs half duplex */#define END_SPEED END_SPEED_100M/* * 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 KS8695_SYS_INT_CONNECT FUNCPTR ks8695IntConnectRtn = intConnect;# define KS8695_SYS_INT_CONNECT(pDrvCtrl,rtn,arg,pResult) \ do { \ *pResult = (*ks8695IntConnectRtn) ((VOIDFUNCPTR *) \ INUM_TO_IVEC (pDrvCtrl->ivec), rtn, (int)arg); \ } while (0)#endif/* Macro to disconnect interrupt handler from vector */#ifndef KS8695_SYS_INT_DISCONNECT STATUS (*ks8695IntDisconnectRtn) \ (int level, FUNCPTR rtn, int arg) = NULL;# define KS8695_SYS_INT_DISCONNECT(pDrvCtrl,rtn,arg,pResult) \ do { \ if (ks8695IntDisconnectRtn != NULL) \ *pResult = (*ks8695IntDisconnectRtn)(pDrvCtrl->ivec, \ rtn, (int)arg); \ else \ *pResult = ERROR; \ } while (0)#endif/* Macro to enable the appropriate interrupt level */#undef KS8695_SYS_INT_ENABLE#ifndef KS8695_SYS_INT_ENABLE STATUS (*ks8695IntEnableRtn)(int level) = intEnable;# define KS8695_SYS_INT_ENABLE(pDrvCtrl) \ do { \ if (ks8695IntEnableRtn != NULL) \ (*ks8695IntEnableRtn)(pDrvCtrl->ilevel); \ } while (0)#endif #undef KS8695_SYS_INT_DISABLE#ifndef KS8695_SYS_INT_DISABLE STATUS (*ks8695IntDisableRtn)(int level) = intDisable;# define KS8695_SYS_INT_DISABLE(pDrvCtrl) \ do { \ if (ks8695IntDisableRtn != NULL) \ (*ks8695IntDisableRtn) (pDrvCtrl->ilevel); \ } while (0)#endif/* Macro to get the ethernet address from the BSP */#ifndef KS8695_SYS_ENET_ADDR_GET STATUS (*ks8695EnetAddrGetRtn)(int unit, char * pResult) = NULL;# define KS8695_SYS_ENET_ADDR_GET(pDevice) \ do { \ if (ks8695EnetAddrGetRtn == NULL) \ bzero ((char *)&pDevice->enetAddr, 6); \ else \ (*ks8695EnetAddrGetRtn)(pDevice->unit, \ (char *)&pDevice->enetAddr); \ } while (0)#endif/* * Macros to do a short (UINT16) access to the chip. Default * assumes a normal memory mapped device. */#ifndef KS8695_OUT_SHORT STATUS (*ks8695OutShortRtn)(UINT addr, UINT value) = NULL;# define KS8695_OUT_SHORT(pDrvCtrl,addr,value) \ do { \ if (ks8695OutShortRtn == NULL) \ (*(USHORT *)addr = value) \ else \ (*ks8695OutShortRtn)((UINT)addr, (UINT)value) \ } while (0)#endif#ifndef KS8695_IN_SHORT STATUS (*ks8695InShortRtn)(UINT addr, USHORT *pData) = NULL;# define KS8695_IN_SHORT(pDrvCtrl,addr,pData) \ do { \ if (ks8695InShortRtn == NULL) \ (*pData = *addr) \ else \ (*ks8695InShortRtn)((UINT)addr, pData) \ } while (0)#endif/* A shortcut for getting the hardware address from the MIB II stuff. */#define KS8695_END_HADDR(pEnd) \ ((pEnd)->mib2Tbl.ifPhysAddress.phyAddress)#define KS8695_END_HADDR_LEN(pEnd) \ ((pEnd)->mib2Tbl.ifPhysAddress.addrLength)/* Cache and PCI-bus related macros */#define KS8695_VIRT_TO_PHYS(virtAddr) \ CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheDmaFuncs, (char *)(virtAddr))#define KS8695_LOCAL_TO_SYS(physAddr) \ LOCAL_TO_SYS_ADDR (pDrvCtrl->unit, (physAddr))#define KS8695_SYS_TO_VIRT(physAddr) \ (KS8695_SYS_TO_LOCAL (((UINT32) KS8695_PHYS_TO_VIRT (physAddr))))#define KS8695_PHYS_TO_VIRT(physAddr) \ CACHE_DRV_PHYS_TO_VIRT (&pDrvCtrl->cacheDmaFuncs, (char *)(physAddr))#define KS8695_SYS_TO_LOCAL(virtAddr) \ SYS_TO_LOCAL_ADDR (pDrvCtrl->unit, (virtAddr))#define KS8695_CACHE_INVALIDATE(address, len) \ CACHE_DRV_INVALIDATE (&pDrvCtrl->cacheFuncs, (address), (len))#define KS8695_CACHE_FLUSH(address, len) \ CACHE_DRV_FLUSH (&pDrvCtrl->cacheFuncs, (address), (len))#define KS8695_VIRT_TO_SYS(virtAddr) \ KS8695_LOCAL_TO_SYS(((UINT32)KS8695_VIRT_TOPHYS(virtAddr)))#define KS8695_CACHE_VIRT_TO_PHYS(address) \ ((UINT32)CACHE_DRV_VIRT_TO_PHYS(&pDrvCtrl->cacheFuncs, (address)))#define KS8695_CACHE_DMA_VIRT_TO_PHYS(address) \ ((UINT32)CACHE_DMA_VIRT_TO_PHYS(&pDrvCtrl->cacheFuncs, (address)))#define KS8695_FLAGS_ISSET(pEnd, bits) ((pEnd)->flags & (bits))/*** END MACROS ***/ /* Should be in endlib.h in my opinion */#define KS8695_M2_INUCAST(pEnd) (pEnd)->mib2Tbl.ifInUcastPkts++#define KS8695_M2_INNUCAST(pEnd) (pEnd)->mib2Tbl.ifInNUcastPkts++#define KS8695_M2_INERRORS(pEnd) (pEnd)->mib2Tbl.ifInErrors++#define KS8695_M2_INDISCARDS(pEnd) (pEnd)->mib2Tbl.ifInDiscards++#define KS8695_M2_INOCTETS(pEnd,bytes) (pEnd)->mib2Tbl.ifInOctets += bytes#define KS8695_M2_OUTUCAST(pEnd) (pEnd)->mib2Tbl.ifOutUcastPkts++#define KS8695_M2_OUTNUCAST(pEnd) (pEnd)->mib2Tbl.ifOutNUcastPkts++#define KS8695_M2_OUTDISCARDS(pEnd) pEnd)->mib2Tbl.ifOutDiscards++#define KS8695_M2_OUTERRORS(pEnd) (pEnd)->mib2Tbl.ifOutErrors++#define KS8695_M2_OUTOCTETS(pEnd,bytes) (pEnd)->mib2Tbl.ifOutOctets += bytes/* The definition of the driver control structure */typedef struct end_device { END_OBJ end; /* The class we inherit from. */ int unit; /* unit number */ int ivec; /* interrupt vector */ int ilevel; /* interrupt level */ char* pShMem; /* real ptr to shared memory */ long flags; /* Our local flags. */ UCHAR enetAddr[6]; /* ethernet address */ CACHE_FUNCS cacheFuncs; /* cache function pointers */ CACHE_FUNCS cacheDmaFuncs; /* cache descriptor */ FUNCPTR freeRtn[128]; /* Array of free routines. */ CL_POOL_ID pClPoolId; /* cluster pool */ BOOL rxHandling; /* rcv task is scheduled */ BOOL txHandling; /* rcv task is scheduled */ BOOL linkHandling; /* WAN link task is scheduled */ /* added KS8695/P specific member variables here */ volatile KS8695_STAT stats; /* KS8695/P stats */ DMA_INFO stDMAInfo; /* DMA information */ UINT32 rev; /* revision number */ struct ks8695_buffer *pTxMblk; struct ks8695_buffer *pRxMblk; INT32 nRxDesc; /* number of Rx descriptors */ INT32 nRxDescNextAvail; /* next available Rx descriptor */ INT32 nRxDescNextToFill; /* next Rx desc to fill new buffer to */ RXDESC *pRxDescriptors; volatile INT32 RxDescEmpty; /* atomic flag for empty Rx descriptor */ INT32 nRxDescTotal; /* total number fo Rx descriptors */ INT32 nTxDesc; /* number of Tx descriptors */ INT32 nTxDescNextAvail; /* next available Tx descriptor */ INT32 nTxDescUsed; /* used Tx descriptor */ volatile INT32 nTransmitCount; /* number of packets to transmit */ INT32 nTxProcessedCount; /* number of packets to transmitted */ INT32 nTxDescTotal; /* total number fo Tx descriptors */ INT32 nTransmitCoalescing; /* Tx packets coalescing count */ volatile INT32 nTxDescAvail; int offset; /* packet offset, should be 0 or 2 */ WDOG_ID watchdog; /* watch dog id */ int nWatchdogDelay; /* watch dog delay period */} END_DEVICE, *PEND_DEVICE;/* * This will only work if there is only a single unit, for multiple * unit device drivers these should be integrated into the END_DEVICE * structure. */M_CL_CONFIG ks8695MclBlkConfig = /* network mbuf configuration table */ { /* no. mBlks no. clBlks memArea memSize ----------- ---------- ------- ------- */ 0, 0, NULL, 0 };CL_DESC ks8695ClDescTbl [] = /* network cluster pool configuration table */ { /* clusterSize num memArea memSize ----------- ---- ------- ------- */ {ETHERMTU + ENET_HEADER_SIZE + 2, 0, NULL, 0} };int ks8695ClDescTblNumEnt = (NELEMENTS(ks8695ClDescTbl));/* Definitions for the flags field */#define KS8695_PROMISCUOUS 0x1#define KS8695_POLLING 0x2#define KS8695_MIN_FBUF (1536) /* min data buffer size *//* DEBUG MACROS */#ifdef DEBUG# define LOGMSG(x,a,b,c,d,e,f) \ if (endDebug) \ { \ logMsg (x,a,b,c,d,e,f); \ }#else# define LOGMSG(x,a,b,c,d,e,f)#endif /* ENDDEBUG */#undef DRV_DEBUG#ifdef DRV_DEBUG#define DRV_DEBUG_OFF 0x00000000#define DRV_DEBUG_RX 0x00000001#define DRV_DEBUG_TX 0x00000002#define DRV_DEBUG_INT 0x00000004#define DRV_DEBUG_POLL (DRV_DEBUG_POLL_RX | DRV_DEBUG_POLL_TX)#define DRV_DEBUG_POLL_RX 0x00000008#define DRV_DEBUG_POLL_TX 0x00000010#define DRV_DEBUG_LOAD 0x00000020#define DRV_DEBUG_IOCTL 0x00000040#define DRV_DEBUG_POLL_REDIR 0x00010000#define DRV_DEBUG_LOG_NVRAM 0x00020000#define DRV_DEBUG_LOG_PHY 0x00040000#define DRV_DEBUG_LOG_TIMER 0x00080000#define DRV_DEBUG_LOG_TASK 0x00100000UINT32 ks8695Debug = 0x00000000;#define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) \ if (ks8695Debug & FLG) \ logMsg(X0, X1, X2, X3, X4, X5, X6);#define DRV_PRINT(FLG,X) \ if (ks8695Debug & 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 void swResetSNMPInfo(PEND_DEVICE pDrvCtrl);LOCAL void macStartRx(PEND_DEVICE pDrvCtrl, BOOLEAN bStart);LOCAL void macStartTx(PEND_DEVICE pDrvCtrl, BOOLEAN bStart);LOCAL void macEnableInterrupt(PEND_DEVICE pDrvCtrl, BOOLEAN bEnable);LOCAL void swCreateLookUpTable(PEND_DEVICE pDrvCtrl);LOCAL void swAutoNegoStart(PEND_DEVICE pDrvCtrl, UINT uPort);LOCAL void ks8695_power_saving(int bSaving);LOCAL void swAutoNegoAdvertisement(PEND_DEVICE pDrvCtrl, UINT uPort);LOCAL void swAutoNegoAdvertisement(PEND_DEVICE pDrvCtrl, UINT uPort);LOCAL void ks8695IntLink(PEND_DEVICE pDrvCtrl);LOCAL void ks8695IntLinkTask(PEND_DEVICE pDrvCtrl);LOCAL void ks8695Int(PEND_DEVICE pDrvCtrl);LOCAL void macConfigureFlow(PEND_DEVICE pDrvCtrl, uint8_t bFlowCtrl);LOCAL int hook_irqs(PEND_DEVICE pDrvCtrl, int req);LOCAL int AllocateTxDescriptors(PEND_DEVICE pDrvCtrl);LOCAL int AllocateRxDescriptors(PEND_DEVICE pDrvCtrl);LOCAL void FreeTxDescriptors(PEND_DEVICE pDrvCtrl);LOCAL void FreeRxDescriptors(PEND_DEVICE pDrvCtrl);LOCAL void CleanTxRing(PEND_DEVICE pDrvCtrl);LOCAL void CleanRxRing(PEND_DEVICE pDrvCtrl);LOCAL void InitTxRing(PEND_DEVICE pDrvCtrl);LOCAL void InitRxRing(PEND_DEVICE pDrvCtrl);LOCAL M_BLK_ID getBufferBlock(PEND_DEVICE pDrvCtrl, UCHAR **pCluster, M_BLK_ID pSrcMblk);LOCAL void ReceiveBufferFill(PEND_DEVICE pDrvCtrl);LOCAL void ReceiveBufferFillEx(PEND_DEVICE pDrvCtrl);LOCAL void swDetectPhyConnection(PEND_DEVICE pDrvCtrl, UINT uPort);LOCAL void SetDefaults(PEND_DEVICE pDrvCtrl);LOCAL void printStr(char *str);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -