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

📄 if_eihk.c

📁 Tornado 2.0.2 source code!vxworks的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
    LINK_WR (&pScb->pCB, pTemp);                /* point chip at CFD */    sys596ChanAtn (unit);               /* notify device of new command */    }    while (1)               /* wait for command acceptance and interrupt */        {        if ((pScb->scbCommand == 0) && (pScb->scbStatus & SCB_S_CNA))            break;        }    /* Acknowledge the event to the device */    pScb->scbCommand = (SCB_S_CX | SCB_S_CNA);    sys596ChanAtn (unit);    while (1)               /* wait for acknowledge acceptance */        {        if (pScb->scbCommand == 0)            break;        }    }/********************************************************************************* eiCommand - deliver a command to the 82596 via SCB** This function causes the device to execute a command.  It should be called* with interrupts from the device disabled.  An error status is returned if* the command field does not return to zero, from a previous command, in a* reasonable amount of time.*/static STATUS eiCommand    (    DRV_CTRL *pDrvCtrl,    UINT16    cmd    )    {    int loopy;    SCB * pScb;    pScb = pDrvCtrl->pScb;    for (loopy = 0x8000; loopy--;)        {        if (pScb->scbCommand == 0)                  /* wait for cmd zero */            break;        }    if (loopy > 0)        {        pScb->scbCommand = cmd;                     /* fill in command */        sys596ChanAtn (pDrvCtrl->idr.ac_if.if_unit);    /* channel attention */        return (OK);        }    else        {        logMsg("ei driver: command field frozen\n", 0, 0, 0, 0, 0, 0);        return (ERROR);        }    }/********************************************************************************* eiTxQPut - place a transmit frame on the transmit queue** The TFD has been filled in with the network pertinent data.  This* routine will enqueue the TFD for transmission and attempt to feed* the queue to the device.*/static void eiTxQPut    (    DRV_CTRL *pDrvCtrl,    TFD *pTfd    )    {    int unit;    unit = pDrvCtrl->idr.ac_if.if_unit;    pTfd->status    = 0;                    /* fill in TFD fields */    pTfd->command   = CFD_C_XMIT;           /* EL set later */    pTfd->count     |= TFD_CNT_EOF;         /* data kept in frame */    pTfd->reserved  = 0;                    /* must be zero */    LINK_WR (& pTfd->lBufDesc, NULL);                /* TBDs not used */    sys596IntDisable (pDrvCtrl->idr.ac_if.if_unit);  /* disable dev ints */    /* enqueue the TFD */    eiQPut (unit,(EI_LIST *)&pDrvCtrl->txQueue, (EI_NODE*)pTfd);    if (pDrvCtrl->txIdle)                             /* transmitter idle */        eiTxQFlush (pDrvCtrl);                        /* flush txQueue */    sys596IntEnable (pDrvCtrl->idr.ac_if.if_unit);  /* enable dev ints */    }/********************************************************************************* eiTxQFlush - make cmd unit of device start processing cmds** This routine flushes the contents of the txQ to the cblQ and starts the* device transmitting the cblQ.  Called only if transmit queue is not empty.* Sometimes called from interrupt handler.*/static void eiTxQFlush    (    DRV_CTRL *pDrvCtrl    )    {    void * pTemp;    extern int sysClkRateGet();     /* we call this */    ((TFD*)pDrvCtrl->txQueue.tail)->command |= CFD_C_EL;  /* EL terminate q */    pDrvCtrl->cblQueue.head = pDrvCtrl->txQueue.head;   /* remember cbl head */    pDrvCtrl->cblQueue.tail = pDrvCtrl->txQueue.tail;   /* remember cbl tail */    eiQInit ((EI_LIST *)&pDrvCtrl->txQueue);            /* tx queue now empty */    pTemp = CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs,                                    pDrvCtrl->cblQueue.head);    LINK_WR (&pDrvCtrl->pScb->pCB, pTemp);          /* point CU to head */    pDrvCtrl->txIdle = FALSE;                   /* transmitter busy */    /* start command unit */    eiCommand (pDrvCtrl, SCB_C_CUSTART);    }/********************************************************************************* eiRxQPut - return a RFD to the receive queue for use by the device*/static void eiRxQPut    (    DRV_CTRL *pDrvCtrl,    RFD *pRfd    )    {    int unit;    RFD *pTail;    RBD *pRbd;    void *pTemp;    unit = pDrvCtrl->idr.ac_if.if_unit;    pRbd = &pRfd->rbd;    /* Initialize the RFD */    pRfd->status = 0;    pRfd->command = RFD_M_EL | RFD_M_FLEXMODE;    pTemp = CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, pRbd);    LINK_WR (&pRfd->lBufDesc, pTemp);    pRfd->actualCnt = 0;    pRfd->bufSize = EH_SIZE;    /* Initialize the RBD */    pRbd->actualCnt = 0;    pTemp = CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, pRfd->enetData);    LINK_WR (&pRbd->pData, pTemp);    pRbd->size = RBD_EL | ETHERMTU;    pTail = (RFD *) pDrvCtrl->rxQueue.tail;         /* remember tail */    /* Put the RFD on the list */    eiQPut (unit, (EI_LIST *) & pDrvCtrl->rxQueue, (EI_NODE *) pRfd);    if (pTail != NULL)        {        pDrvCtrl->wdRxTimeout = 0;          /* reset timeout count */        /* update RBD links */        pTemp = CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, pRbd);        LINK_WR (&pTail->rbd.lNext, pTemp);        pTail->rbd.size &= ~RBD_EL;        pTail->command &= ~CFD_C_EL;        /* clear old tail EL */        if (pTail->status & (CFD_S_COMPLETE | CFD_S_BUSY))            {            pDrvCtrl->pFreeRfd = pRfd;          /* link questionable */            }        else if (!(pDrvCtrl->pScb->scbStatus & SCB_S_RUREADY))            /* receiver dormant */            {            eiRxStartup (pDrvCtrl);             /* start receive unit */            }        }    else        {        pDrvCtrl->pFreeRfd = pRfd;              /* first free RFD */        }    }/********************************************************************************* eiRxQGet - get a successfully received frame from the receive queue** RETURNS: ptr to valid RFD, or NULL if none available*/static RFD *eiRxQGet    (    DRV_CTRL *pDrvCtrl    )    {    RFD *pRfd = NULL;    if (eiRxQFull (pDrvCtrl))        pRfd = (RFD *) eiQGet ((EI_LIST *)&pDrvCtrl->rxQueue);    return (pRfd);    }/********************************************************************************* eiRxQFull - boolean function to determine fullness of receive queue** RETURNS: TRUE if completely received frame is available, FALSE otherwise.*/static BOOL eiRxQFull    (    DRV_CTRL *pDrvCtrl    )    {    return ((pDrvCtrl->rxQueue.head != NULL) &&        (((RFD*)pDrvCtrl->rxQueue.head)->status & CFD_S_COMPLETE));    }/********************************************************************************* eiQInit - initialize a singly linked node queue*/static void eiQInit    (    EI_LIST *pQueue    )    {    pQueue->head = pQueue->tail = NULL;         /* init head & tail */    }/********************************************************************************* eiQGet - get a node from the head of a node queue** RETURNS: ptr to useable node, or NULL ptr if none available*/static EI_NODE *eiQGet    (    EI_LIST *pQueue    )    {    EI_NODE *pNode;    if ((pNode = (EI_NODE *) pQueue->head) != NULL)     /* if list not empty */        pQueue->head = pNode->pNext;                    /* advance ptr */    return (pNode);    }/********************************************************************************* eiQPut - put a node on the tail of a node queue*/static void eiQPut    (    int unit,    EI_LIST *pQueue,    EI_NODE *pNode    )    {    void * pTemp;    DRV_CTRL *pDrvCtrl;    pDrvCtrl = & drvCtrl [unit];    LINK_WR (&pNode->lNext, NULL);                    /* mark "end of list" */    pNode->pNext = NULL;    if (pQueue->head == NULL)                        /* if list empty */        pQueue->tail = pQueue->head = pNode;         /* set both ptrs */    else        {        pTemp = CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, pNode);        LINK_WR (&pQueue->tail->lNext, pTemp);       /* link node on tail */        pQueue->tail->pNext = pNode;        pQueue->tail = pNode;                        /* update tail ptr */        }    }/********************************************************************************* eiWatchDog - if the watchdog timer fired off, we've hung during a transmit** Check the scb command to verify and if so, reinit.*/static void eiWatchDog    (    int unit        /* unit number */    )    {    DRV_CTRL *pDrvCtrl = &drvCtrl [unit];    SCB *pScb;    int reset = FALSE;    pScb = pDrvCtrl->pScb;    /* Test for transmit timeout.     *     * Timeout occurs if the scb status indicates that CU (transmit)      * remains active for EI_TX_TIMEOUT iterations of eiWatchDog.     * It might make sense to loop through the cfd's to look for     * a complete bit as a sanity check, but given that transmit     * was active, we will go ahead and do a reset.     */    if ((pDrvCtrl->txIdle == FALSE)        && (pScb->scbStatus & SCB_S_CUACTIVE))        {        if (++(pDrvCtrl->wdTxTimeout) > EI_TX_TIMEOUT)            {            pDrvCtrl->transLocks++;			  /* failure count */            pDrvCtrl->idr.ac_if.if_oerrors++;             /* incr err count */            pDrvCtrl->idr.ac_if.if_opackets--;            /* decr sent count */            reset = TRUE;            }        }    /* Test for receive timeout.     *     * Timeout occurs if the scb status indicates that RU (receive)      * remains out of resources for EI_RX_TIMEOUT iterations of eiWatchDog.     */    if (pScb->scbStatus & SCB_S_RUNORSRC)        {        if (++(pDrvCtrl->wdRxTimeout) > EI_RX_TIMEOUT)            {            pDrvCtrl->recvLocks++;			  /* failure count */            reset = TRUE;            }        }    /* reinitialize the unit or restart the watchdog */    if (reset)	netJobAdd ((FUNCPTR) eiInit, unit,0, 0, 0, 0);    else        wdStart (pDrvCtrl->wid, 		(int) pDrvCtrl->wdInterval, 		(FUNCPTR) eiWatchDog, 		unit);    }/******************************************************************************//* END OF FILE */

⌨️ 快捷键说明

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