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

📄 if_eitp.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* Disable system interrupts (NOTE #1) */	intLevel = intLock ();    if ((pScb->scbStatus & SCB_S_RUMASK) != SCB_S_RUIDLE)        eiCommand (pDrvCtrl, SCB_C_RUABORT);            /* abort if not idle */    eiCommand (pDrvCtrl, SCB_C_RUSTART);              /* start receive unit */	/* Re-enable system interrupts */   	intUnlock (intLevel);    }/********************************************************************************* eiAction - execute the specified action with the CFD pointed to in pDrvCtrl** Do the command contained in the CFD synchronously, so that we know* it's complete upon return.  This routine assumes that interrupts from the* device have been disabled.*/static void eiAction    (    int    unit,    UINT16 action    )    {    void     *pTemp;    CFD      *pCfd;    SCB      *pScb;    DRV_CTRL *pDrvCtrl;    pDrvCtrl = & drvCtrl [unit];    pCfd = pDrvCtrl->pCfd;    pScb = pDrvCtrl->pScb;    while (1)                   /* wait for idle command unit */        {        if ((pScb->scbStatus & SCB_S_CUMASK) == SCB_S_CUIDLE)            break;        }    { /* Prepare and issue the command to the device */    /* fill in CFD */    pCfd->cfdStatus  = 0;                       /* clear status */    pCfd->cfdCommand = CFD_C_EL | action;       /* fill in action */    LINK_WR (&pCfd->link, NULL);                /* terminate link */    /* and the SCB */    pScb->scbCommand =                        SCB_S_CX |              /* ack any events */                        SCB_S_FR |                        SCB_S_CNA |                        SCB_S_RNR |                        SCB_C_CUSTART;          /* start command unit */    pTemp = CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, pCfd);    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    )    {    SCB * pScb;    pScb = pDrvCtrl->pScb;    while (1)        {        if (pScb->scbCommand == 0)                  /* wait for cmd zero */            break;        }    pScb->scbCommand = cmd;                     /* fill in command */    sys596ChanAtn (pDrvCtrl->idr.ac_if.if_unit);    /* channel attention */    return (OK);    }/********************************************************************************* 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;	int intLevel;    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 */	/* Disable system interrupts (NOTE #1) */	intLevel = intLock ();    /* enqueue the TFD */    eiQPut (unit,(EI_LIST *)&pDrvCtrl->txQueue, (EI_NODE*)pTfd);    if (pDrvCtrl->txIdle)                             /* transmitter idle */        eiTxQFlush (pDrvCtrl);                        /* flush txQueue */	/* Re-enable system interrupts */   	intUnlock (intLevel);    }/********************************************************************************* 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 watchdog */    wdStart (            pDrvCtrl->wid,            (int) (sysClkRateGet() >> 1),            (FUNCPTR) eiWatchDog,            pDrvCtrl->idr.ac_if.if_unit            );    /* 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;    unit = pDrvCtrl->idr.ac_if.if_unit;    pRfd->status    = 0;                    /* clear status */    pRfd->command   = CFD_C_EL;             /* new end of list */    pRfd->actualCnt  = 0;                   /* clear actual count */    pRfd->bufSize   = ETHERMTU + EH_SIZE;   /* fill in size */    pRfd->refCnt    = 0;                    /* initialize ref cnt */    LINK_WR (& pRfd->lBufDesc, 0xffffffff);         /* no RBD used */    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)        {        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;    SCB *pScb;    pScb = pDrvCtrl->pScb;    pDrvCtrl = & drvCtrl [unit];    /* sanity check.     * If the scb status indicates that CU (transmit) is active     * It might make sense to loop through the cfd's to look for     * a complete bit as a sanity check , but given that we are     * here and that transmit was active, we will go ahead and do     * a reset.     */    if (pScb->scbStatus & SCB_S_CUACTIVE)        {        pDrvCtrl->transLocks++;                     /* local failure count */        pDrvCtrl->idr.ac_if.if_oerrors++;           /* incr err count */        pDrvCtrl->idr.ac_if.if_opackets--;          /* decr sent count */        }    }/* NOTES * * NOTE #1: *	The TP41 has a major design oversite.  The interrupt pin from the *	82596 connects directly to the CPU.  Since the 82596 provides no way *	to disable the device from generating interrupts, there is no way to *	selectively disable the 82596 interrupt.  The only option is to disable *	all interrupts in the system during critical code regions. *//* END OF FILE */

⌨️ 快捷键说明

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