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

📄 mbcend.c

📁 Tornado 2.0.2 source code!vxworks的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	if (!(pDrvCtrl->flags & MBC_POLLING))	    END_TX_SEM_GIVE (&pDrvCtrl->end);        return (END_ERR_BLOCK);	}    pOrig = pBuf = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId);    if (pBuf == NULL)        {	DRV_LOG (DRV_DEBUG_TX | DRV_DEBUG_ERROR,		 "%s%d: mbcSend: out of clusters\n",		 (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6);	if (!(pDrvCtrl->flags & MBC_POLLING))	    END_TX_SEM_GIVE (&pDrvCtrl->end);        netMblkClChainFree (pMblk);        return (ERROR);        }    pBuf += pDrvCtrl->offset;    len = netMblkToBufCopy (pMblk, pBuf, NULL);    netMblkClChainFree (pMblk);     len = max (len, ETHERSMALL);    /* place a transmit request */    if (!(pDrvCtrl->flags & MBC_POLLING))        oldLevel = intLock ();        pTxBd->dataPointer = pBuf;    pTxBd->dataLength = len;    pTxBd->statusMode &= ~(MBC_TXBD_ERRS|MBC_TXBD_RC);    pTxBd->statusMode |= MBC_TXBD_R;    /* Advance our management index, and register for cleaning */    pDrvCtrl->txBdNext = (pDrvCtrl->txBdNext + 1) % pDrvCtrl->txBdNum;    pDrvCtrl->freeRtn [pDrvCtrl->txBdNext] = (FUNCPTR) netClFree;    pDrvCtrl->freeData [pDrvCtrl->txBdNext].arg1 = pDrvCtrl->end.pNetPool;    pDrvCtrl->freeData [pDrvCtrl->txBdNext].arg2 = pOrig;    if (!(pDrvCtrl->flags & MBC_POLLING))	{        intUnlock (oldLevel);	END_TX_SEM_GIVE (&pDrvCtrl->end);	}        /* Bump the statistic counter. */    END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);    return (OK);    }/******************************************************************************** mbcPacketGet - get next received message** Get next received message.  Returns NULL if none are* ready.** RETURNS: ptr to next packet, or NULL if none ready.** NOMANUAL*/char* mbcPacketGet    (    MBC_DEVICE *	pDrvCtrl	/* device structure */    )    {    volatile MBC_BD *	pRxBd;        pRxBd = &pDrvCtrl->rxBdBase [pDrvCtrl->rxBdNext];        while (!(pRxBd->statusMode & MBC_RXBD_E))        {        /* data chaining is not supported - check all error conditions */        if (((pRxBd->statusMode & (MBC_RXBD_F  | MBC_RXBD_L))	                       == (MBC_RXBD_F  | MBC_RXBD_L)) &&            !(pRxBd->statusMode & (MBC_RXBD_CL | MBC_RXBD_OV |                                   MBC_RXBD_CR | MBC_RXBD_SH |                                   MBC_RXBD_NO | MBC_RXBD_LG)))	    {	    return (pRxBd->dataPointer);	    }	END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);		/*	 * Fix for errata #9 -- Device Errata, Feb 20, 1997.	 * Ethernet frames may be incorrectly received after a rx FIFO	 * overflow.	 */	if ((pRxBd->statusMode & MBC_RXBD_L)	    && !(pRxBd->statusMode & MBC_RXBD_F))	    {	    mbcDeviceRestart (pDrvCtrl);	    return (NULL);	    }        /* reset buffer descriptor as empty */        pRxBd->statusMode |= MBC_RXBD_E;                /* Advance our management index */        pDrvCtrl->rxBdNext = (pDrvCtrl->rxBdNext + 1) % pDrvCtrl->rxBdNum;        pRxBd = &pDrvCtrl->rxBdBase [pDrvCtrl->rxBdNext];        }    return (NULL);    }/******************************************************************************** mbcRecv - process the next incoming packet** Handles one incoming packet.  The packet is checked for errors.** RETURNS: OK.** NOMANUAL**/LOCAL STATUS mbcRecv    (    MBC_DEVICE *	pDrvCtrl,	/* device structure */    char *		pData		/* packet to process */    )    {    int			len;    M_BLK_ID		pMblk;    char *		pNewCluster;    char *		pCluster;    CL_BLK_ID		pClBlk;    volatile MBC_BD *	pRxBd;    pRxBd = &pDrvCtrl->rxBdBase [pDrvCtrl->rxBdNext];    /*     * We implicitly are loaning here, if copying is necessary this     * step may be skipped, but the data must be copied before being     * passed up to the protocols.     */        pNewCluster = netClusterGet (pDrvCtrl->end.pNetPool, pDrvCtrl->pClPoolId);    if (pNewCluster == NULL)        {	DRV_LOG (DRV_DEBUG_RX | DRV_DEBUG_ERROR,		 "%s%d: mbcRecv: out of clusters\n",		 (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6);	END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);	goto cleanRXD;        }    /* Grab a cluster block to marry to the cluster we received. */    pClBlk = netClBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT);    if (pClBlk == NULL)        {	DRV_LOG (DRV_DEBUG_RX | DRV_DEBUG_ERROR,		 "%s%d: mbcRecv: out of cluster blocks\n",		 (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6);        netClFree (pDrvCtrl->end.pNetPool, pNewCluster);	END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);	goto cleanRXD;        }        /*     * OK we've got a spare, let's get an M_BLK_ID and marry it to the     * one in the ring.     */    pMblk = mBlkGet (pDrvCtrl->end.pNetPool, M_DONTWAIT, MT_DATA);    if (pMblk == NULL)        {	DRV_LOG (DRV_DEBUG_RX | DRV_DEBUG_ERROR,		 "%s%d: mbcRecv: out of M blocks\n",		 (int) DEV_NAME, pDrvCtrl->unit, 3, 4, 5, 6);        netClBlkFree (pDrvCtrl->end.pNetPool, pClBlk);         netClFree (pDrvCtrl->end.pNetPool, pNewCluster);	END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_ERRS, +1);	goto cleanRXD;        }    DRV_LOG (DRV_DEBUG_RX,	     "%s%d: mbcRecv %d: dataLength=%d dataPointer=%x data=%x\n",	     (int) DEV_NAME, pDrvCtrl->unit,	     pDrvCtrl->rxBdNext, pRxBd->dataLength,	     (int) pRxBd->dataPointer, (int) pData);    /* Add one to our unicast data. */    END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);    len = pRxBd->dataLength;    pCluster = pRxBd->dataPointer - pDrvCtrl->offset;    /* Join the cluster to the MBlock */    netClBlkJoin (pClBlk, pCluster, len, NULL, 0, 0, 0);    netMblkClJoin (pMblk, pClBlk);    pMblk->mBlkHdr.mData += pDrvCtrl->offset;    pMblk->mBlkHdr.mLen = len;    pMblk->mBlkHdr.mFlags |= M_PKTHDR;    pMblk->mBlkPktHdr.len = len;    /* make the packet data coherent */    MBC_CACHE_INVALIDATE (pMblk->mBlkHdr.mData, len);    /* Installed (adjusted) new cluster, and reset descriptor */    pRxBd->dataPointer = pNewCluster + pDrvCtrl->offset;    pRxBd->statusMode |= MBC_RXBD_E;    /* Advance our management index */    pDrvCtrl->rxBdNext = (pDrvCtrl->rxBdNext + 1) % pDrvCtrl->rxBdNum;#ifdef DRV_DEBUG    {    char *pAddress = pCluster + pDrvCtrl->offset;    if (pAddress[0] & 0x01)	DRV_LOG (DRV_DEBUG_RX | DRV_DEBUG_MULTI,		 "Recv Multicast %02x:%02x:%02x:%02x:%02x:%02x\n",		 pAddress[0]&0xff, pAddress[1]&0xff, pAddress[2]&0xff,		 pAddress[3]&0xff, pAddress[4]&0xff, pAddress[5]&0xff);    }#endif    /* Call the upper layer's receive routine. */    END_RCV_RTN_CALL (&pDrvCtrl->end, pMblk);    return (OK);cleanRXD:    /* Reset descriptor and advance management index */    pRxBd->statusMode |= MBC_RXBD_E;    pDrvCtrl->rxBdNext = (pDrvCtrl->rxBdNext + 1) % pDrvCtrl->rxBdNum;    return (OK);    }/******************************************************************************** mbcHandleRcvInt - 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.** The double loop is to protect against a race condition where the interrupt* code see rxHandling as TRUE, but it is then turned off by task code.* This race is not fatal, but does cause occassional delays until a second* packet is received and then triggers the netTask to call this routine again.** RETURNS: N/A.*/LOCAL void mbcHandleRcvInt    (    MBC_DEVICE *	pDrvCtrl	/* interrupting device */    )    {    char *	pData;    do        {        pDrvCtrl->rxHandling = TRUE;        while ((pData = mbcPacketGet (pDrvCtrl)) != NULL)            mbcRecv (pDrvCtrl, pData);        pDrvCtrl->rxHandling = FALSE;        }    while (mbcPacketGet (pDrvCtrl) != NULL);    }/******************************************************************************** mbcIoctl - the driver I/O control routine** Process an ioctl request.** RETURNS: A command specific response, usually OK or ERROR.*/LOCAL int mbcIoctl    (    void *		pObj,		/* device receiving command */    int			cmd,		/* ioctl command code */    caddr_t		data		/* command argument */    )    {    MBC_DEVICE *	pDrvCtrl = pObj;	/* device receiving command */    int			error = 0;    long		value;    switch (cmd)            {        case EIOCSADDR:	    if (data == NULL)		return (EINVAL);            bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end),		   END_HADDR_LEN(&pDrvCtrl->end));            break;        case EIOCGADDR:	    if (data == NULL)		return (EINVAL);            bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *) data,		   END_HADDR_LEN(&pDrvCtrl->end));            break;        case EIOCSFLAGS:	    value = (long)data;	    if (value < 0)		{		value = -(value - 1);		END_FLAGS_CLR (&pDrvCtrl->end, value);		}	    else		{		END_FLAGS_SET (&pDrvCtrl->end, value);		}	    mbcConfig (pDrvCtrl);            break;        case EIOCGFLAGS:	    *(int *)data = END_FLAGS_GET(&pDrvCtrl->end);            break;	case EIOCPOLLSTART:	/* Begin polled operation */	    mbcPollStart (pDrvCtrl);	    break;	case EIOCPOLLSTOP:	/* End polled operation */	    mbcPollStop (pDrvCtrl);	    break;        case EIOCGMIB2:		/* return MIB information */            if (data == NULL)                return (EINVAL);            bcopy ((char *)&pDrvCtrl->end.mib2Tbl, (char *) data,		   sizeof(pDrvCtrl->end.mib2Tbl));            break;	            case EIOCGFBUF:		/* return minimum First Buffer for chaining */            if (data == NULL)                return (EINVAL);            *(int *) data = MBC_MIN_FBUF;            break;	            default:            error = EINVAL;        }    return (error);    }/******************************************************************************** mbcAddrFilterSet - set the address filter for multicast addresses** This routine goes through all of the multicast addresses on the list* of addresses (added with the endAddrAdd() routine) and sets the* device's filter correctly.** RETURNS: N/A.*/void mbcAddrFilterSet    (    MBC_DEVICE *	pDrvCtrl		/* device to be updated */    )    {    int			len;    int			count;    u_char		c;    u_char *		pCp;    u_long		crc;    ETHER_MULTI *	pCurr;        pDrvCtrl->mcastFilter[0] = 0x00;    pDrvCtrl->mcastFilter[1] = 0x00;    pDrvCtrl->mcastFilter[2] = 0x00;    pDrvCtrl->mcastFilter[3] = 0x00;    pDrvCtrl->mcastFilter[4] = 0x00;    pDrvCtrl->mcastFilter[5] = 0x00;    pDrvCtrl->mcastFilter[6] = 0x00;    pDrvCtrl->mcastFilter[7] = 0x00;    for (pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end);	 pCurr != NULL;	 pCurr = END_MULTI_LST_NEXT(pCurr))	{	/*	 * AUTODIN-II, adapted for ethernet (bit reversed),	 * taken from the ln7990End.c driver	 */	pCp = (unsigned char *)&pCurr->addr;	crc = 0xffffffff;	for (len = 6; --len >= 0;)	    {	    c = *pCp++;	    for (count = 0; count < 8; count++)		{		if ((c & 0x01) ^ (crc & 0x01))		    {		    crc >>= 1;		    crc = crc ^ 0xedb88320;		    }		else		    {		    crc >>= 1;		    }		c >>= 1;		}	    }	/* Just want the 6 most significant bits. */	crc = crc >> 26;	/* Turn on the corresponding bit in the filter. */	pDrvCtrl->mcastFilter [crc >> 3] |= (1 << (crc & 0x07));	}    }/******************************************************************************** mbcPollRcv - routine to receive a packet in polled mode.** This routine is called by a user to try and get a packet from the

⌨️ 快捷键说明

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