📄 muxlib.c
字号:
* RETURNS: OK; ENETDOWN, if <pCookie> does not represent a valid driver;* or ERROR, if the driver's registered endMCastAddrGet() or nptMCastAddrGet() * routines fail.** ERRNO: S_muxLib_NO_DEVICE*/int muxMCastAddrGet ( void * pCookie, /* binding instance from muxBind() or muxTkBind() */ MULTI_TABLE * pTable /* pointer to a table to be filled and returned. */ ) { int error; END_OBJ * pEnd; pEnd = PCOOKIE_TO_ENDOBJ (pCookie); if (pEnd == NULL) { errnoSet(S_muxLib_NO_DEVICE); error = ENETDOWN; } else { error = pEnd->pFuncTable->mCastAddrGet(pEnd, pTable); } return (error); }/******************************************************************************** muxUnbind - detach a network service from the specified device** This routine disconnects a network service from the specified device. The* <pCookie> argument indicates the service/device binding returned by the* muxBind() or muxTkBind() routine. The <type> and <stackRcvRtn> arguments* must also match the values given to the original muxBind() or muxTkBind()* call.** NOTE: If muxUnbind() returns ERROR, and 'errno' is set to EINVAL, this* indicates that the device is not bound to the service.** RETURNS: OK; or ERROR, if muxUnbind() fails.* * VXWORKS AE PROTECTION DOMAINS* Under VxWorks AE, you can call muxUnBind() from within the kernel * protection domain only, and the data referenced in the <stackRcvRtn> and * <pCookie> parameters must reside in the kernel protection domain. * This restriction does not apply under non-AE versions of VxWorks. ** ERRNO: EINVAL, S_muxLib_NO_DEVICE*/STATUS muxUnbind ( void * pCookie, /* binding instance from muxBind() or muxTkBind() */ long type, /* type passed to muxBind() or muxTkBind() call */ FUNCPTR stackRcvRtn /* pointer to stack receive routine */ ) { int error; END_OBJ * pEnd; NET_PROTOCOL * pNode; FUNCPTR netStackRcvRtn = NULL; pEnd = PCOOKIE_TO_ENDOBJ (pCookie); if (pEnd == NULL) { errnoSet (S_muxLib_NO_DEVICE); error = EINVAL; return error; } else { /* Find and remove the matching binding. */ for (pNode = (NET_PROTOCOL *)lstFirst (&pEnd->protocols); pNode != NULL; pNode = (NET_PROTOCOL *)lstNext(&pNode->node)) { if (pNode->pNptCookie != pCookie) continue; /* * If necessary, fetch the actual stack receive routine * instead of the wrapper installed for END devices. */ if (pNode->nptFlag) { MUX_ID muxId = (MUX_ID)pNode->pSpare; if (muxId) netStackRcvRtn = muxId->netStackRcvRtn; } else netStackRcvRtn = pNode->stackRcvRtn; /* This test should always succeed since the entry matches. */ if (netStackRcvRtn == stackRcvRtn && pNode->type == type) { if (pNode->type == MUX_PROTO_SNARF) (pEnd->snarfCount)--; if (pNode->type == MUX_PROTO_OUTPUT) pEnd->outputFilter = NULL; lstDelete (&pEnd->protocols, &pNode->node); muxTkUnbindUpdate (pNode->pNptCookie); KHEAP_FREE( (char *)pNode); return (OK); } } } errnoSet (EINVAL); return (ERROR); } /******************************************************************************** muxDevUnload - unloads a device from the MUX** This routine unloads a device from the MUX. This breaks any network* connections that use the device. When this routine is called, each service* bound to the device disconnects from it with the stackShutdownRtn() routine* that was registered by the service. The stackShutdownRtn() should call* muxUnbind() to detach from the device. Then, muxDevUnload() calls the* device's endUnload() or nptUnload() routine.** .IP <pName>* Expects a pointer to a string containing the name of the device, for example* 'ln' or 'ei'** .IP <unit>* Expects the unit number of the device indicated by <pName>** VXWORKS AE PROTECTION DOMAINS* Under VxWorks AE, you can call muxDevUnLoad() from within the kernel * protection domain only. This restriction does not apply under non-AE * versions of VxWorks. ** RETURNS: OK, on success; ERROR, if the specified device was not found* or some other error occurred; or the error value returned by the driver's* unload() routine.** ERRNO: S_muxLib_UNLOAD_FAILED, S_muxLib_NO_DEVICE**/STATUS muxDevUnload ( char * pName, /* a string containing the name of the device */ /* for example, ln or ei */ int unit /* the unit number */ ) { int error; END_OBJ * pEnd = NULL; NET_PROTOCOL * pNetNode; NET_PROTOCOL * pNetNodeNext; END_TBL_ROW * pNode; void * pTemp = NULL; pEnd = endFindByName (pName, unit); if (pEnd != NULL) { semTake (muxLibState.lock, WAIT_FOREVER); /* * Find which row we're in. We know it's here because * the endFindByName() routine was successful. */ for (pNode = (END_TBL_ROW *)lstFirst (&endList); pNode != NULL; pNode = (END_TBL_ROW *)lstNext (&pNode->node)) { if (STREQ(pNode->name, pName)) break; } /* First we shutdown all of the protocols. */ for (pNetNode = (NET_PROTOCOL *) lstFirst (&pEnd->protocols); pNetNode != NULL; pNetNode = pNetNodeNext) { /* Save pointer to next node as shutdown rtn will free pNetNode */ pNetNodeNext = (NET_PROTOCOL *) lstNext (&pNetNode->node); if (pNetNode->stackShutdownRtn != NULL) { /* * stackShutdownRtn() is expected to call muxUnbind() which * will free the NET_PROTOCOL node, so that operation is not * necessary here. The END and NPT devices use different * shutdown prototypes. Select the appropriate format. */ if (pNetNode->nptFlag) { MUX_ID muxId = (MUX_ID)pNetNode->pSpare; void * pSpare = NULL; pSpare = (muxId) ? muxId->pNetCallbackId : NULL; pNetNode->stackShutdownRtn(pSpare); } else pNetNode->stackShutdownRtn (pEnd, pNetNode->pSpare); } else { /* * If no shutdown rtn then muxUnbind () will not be called and * we need to free the pNetNode ourselves. */ lstDelete (&pEnd->protocols, &pNetNode->node); KHEAP_FREE ((char *)pNetNode); } } /* Release BIB and delete node before unloading device driver */ muxTkUnloadUpdate (pEnd); lstDelete (&pNode->units, &pEnd->node); /* remember the device specific value for backward compatibility purpose */ pTemp = pEnd->devObject.pDevice; /* Unload (destroy) the end object */ error = pEnd->pFuncTable->unload (pEnd); /* * XXX Freeing END_OBJ(or DRV_CTRL) should be done by END, not here. * In futre, this code will be removed. */ if (pTemp == pEnd) { /* for backward compatibility, free the end_object */ KHEAP_FREE ((char *)pTemp); } /* * XXX I don't see how 'unload' can really fail. There's nothing the mux * can do to recover or continue using the END_OBJ. All the protocols are * already gone. */ if (error != OK) { errnoSet (S_muxLib_UNLOAD_FAILED); semGive (muxLibState.lock); return (ERROR); } /* Is this row empty? If so, remove it. */ if (lstCount (&pNode->units) == 0) { lstDelete (&endList, &pNode->node); KHEAP_FREE ((char *)pNode); } error = OK; semGive (muxLibState.lock); } else { errnoSet (S_muxLib_NO_DEVICE); error = ERROR; } return (error); }#endif /* STANDALONE_AGENT *//******************************************************************************** muxLinkHeaderCreate - attach a link-level header to a packet** This routine constructs a link-level header using the source address* of the device indicated by the <pCookie> argument as returned from the* muxBind() routine.** The <pDstAddr> argument provides an M_BLK_ID buffer containing the* link-level destination address.* Alternatively, the <bcastFlag> argument, if TRUE, indicates that the* routine should use the link-level broadcast address, if available for* the device. Although other information contained in the <pDstAddr>* argument must be accurate, the address data itself is ignored in that case.** The <pPacket> argument contains the contents of the resulting link-level* frame. This routine prepends the new link-level header to the initial* 'mBlk' in that network packet if space is available or allocates a new* 'mBlk'-'clBlk'-cluster triplet and prepends it to the 'mBlk' chain. * When construction of the header is complete, it returns an M_BLK_ID that * points to the initial 'mBlk' in the assembled link-level frame.** RETURNS: M_BLK_ID or NULL.** ERRNO: S_muxLib_INVALID_ARGS*/M_BLK_ID muxLinkHeaderCreate ( void * pCookie, /* protocol/device binding from muxBind() */ M_BLK_ID pPacket, /* structure containing frame contents */ M_BLK_ID pSrcAddr, /* structure containing source address */ M_BLK_ID pDstAddr, /* structure containing destination address */ BOOL bcastFlag /* use broadcast destination (if available)? */ ) { END_OBJ * pEnd; M_BLK_ID pMblkHdr = NULL; pEnd = PCOOKIE_TO_ENDOBJ (pCookie); if (pEnd == NULL) { errnoSet(S_muxLib_INVALID_ARGS); return (NULL); } if (pEnd->pFuncTable->formAddress != NULL) { pMblkHdr = pEnd->pFuncTable->formAddress (pPacket, pSrcAddr, pDstAddr, bcastFlag); } else { switch (pEnd->mib2Tbl.ifType) { case M2_ifType_ethernet_csmacd: case M2_ifType_iso88023_csmacd: M_PREPEND(pPacket, SIZEOF_ETHERHEADER, M_DONTWAIT); if ( pPacket == NULL) return NULL; if (bcastFlag) bcopy (etherbroadcastaddr, pPacket->m_data, 6); else bcopy(pDstAddr->m_data, pPacket->m_data, pDstAddr->m_len); bcopy(pSrcAddr->m_data, pPacket->m_data + pDstAddr->m_len, pSrcAddr->m_len); ((struct ether_header *)pPacket->m_data)->ether_type = pDstAddr->mBlkHdr.reserved; pMblkHdr = pPacket; break; default: break; } } return (pMblkHdr); }/******************************************************************************** muxAddressForm - form a frame with a link-layer address** Use this routine to create a frame with an appropriate link-layer address. * As input, this function expects the source address, the destination address, * and the data you want to include in the frame. When control returns from the * muxAddressForm() call, the <pMblk> parameter references a frame ready for * transmission. Internally, muxAddressForm() either prepended the link-layer * header to the data buffer supplied in <pMblk> (if there was enough room) or * it allocated a new 'mBlk'-'clBlk'-cluster and prepended the new 'mBlk' to * the 'mBlk' chain supplied in <pMblk>.** NOTE: You should set the 'pDstAddr.mBlkHdr.reserved' field to the network* service type.** .IP <pCookie> 13* Expects the cookie returned from the muxBind(). This cookie * indicates the device to which the MUX has bound this protocol. * .IP <pMblk>* Expects a pointer to the 'mBlk' structure that contains the packet. * .IP <pSrcAddr>* Expects a pointer to the 'mBlk' that contains the source address.* .IP <pDstAddr>* Expects a pointer to the 'mBlk' that contains the destination address.** NOTE: This routine is used only with ENDs, and is not needed for NPT* drivers.** VXWORKS AE PROTECTION DO
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -