📄 ntend.c
字号:
/* ntEnd.c - END network interface driver to ULIP for vxSim for Windows NT *//* Copyright 1984-2000 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01k,02mar01,pai fixed ntInt() prototype and cleaned up some compiler warnings.01j,02mar01,pai fixed SPRs #31983 and #31064.01i,02mar01,pai adapted some of ericl's warning fixes from VxWorks AE work.01h,02mar01,pai passing in correct type of pointer in strtok_r. (SPR 62224).01g,02mar01,pai corrected the handling of EIOCSFLAGS ioctl (SPR# 29423).01f,02mar01,pai removed reference to etherLib.01e,02mar01,pai updated ntResolv API to new network stack (SPR #31357).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 "stdio.h"#include "stdlib.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 "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 + SIZEOF_ETHERHEADER + 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/* externals */IMPORT int endMultiLstCnt (END_OBJ *);/* forward declarations */STATUS ntPollStart (NTEND_DEVICE * pDrvCtrl);STATUS ntPollStop (NTEND_DEVICE * pDrvCtrl);void ntAddrFilterSet (NTEND_DEVICE * pDrvCtrl);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 ();LOCAL int ntArpResolv (struct arpcom * ap, struct rtentry * rt, struct mbuf * m, struct sockaddr * dst, unsigned char * desten);/* globals */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));/* locals *//* * Declare our function table. This is static across all driver * instances. */LOCAL NET_FUNCS ntFuncTable = { (FUNCPTR)ntStart, /* Function to start the device. */ (FUNCPTR)ntStop, /* Function to stop the device. */ (FUNCPTR)ntUnload, /* Unloading function for the driver. */ (FUNCPTR)ntIoctl, /* Ioctl function for the driver. */ (FUNCPTR)ntSend, /* Send function for the driver. */ (FUNCPTR)ntMCastAdd, /* Multicast address add function for the */ /* driver. */ (FUNCPTR)ntMCastDel, /* Multicast address delete function for */ /* the driver. */ (FUNCPTR)ntMCastGet, /* Multicast table retrieve function for */ /* the driver. */ (FUNCPTR)ntPollSend, /* Polling send function for the driver. */ (FUNCPTR)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; /* initialize various pointers */ 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 * pHolder = NULL; /* Parse the initString */ /* Unit number. */ pDrvCtrl->unit = 0; pDrvCtrl->ivec = 0xc002; pDrvCtrl->ilevel = 1; return(OK); tok = strtok_r (initString, ":", &pHolder); if (tok == NULL) return ERROR; pDrvCtrl->unit = atoi (tok); /* Interrupt vector. */ tok = strtok_r (NULL, ":", &pHolder); if (tok == NULL) return ERROR; pDrvCtrl->ivec = atoi (tok); /* Interrupt level. */ tok = strtok_r (NULL, ":", &pHolder); 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 */ ) { /* 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 ((VOIDFUNCPTR *)0xc002, &ntInt, (int)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; } /* SPR #31064 fix use packet length rather than ETHERMTU */ bcopy (pRcvBuffer, pNewCluster, len); 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, len, 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;#if FALSE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -