📄 muxlib.c
字号:
/* muxLib.c - MUX network interface library *//* Copyright 1984 - 1999 Wind River Systems, Inc. *//*modification history--------------------02r,31mar99,spm removed \040 codes from muxMCastAddrGet() entry (SPR #26268)02q,03mar99,pul fix for SPR# 2428502p,02mar99,pul fixed the return value for muxUnbind(): SPR# 24293020,13nov98,n_s added muxDevStopAll function. Added reboot hook in muxLibInit so that muxDevStop all is called prior to reboot. spr #2322902n,09sep98,ham corrected the comprison of ifTypes and MUX_MAX_IFTYPE.02m,09sep98,ham cont'd SPR#22298.02l,08sep98,ham moved MUX_MAX_TYPE to h/muxLib.h, SPR#22298.02k,21aug98,n_s fixed ifInUnknownProtos update in muxReceive, ifOutNUcastPkts update in muxSend (). spr 21074.02j,16jul98,n_s Added semGive () to ERROR condition for driver unload call in muxDevUnload ().02i,13jul98,n_s fixed muxDevLoad () to limit device name strcpy () to END_NAME_MAX. spr # 2164202h,13jul98,n_s fixed muxBind () to clear malloc'd NET_PROTOCOL. spr # 2164402g,24jun98,n_s fixed muxUnbind () to check NET_PROTOCOL node for type 02f,15jun98,n_s fixed muxDevUnload () and muxUnbind (). spr # 2154202e,13feb98,n_s fixed endFindByName () to handle multiple devices. spr # 21055.02d,02feb98,spm removed unneeded '&' operator and corrected spacing02c,17jan98,gnn fixed a bug in the output filter with passing LL_HDR_INFO.02b,17jan98,gnn changed output routines so they can be BOOL like receive routines.02a,17jan98,kbw made man page fixes01z,14dec97,kbw made man page fixes01y,10dec97,kbw made man page fixes01x,08dec97,gnn END code review fixes.01w,21oct97,kbw made man page fixes01v,08oct97,vin fixed muxPacketAddrGet().01u,07oct97,vin fixed a problem with calling muxIoctl, removed IFF_LOAN01t,03oct97,gnn added error routine and cleaned up function prototypes01s,25sep97,gnn SENS beta feedback fixes01r,25aug97,gnn documenatation changs to make mangen happy.01q,25aug97,gnn fixed a bug in the restart routine.01p,22aug97,gnn updated polled mode support.01o,19aug97,gnn changes due to new buffering scheme.01n,12aug97,gnn changes necessitated by MUX/END update.01m,31jul97,kbw fixed man page bug that broke build, comment in comment01l,31jul97,kbw fixed man page problems found in beta review01k,15may97,gnn removed many warnings. added code to handle MUX_PROTO_OUTPUT.01j,30apr97,jag man edits for funtion muxBufInit()01i,17apr97,gnn removed muxDevStart from muxDevLoad.01h,07apr97,gnn added errnoSet calls added muxDevNameGet. modified the way muxDevLoad works.01g,12mar97,gnn fixed a bug in muxReceive's calling API.01f,03feb97,gnn Modified muxBuf code to be more generic and support other, non-TMD systems.01e,29jan97,gnn Removed the code to start the tNetTask.01d,21jan97,gnn Added muxBuf* code to handle buffering system. Added code to handle the new SNARF option. Removed all loaning and reference counting stuff. Removed TxBuf stuff.01e,23oct96,gnn name changes to follow coding standards. removed some compiler warnings.01d,22oct96,gnn added routines to start and stop drivers. added code to handle buffer loaning startup requests on both the protocol and device side. replaced netVectors with netBuffers.01c,23sep96,gnn moved some generic code to here from the driver.01b,22Apr96,gnn filling in with real code.01a,21Mar96,gnn written.*/ /*DESCRIPTIONThis library provides the routines that define the MUX interface, a facilitythat handles communication between the data link layer and the networkprotocol layer. Using the MUX, the VxWorks network stack has decoupled thedata link and network layers. Thus, drivers and protocols no longer need knowledge of each other's internals. As a result, the network driver and protocol are nearly independent of each another. This independence makes it much easier to add a new drivers or protocols. For example, if you add a new END, all existing MUX-based protocols can use the newdriver. Likewise, if you add a new MUX-based protocol, any existing END can use the MUX to access the new protocol. INCLUDE FILES: errno.h, lstLib.h, logLib.h, string.h,m2Lib.h, bufLib.h, if.h, end.h, muxLib.hSEE ALSO.I "Network Protocol Toolkit User's Guide"*//* includes */#include "vxWorks.h"#include "taskLib.h"#include "stdio.h"#include "errno.h"#include "errnoLib.h"#include "lstLib.h"#include "logLib.h"#include "string.h"#include "m2Lib.h"#include "net/if.h" /* Needed for IFF_LOAN flag. */#include "bufLib.h"#include "semLib.h"#include "end.h" /* Necessary for any END as well as the MUX */#include "muxLib.h"#include "etherLib.h"#include "rebootLib.h"/* defints */#define STREQ(A, B) (strcmp(A, B) == 0 ? 1 : 0)#define NET_TASK_NAME "tNetTask"/* globals */int muxDebug = 0;SEM_ID muxLock = NULL; /* To lock on muxDevLoads. *//* locals */LOCAL LIST endList;LOCAL LIST addrResList[MUX_MAX_IFTYPE + 1]; /* IFT_xxx begins from 1 *//* forward declarations *//********************************************************************************* muxLibInit - initialize global state for the MUX** This routine initializes all global state for the MUX.** RETURNS: OK or ERROR.*/STATUS muxLibInit (void) { int count; if (muxLock != NULL) return (OK); muxLock = semBCreate(SEM_Q_PRIORITY, SEM_FULL); if (muxLock == NULL) return (ERROR); /* Initialize our lists to empty. */ /* addrResList[0] will not be used because IFT_xxx begins from 1 */ for (count = 0; count <= MUX_MAX_IFTYPE; count++) lstInit (&addrResList[count]); lstInit (&endList); /* Add hook to stop all ENDs when the system reboots */ if (rebootHookAdd ((FUNCPTR) muxDevStopAll) != OK) { return (ERROR); } return (OK); } /******************************************************************************* * muxDevLoad - load a driver into the MUX* * The muxDevLoad() routine loads a network driver into the MUX. Internally, * this routine calls the specified endLoad() to initialize the software state * of the device. After the device is initialized, muxDevStart() must be called * to start the device. * .IP <unit> 15* Expects the unit number of the device. * .IP <endLoad> * Expects a pointer to the network driver's endLoad() entry point. * .IP <pInitString> * Expects a pointer to an initialization string, a colon-delimited list of * options. The muxDevLoad() routine passes this along blindly to * the endLoad() function.* .IP <loaning> * Expects a boolean value that tells the MUX whether the driver * supports buffer loaning on this device. If the low-level device cannot * support buffer loaning, passing in TRUE has no effect. * .IP <pBSP>* This argument is passed blindly to the driver, which may or may not use it. * It is provided so that the BSP can pass in tables of functions that the* driver can use but which are specific to the particular BSP on which* it runs.* * RETURNS: A pointer to the new device or NULL if an error occurred.** ERRNO: S_muxLib_LOAD_FAILED*/END_OBJ* muxDevLoad ( int unit, /* unit number fo device */ END_OBJ* (*endLoad) (char*, void*), /* load function of the driver */ char* pInitString, /* init string for this driver */ BOOL loaning, /* we loan buffers */ void* pBSP /* for BSP group */ ) { extern LIST endList; END_OBJ* pNew; END_TBL_ROW* pNode; char initString [END_INIT_STR_MAX]; char devName [END_NAME_MAX]; BOOL found = FALSE; bzero ( (char *)initString, END_INIT_STR_MAX); bzero ( (char *)devName, END_NAME_MAX); /* Let's mutually exclude here, wouldn't you say? */ semTake (muxLock, WAIT_FOREVER); /* * Loading a device is a two pass algorithm. * * This is Pass 1. * * In the first pass we as the device what its name is. If that name * exists in our table then we add the new node to the end of the * already existing list. If not then we create a new row in the * table, and place the new node as the zero'th (0) element in the node's * list. */ if (endLoad ( (char *)devName, NULL) != 0) { goto muxLoadErr; } if (endFindByName ( (char *)devName, unit) != NULL) { goto muxLoadErr; } for (pNode = (END_TBL_ROW *)lstFirst(&endList); pNode != NULL; pNode = (END_TBL_ROW *)lstNext(&pNode->node)) { if (STREQ (pNode->name, (char *)devName)) { found = TRUE; break; } } /* If there is no row for this device then add it. */ if (!found) { pNode = malloc(sizeof(END_TBL_ROW)); if (pNode == NULL) { goto muxLoadErr; } bzero ((char *)pNode, sizeof(END_TBL_ROW)); strncpy(pNode->name, devName, END_NAME_MAX - 1); pNode->name [END_NAME_MAX - 1] = EOS; lstAdd(&endList, &pNode->node); } /* * This is Pass 2. * * Now that we can determine a unique number we assign that number, to * the device and actually load it. */ sprintf ( (char *)initString, "%d:%s", unit, pInitString); pNew = (END_OBJ *)endLoad ( (char *)initString, pBSP); if (pNew == NULL) { goto muxLoadErr; } muxIoctl (pNew, EIOCSFLAGS, (char *)pNew->flags); /* * Leave this stuff last to prevent a race condition. The condition * would be that the driver could call the receive routine * (it should always of course check to make sure there is one) * before the buffer pool was set up. This would be bad. * */ lstAdd(&pNode->units, &pNew->node); pNew->receiveRtn = (FUNCPTR)muxReceive; semGive (muxLock); return (pNew); muxLoadErr: errnoSet (S_muxLib_LOAD_FAILED); semGive (muxLock); return (NULL); }/****************************************************************************** * muxDevStart - start a device by calling its start routine** This routine starts a device that is already initialized and loaded * into the MUX. Internally, muxDevStart() calls the device's endStart(), * which handles registering the driver's interrupt service routine and * whatever else is needed to allow the device to handle receiving and * transmitting. This call to endStart() provides a device-dependent way * to put the device into a running state. * * .IP <pCookie>* Expects a pointer to the END_OBJ returned from the muxDevLoad() that * loaded this driver into the MUX. This "cookie" is an identifier for the * device. * .LP** RETURNS: OK, ENETDOWN if <pCookie> does not represent a valid device,* or ERROR if the start routine for the device fails.** ERRNO: S_muxLib_NO_DEVICE*/STATUS muxDevStart ( void* pCookie /* a pointer to cookie returned by muxDevLoad() */ ) { int error; END_OBJ* pEnd; pEnd = (END_OBJ *)pCookie; if (pEnd == NULL) { errnoSet (S_muxLib_NO_DEVICE); error = ENETDOWN; } else { error = pEnd->pFuncTable->start(pEnd); } if (error == OK) { pEnd->mib2Tbl.ifAdminStatus = M2_ifAdminStatus_up; pEnd->mib2Tbl.ifOperStatus = M2_ifOperStatus_up; } return (error); }/****************************************************************************** * muxDevStop - stop a device by calling its stop routine** This routine stops the device specified in the <pCookie> parameter.* Internally, muxDevStop() calls the device's own stop routine, thus* putting the device into a stopped state in a device-dependent manner. * * .IP <pCookie> * Expects the pointer returned as the function value of the muxDevLoad() * call for this device. This pointer identifies the device to which the * MUX has bound this protocol. * .LP** RETURNS: OK, ENETDOWN if <pCookie> does not represent a valid device, or* ERROR if the stop routine for the device fails.** ERRNO: S_muxLib_NO_DEVICE*/STATUS muxDevStop ( void* pCookie /* pointer to cookie that identifies the device */ ) { int error; END_OBJ* pEnd; pEnd = (END_OBJ *)pCookie; if (pEnd == NULL) { errnoSet (S_muxLib_NO_DEVICE); error = ENETDOWN; } else { error = pEnd->pFuncTable->stop(pEnd); } return (error); }/******************************************************************************** muxShow - all configured Enhanced Network Drivers** If a driver is specified <pDevName> and <unit>, this routine reports the* name and type of each protocol bound to it.* If a <pDevName> is not given, the entire list of devices and their protocols* is shown.** .IP <pDevName> 20* Expects a pointer to a string containing the device name, or NULL* .IP <unit>* Expects a unit number for the device* .LP** RETURNS: N/A*/void muxShow ( char *pDevName, /* pointer to device name */ int unit /* unit number for the device */ ) { int curr; NET_PROTOCOL* pProto; END_OBJ* pEnd; END_TBL_ROW* pNode; /* If the name is not NULL then find the specific interface to show. */ if (pDevName != NULL) { pEnd = endFindByName(pDevName, unit); if (pEnd == NULL) { printf("Device %s unit %d not found.\n", pDevName, unit); return; } printf("Device: %s Unit: %d\n", pEnd->devObject.name, pEnd->devObject.unit); printf("Description: %s\n", pEnd->devObject.description); /* See if there is an output protocol. */ if (pEnd->outputFilter != NULL) { printf("Output protocol: Recv 0x%lx\n", (unsigned long)pEnd->outputFilter); } /* List the rest of the regular protocols for the device. */ curr = 0; for (pProto = (NET_PROTOCOL *)lstFirst(&pEnd->protocols); pProto != NULL; pProto = (NET_PROTOCOL *)lstNext(&pProto->node)) { printf("Protocol: %s\tType: %ld\tRecv 0x%lx\tShutdown 0x%lx\n", pProto->name, pProto->type, (unsigned long)pProto->stackRcvRtn, (unsigned long) pProto->stackShutdownRtn); curr++; } } else /* Show ALL configured ENDs. */ { for (pNode = (END_TBL_ROW *)lstFirst(&endList); pNode != NULL; pNode = (END_TBL_ROW *)lstNext(&pNode->node)) { for (pEnd = (END_OBJ *)lstFirst(&pNode->units); pEnd != NULL; pEnd = (END_OBJ *)lstNext(&pEnd->node)) { printf("Device: %s Unit: %d\n", pEnd->devObject.name, pEnd->devObject.unit); printf("Description: %s\n", pEnd->devObject.description); if (pEnd->outputFilter != NULL) { printf("Output protocol: Recv 0x%lx\n", (unsigned long)pEnd->outputFilter); } curr = 0; for (pProto = (NET_PROTOCOL *)lstFirst(&pEnd->protocols); pProto != NULL; pProto = (NET_PROTOCOL *)lstNext(&pProto->node)) { printf("Protocol: %s\tType: %ld\tRecv 0x%lx\tShutdown 0x%lx\n", pProto->name, pProto->type, (unsigned long)pProto->stackRcvRtn, (unsigned long)pProto->stackShutdownRtn); curr++; } } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -