ixethaccend.c

来自「ixEthAccEnd END network interface driver」· C语言 代码 · 共 1,681 行 · 第 1/4 页

C
1,681
字号
END_DEVICE  *pDrvCtrl   /* device structure */){    /* Not supported by this device */    return(char *)NULL;}/********************************************************************************* ixEthAccEndHandleRcvInt - 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 ixEthAccEndHandleRcvInt(END_DEVICE *pDrvCtrl,   /* interrupting device */IX_ETH_ACC_REC_BUF *pBufList){    M_BLK_ID pMblk = pBufList->ix_rec_buf;#if defined(IXP_DRV_DEBUG_LOG) || defined(IXP_DRV_DEBUG)    int unit = pDrvCtrl->unit;#endif    int         oldLevel;    IxEthAccStatus result;    do        {        /* Expunge buffer data from cache. The header was done earlier */#ifdef IXE_CACHED_BUFFERS_ENABLE        IXP425_END_CACHE_INVALIDATE (pMblk->m_data, pMblk->m_len);#endif /* IXE_CACHED_BUFFERS_ENABLE */        IXP_DRV_LOG (IXP_DRV_DEBUG_RX, "Rx ixe[%d] Hdr: 0x%08X Buf: 0x%08X Sz: 0x%08X\n"                 , unit                 , (int)pMblk                 , (int)pMblk->m_data                 , (int)pMblk->m_len                 , 5, 6);#ifdef IXP_DRV_DEBUG_LOG        ixEthAccRxBufs[unit][ixEthAccRxBufsIndex[unit]].pMhdr = pMblk;        ixEthAccRxBufs[unit][ixEthAccRxBufsIndex[unit]].pData = pMblk->m_data;        ixEthAccRxBufs[unit][ixEthAccRxBufsIndex[unit]].pSize = pMblk->m_len;        if( ++ixEthAccRxBufsIndex[unit] >= IXETHACC_BUF_HISTORY_CNT)            ixEthAccRxBufsIndex[unit] = 0;#endif /* IXP_DRV_DEBUG_LOG */        /* Add one to our unicast data. */        END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);        /* Other stats inc */        /* No chained MBUF's on receive side */        pMblk->mBlkHdr.mFlags |= M_PKTHDR;        pMblk->mBlkPktHdr.len = pMblk->m_len;        pMblk->m_next = 0;        /* IXP_DRV_LOG (IXP_DRV_DEBUG_RX, "Calling upper layer!\n", 1, 2, 3, 4, 5, 6); */        /* Call the upper layer's receive routine. */        END_RCV_RTN_CALL(&pDrvCtrl->end, pMblk);        /*          * Load Rx path with a new buffer.         */        oldLevel = intLock ();  /* protect IxEthAccEndInt */        pDrvCtrl->rxBufsActive--;        /* The number of cblk/mblk pairs owned by NPE */        /* Mark this buffer done */        pBufList->ix_rec_buf = NULL;        /* Step to the next buffer */        pBufList = pBufList->ix_rec_next;        pDrvCtrl->rxHandling--;        /* Are we done ? */        if ( (pMblk = pBufList->ix_rec_buf) == NULL )            pDrvCtrl->rxHandling = 0;        intUnlock (oldLevel);        }    while ( pMblk );    /* Return buffers to the Intel Ethernet Engine */    do            {        if ((pMblk = netTupleGet(pDrvCtrl->end.pNetPool,                                    IX_ETHACC_RX_MBUF_MIN_SIZE,                                    M_DONTWAIT,                                    MT_HEADER,                                    FALSE ))            == NULL)            {            /* Clear the error */            if( errnoGet () == S_netBufLib_NO_POOL_MEMORY )                errnoSet(0);            break;                }        /* Force Quad align for Ip packet */        pMblk->m_data += 2;        pMblk->m_len = IX_ETHACC_RX_MBUF_MIN_SIZE;        pMblk->m_next = NULL;#ifdef IXE_CACHED_BUFFERS_ENABLE        IXP425_END_CACHE_FLUSH(pMblk,sizeof(M_BLK));        IXP425_END_CACHE_FLUSH(pMblk->m_data, IX_ETHACC_RX_MBUF_MIN_SIZE);#endif /* IXE_CACHED_BUFFERS_ENABLE */#ifdef IXP_DRV_DEBUG_LOG        ixEthAccRtnRxBufs[unit][ixEthAccRtnRxBufsIndex[unit]].pMhdr = pMblk;        ixEthAccRtnRxBufs[unit][ixEthAccRtnRxBufsIndex[unit]].pData = pMblk->m_data;        ixEthAccRtnRxBufs[unit][ixEthAccRtnRxBufsIndex[unit]].pSize = pMblk->m_len;        if( ++ixEthAccRtnRxBufsIndex[unit] >= IXETHACC_BUF_HISTORY_CNT)            ixEthAccRtnRxBufsIndex[unit] = 0;#endif /* IXP_DRV_DEBUG_LOG */        oldLevel = intLock ();  /* protect IxEthAccEndInt */        result = ixEthAccPortRxFreeReplenish    ( pDrvCtrl->unit, pMblk);        pDrvCtrl->rxBufsActive++;        /* The number of cblk/mblk pairs owned by NPE */        intUnlock (oldLevel);        if ( result != IX_ETH_ACC_SUCCESS)            {            /* Free buffer back */            netMblkClChainFree (pMblk);            IXP_DRV_LOG(IXP_DRV_DEBUG_RX,"Error:Registering IxEthAcc Rx Callbacks Port[%d]\n",pDrvCtrl->unit,2,3,4,5,6);            break;            }        }    while ( pMblk != 0 && (pDrvCtrl->rxBufsActive < pDrvCtrl->rxBufsAlloc));}/********************************************************************************* ixEthAccEndSend - 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, ERROR, or END_ERR_BLOCK.*/LOCAL STATUS ixEthAccEndSend(END_DEVICE * pDrvCtrl,  /* device ptr */M_BLK_ID     pMblk      /* data to send */){#if defined(IXP_DRV_DEBUG_LOG) || defined(IXP_DRV_DEBUG)    int unit = pDrvCtrl->unit;#endif    STATUS rtnStatus = OK;    M_BLK *mbufPtr;    if (pMblk == NULL)        return ERROR;    /*     * Obtain exclusive access to transmitter.  This is necessary because     * we might have more than one stack transmitting at once.     */    if (!(pDrvCtrl->flags & IxEthAccEnd_POLLING))        {        END_TX_SEM_TAKE (&pDrvCtrl->end, WAIT_FOREVER);        }    for ( mbufPtr = pMblk; mbufPtr; mbufPtr = mbufPtr->m_next )        {        /* Force outbound packets to 60 bytes minimum */        if ( mbufPtr->m_pkthdr.len < 60 )            mbufPtr->m_pkthdr.len = 60;/*        mbufPtr->m_len = mbufPtr->m_pkthdr.len;*/        IXP_DRV_LOG (IXP_DRV_DEBUG_TX, "Tx ixe[%d] Hdr: 0x%08X Buf: 0x%08X Sz: 0x%08X\n",                      unit, (int)mbufPtr, (int)mbufPtr->m_data, mbufPtr->m_pkthdr.len, 5, 6);#ifdef IXP_DRV_DEBUG_LOG        ixEthAccTxBufs[unit][ixEthAccTxBufsIndex[unit]].pMhdr = mbufPtr;        ixEthAccTxBufs[unit][ixEthAccTxBufsIndex[unit]].pData = mbufPtr->m_data;        ixEthAccTxBufs[unit][ixEthAccTxBufsIndex[unit]].pSize = mbufPtr->m_len;        if( ++ixEthAccTxBufsIndex[unit] >= IXETHACC_BUF_HISTORY_CNT)            ixEthAccTxBufsIndex[unit] = 0;#endif /* IXP_DRV_DEBUG_LOG */        /* Xmit blocks and buffers can come from cached memory */        IXP425_END_CACHE_FLUSH(mbufPtr, sizeof(M_BLK));        IXP425_END_CACHE_FLUSH(mbufPtr->m_data, mbufPtr->m_pkthdr.len);    }    /* place a transmit request */    if ( ixEthAccPortTxFrameSubmit(pDrvCtrl->unit, pMblk,IX_ETH_ACC_TX_DEFAULT_PRIORITY) != IX_ETH_ACC_SUCCESS )        {        IXP_DRV_LOG (IXP_DRV_DEBUG_TX, "Error Tx Send Unit[%d] : Buffer:08x%08X\n",                     pDrvCtrl->unit, (int)pMblk, 3, 4, 5, 6);        rtnStatus = ERROR;        }        else        {        /* Bump the statistics counters. */        if ( ! pMblk->mBlkHdr.mData[0] & (UINT8) 0x01 )            END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);        }    if (!(pDrvCtrl->flags & IxEthAccEnd_POLLING))        {        END_TX_SEM_GIVE (&pDrvCtrl->end);        }    return(rtnStatus);}/********************************************************************************* ixEthAccEndIoctl - the driver I/O control routine** Process an ioctl request.** RETURNS: A command specific response, usually OK or ERROR.*/LOCAL STATUS ixEthAccEndIoctl(END_DEVICE * pDrvCtrl,  /* device receiving command */int cmd,            /* ioctl command code */caddr_t data        /* command argument */){    int error = 0;    long value;    IXP_DRV_LOG (IXP_DRV_DEBUG_IOCTL, "ixe: Ioctl:unit[%d]:CMD:0x%08X\n", pDrvCtrl->unit, cmd, 3, 4, 5, 6);    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);                END_FLAGS_CLR (&pDrvCtrl->end, value);                } else                {                END_FLAGS_SET (&pDrvCtrl->end, value);                }            ixEthAccEndConfig (pDrvCtrl);            break;        case EIOCGFLAGS:            *(int *)data = END_FLAGS_GET(&pDrvCtrl->end);            break;        case EIOCPOLLSTART: /* Begin polled operation */            ixEthAccEndPollStart (pDrvCtrl);            break;        case EIOCPOLLSTOP:  /* End polled operation */            ixEthAccEndPollStop (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 = IxEthAccEnd_MIN_FBUF;            break;        default:            error = EINVAL;        }    return(error);}/******************************************************************************** ixEthAccEndConfig - reconfigure the interface under us.** Reconfigure the interface setting promiscuous mode, and changing the* multicast interface list.** RETURNS: N/A.*/LOCAL void ixEthAccEndConfig(END_DEVICE *pDrvCtrl    /* device to be re-configured */){    /* Set promiscuous mode if it's asked for. */    if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC)        {        IXP_DRV_LOG ((IXP_DRV_DEBUG_IOCTL | IXP_DRV_DEBUG_LOAD), "Setting promiscuous mode on!\n",                 1, 2, 3, 4, 5, 6);        ixEthAccPortPromiscuousModeSet(pDrvCtrl->unit);        } else        {        IXP_DRV_LOG ((IXP_DRV_DEBUG_IOCTL | IXP_DRV_DEBUG_LOAD), "Setting promiscuous mode off!\n",                 1, 2, 3, 4, 5, 6);        ixEthAccPortPromiscuousModeClear(pDrvCtrl->unit);        }    /* Set up address filter for multicasting. */    if (END_MULTI_LST_CNT(&pDrvCtrl->end) > 0)        {        ixEthAccEndAddrFilterSet (pDrvCtrl);        }    return;}/******************************************************************************** ixEthAccEndAddrFilterSet - 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 ixEthAccEndAddrFilterSet(END_DEVICE *pDrvCtrl    /* device to be updated */){    ETHER_MULTI* pCurr;    pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end);    while (pCurr != NULL)        {        pCurr = END_MULTI_LST_NEXT(pCurr);        }}/********************************************************************************* ixEthAccEndPollRcv - routine to receive a packet in polled mode.** This routine is called by a user to try and get a packet from the* device.** RETURNS: OK upon success.  EAGAIN is returned when no packet is available.*/LOCAL STATUS ixEthAccEndPollRcv(END_DEVICE * pDrvCtrl,  /* device to be polled */M_BLK_ID      pMblk     /* ptr to buffer */){#ifdef IXE_ETHACC_POLL_ENABLE    u_short stat;    char* pPacket;    int len;    IXP_DRV_LOG (IXP_DRV_DEBUG_POLL_RX, "ixEthAccEndPollRcv\n", 1, 2, 3, 4, 5, 6);    stat = ixEthAccEndStatusRead (pDrvCtrl);    if (!(stat & IxEthAccEnd_RINT))        {        IXP_DRV_LOG (IXP_DRV_DEBUG_POLL_RX, "ixEthAccEndPollRcv no data\n", 1,                 2, 3, 4, 5, 6);        return(EAGAIN);        }    /* Get packet and  length from device buffer/descriptor */    pPacket = NULL; /* DUMMY CODE */    len = 64;       /* DUMMY CODE */

⌨️ 快捷键说明

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