⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 endlib.c

📁 操作系统vxworks平台下end设备的驱动程序,支持多种芯片,支持多种cpu
💻 C
📖 第 1 页 / 共 2 页
字号:
* through <pSrcAddr> and <pDstAddr> mBlks and returns an M_BLK_ID to the* assembled link level header.  If the <bcastFlag> argument is TRUE, it* sets the destination address to the link-level broadcast address and* ignores the <pDstAddr> contents. This routine prepends the link level header* into <pMblk> if there is enough space available or it allocates a new* mBlk/clBlk/cluster and prepends the new mBlk to the mBlk chain passed in* <pMblk>.  This routine returns a pointer to an mBlk which contains the* link level header information.** RETURNS: M_BLK_ID or NULL.** NOMANUAL*/M_BLK_ID end8023AddressForm    (    M_BLK_ID pMblk,    M_BLK_ID pSrcAddr,    M_BLK_ID pDstAddr,    BOOL bcastFlag    )    {    short dataLen;     /* length of data including LLC */    USHORT *pSrc;    USHORT *pDst;    struct llc * pLlc; /* link layer control header */    dataLen = pMblk->mBlkPktHdr.len + LLC_SNAP_FRAMELEN;    dataLen = htons (dataLen);     M_PREPEND(pMblk, SIZEOF_ETHERHEADER + LLC_SNAP_FRAMELEN, M_DONTWAIT);    if (pMblk != NULL)	{        /* Fill in destination address */        pDst = (USHORT *)pMblk->m_data;	if (bcastFlag)            {            pDst[0] = 0xFFFF;            pDst[1] = 0xFFFF;            pDst[2] = 0xFFFF;            }	else            {            pSrc = (USHORT *)pDstAddr->m_data;            pDst[0] = pSrc[0];            pDst[1] = pSrc[1];            pDst[2] = pSrc[2];            }        /* Fill in source address */        pDst += 3;        pSrc = (USHORT *)pSrcAddr->m_data;        pDst[0] = pSrc[0];        pDst[1] = pSrc[1];        pDst[2] = pSrc[2];        /* Fill in length */        pDst += 3;        pDst[0] = dataLen;	/* Fill in LLC using SNAP values */	pDst++;        pLlc = (struct llc *) pDst;	pLlc->llc_dsap = LLC_SNAP_LSAP;	pLlc->llc_ssap = LLC_SNAP_LSAP; 	pLlc->llc_un.type_snap.control = LLC_UI;        pLlc->llc_un.type_snap.org_code[0] =        pLlc->llc_un.type_snap.org_code[1] =        pLlc->llc_un.type_snap.org_code[2] = 0;	/* Enter ethernet network type code into the LLC snap field */        pLlc->llc_un.type_snap.ether_type = pDstAddr->mBlkHdr.reserved;	}    return (pMblk);    }/******************************************************************************** endEtherAddressForm - form an Ethernet address into a packet** This routine accepts the source and destination addressing information * through <pSrcAddr> and <pDstAddr> and returns an 'M_BLK_ID' that points * to the assembled link-level header.  To do this, this routine prepends * the link-level header into the cluster associated with <pMblk> if there * is enough space available in the cluster.  It then returns a pointer to * the pointer referenced in <pMblk>.  However, if there is not enough space * in the cluster associated with <pMblk>, this routine reserves a * new 'mBlk'-'clBlk'-cluster construct for the header information. * It then prepends the new 'mBlk' to the 'mBlk' passed in <pMblk>.  As the * function value, this routine then returns a pointer to the new 'mBlk', * which the head of a chain of 'mBlk' structures.  The second element of this * chain is the 'mBlk' referenced in <pMblk>. ** RETURNS: M_BLK_ID or NULL.*/M_BLK_ID endEtherAddressForm    (    M_BLK_ID pMblk,     /* pointer to packet mBlk */    M_BLK_ID pSrcAddr,  /* pointer to source address */    M_BLK_ID pDstAddr,  /* pointer to destination address */    BOOL bcastFlag      /* use link-level broadcast? */    )    {    USHORT *pDst;    USHORT *pSrc;    M_PREPEND(pMblk, SIZEOF_ETHERHEADER, M_DONTWAIT);    /*     * This routine has been optimized somewhat in order to avoid     * the use of bcopy(). On some architectures, a bcopy() could     * result in a call into (allegedly) optimized architecture-     * specific routines. This may be fine for copying large chunks     * of data, but we're only copying 6 bytes. It's simpler just     * to open code some 16-bit assignments. The compiler would be     * hard-pressed to produce sub-optimal code for this, and it     * avoids at least one function call (possibly several).     */    if (pMblk != NULL)	{        pDst = (USHORT *)pMblk->m_data;	if (bcastFlag)            {            pDst[0] = 0xFFFF;            pDst[1] = 0xFFFF;            pDst[2] = 0xFFFF;            }	else            {            pSrc = (USHORT *)pDstAddr->m_data;            pDst[0] = pSrc[0];            pDst[1] = pSrc[1];            pDst[2] = pSrc[2];            }	/* Advance to the source address field, fill it in. */        pDst += 3;        pSrc = (USHORT *)pSrcAddr->m_data;        pDst[0] = pSrc[0];        pDst[1] = pSrc[1];        pDst[2] = pSrc[2];	((struct ether_header *)pMblk->m_data)->ether_type =	    pDstAddr->mBlkHdr.reserved;	}    return (pMblk);    }/******************************************************************************** endEtherPacketDataGet - return the beginning of the packet data** This routine fills the given <pLinkHdrInfo> with the appropriate offsets.** RETURNS: OK or ERROR.*/STATUS endEtherPacketDataGet    (    M_BLK_ID            pMblk,    LL_HDR_INFO *       pLinkHdrInfo    )    {    struct ether_header *  pEnetHdr;    struct ether_header    enetHdr;    struct llc *           pLLCHdr;    struct llc             llcHdr;    USHORT                 etherType;    pLinkHdrInfo->destAddrOffset        = 0;    pLinkHdrInfo->destSize              = 6;    pLinkHdrInfo->srcAddrOffset         = 6;    pLinkHdrInfo->srcSize               = 6;    /* Try for RFC 894 first as it's the most common. */    /*      * make sure entire ether_header is in first M_BLK      * if not then copy the data to a temporary buffer      */    if (pMblk->mBlkHdr.mLen < SIZEOF_ETHERHEADER) 	{	pEnetHdr = &enetHdr;	if (netMblkOffsetToBufCopy (pMblk, 0, (char *) pEnetHdr, 				    SIZEOF_ETHERHEADER, (FUNCPTR) bcopy) 	    < SIZEOF_ETHERHEADER)	    {	    return (ERROR);	    }	}    else	pEnetHdr = (struct ether_header *)pMblk->mBlkHdr.mData;    etherType = ntohs(pEnetHdr->ether_type);    /* Deal with 802.3 addressing. */    /* Here is the algorithm. */    /* If the etherType is less than the MTU then we know that */    /* this is an 802.x address from RFC 1700. */    if (etherType <= ETHERMTU)	{	/* 	 * make sure entire ether_header + llc_hdr is in first M_BLK 	 * if not then copy the data to a temporary buffer 	 */		if (pMblk->mBlkHdr.mLen < SIZEOF_ETHERHEADER + LLC_SNAP_FRAMELEN)	    {	    pLLCHdr = &llcHdr;	    if (netMblkOffsetToBufCopy (pMblk, SIZEOF_ETHERHEADER, 					(char *) pLLCHdr, LLC_SNAP_FRAMELEN,					(FUNCPTR) bcopy)		< LLC_SNAP_FRAMELEN)		{		return (ERROR);		}	    }	else	    pLLCHdr = (struct llc *)((char *)pEnetHdr + SIZEOF_ETHERHEADER);		/* Now it may be IP over 802.x so we check to see if the */	/* destination SAP is IP, if so we snag the ethertype from the */	/* proper place. */		/* Now if it's NOT IP over 802.x then we just used the DSAP as */	/* the etherType.  */		if (pLLCHdr->llc_dsap == LLC_SNAP_LSAP)	    {	    etherType = ntohs(pLLCHdr->llc_un.type_snap.ether_type);	    pLinkHdrInfo->dataOffset = SIZEOF_ETHERHEADER + 8;	    }	else	    { /* no SNAP header */	    pLinkHdrInfo->dataOffset = SIZEOF_ETHERHEADER + 3;	    etherType = pLLCHdr->llc_dsap;	    }	}    else	{	pLinkHdrInfo->dataOffset        = SIZEOF_ETHERHEADER;	}    pLinkHdrInfo->pktType               = etherType;    return (OK);    }/******************************************************************************** endEtherPacketAddrGet - locate the addresses in a packet** This routine takes a 'M_BLK_ID', locates the address information, and * adjusts the M_BLK_ID structures referenced in <pSrc>, <pDst>, <pESrc>, * and <pEDst> so that their pData members point to the addressing * information in the packet.  The addressing information is not copied. * All 'mBlk' structures share the same cluster.** RETURNS: OK or ERROR.*/STATUS endEtherPacketAddrGet    (    M_BLK_ID pMblk, /* pointer to packet */    M_BLK_ID pSrc,  /* pointer to local source address */    M_BLK_ID pDst,  /* pointer to local destination address */    M_BLK_ID pESrc, /* pointer to remote source address (if any) */    M_BLK_ID pEDst  /* pointer to remote destination address (if any) */    )    {    if (pSrc != NULL)	{	pSrc = netMblkDup (pMblk, pSrc);	pSrc->mBlkHdr.mData += 6;	pSrc->mBlkHdr.mLen = 6;	}    if (pDst != NULL)	{	pDst = netMblkDup (pMblk, pDst);	pDst->mBlkHdr.mLen = 6;	}    if (pESrc != NULL)	{	pESrc = netMblkDup (pMblk, pESrc);	pESrc->mBlkHdr.mData += 6;	pESrc->mBlkHdr.mLen = 6;	}    if (pEDst != NULL)	{	pEDst = netMblkDup (pMblk, pEDst);	pEDst->mBlkHdr.mLen = 6;	}        return (OK);    }/*************************************************************************** * * endPollStatsPoll - poll an interface's information * * This routine calls the endPollStatsIfPoll() routine to gather * information from a particular interface, then re-arms the interface's * polling watchdog timer. * * NOMANUAL * * RETURNS: N/A * */LOCAL void endPollStatsPoll    (    END_IFDRVCONF	*pDrvConf    )    {    if (pDrvConf == NULL)        return;    /* Gather the stats */    pDrvConf->ifPollRtn (pDrvConf);    /* Reload the watchdog. */    wdStart(pDrvConf->ifWatchdog, pDrvConf->ifPollInterval,            (FUNCPTR) endPollStatsJobQueue, (int) (pDrvConf));    return;    }/*************************************************************************** * * endPollStatsJobQueue - polling stats counter scheduler routine * * This routine is an intermediary function necessitated by the fact * that wdStart() only takes two arguments: we need to pass it three * (netJobAdd(), plus two others). This routine just invokes netJobAdd() * to call the endPollStatsIfPoll() routine and passes it a pointer to * the END_IFDRVCONF structure being polled. We must use netJobAdd() * here to avoid executing the rest of the polling code at interrupt * context. * * NOMANUAL * * RETURNS: N/A * */LOCAL void endPollStatsJobQueue    (    END_IFDRVCONF	*pDrvConf    )    {    netJobAdd ((FUNCPTR) endPollStatsPoll, (int) pDrvConf, 0, 0, 0, 0);    return;    }/******************************************************************************** endPollStatsInit - initialize polling statistics updates** This routine is used to begin polling of the interface specified by* pCookie and will periodically call out to the pIfPollRtn function, which* will collect the interface statistics. If the driver supports polling* updates, this routine will start a watchdog that will invoke the* pIfPollRtn routine periodically. The watchdog will automatically* re-arm itself. The pIfPollRtn will be passed a pointer to the driver's* END_IFDRVCONF structure as an argument.** RETURNS: ERROR if the driver doesn't support polling, otherwise OK.*/STATUS endPollStatsInit    (    void *		pCookie,    FUNCPTR		pIfPollRtn    )    {    END_IFDRVCONF *	pDrvConf;    int			error;    /* Sanity check */    if (pCookie == NULL || pIfPollRtn == NULL)        return (ERROR);    /* Get this driver's configuration info */    error = muxIoctl (pCookie, EIOCGPOLLCONF, (caddr_t) &pDrvConf);    /* Return error if driver doesn't support stats polling. */    if (error)        return (error);    /* Create the watchdog. */    pDrvConf->ifWatchdog = wdCreate ();    if (pDrvConf->ifWatchdog == NULL)        return (ERROR);    pDrvConf->ifEndObj = NULL;    pDrvConf->ifMuxCookie = pCookie;    pDrvConf->ifPollRtn = pIfPollRtn;    /* Kick off the watchdog. */    wdStart (pDrvConf->ifWatchdog, pDrvConf->ifPollInterval,             (FUNCPTR) endPollStatsJobQueue, (int) (pDrvConf));    return (OK);    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -