📄 ntend.c
字号:
/* ntEnd.c - END network interface driver to ULIP for vxSim for Windows NT *//* Copyright 1984-1999 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01d,29mar99,dat SPR 26119, documentation, usage of .bS/.bE01c,10jun98,cym changed sprintf to bcopy.01b,01jun98,cym changed interrupt handler to not use free.01a,21jan98,cym written based on templateEnd.c.*//*DESCRIPTION This driver provides a fake ethernet intface to the "ULIP" driverwritten by WRS. The driver essentially gets packets from vxWorks, and writesthem directly to file, where the ULIP driver handles them.The macro SYS_ENET_ADDR_GET is used to get the ethernet address (MAC)for the device. The single argument to this routine is the NTEND_DEVICEpointer. By default this routine copies the ethernet address stored inthe global variable ntEnetAddr into the NTEND_DEVICE structure.INCLUDES:end.h endLib.h etherMultiLib.hSEE ALSO: muxLib, endLib.I "Writing and Enhanced Network Driver"*/#include "vxWorks.h"#include "intLib.h"#include "netLib.h"#include "sysLib.h"#include "net/mbuf.h"#include "iv.h"#include "memLib.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 "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 "netBufLib.h"#include "muxLib.h"extern int simUlipAlive;extern int simUlipRcvLen;extern char *simUlipRcvBuffer;extern void simUlipInit();extern int simUlipWrite(); extern int simUlipRcvCount;extern int simUlipReadCount;extern void simUlipBufFree();/***** LOCAL DEFINITIONS *****//* Configuration items */#define NT_BUFSIZ (ETHERMTU + ENET_HDR_REAL_SIZ + 6)#define NT_SPEED 10000000/* * 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 get the ethernet address from the BSP */#ifndef SYS_ENET_ADDR_GET# define SYS_ENET_ADDR_GET(pDevice) \ { \ IMPORT unsigned char ntEnetAddr[]; \ bcopy ((char *)ntEnetAddr, (char *)(&pDevice->enetAddr), 6); \ }#endif/* XXX cym the ULIP driver is always ethernet address 254. *//* 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)typedef struct free_args { void* arg1; void* arg2; } FREE_ARGS; /* The definition of the driver control structure */typedef struct ntend_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 */ CL_POOL_ID pClPoolId; END_ERR lastError; /* Last error passed to muxError */ } NTEND_DEVICE;/* Definitions for the flags field */#define NT_PROMISCUOUS_FLAG 0x1#define NT_RCV_HANDLING_FLAG 0x2#define NT_POLLING 0x4/***** LOCALS *****//* forward static functions */void ntInt (NTEND_DEVICE *pDrvCtrl);LOCAL void ntHandleRcvInt (NTEND_DEVICE *pDrvCtrl, void *buf, int len);LOCAL void ntConfig (NTEND_DEVICE *pDrvCtrl);/* END Specific interfaces. *//* This is the only externally visible interface. */END_OBJ* ntLoad (char* initString,void *nothing);LOCAL STATUS ntStart (NTEND_DEVICE* pDrvCtrl);LOCAL STATUS ntStop (NTEND_DEVICE* pDrvCtrl);LOCAL STATUS ntUnload ();LOCAL int ntIoctl (NTEND_DEVICE* pDrvCtrl, int cmd, caddr_t data);LOCAL STATUS ntSend (NTEND_DEVICE* pDrvCtrl, M_BLK_ID pBuf); LOCAL STATUS ntMCastAdd (NTEND_DEVICE* pDrvCtrl, char* pAddress);LOCAL STATUS ntMCastDel (NTEND_DEVICE* pDrvCtrl, char* pAddress);LOCAL STATUS ntMCastGet (NTEND_DEVICE* pDrvCtrl, MULTI_TABLE* pTable);LOCAL STATUS ntPollSend (NTEND_DEVICE* pDrvCtrl, M_BLK_ID pBuf);LOCAL STATUS ntPollRcv (NTEND_DEVICE* pDrvCtrl, M_BLK_ID pBuf);LOCAL STATUS ntParse ();LOCAL STATUS ntMemInit ();int ntRsize = 5;int ntTsize = 5;int ntNumMBufs = 128;/* network buffers configuration */M_CL_CONFIG ntMclConfig = /* mBlk configuration table */ { 0, 0, NULL, 0 };CL_DESC ntClDescTbl [] = /* network cluster pool configuration table */ { /* clusterSize num memArea memSize ----------- ---- ------- ------- */ {NT_BUFSIZ, 0, NULL, 0} };int ntClDescTblNumEnt = (NELEMENTS(ntClDescTbl));/* * Declare our function table. This is static across all driver * instances. */LOCAL NET_FUNCS ntFuncTable = { ntStart, /* Function to start the device. */ ntStop, /* Function to stop the device. */ ntUnload, /* Unloading function for the driver. */ ntIoctl, /* Ioctl function for the driver. */ ntSend, /* Send function for the driver. */ ntMCastAdd, /* Multicast address add function for the */ /* driver. */ ntMCastDel, /* Multicast address delete function for */ /* the driver. */ ntMCastGet, /* Multicast table retrieve function for */ /* the driver. */ ntPollSend, /* Polling send function for the driver. */ ntPollRcv, /* Polling receive function for the driver. */ endEtherAddressForm, /* Put address info into a packet. */ endEtherPacketDataGet, /* Get a pointer to packet data. */ endEtherPacketAddrGet /* Get packet addresses. */ };/********************************************************************************* ntLoad - 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:** "unit:register addr:int vector:int level:shmem addr:shmem size:shmem width"** RETURNS: An END object pointer or NULL on error.*/END_OBJ* ntLoad ( char* initString, /* String to be parse by the driver. */ void* nothing ) { NTEND_DEVICE *pDrvCtrl; if (initString == NULL) { return(0); } if (*initString == '\0') { bcopy("nt", initString,3); return(0); } /* allocate the device structure */ pDrvCtrl = (NTEND_DEVICE *)calloc (sizeof (NTEND_DEVICE), 1); if (pDrvCtrl == NULL) goto errorExit; /* parse the init string, filling in the device structure */ if (ntParse (pDrvCtrl, initString) == ERROR) goto errorExit; /* Ask the BSP to provide the ethernet address. */ SYS_ENET_ADDR_GET(pDrvCtrl); /* initialize the END and MIB2 parts of the structure */ if (END_OBJ_INIT (&pDrvCtrl->end, (DEV_OBJ *)pDrvCtrl, "nt", pDrvCtrl->unit, &ntFuncTable, "Windows NT ULIP END") == ERROR || END_MIB_INIT (&pDrvCtrl->end, M2_ifType_ethernet_csmacd, &pDrvCtrl->enetAddr[0], 6, NT_BUFSIZ, NT_SPEED) == ERROR) goto errorExit; /* Perform memory allocation/distribution */ if (ntMemInit (pDrvCtrl) == ERROR) goto errorExit; /* reset and reconfigure the device */ ntConfig (pDrvCtrl); /* set the flags to indicate readiness */ END_OBJ_READY (&pDrvCtrl->end, IFF_NOARP | IFF_UP | IFF_RUNNING | IFF_POINTOPOINT ); /*IFF_NOTRAILERS | IFF_MULTICAST | IFF_LOAN| IFF_SCAT);*/winHexOut(&pDrvCtrl->end); return (&pDrvCtrl->end);errorExit: if (pDrvCtrl != NULL) free ((char *)pDrvCtrl); return NULL; }/********************************************************************************* ntParse - parse the init string** Parse the input string. Fill in values in the driver control structure.** The initialization string format is:* .CS* "unit:csrAdr:rapAdr:vecnum:intLvl:memAdrs:memSize:memWidth"* .CE** .IP <unit>* Device unit number, a small integer.* .IP <vecNum>* Interrupt vector number (used with sysIntConnect)* .IP <intLvl>* Interrupt level (isn't really used)* .LP** RETURNS: OK or ERROR for invalid arguments.*/STATUS ntParse ( NTEND_DEVICE * pDrvCtrl, char * initString ) { char* tok; char** holder = NULL; long address; /* Parse the initString */ /* Unit number. */ pDrvCtrl->unit = 0; pDrvCtrl->ivec = 0xc002; pDrvCtrl->ilevel = 1; return(OK); tok = strtok_r (initString, ":", holder); if (tok == NULL) return ERROR; pDrvCtrl->unit = atoi (tok); /* Interrupt vector. */ tok = strtok_r (NULL, ":", holder); if (tok == NULL) return ERROR; pDrvCtrl->ivec = atoi (tok); /* Interrupt level. */ tok = strtok_r (NULL, ":", holder); if (tok == NULL) return ERROR; pDrvCtrl->ilevel = atoi (tok); return OK; }/********************************************************************************* ntMemInit - initialize memory for the chip** This routine is highly specific to the device. ** RETURNS: OK or ERROR.*/STATUS ntMemInit ( NTEND_DEVICE * pDrvCtrl /* device to be initialized */ ) { char *pBuf; int sz; /* Set up a net Pool */ if ((pDrvCtrl->end.pNetPool = malloc (sizeof(NET_POOL))) == NULL) return (ERROR); ntMclConfig.mBlkNum = ntNumMBufs; ntMclConfig.clBlkNum = ntNumMBufs; ntMclConfig.memSize = (ntMclConfig.mBlkNum * (MSIZE + sizeof (long))) + (ntMclConfig.clBlkNum * (CL_BLK_SZ + sizeof(long))); /* allocate memory pool */ if ((ntMclConfig.memArea = (char *) memalign (sizeof(long), ntMclConfig.memSize)) == NULL) return (ERROR); ntClDescTbl[0].clNum = ntNumMBufs; ntClDescTbl[0].memSize = (ntClDescTbl[0].clNum * (NT_BUFSIZ + 8)) + sizeof(int); ntClDescTbl[0].memArea = malloc ( ntClDescTbl[0].memSize ); if (netPoolInit(pDrvCtrl->end.pNetPool, &ntMclConfig, &ntClDescTbl[0], ntClDescTblNumEnt, NULL) == ERROR) { winOut("Couldn't Initialize Net Pool\n"); return (ERROR); } /* Store the cluster pool id as others need it later. */ pDrvCtrl->pClPoolId = clPoolIdGet(pDrvCtrl->end.pNetPool, NT_BUFSIZ, FALSE); return OK; }/********************************************************************************* ntStart - start the device** This function calls BSP functions to connect interrupts and start the* device running in interrupt mode.** RETURNS: OK or ERROR**/LOCAL STATUS ntStart ( NTEND_DEVICE *pDrvCtrl ) {/* XXX cym add stuff to interface to polled thread */ intConnect(0xc002,&ntInt,pDrvCtrl); simUlipInit(); return (OK); }/********************************************************************************* ntHandleRcvInt - task level interrupt service for input packets** This routine is called at task level indirectly by the interrupt* service routine to do any message received processing.** RETURNS: N/A.*/LOCAL void ntHandleRcvInt ( NTEND_DEVICE *pDrvCtrl, void *pRcvBuffer, int len ) { M_BLK_ID pMblk; char * pNewCluster; CL_BLK_ID pClBlk; pNewCluster = netClusterGet(pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId); if(pNewCluster == NULL) { return; } bcopy(pRcvBuffer,pNewCluster,ETHERMTU); simUlipBufFree(pRcvBuffer); pClBlk = netClBlkGet(pDrvCtrl->end.pNetPool,M_DONTWAIT); if(pClBlk == NULL) { netClFree (pDrvCtrl->end.pNetPool,pNewCluster); return; } pMblk = mBlkGet(pDrvCtrl->end.pNetPool,M_DONTWAIT,MT_DATA); if( pMblk == NULL) { netClBlkFree (pDrvCtrl->end.pNetPool,pClBlk); netClFree (pDrvCtrl->end.pNetPool,pNewCluster); return; } END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1); netClBlkJoin(pClBlk,pNewCluster,ETHERMTU,NULL,0,0,0); netMblkClJoin(pMblk,pClBlk); pMblk->mBlkHdr.mFlags |= M_PKTHDR; pMblk->mBlkHdr.mLen = NT_BUFSIZ ; pMblk->mBlkPktHdr.len = NT_BUFSIZ ; END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk); }/********************************************************************************* ntSend - the driver send routine** This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.* The buffer must already have the addressing information properly installed* in it. This is done by a higher layer. The last arguments are a free* routine to be called when the device is done with the buffer and a pointer* to the argument to pass to the free routine. ** RETURNS: OK or ERROR.*/LOCAL STATUS ntSend ( NTEND_DEVICE *pDrvCtrl, /* device ptr */ M_BLK_ID pNBuff /* data to send */ ) { int len; int oldLevel;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -