📄 smend.c
字号:
#define SM_END_IS_LOADED \ ((pSmEndDev->flags & S_LOADED) != 0)#define SM_END_UNLOAD \ (pSmEndDev->flags &= ~S_LOADED)#define SM_END_IS_ACTIVE \ ((pSmEndDev->flags & S_ACTIVE) == S_ACTIVE)#define SM_END_POLL_SM_RDY \ ((pSmEndDev->flags & S_POLLED_SM_RDY) == S_POLLED_SM_RDY)#define MUX_IS_POLLING \ ((pSmEndDev->flags & S_POLLED_END_RDY) == S_POLLED_END_RDY)#define SM_IS_POLLED_LOCKED \ ((pSmEndDev->flags & S_POLLED_SM_LOCKED) != 0)#define SM_END_INTR_RDY \ ((pSmEndDev->flags & MODE_INTR_MASK) == S_INTR_RDY)#define SM_END_STOP \ {pSmEndDev->flags &= ~S_RUNNING; \ END_FLAGS_CLR (&pSmEndDev->end, IFF_RUNNING);}#define SM_END_START \ {pSmEndDev->flags |= S_RUNNING; \ END_FLAGS_SET (&pSmEndDev->end, IFF_RUNNING);}#define SM_RCV_TASK_ACTIVE \ (pSmEndDev->flags |= S_RCV_TASK_ACTIVE)#define SM_RCV_TASK_INACTIVE \ (pSmEndDev->flags &= ~S_RCV_TASK_ACTIVE)/* DEBUG MACROS */#define TUPLE /* XXXmas */#define SM_DBG /* XXXmas */#ifdef SM_DBG# define SM_DBG_OFF 0x0000# define SM_DBG_RX 0x0001# define SM_DBG_TX 0x0002# define SM_DBG_INT 0x0004# define SM_DBG_POLL (SM_DBG_POLL_RX | SM_DBG_POLL_TX)# define SM_DBG_POLL_RX 0x0008# define SM_DBG_POLL_TX 0x0010# define SM_DBG_LOAD 0x0020# define SM_DBG_MEM_INIT 0x0040# define SM_DBG_UNLOAD 0x0080# define SM_DBG_IOCTL 0x0100# define SM_DBG_START 0x0200# define SM_DBG_STOP 0x0400# define SM_DBG_CFG 0x0800# define SM_DBG_RSLV 0x1000# define SM_LOG(FLG, X0, X1, X2, X3, X4, X5, X6) \ if (smEndDebug & FLG) \ {logMsg(X0, X1, X2, X3, X4, X5, X6); taskDelay(3);}#else /*SM_DBG*/# define SM_LOG(FLG, X0, X1, X2, X3, X4, X5, X6)#endif /*SM_DBG*//* typedefs *//* Allowed State Changes */typedef enum {SC_NONE, SC_INIT, SC_POLL2INT, SC_INT2POLL} STATE_CHANGE;/* * The definition of the shared memory device control structure * * typedef struct sm_end_device /@ SM_END_DEV @/ * { * END_OBJ end; /@ The class we inherit from. @/ * UINT cookie; /@ sm device validation cookie @/ * unsigned localCpu; /@ local cpu number @/ * int unit; /@ unit number @/ * ULONG busSpace; /@ bus address space for pAnchor/pmem@/ * SM_ANCHOR * pAnchor; /@ pointer to shared memory anchor @/ * char * pMem; /@ pointer to start of shared memory @/ * ULONG memSize; /@ total shared memory size in bytes @/ * unsigned tasType; /@ test-and-set type (HARD/SOFT) @/ * unsigned maxCpus; /@ max #CPUs supported in 'sm' @/ * unsigned masterCpu; /@ master CPU number @/ * ULONG maxPktBytes; /@ max #packets in shared memory @/ * char * startAddr; /@ start of seq addrs (0 = not seq) @/ * char * ipAddr; /@ non-seq. IP address @/ * int maxPackets; /@ max #packets CPU can receive @/ * int intType; /@ interrupt method @/ * int intArg1; /@ 1st interrupt argument @/ * int intArg2; /@ 2nd interrupt argument @/ * int intArg3; /@ 3rd interrupt argument @/ * int ticksPerBeat; /@ #CPU ticks per heartbeat @/ * ULONG mbNum; /@ number of mBlks to allocate @/ * ULONG cbNum; /@ number of clBlks to allocate @/ * BOOL smAlloc; /@ sm allocated? @/ * BOOL isMaster; /@ we are master CPU? @/ * ULONG flags; /@ Our local flags. @/ * SM_PKT_MEM_HDR * pSmPktHdr; /@ sm packet header @/ * CL_POOL_ID clPoolId; /@ cluster pool ID @/ * M_BLK_ID tupleId; /@ receive-ready tuple (mBlk) ID @/ * M_BLK_ID pollQ; /@ polled tuple queue @/ * M_BLK_ID pollQLast; /@ polled tuple queue last entry @/ * void * pMclBlkCfg; /@ mBlk/clBlk config memory @/ * void * pClustMem; /@ cluster pool memory @/ * * /@ old SM_SOFTC section @/ * * struct arpcom arpcom; /@ common ethernet structure@/ * SM_PKT_DESC smPktDesc; /@ shared mem packet desc @/ * u_long masterAddr; /@ master's IP address @/ * } SM_END_DEV; *//* globals */#ifdef SM_DBGint smEndDebug = NONE; /* section debug enable switch */int smEndRxInts = 0; /* number of receive interrupts received */int smEndTxInts = 0; /* number of transmit interrupts generated */#endif /* SM_DBG *//* unit -> SM_END_DEV * Table */SM_END_DEV ** unitTbl = NULL;/* LOCALS *//* forward static functions */LOCAL STATUS smEndParse (SM_END_DEV * pSmEndDev, char * pParamStr);LOCAL STATUS smEndMemInit (SM_END_DEV * pSmEndDev);LOCAL STATUS smEndConfig (SM_END_DEV * pSmEndDev, STATE_CHANGE sDelta);LOCAL void smEndHwAddrSet (SM_END_DEV * pSmEndDev);LOCAL void smEndIsr (SM_END_DEV * pSmEndDev);LOCAL void smEndSrvcRcvInt (SM_END_DEV * pSmEndDev);LOCAL STATUS smEndRecv (SM_END_DEV * pSmEndDev, SM_PKT * pPkt, M_BLK_ID pMblk);LOCAL void smEndPollQPut (SM_END_DEV * pSmEndDev, M_BLK_ID mBlkId);LOCAL int smEndPollQGet (SM_END_DEV * pSmEndDev, M_BLK_ID mBlkId);LOCAL void smEndPollQFree (SM_END_DEV * pSmEndDev);LOCAL void smEndPulse (SM_PKT_MEM_HDR * pSmPktHdr);LOCAL M_BLK_ID smEndTupleGet (SM_END_DEV * pSmEndDev);LOCAL STATUS smEndTupleChainWalk (M_BLK * pMblk, UINT * pFragNum, UINT16 * pPktType, UINT * pMaxSize);LOCAL int smEndAddrResolve (FAST struct arpcom * pAc, FAST struct rtentry * pRt, struct mbuf * pMbuf, FAST struct sockaddr * pDestIP, FAST u_char * pDestHW);/* END Specific interfaces *//* This is the only externally visible interface. */END_OBJ * smEndLoad (char* initString);LOCAL STATUS smEndUnload (void *);LOCAL STATUS smEndStart (void *);LOCAL STATUS smEndStop (void *);LOCAL int smEndIoctl (void *, int, caddr_t);LOCAL STATUS smEndSend (void *, M_BLK_ID); LOCAL STATUS smEndMCastAddrAdd (void *, char *);LOCAL STATUS smEndMCastAddrDel (void *, char *);LOCAL STATUS smEndMCastAddrGet (void *, MULTI_TABLE *);LOCAL STATUS smEndPollSend (void *, M_BLK_ID);LOCAL STATUS smEndPollRecv (void *, M_BLK_ID);LOCAL STATUS smEndPollStart (void *);LOCAL STATUS smEndPollStop (void *);#if FALSE /* XXXmas future enhancement */LOCAL void smEndAddrFilterSet (void *);#endif/* * Declare our function entry table. This is static across all END driver * instances. */LOCAL NET_FUNCS smEndFuncTable = { (FUNCPTR)smEndStart, /* Function to start the device */ (FUNCPTR)smEndStop, /* Function to stop the device */ (FUNCPTR)smEndUnload, /* Unloading function of the driver */ (FUNCPTR)smEndIoctl, /* Ioctl function of the driver */ (FUNCPTR)smEndSend, /* Send function of the driver */ (FUNCPTR)smEndMCastAddrAdd, /* Multicast add function of the driver */ (FUNCPTR)smEndMCastAddrDel, /* Multicast delete function of the driver */ (FUNCPTR)smEndMCastAddrGet, /* Multicast retrieve function of the driver */ (FUNCPTR)smEndPollSend, /* Polling send function */ (FUNCPTR)smEndPollRecv, /* Polling receive function */ endEtherAddressForm, /* put address info into a NET_BUFFER */ endEtherPacketDataGet, /* get pointer to data in NET_BUFFER */ endEtherPacketAddrGet /* Get packet addresses */ };LOCAL int pollTaskId = NONE;/* * This array will only be needed until there are functional intConnect(), * intDisconnect(), intEnable() and intDisable() routines for all BSPs. */LOCAL BOOL connected[SM_NUM_INT_TYPES] = {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE};/******************************************************************************** smEndLoad - attach the sm interface to the MUX, initialize driver and device** This routine attaches an 'sm' Ethernet interface to the network MUX. This* routine makes the interface available by allocating and filling in an END_OBJ* structure, a driver entry table, and a MIB2 interface table.** Calls to this routine evoke different results depending upon the parameter* string it receives. If the string is empty, the MUX is requesting that the* device name be returned, not an intialized END_OBJ pointer. If the string* is not empty, a load operation is being requested with initialization being* done with the parameters parsed from the string.** Upon successful completion of a load operation by this routine, the driver* will be ready to be started, not active. The system will start the driver* when it is ready to accept packets.** The shared memory region will be initialized, via smPktSetup(), during the* call to this routine if it is executing on the designated master CPU.* The smEndLoad() routine can be called to load only one device unit at a time.** Input parameters are specified in the form of an ASCII string of colon (:)* delimited values of the form:** "<unit>:<busSpace>:<pAnchor>:<pMem>:<memSize>:<tasType>:<maxCpus>:* <masterCpu>:<maxPktBytes>:<startAddr>:<ipAddr>:<maxInputPkts>:<intType>:* <intArg1>:<intArg2>:<intArg3>:<mbNum>:<cbNum>"** The <unit> parameter denotes the logical device unit number assigned by the* operating system. Specified using radix 10.** The <busSpace> parameter denotes the bus address space. NONE = local, else,* a VME AM or PCI space identifier is required. This value applies to the* <pAnchor> and <pMem> parameters. Specified using radix 16. [NOT SUPPORTED]** The <pAnchor> parameter is the local address by which the local CPU may* access the shared memory anchor. Specified using radix 16.** The <pMem> parameter contains either the local address of shared memory or* the value NONE (-1), which implies that shared memory is to be allocated* dynamically. Specified using radix 16.** The <memSize> parameter is the size, in bytes, of the shared memory region.* Specified using radix 16.** The <tasType> parameter specifies the test-and-set operation to be used to* obtain exclusive access to the shared data structures. It is preferable* to use a genuine test-and-set instruction, if the hardware permits it. In* this case, <tasType> should be SM_TAS_HARD. If any of the CPUs on the* backplane network do not support the test-and-set instruction, <tasType>* should be SM_TAS_SOFT. Specified using radix 10.** The <maxCpus> parameter specifies the maximum number of CPUs that may* use the shared memory region. Specified using radix 10.** The <masterCpu> parameter indicates the shared memory master CPU number.* Specified in radix 10.** The <maxPktBytes> parameter specifies the size, in bytes, of the data* buffer in shared memory packets. This is the largest amount of data* that may be sent in a single packet. If this value is not an exact* multiple of 4 bytes, it will be rounded up to the next multiple of 4.* If zero, the default size specified in DEFAULT_PKT_SIZE is used.* Specified using radix 10.** The <startAddr> parameter is only applicable if sequential addressing is* enabled. If <startAddr> is non-zero, it specifies the starting address to* use for sequential addressing on the backplane. If <startAddr> is zero,* sequential addressing is disabled and <ipAddr> must be non-zero. Specified* using radix 16.** The <ipAddr> parameter is only applicable if sequential addressing is* not enabled. If <ipAddr> is non-zero, it specifies the IP address to* use for this CPU on the backplane. If <ipAddr> is zero, <startAddr> must* be non-zero. Specified using radix 16.** The <maxInputPkts> parameter specifies the maximum number of incoming shared* memory packets which may be queued to this CPU at one time. If zero, the* default value is used. Specified using radix 10.** The <intType> parameter allows a CPU to announce the method by which it is to* be notified of input packets which have been queued to it. Specified using* radix 10.** The <intArg1>, <intArg2>, and <intArg3> parameters are arguments chosen based* on, and required by, the interrupt method specified. They are used to* generate an interrupt of type <intType>. Specified using radix 16.** If <mbNum> is non-zero, it specifies the number of mBlks to allocate in the* driver memory pool. If <mbNum> is less than 0x10, a default value is used.* Specified using radix 16.** If <cbNum> is non-zero, it specifies the number of clBlks and, therefore, the* number of clusters, to allocate in the driver memory pool. If <cbNum> is* less than 0x10, a default value is used. Specified using radix 16.** The number of clBlks is also the number of clusters which will be allocated.* The clusters allocated in the driver memory pool all have a size of* SM_END_CLST_SIZ bytes. This size is defined such that an ethernet address* plus the largest MTU size can be contained and so that the size as allocated* by the netPoolInit() routine is an integer multiple of sizeof(int).** XXXmas NOTE: to be added later: multicasting and zero-copy** RETURNS: return values are dependent upon the context implied by the* parameter string length as shown below.** Length Return Value* -------- ---------------------------------------------------------------* 0 OK and device name copied to input string pointer or ERROR if* NULL string pointer.* non-0 END_OBJ * to initialized object or ERROR if bogus string or an* internal error occurs.** SEE ALSO: smEndParse()*/END_OBJ * smEndLoad ( char * pParamStr /* pointer to initialization parameter string */ ) { SM_END_DEV * pSmEndDev = NULL; /* device control pointer */ SM_ANCHOR * pAnchor; /* addr of anchor */ int anchorSet = ERROR; /* anchor visible */ int tics = smUtilProcNumGet(); /* sm probe delay period */ int temp; /* temp for vxMemProbe */ static UCHAR enetAddr[EADDR_LEN] = {0,0,0,0,0,0}; /* ethernet adrs*/ static char devName [] = SM_END_DEV_NAME; static int smEndDevAttr = (IFF_UP | IFF_NOTRAILERS | IFF_BROADCAST);#if FALSE /* XXXmas future enhancement */ static int smEndDevAttr = (IFF_UP | IFF_NOTRAILERS | IFF_BROADCAST | IFF_MULTICAST);#endifSM_LOG (SM_DBG_LOAD, "smEndLoad: pParamStr = %#X, len = %d\n", (unsigned)pParamStr, strlen (pParamStr), 0, 0, 0, 0); /* If parameter string pointer is NULL, just return ERROR */ if (pParamStr == NULL) { SM_LOG (SM_DBG_LOAD, "smEndLoad: ERROR: no param string ptr...\n", 0, 0, 0, 0, 0, 0); return ((END_OBJ *)ERROR); } /* * If parameter string is empty, MUX is requesting device name, * not a load operation. Just copy name to pointer and return OK. */ if (*pParamStr == 0) { strcpy (pParamStr, devName); SM_LOG (SM_DBG_LOAD, "smEndLoad: 1st pass: Returning dev name <%s>\n", (unsigned)pParamStr, 0, 0, 0, 0, 0); return ((END_OBJ *)OK); } /* * load operation requested * allocate required memory for structures */ /* allocate the SM_END_DEV structure */ SM_LOG (SM_DBG_LOAD, "smEndLoad: 2nd pass\n", 0, 0, 0, 0, 0, 0); if ((pSmEndDev = (SM_END_DEV *)calloc (1, sizeof (SM_END_DEV))) == NULL) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -