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

📄 iolicomend.c

📁 操作系统vxworks平台下end设备的驱动程序,支持多种芯片,支持多种cpu
💻 C
📖 第 1 页 / 共 5 页
字号:
        pMCastNode != NULL;        pMCastNode = END_MULTI_LST_NEXT (pMCastNode))        {        for (ix = 0; ix < EADDR_LEN; ix++)            *(pData++) = pMCastNode->addr[ix];	        index++;        }    /* Set variables to copy the buffer in */    length = index * EADDR_LEN;    pData--;    s = intLock ();    /* disable ints during update */    /* 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_MC_SETUP);    /* 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 (length & ~XMT_CHAIN);    /* copy data */    for (; length > 0 ; length -= 2)        {        PCMCIA_IO_WRITE((UINT)(pDrvCtrl->pcmcia.oliAddr + I595_R14),					*pData--);        PCMCIA_IO_WRITE((UINT)(pDrvCtrl->pcmcia.oliAddr + I595_R15),					*pData--);        }    /* 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 MC_SETUP command to the 82595TX */    RUNCMD((UINT)(pDrvCtrl->pcmcia.oliAddr), CMD_MC_SETUP);    /* incr BD count */    pDrvCtrl->txBdNext = (pDrvCtrl->txBdNext + 1) % pDrvCtrl->txBdNum;    /* Spin until we've sent it. */    while (!(PCMCIA_IO_READ(pDrvCtrl->pcmcia.oliAddr + I595_R1) & BNK0_EXE_IT));    /* clear execution interrupt */    PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R1, BNK0_EXE_IT);    /* clean the transmit queue */    iOlicomTxBdQueueClean(pDrvCtrl);    intUnlock (s);   /* now iOlicomInt won't get confused */    /* free the buffer */    NET_BUF_FREE (pFltrFrm);    /* release exclusive access */    END_TX_SEM_GIVE (&pDrvCtrl->endObj);    END_LOG_MSG (END_DEBUG_ADDR, "iOlicomAddrFilterSet() exit\n",		 0, 0, 0, 0, 0, 0);    return (OK);    }/********************************************************************************* iOlicomPollReceive - routine to receive a packet in polled mode.** This routine is called by a user to try and get a packet from the* device. It returns EAGAIN if no packet is available. The caller must* supply a M_BLK_ID with enough space to contain the receiving packet. If* enough buffer is not available then EAGAIN is returned.** These routine should not call any kernel functions.** RETURNS: OK on success, EAGAIN on failure.*/LOCAL STATUS iOlicomPollReceive    (    END_DEVICE *	pDrvCtrl,	/* pointer to END_DEVICE structure */    M_BLK  *		pMblk    )    {    char *		pPacket;    int			status;    int			length;    int			event;    int			start;    int			nextStop;    BOOL		gotOne=FALSE;    volatile UINT8 *	pR14;    END_LOG_MSG (END_DEBUG_ALL_FUNCS, "iOlicomPollReceive()\n",		 0, 0, 0, 0, 0, 0);    if ((pMblk->mBlkHdr.mFlags & M_EXT) != M_EXT)        return (EAGAIN);    /* Read the device status register */    status = PCMCIA_IO_READ(pDrvCtrl->pcmcia.oliAddr + I595_R1);    /* If no interrupt then return. */    if (!(status & BNK0_RX_IT))	{	END_LOG_MSG (END_DEBUG_POLL_RX, "iOlicomPollReceive no rint\n",			 0, 0, 0, 0, 0, 0);        return (EAGAIN);	}    /*     * The RCV STOP register points to the last pair of bytes     * BEFORE the start of the next packet so we must add two     * bytes to reach the correct address.     */    start = PCMCIA_IO_READ(pDrvCtrl->pcmcia.oliAddr + I595_R6);    start |= (PCMCIA_IO_READ(pDrvCtrl->pcmcia.oliAddr + I595_R7) << 8);    start += 2;    /* Handle the roll over case */    if (start > RAM_RX_LIMIT)	start -= RAM_RX_BASE;    /* Set up address from where we wish to start reading data */    PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R12, start);    PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R13, (start >> 8));    /* The first word describes the state of reception.  */    READ_R14_R15 (event);    /* The following bit will be set once the packet is complete in memory. */    if (event & RCV_EOF)        {        /* Collect the status of the packet */	READ_R14_R15 (status);	/* get next packet pointer */	READ_R14_R15 (nextStop);	/* The next stop value is 2 bytes back in the circular buffer */	nextStop -= 2;	/* Handle the roll over case */	if (nextStop < RAM_RX_BASE)	    nextStop += RAM_RX_BASE;        /* get packet length */	READ_R14_R15 (length);        /* Check for errors */        if (!(status & RCV_OK) || ((length - SIZEOF_ETHERHEADER) <= 0))            {            /* bump input error packet counter */            END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);            }        else            {            /*             * We always read an even number of bytes from the controller,             * so adjust the length if necessary.             */            if ((length & ODD_MSK) != 0)                ++length;            /* Upper layer provides the buffer. */            if (pMblk->mBlkHdr.mLen < length)                goto pollRecvExit;	    /* Deal with memory aligment */	    if (((int) pMblk->mBlkHdr.mData & 0x3) == 0)		pMblk->mBlkHdr.mData += pDrvCtrl->offset;            pMblk->mBlkHdr.mFlags |= M_PKTHDR;	/* set the packet header */	    pMblk->mBlkPktHdr.len  = length;	/* set the total len */	    pMblk->mBlkHdr.mLen    = length;	/* set the data len */            /* Copy data.	     *	     * Set up the pointer just before the loop: provokes code	     * generator into producing much better code.	     */	    pR14 = (volatile UINT8 *) (pDrvCtrl->pcmcia.oliAddr + I595_R14);            for (pPacket = pMblk->mBlkHdr.mData; length != 0; length -=2)		READ_PTR_R14_R15 (pPacket, pR14);	    gotOne = TRUE;            /* bump input packet counter */            END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);            }        /* Update the STOP register from the next packet pointer */	PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R6, nextStop);	PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R7, (nextStop >> 8));	}pollRecvExit:    /* clear receive interrupts. */    PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R1, BNK0_RX_IT);    return (gotOne ? OK : EAGAIN);    }/********************************************************************************* iOlicomPollSend - routine to send a packet in polled mode.** This routine is called by a user to try and send a packet on the* device. It sends a packet directly on the network from the caller without* going through the normal processes of queuing a pacet on an output queue* and the waiting for the device to decide to transmit it.** If it detects a transmission error, the restart command is issued.** These routine should not call any kernel functions.** RETURNS: OK on success, EAGAIN on failure*/LOCAL STATUS iOlicomPollSend    (    END_DEVICE *	pDrvCtrl,	/* pointer to END_DEVICE structure */    M_BLK *		pMblk    )    {    TX_BD *		pTxBd;    char *		pBuf;    char *		pData;    ULONG		addrC;    int			len;    int			status;    volatile UINT8 *	pR14;    END_LOG_MSG (END_DEBUG_ALL_FUNCS, "iOlicomPollSend()\n",		 0, 0, 0, 0, 0, 0);    if (DRV_FLAGS_ISSET(OLI_TX_STOP))        return (EAGAIN);    /* get a free transmit frame descriptor */    pTxBd = iOlicomTxBdGet (pDrvCtrl);    addrC = (ULONG) pTxBd->dataPointer;    /* get a free buffer */    pBuf = NET_BUF_ALLOC ();    if ((pTxBd == NULL) || (pBuf == NULL))        {        iOlicomTxBdQueueClean (pDrvCtrl);        if (pBuf)            NET_BUF_FREE (pBuf);        return (EAGAIN);        }   /* copy the MBLK */    len = netMblkToBufCopy (pMblk, pBuf, NULL);    /* 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 = pBuf; len > 0; len -= 2)        WRITE_PTR_R14_R15 (pData, pR14);    /* 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);    /* incr BD count */    pDrvCtrl->txBdNext = (pDrvCtrl->txBdNext + 1) % pDrvCtrl->txBdNum;    /* Bump the statistic counter. */    END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);    /* Spin until we've sent it. */    while (!(PCMCIA_IO_READ(pDrvCtrl->pcmcia.oliAddr + I595_R1) & BNK0_TX_IT));    /* clear transmit interrupt */    PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R1, BNK0_TX_IT);    /* Free the data immediately. */    NET_BUF_FREE (pBuf);    /* check for output errors */    addrC = (ULONG) pTxBd->dataPointer + 2;    PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R12, addrC);    PCMCIA_IO_WRITE(pDrvCtrl->pcmcia.oliAddr + I595_R13, (addrC >> 8));    READ_R14_R15 (status);    if (!(status & XMT_OK))        return (EAGAIN);    /*     * we are allowed to do this because transmit queue is empty when we     * start polling mode.     */    pDrvCtrl->txBdIndexC = pDrvCtrl->txBdNext;    return (OK);    }/******************************************************************************** iOlicomMCastAddrAdd - add a multicast address for the device** This routine adds a multicast address to whatever the driver* is already listening for.  It then resets the address filter.** RETURNS: OK on success, ERROR otherwise.*/LOCAL STATUS iOlicomMCastAddrAdd    (    END_DEVICE *	pDrvCtrl,	/* pointer to END_DEVICE structure */    char *		pAddress	/* address to add to the table */    )    {    int	error;    END_LOG_MSG (END_DEBUG_ALL_FUNCS, "iOlicomMCastAddrAdd\n",   		 0, 0, 0, 0, 0, 0);    if ((error = etherMultiAdd (&pDrvCtrl->endObj.multiList,		pAddress)) == ENETRESET)	    iOlicomConfig (pDrvCtrl);    return (OK);    }/******************************************************************************* iOlicomMCastAddrDel - delete a multicast address for the device** This routine removes a multicast address from whatever the driver* is listening for.  It then resets the address filter.** RETURNS: OK on success, ERROR otherwise.*/LOCAL STATUS iOlicomMCastAddrDel    (    END_DEVICE *	pDrvCtrl,	/* pointer to END_DEVICE structure */    char *		pAddress	/* address to delete from the table */    )    {    int	error;    END_LOG_MSG (END_DEBUG_ALL_FUNCS, "iOlicomMCastAddrDel\n", 0, 0, 0, 0, 0,0);    if ((error = etherMultiDel (&pDrvCtrl->endObj.multiList,	     (char *)pAddress)) == ENETRESET)	    iOlicomConfig (pDrvCtrl);    return (OK);    }/******************************************************************************* iOlicomMCastAddrGet - get the multicast address list for the device** This routine gets the multicast list of whatever the driver* is already listening for.** RETURNS: OK on success, ERROR otherwise.*/LOCAL STATUS iOlicomMCastAddrGet    (    END_DEVICE *	pDrvCtrl,	/* pointer to END_DEVICE structure */    MULTI_TABLE *	pTable		/* table to fill in with addresses */    )    {    int	error;    END_LOG_MSG (END_DEBUG_ALL_FUNCS, "iOlicomMCastAddrGet\n", 0, 0, 0, 0, 0,0);    error = etherMultiGet (&pDrvCtrl->endObj.multiList, pTable);    return (error);    }/**********************************************************************

⌨️ 快捷键说明

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