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

📄 iolicomend.c

📁 操作系统vxworks平台下end设备的驱动程序,支持多种芯片,支持多种cpu
💻 C
📖 第 1 页 / 共 5 页
字号:
LOCAL STATUS iOlicomRecv    (    END_DEVICE *	pDrvCtrl,	/* pointer to END_DEVICE structure */    RX_BD *		pRxBd    )    {    END_OBJ *   pOliObj = &pDrvCtrl->endObj;    M_BLK_ID    pMblk;      /* MBLK to send upstream */    CL_BLK_ID   pClBlk;     /* pointer to clBlk */    char *      pBuf;       /* A replacement buffer for the current RxD */    char *      pData;      /* Data pointer for the current RxD */    int         len;        /* Len of the current data */    END_LOG_MSG (END_DEBUG_RX, "iOlicomRecv\n", 0, 0, 0, 0, 0, 0);    /* Allocate an MBLK, and a replacement buffer */    pMblk = NET_MBLK_ALLOC();    pBuf  = NET_BUF_ALLOC();    pClBlk = NET_CL_BLK_ALLOC();    if ((pMblk == NULL) || (pBuf == NULL) || (pClBlk == NULL))        {        END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);        if (pMblk)            NET_MBLK_FREE (pMblk);        if (pBuf)            NET_BUF_FREE (pBuf);        if (pClBlk)            NET_CL_BLK_FREE (pClBlk);        goto cleanRxBd;        }    /* Get the data pointer and len from the current RX_BD */    len   = pRxBd->dataLength;    pData = pRxBd->dataPointer;    pData -= pDrvCtrl->offset;    /* Associate the data pointer with the CL_BLK */    NET_CL_BLK_JOIN (pClBlk, pData, OLI_BUFSIZ);    /* Associate the CL_BLK with the MBLK */    NET_MBLK_CL_JOIN (pMblk, pClBlk);    pMblk->mBlkHdr.mData  += pDrvCtrl->offset;    pMblk->mBlkHdr.mFlags |= M_PKTHDR;	/* set the packet header */    pMblk->mBlkHdr.mLen    = len;	/* set the data len */    pMblk->mBlkPktHdr.len  = len;	/* set the total len */    /* Deal with memory alignment. */    pBuf += pDrvCtrl->offset;    /* Install the new data buffer */    pRxBd->dataPointer = pBuf;    /* mark the descriptor ready to receive */    pRxBd->statusMode |= RX_BD_EMPTY;    /* Bump the statistic counter. */    END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);    /* send up to protocol */    END_LOG_MSG (END_DEBUG_RX, ("Calling upper layer! \n"), 0, 0, 0, 0, 0, 0);    END_RCV_RTN_CALL (pOliObj, pMblk);    return OK;cleanRxBd:    /* mark the descriptor ready to receive */    pRxBd->statusMode |= RX_BD_EMPTY;    return OK;    }/********************************************************************************* iOlicomSend - the driver send routine** This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.* The buffer must already have the addressing information properly installed* in it.  This is done by a higher layer.** RETURNS: OK or ERROR.*/LOCAL STATUS iOlicomSend    (    END_DEVICE *	pDrvCtrl,	/* pointer to END_DEVICE structure */    M_BLK *		pMblk    )    {    TX_BD *		pTxBd;    char *		pBuf;    UINT8 *		pData;    UINT8 *		pDataEnd;    ULONG		addrC;    int			len;    int			s;    volatile UINT8 *	pR14;    END_LOG_MSG (END_DEBUG_ALL_FUNCS, "iOlicomSend()\n", 0, 0, 0, 0, 0, 0);    END_LOG_MSG (END_DEBUG_TX, "iOlicomSend()\n", 0, 0, 0, 0, 0, 0);    if (DRV_FLAGS_ISSET (OLI_POLLING))        {         NET_MBLK_CHAIN_FREE (pMblk); /* free the given mBlk chain */        errno = EINVAL;        return (ERROR);        }    /*     * Obtain exclusive access to transmitter.  This is necessary because     * we might have more than one stack transmitting at once.     */    END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);    END_LOG_MSG (END_DEBUG_TX, "iOlicomSend() got semaphore\n",		 0, 0, 0, 0, 0, 0);    /* get a free transmit frame descriptor */    pTxBd = iOlicomTxBdGet (pDrvCtrl);    addrC = (ULONG) pTxBd->dataPointer;    /* get a free buufer */    pBuf = NET_BUF_ALLOC();    if ((pTxBd == NULL) || (pBuf == NULL))        {        END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);        END_TX_SEM_GIVE (&pDrvCtrl->endObj);        if (pBuf)            NET_BUF_FREE (pBuf);        if (! DRV_FLAGS_ISSET(OLI_TX_CLEANING | OLI_TX_STOP))	    iOlicomTxBdQueueClean (pDrvCtrl);	s = intLock();        DRV_FLAGS_SET(OLI_TX_STOP);        /* transmitter not ready */	intUnlock (s);	/* just return without freeing mBlk chain */        return (END_ERR_BLOCK);        }    /* Copy and free the MBLK */    len = netMblkToBufCopy (pMblk, pBuf, NULL);    NET_MBLK_CHAIN_FREE (pMblk);    s = intLock();    /* Write the transmit buffer base address. */    PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R12, addrC);    PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R13, (addrC >> 8));    /* Write the command opcode, and reserved field for the packet */    WRITE_R14_R15 (CMD_TRANSMIT);    /* Write 16 bit status field */    WRITE_R14_R15 (0x00);    /* Write the chain pointer */    WRITE_R14_R15 (0x00);    /* Write the byte count low and high bytes */    WRITE_R14_R15 (len & ~XMT_CHAIN);    /*     * Copy data. Initialise pointer here to provoke the compiler into     * generating better code     */    pR14 = (volatile UINT8 *) (pDrvCtrl->pcmcia.oliAddr + I595_R14);    for (pData = (UINT8 *)pBuf, pDataEnd = pData + len; pData < pDataEnd ; )	WRITE_PTR_R14_R15 (pData, pR14);    /*     * The Ethernet chip can't receive a transmit command while a     * TRANSMIT is already in progress. The following test checks if the     * 82595TX chip is transmitting a packet before issuing another transmit     * command.     */    if (pDrvCtrl->txBdIndexC == pDrvCtrl->txBdNext)	{	/* Write the XMT base address register */	PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R10, addrC);	PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R11, (addrC >> 8));	/* Issue a XMT command to the 82595TX */	RUNCMD((UINT)(pDrvCtrl->pcmcia.oliAddr), CMD_TRANSMIT);	}    /* Save the buf info */    pDrvCtrl->freeBuf[pDrvCtrl->txBdNext].pClBuf  = pBuf;    /* incr BD count */    pDrvCtrl->txBdNext = (pDrvCtrl->txBdNext + 1) % pDrvCtrl->txBdNum;    intUnlock(s);    /* release exclusive access */    END_TX_SEM_GIVE (&pDrvCtrl->endObj);    /* Bump the statistic counter. */    END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);    END_LOG_MSG (END_DEBUG_ALL_FUNCS, "iOlicomSend() exit\n", 0, 0, 0, 0, 0, 0);    return (OK);    }/********************************************************************************* iOlicomTxBdGet - get an available transmit descriptor** Get next transmited message descriptor.  Returns NULL if none are* ready.** RETURNS: an available transmit descriptor, otherwise NULL.*/LOCAL TX_BD * iOlicomTxBdGet    (    END_DEVICE *	pDrvCtrl    )    {    ULONG       addrC;    int         status;    TX_BD *	pTxBd = &pDrvCtrl->txBdBase[pDrvCtrl->txBdNext];    addrC = (ULONG) pTxBd->dataPointer;    PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R12, addrC);    PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R13, (addrC >> 8));    READ_R14_R15 (status);    /* check if a transmit buffer descriptor is available */    if (!(status & TX_BD_READY) ||	 ((pDrvCtrl->txBdNext + 1) % pDrvCtrl->txBdNum) == pDrvCtrl->txBdIndexC)        return (NULL);    return (pTxBd);    }/********************************************************************************* iOlicomIoctl - the driver I/O control routine** Process an ioctl request.** This routine implements the network interface control functions.* It handles EIOCSADDR, EIOCGADDR, EIOCSFLAGS, EIOCGFLAGS,* EIOCPOLLSTART, EIOCPOLLSTOP, EIOCGMIB2, EIOCGFBUF commands.** RETURNS: OK if successful, otherwise EINVAL.*/LOCAL int iOlicomIoctl    (    END_DEVICE *	pDrvCtrl,	/* pointer to END_DEVICE structure */    int			cmd,		/* command to process */    char *		data		/* pointer to data */    )    {    int		error = 0;    long	value;    END_LOG_MSG (END_DEBUG_ALL_FUNCS, "iOlicomIoctl()\n", 0, 0, 0, 0, 0, 0);    switch ((UINT)cmd)        {        case EIOCSADDR:	    if (data == NULL)		return (EINVAL);            memcpy ((char *)END_HADDR(&pDrvCtrl->endObj), (char *)data,		   END_HADDR_LEN(&pDrvCtrl->endObj));            break;        case EIOCGADDR:	    if (data == NULL)		return (EINVAL);            memcpy ((char *)data, (char *)END_HADDR(&pDrvCtrl->endObj),		    END_HADDR_LEN(&pDrvCtrl->endObj));            break;        case EIOCSFLAGS:	    value = (long)data;	    if (value < 0)		{		value = -value;		value--;		END_FLAGS_CLR (&pDrvCtrl->endObj, value);		}	    else		{		END_FLAGS_SET (&pDrvCtrl->endObj, value);		}	    iOlicomConfig (pDrvCtrl);	    END_LOG_MSG (END_DEBUG_IOCTL, "endFlags %#x\n",			END_FLAGS_GET(&pDrvCtrl->endObj), 0, 0, 0, 0 ,0);            break;        case EIOCGFLAGS:	    *(int *)data = END_FLAGS_GET(&pDrvCtrl->endObj);            break;	case EIOCPOLLSTART:	    error = iOlicomPollStart (pDrvCtrl);	    break;	case EIOCPOLLSTOP:	    error = iOlicomPollStop (pDrvCtrl);	    break;        case EIOCGMIB2:            if (data == NULL)                return (EINVAL);            memcpy((char *)data, (char *)&pDrvCtrl->endObj.mib2Tbl,                  sizeof(pDrvCtrl->endObj.mib2Tbl));            break;        case EIOCGFBUF:            if (data == NULL)                return (EINVAL);            *(int *)data = OLI_MIN_FBUF;            break;        default:            error = EINVAL;        }    return (error);    }/******************************************************************************** iOlicomConfig - reconfigure the interface under us.** Reconfigure the interface setting promiscuous mode, and changing the* multicast interface list.** RETURNS: N/A*/LOCAL void iOlicomConfig    (    END_DEVICE *	pDrvCtrl	/* pointer to END_DEVICE structure */    )    {    /* Set promiscuous mode if it's asked for. */    if (END_FLAGS_GET (&pDrvCtrl->endObj) & IFF_PROMISC)	{	END_LOG_MSG (END_DEBUG_IOCTL, "Setting promiscuous mode on!\n",			 0, 0, 0, 0, 0, 0);        SELECTBANK (pDrvCtrl->pcmcia.oliAddr, 2);        PCMCIA_IO_WRITE (pDrvCtrl->pcmcia.oliAddr + I595_R2,		(PCMCIA_IO_READ (pDrvCtrl->pcmcia.oliAddr + I595_R2) |			BNK2_PCS_EN));	}    else	{	END_LOG_MSG (END_DEBUG_IOCTL, "Setting promiscuous mode off!\n",			 0, 0, 0, 0, 0, 0);	}    /* setup ethernet address and filtering mode */	    iOlicomAddrFilterSet (pDrvCtrl);    return;    }/******************************************************************************** iOlicomAddrFilterSet - set the address filter for multicast addresses** This routine goes through all of the multicast addresses on the list* of addresses (added with the iOlicomAddrAdd() routine) and sets the* device's filter correctly.** RETURNS: OK on success, ERROR otherwise.*/LOCAL STATUS iOlicomAddrFilterSet    (    END_DEVICE *	pDrvCtrl	/* pointer to END_DEVICE structure */    )    {    UINT8 *     pFltrFrm;    UINT8 *     pData;    ETHER_MULTI * pMCastNode;    TX_BD *	pTxBd;    int         length;    int         ix;    int         s;    int         index = 0;    ULONG       addrC;    END_LOG_MSG (END_DEBUG_ADDR, "iOlicomAddrFilterSet \n", 0, 0, 0, 0, 0, 0);    /* gain exclusive access to transmitter */    END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);    /* Select bank 0 of the Olicom register set */    SELECTBANK(pDrvCtrl->pcmcia.oliAddr, 0);    /* get a free transmit frame descriptor */    pTxBd = iOlicomTxBdGet (pDrvCtrl);    if (pTxBd == NULL)        {	END_TX_SEM_GIVE (&pDrvCtrl->endObj);        return (ERROR);        }    addrC = (ULONG) pTxBd->dataPointer;    /* get a buffer */     pFltrFrm = (UINT8 *)NET_BUF_ALLOC();     if (pFltrFrm == NULL)         {         END_LOG_MSG (END_DEBUG_LOAD, "netClusterGet failed\n",					0, 0, 0, 0, 0, 0);         END_TX_SEM_GIVE (&pDrvCtrl->endObj);         return (ERROR);         }    /* clear all entries */    memset (pFltrFrm, 0, FLTR_FRM_SIZE);    /* install multicast addresses */    pData = pFltrFrm;    for (pMCastNode = END_MULTI_LST_FIRST (&pDrvCtrl->endObj);

⌨️ 快捷键说明

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