📄 cs8900aend.c
字号:
/* cs8900aEnd.c - cs8900a Enhanced Network Driver (END) *//*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 cs8900a_OUT_SHORT and cs8900a_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 (*cs8900aIntConnectRtn)(int level, FUNCTPR pFunc, int arg); IMPORT STATUS (*cs8900aIntDisconnectRtn)(int level, FUNCTPR pFunc, int arg); IMPORT STATUS (*cs8900aIntEnableRtn) (int level); IMPORT STATUS (*cs8900aEnetAddrGetRtn)(int unit, char *pResult); IMPORT STATUS (*cs8900aOutShortRtn)(UINT addr, UINT value); IMPORT STATUS (*cs8900aInShortRtn)(UINT addr, USHORT *pData); cs8900aIntConnectRtn = intConnect; /@ must not be NULL @/ cs8900aIntDisconnectRtn = NULL; cs8900aIntEnableRtn = NULL; cs8900aEndAddrGetRtn = NULL; cs8900aOutShortRtn = NULL; cs8900aInShortRtn = NULL;.CEExcecpt for cs8900aIntConnectRtn and cs8900aIntEnableRtn, 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. Thiscs8900a 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"#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 "string.h"/* addition. */ #include "cs8900a.h" /* Maximum number of CS8900 chips */ #define MAXUNITS 1 /* read one byte from I/O space */ #ifndef CS_IN_BYTE #define CS_IN_BYTE(reg,pAddr) (*(pAddr) = *((volatile UCHAR*)(reg))) #endif /*CS_IN_BYTE*/ /* read a short (16bits) from I/O */ #ifndef CS_IN_WORD #define CS_IN_WORD(reg,pAddr) (*((volatile USHORT*)(pAddr))) = *((volatile USHORT*)(reg))) #endif /*CS_IN_WORD*/ /* write a short to I/O space */ #ifndef CS_OUT_WORD #define CS_OUT_WORD(reg,data) (*((volatile USHORT*)(reg)) = data) #endif /*CS_OUT_WORD*/ /* enable interrupt level */ #ifndef CS_INT_ENABLE #define CS_INT_ENABLE(level,pResult) (*pResult = intEnable(level)) #endif /*CS_INT_ENABLE*/ /* connect routine to intr. vector */ #ifndef CS_INT_CONNECT #define CS_INT_CONNECT(ivec,rtn,arg,pResult) (*pResult = intConnect(ivec,rtn,arg)) #endif /*CS_INT_CONNECT*/IMPORT int endMultiLstCnt (END_OBJ* pEnd);/* defines */#define DRV_NAME "cs"#define DRV_NAME_LEN (sizeof(DRV_NAME) + 1)#define DRV_DESC "Cirrus Logic CS8900A END driver"#define DRV_DESC_LEN (sizeof(DRV_DESC) + 1)#define TASK_CS_INT_PRI (54)/* Configuration items */#ifndef ETHERMTU#define ETHERMTU (1500)#endif#define END_BUFSIZ (ETHERMTU + SIZEOF_ETHERHEADER + 6)#define EH_SIZE (14)#define END_SPEED_10M 10000000 /* 10Mbs */#define END_SPEED_100M 100000000 /* 100Mbs */#define END_SPEED END_SPEED_10M/* * Default macro definitions for BSP interface. * These macros can be redefined in a wrapper file, to generate * a new module with an optimized interface. *//* 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)/* typedefs *//* mac address mask */typedef struct struct_mac_address{ USHORT i_g : 1; USHORT u_l : 1; USHORT val15_2 : 14; UINT val47_16;}STRUCT_MAC_ADDRESS;/* 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. */ USHORT enetAddr[3]; /* ethernet address */ CACHE_FUNCS* pCacheFuncs; /* cache function pointers */ FUNCPTR freeRtn[128]; /* Array of free routines. *//* struct free_args freeData[128]; Array of free arguments */ /* the free routines. */ CL_POOL_ID pClPoolId; /* cluster pool */ BOOL rxHandling; /* rcv task is scheduled */ /* chip */ USHORT io_addr; /* The io base of the cs8900a. */ UINT mem_addr; /* The mem base of the cs8900a. */ USHORT chip_int_num; /* The cs8900a intrX(0..3) */ USHORT chip_dma_num; /* The cs8900a dmaX(0..2) */ UINT media_type; /* The media type in software. */ BOOL in_memory_mode; /* The flag of mode.(io(false) or memory(true)) */ BOOL resetting; UINT rx_depth; UINT max_rx_depth; UINT max_tx_depth; UINT loan_count; STRUCT_MAC_ADDRESS * p_mac_adr;}END_DEVICE;typedef struct self_pkg_buf{ char * p_char; int len;}self_pkg_buf, * p_self_pkg_buf;/* * 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. *//* -------------------------------- no. mBlks no. clBlks memArea memSize *//* network mbuf configuration table --------- ---------- ------- ------- */M_CL_CONFIG cs8900aMclBlkConfig = { 0, 0, NULL, 0};/* ---------------------------------------- clusterSize num memArea memSize *//* network cluster pool configuration table ----------- --- ------- --------- */CL_DESC cs8900aClDescTbl [] = {{ 0, 0, NULL, 0 }};int cs8900aClDescTblNumEnt = (NELEMENTS(cs8900aClDescTbl));/* Definitions for the flags field */#define cs8900a_PROMISCUOUS 0x1#define cs8900a_POLLING 0x2#define cs8900a_MIN_FBUF (1536) /* min first 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 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_IOCTL 0x0040 #define DRV_DEBUG_POLL_REDIR 0x10000 #define DRV_DEBUG_LOG_NVRAM 0x20000 int cs8900aDebug = 0x00; int cs8900aTxInts = 0; #define DRV_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) if(cs8900aDebug & FLG)logMsg(X0, X1, X2, X3, X4, X5, X6); #define DRV_PRINT(FLG,X) if(cs8900aDebug & 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 *//* forward static functions */LOCAL void cs8900aReset(END_DEVICE *pDrvCtrl);LOCAL void cs8900aRecv(END_DEVICE * pDrvCtrl, char * pNewCluster, int len);LOCAL void cs8900aConfig(END_DEVICE *pDrvCtrl);/* END Specific interfaces. *//* This is the only externally visible interface. */END_OBJ* cs8900aLoad(char* initString, void* p_v);LOCAL STATUS cs8900aStart(END_DEVICE* pDrvCtrl);LOCAL STATUS cs8900aStop(END_DEVICE* pDrvCtrl);LOCAL int cs8900aIoctl(END_DEVICE* pDrvCtrl, int cmd, caddr_t data);LOCAL STATUS cs8900aUnload(END_DEVICE* pDrvCtrl);LOCAL STATUS cs8900aSend(END_DEVICE* pDrvCtrl, M_BLK_ID pBuf);LOCAL void cs8900aInt(END_DEVICE* pDrvCtrl);LOCAL STATUS cs8900aMCastAdd(END_DEVICE* pDrvCtrl, char* pAddress);LOCAL STATUS cs8900aMCastDel(END_DEVICE* pDrvCtrl, char* pAddress);LOCAL STATUS cs8900aMCastGet(END_DEVICE* pDrvCtrl, MULTI_TABLE* pTable);LOCAL STATUS cs8900aPollStart(END_DEVICE* pDrvCtrl);LOCAL STATUS cs8900aPollStop(END_DEVICE* pDrvCtrl);LOCAL STATUS cs8900aPollSend(END_DEVICE* pDrvCtrl, M_BLK_ID pBuf);LOCAL STATUS cs8900aPollRcv(END_DEVICE* pDrvCtrl, M_BLK_ID pBuf);LOCAL void cs8900aAddrFilterSet(END_DEVICE *pDrvCtrl);LOCAL STATUS cs8900aMemInit();void cs_pp_w(END_DEVICE* pDrvCtrl, USHORT offset, USHORT value);USHORT cs_pp_r(END_DEVICE* pDrvCtrl, USHORT offset);void cs_chip_generate_interrupt(END_DEVICE * pDrvCtrl);int cs_chip_get_rx_miss_num(END_DEVICE * pDrvCtrl);int cs_chip_get_tx_col_num(END_DEVICE * pDrvCtrl);STATUS cs_chip_int_disable(END_DEVICE * pDrvCtrl);STATUS cs_chip_int_enable(END_DEVICE * pDrvCtrl);STATUS cs_chip_loop_set(END_DEVICE * pDrvCtrl, int val);void cs_chip_rx_frame_drop(END_DEVICE * pDrvCtrl, int num);STATUS cs_chip_select_rx_frame_type(END_DEVICE * pDrvCtrl, USHORT type_mask, int val);STATUS cs_chip_self_reset(END_DEVICE * pDrvCtrl);STATUS cs_chip_set_full_duplex(END_DEVICE * pDrvCtrl, int val);STATUS cs_chip_set_link_dep(END_DEVICE * pDrvCtrl, int val);STATUS cs_chip_set_tx_crc(END_DEVICE * pDrvCtrl, int val);STATUS cs_chip_to_mem_mode(END_DEVICE * pDrvCtrl, int flag);STATUS cs_chip_tx_force_terminate(END_DEVICE * pDrvCtrl, int val);STATUS cs_chip_send_frame(END_DEVICE * pDrvCtrl, USHORT * p_src_buf, int length);STATUS cs_soft_end_init(END_DEVICE * pDrvCtrl);int cs8900a_pin_enable(void);int cs8900a_pin_disable(void);STATUS cs_chip_event_enable(END_DEVICE * pDrvCtrl);STATUS mask32_change_bsp(int* dist32, int num, int len, int src);/* * Declare our function table. This is static across all device * instances. */LOCAL NET_FUNCS cs8900aFuncTable ={ (FUNCPTR) cs8900aStart, /* Function to start the device. */ (FUNCPTR) cs8900aStop, /* Function to stop the device. */ (FUNCPTR) cs8900aUnload, /* Unloading function for the driver. */ (FUNCPTR) cs8900aIoctl, /* Ioctl function for the driver. */ (FUNCPTR) cs8900aSend, /* Send function for the driver. */ (FUNCPTR) cs8900aMCastAdd, /* Multicast add function for the driver. */ (FUNCPTR) cs8900aMCastDel, /* Multicast delete function for the driver. */ (FUNCPTR) cs8900aMCastGet, /* Multicast retrieve function for the driver. */ (FUNCPTR) cs8900aPollSend, /* Polling send function */ (FUNCPTR) cs8900aPollRcv, /* Polling receive function */ endEtherAddressForm, /* put address info into a NET_BUFFER */ endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */ endEtherPacketAddrGet /* Get packet addresses. */};END_DEVICE * p_end_device;int display_net_event = 0;/* * cs8900aLoad - 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 the initString. * * The string contains the target specific parameters like this: * * "register addr:int vector:int level:shmem addr:shmem size:shmem width" * * 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 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 empty. */END_OBJ* cs8900aLoad ( char* initString, /* String to be parsed by the driver. */ void* p_v ){ END_DEVICE *pDrvCtrl; DRV_LOG(DRV_DEBUG_LOAD, "Loading cs8900a...\n", 1, 2, 3, 4, 5, 6); if(initString == NULL) { DRV_LOG(DRV_DEBUG_LOAD, "cs8900aLoad: NULL initStr\r\n",0,0,0,0,0,0); return NULL; } if(initString[0] == EOS) { bcopy((char *)DRV_NAME, initString, DRV_NAME_LEN); return NULL; } /* else initString is not blank, pass two ... */ /* allocate the device structure */ pDrvCtrl = (END_DEVICE*)calloc(sizeof(END_DEVICE), 1); if(pDrvCtrl == NULL) goto errorExit; cs_soft_end_init(pDrvCtrl); /* * initialize the END and MIB2 parts of the structure * The M2 element must come from m2Lib.h * This cs8900a is set up for a DIX type ethernet device. */ if( (END_OBJ_INIT(&pDrvCtrl->end, (DEV_OBJ*)pDrvCtrl, DRV_NAME, pDrvCtrl->unit, &cs8900aFuncTable,DRV_DESC) == ERROR) || (END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd, (UCHAR*)&(pDrvCtrl->enetAddr[0]), 6, ETHERMTU,END_SPEED) == ERROR)) { goto errorExit; } /* Perform memory allocation/distribution */ if(cs8900aMemInit(pDrvCtrl) == ERROR) goto errorExit; /* reset and reconfigure the device */ cs8900aReset(pDrvCtrl); cs8900aConfig(pDrvCtrl); /* set the flags to indicate readiness */ END_OBJ_READY(&pDrvCtrl->end, IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST); DRV_LOG(DRV_DEBUG_LOAD, "Done loading cs8900a...", 1, 2, 3, 4, 5, 6); p_end_device = pDrvCtrl; pDrvCtrl->p_mac_adr = (void *)(pDrvCtrl->enetAddr); return (&(pDrvCtrl->end));errorExit: if(pDrvCtrl != NULL) free((char *)pDrvCtrl); p_end_device = NULL; return NULL;}/* * cs8900aMemInit - initialize memory for the chip * * This routine is highly specific to the device. * * Design choices available:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -