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

📄 if_eidve.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    }/********************************************************************************* eiInt - entry point for handling interrupts from the 82596** The interrupting events are acknowledged to the device, so that the device* will deassert its interrupt signal.  The amount of work done here is kept* to a minimum; the bulk of the work is defered to the netTask.  Several flags* are used here to synchronize with task level code and eliminate races.*/static void eiInt    (    DRV_CTRL *pDrvCtrl    )    {    UINT16  event;    SCB *pScb;    int unit;    pScb = pDrvCtrl->pScb;    unit = pDrvCtrl->idr.ac_if.if_unit;    event = pScb->scbStatus & (SCB_S_CX | SCB_S_FR | SCB_S_CNA | SCB_S_RNR);#ifdef EI_DEBUG    logMsg ("ei: interrupt: event=%x\n", event, 0, 0, 0, 0, 0);#endif /* EI_DEBUG */    eiCommand (pDrvCtrl, event);                        /* ack the events */    sys596IntAck (unit);                                /* ack 596 interrupt */    /* Handle transmitter interrupt */    if (event & SCB_S_CNA)                              /* reclaim tx tfds */        {        pDrvCtrl->wdTxTimeout = 0;              /* reset timeout count */        if (pDrvCtrl->cleanQueue.head == NULL)      /* clean queue empty */            {            pDrvCtrl->cleanQueue.head = pDrvCtrl->cblQueue.head; /* new head */            pDrvCtrl->cleanQueue.tail = pDrvCtrl->cblQueue.tail; /* new tail */            }        else                                            /* concatenate queues */            {            LINK_WR ( (EI_LINK * ) &(pDrvCtrl->cleanQueue.tail->pNext),                        (void*) pDrvCtrl->cblQueue.head);             pDrvCtrl->cleanQueue.tail = pDrvCtrl->cblQueue.tail;            }        if (!pDrvCtrl->txCleaning)                          /* not cleaning? */            {            pDrvCtrl->txCleaning = TRUE;                    /* set flag */            netJobAdd ((FUNCPTR) eiTxCleanQ, (int) pDrvCtrl, 0, 0, 0, 0);                            /* defer cleanup */            }        if (pDrvCtrl->txQueue.head != NULL)             /* anything to flush? */            eiTxQFlush (pDrvCtrl);                      /* flush the tx q */        else            pDrvCtrl->txIdle = TRUE;                    /* transmitter idle */        }    /* Handle receiver interrupt */    if (event & SCB_S_FR)	{	pDrvCtrl->wdRxTimeout = 0;                 	/* reset timeout count */	if (!(pDrvCtrl->rcvHandling))            {            pDrvCtrl->rcvHandling = TRUE;            (void) netJobAdd ((FUNCPTR) eiHandleRecvInt, (int) pDrvCtrl,0, 0, 0, 0);         /* netTask processes */	    }        }    }/********************************************************************************* eiTxCleanQ - checks errors in completed TFDs and moves TFDs to free queue** This routine is executed by netTask.  It "cleans" the TFDs on the clean-up* queue by checking each one for errors and then returning the TFD to the* "free TFD" queue.  The startup routine is sometimes called here to eliminate* the lock-out case where the driver input queue is full but there are no* TFDs available.*/static void eiTxCleanQ    (    DRV_CTRL *pDrvCtrl    )    {    TFD *pTfd;    BOOL needTxStart;    int unit;    unit = pDrvCtrl->idr.ac_if.if_unit;    do        {        pDrvCtrl->txCleaning = TRUE;        if (pDrvCtrl->tfdQueue.head == NULL)              /* tfd queue empty */            needTxStart = TRUE;                           /* set flag */        else            needTxStart = FALSE;        /* process transmitted frames */        while (1)            {            /* Get TFD. No ints allowed while manipulating this queue. */            sys596IntDisable (unit);            pTfd = (TFD*) eiQGet ((EI_LIST *)&pDrvCtrl->cleanQueue);            sys596IntEnable (unit);            if (pTfd == NULL)                break;            pDrvCtrl->idr.ac_if.if_collisions +=         /* add any colls */                (pTfd->status & CFD_S_RETRY) ? 16 :  /* excessive colls */                (pTfd->status & CFD_S_COLL_MASK);    /* some colls */            if (!(pTfd->status & CFD_S_OK))          /* packet not sent */                {                pDrvCtrl->idr.ac_if.if_oerrors++;        /* incr err count */                pDrvCtrl->idr.ac_if.if_opackets--;       /* decr sent count */                }            /* return to tfdQ */            eiQPut (unit,(EI_LIST *)&pDrvCtrl->tfdQueue, (EI_NODE*)pTfd);            }        if (needTxStart)                                  /* check flag */            eiTxStartup (pDrvCtrl);        pDrvCtrl->txCleaning = FALSE;        }    while (pDrvCtrl->cleanQueue.head != NULL);            /* check again */    }/********************************************************************************* eiHandleRecvInt - 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.*/static void eiHandleRecvInt    (    DRV_CTRL *pDrvCtrl    )    {    RFD *pRfd;    do        {        pDrvCtrl->rcvHandling = TRUE;             /* interlock with eiInt() */        while ((pRfd = eiRxQGet (pDrvCtrl)) != NULL)            if (eiReceive (pDrvCtrl, pRfd) == OK)                eiRxQPut (pDrvCtrl, pRfd);        pDrvCtrl->rcvHandling = FALSE;            /* interlock with eiInt() */        }    while (eiRxQFull (pDrvCtrl));              /* make sure rx q still empty */    }/********************************************************************************* eiReceive - pass a received frame to the next layer up** Strips the Ethernet header and passes the packet to the appropriate* protocol.  The return value indicates if buffer loaning was used to hold* the data.  A return value of OK means that loaning was not done, and it* is therefore 'ok' to return the RFD to the Rx queue.  A return value of ERROR* means that buffer loaning was employed, and so the RFD is still in use and* should not be returned to the Rx queue.  In this latter case, the RFD will* eventually be returned by the protocol, via a call to our eiLoanFree().*/static STATUS eiReceive    (    DRV_CTRL *pDrvCtrl,    RFD *pRfd    )    {    ETH_HDR     *pEh;    u_char      *pData;    int         len;    UINT16      etherType;    MBUF        *m = NULL;    BOOL        rfdLoaned = FALSE;    /* Check packet for errors.  This should be completely unnecessary,     * but since Intel does not seem capable of explaining the exact     * functioning of the 'save bad frames' config bit, we will look for     * errors.     */    if  (        ( pRfd->status & ( RFD_S_OK | RFD_S_COMPLETE ) ) !=        ( RFD_S_OK | RFD_S_COMPLETE )        )        {        ++pDrvCtrl->idr.ac_if.if_ierrors;            /* bump error counter */        eiRxQPut (pDrvCtrl, pRfd);                   /* free the RFD */        return (ERROR);        }    /* Bump input packet counter. */    ++pDrvCtrl->idr.ac_if.if_ipackets;    len = pRfd->actualCnt & ~0xc000;        /* get frame length */    pEh = (ETH_HDR *)pRfd->enetHdr;         /* get ptr to ethernet header */    /* Service input hook */    if ( (etherInputHookRtn != NULL) )        {        if  ( (* etherInputHookRtn) (&pDrvCtrl->idr, (char *)pEh, len) )            {            eiRxQPut (pDrvCtrl, pRfd);                  /* free the RFD */            return (OK);            }        }    len -= EH_SIZE;    pData = (u_char *) pRfd->enetData;    etherType = ntohs (pEh->ether_type);    /* we can loan out receive frames from 82596 receive queue if:     *     * 1) the threshold of loanable frames has not been exceeded     * 2) size of the input ethernet frame is large enough to be used with     *    clustering.     */    if ((pDrvCtrl->nLoanRfds > 0) &&        ((m = build_cluster (pData, len, &pDrvCtrl->idr, MC_EI, &pRfd->refCnt,                 eiLoanFree, (int) pDrvCtrl, (int) pRfd, NULL)) != NULL))        {        pDrvCtrl->nLoanRfds --;             /* one less to loan */        rfdLoaned = TRUE;               /* we loaned a frame */        }    else        m = copy_to_mbufs (pData, len, 0, &pDrvCtrl->idr);    if (m != NULL)#ifdef BSD43_DRIVER        do_protocol_with_type (etherType, m, &pDrvCtrl->idr, len);#else        do_protocol (pEh, m, &pDrvCtrl->idr, len);#endif    return ((rfdLoaned) ? ERROR : OK);    }/********************************************************************************* eiLoanFree - return a loaned receive frame descriptor** This routine is called by the protocol code when it has completed use of* an RFD that we loaned to it.*/static void eiLoanFree    (    DRV_CTRL *pDrvCtrl,    RFD *pRfd    )    {    eiRxQPut (pDrvCtrl, pRfd);    pDrvCtrl->nLoanRfds ++;    }/********************************************************************************* eiDeviceStart - reset and start the device** This routine assumes interrupts from the device have been disabled, and* that the driver control structure has been initialized.*/static STATUS eiDeviceStart    (    int unit                              /* physical unit number */    )    {    void     *pTemp;    DRV_CTRL *pDrvCtrl;    SCP      *pScp;                       /* system config ptr */    ISCP     *pIscp;                      /* intermediate system config ptr */    SCB      *pScb;                       /* system control block ptr */    /* Get pointers */    pDrvCtrl = & drvCtrl [unit];    pScp = pDrvCtrl->pScp;    pIscp = pDrvCtrl->pIscp;    pScb = pDrvCtrl->pScb;    /* Issue the reset operation to the device */    sys596Port (unit, PORT_RESET, NULL);    /* Initialize the SCP */    pScp->scpRsv1 =    pScp->scpRsv2 =    pScp->scpRsv3 = 0;    pScp->scpSysbus = pDrvCtrl->sysbus;    pTemp = CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, pIscp);    LINK_WR (&pScp->pIscp, pTemp);              /* point SCP to ISCP */    /* Initialize the ISCP */    pIscp->iscpBusy = 1;    pIscp->iscpRsv1 = 0;    pTemp = CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, pScb);    LINK_WR (&pIscp->pScb, pTemp);              /* point ISCP to SCB */    /* Initialize the SCB */    bzero ((char *)pScb, sizeof (SCB));    /* Tell the device where the SCP is located */    pTemp = CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, pScp);    sys596Port (unit, PORT_NEWSCP, (UINT32) pTemp);    sys596ChanAtn (unit);    /*     * The device will now read our SCP and ISCP. It will clear the busy     * flag in the ISCP.     */    taskDelay (50);    if ( pIscp->iscpBusy == 1 )        {        printf ("\nei: device did not initialize\n");        return (ERROR);        }    return (OK);    }/********************************************************************************* eiDiag - format and issue a diagnostic command*/static void eiDiag    (    int unit    )    {    DRV_CTRL *pDrvCtrl;    pDrvCtrl = & drvCtrl [unit];    bzero ((char *)pDrvCtrl->pCfd, sizeof (CFD));       /* zero command frame */    eiAction (unit, CFD_C_DIAG);                /* run diagnostics */    if (!(pDrvCtrl->pCfd->cfdStatus & CFD_S_OK))        printErr ("eiDiag: i82596 diagnostics failed.\n");    }/********************************************************************************* eiConfig - format and issue a config command*/static void eiConfig    (    int unit    )    {    DRV_CTRL *pDrvCtrl;    pDrvCtrl = & drvCtrl [unit];    bzero ((char *)pDrvCtrl->pCfd, sizeof (CFD));       /* zero command frame */    /* Recommeded i82596 User's Manual configuration values.  Note that     * the original manual, #296443-001, was full of errors.  Errors in the     * description of the config bytes that I am aware of are noted below.     * It is possible there are further errors.  Intel has replaced the     * manual with #296853-001, which does correct some errors, but not all.     */    pDrvCtrl->pCfd->cfdConfig.ccByte8  = 0x8e;    pDrvCtrl->pCfd->cfdConfig.ccByte9  = 0xc8;    /* The manual is wrong about bit 7 in byte 10.     * A '0' allows reception of bad packets.     * A '1' causes rejection of bad packets.     */    pDrvCtrl->pCfd->cfdConfig.ccByte10 = 0xc0;    pDrvCtrl->pCfd->cfdConfig.ccByte11 = 0x2e;      /* loopback, NSAI */    pDrvCtrl->pCfd->cfdConfig.ccByte12 = 0x00;    pDrvCtrl->pCfd->cfdConfig.ccByte13 = 0x60;    pDrvCtrl->pCfd->cfdConfig.ccByte14 = 0x00;    pDrvCtrl->pCfd->cfdConfig.ccByte15 = 0xf2;    pDrvCtrl->pCfd->cfdConfig.ccByte16 = 0x00;      /* promiscuous off */    pDrvCtrl->pCfd->cfdConfig.ccByte17 = 0x00;    pDrvCtrl->pCfd->cfdConfig.ccByte18 = 0x40;    /* The manual is wrong about 2 bits in byte 19.     * Bit 5, multicast, a '1' disables.     * Bit 2, include CRC, a '1' disables.     */    pDrvCtrl->pCfd->cfdConfig.ccByte19 = 0xff;    pDrvCtrl->pCfd->cfdConfig.ccByte20 = 0x00;    pDrvCtrl->pCfd->cfdConfig.ccByte21 = 0x3f;    eiAction (unit, CFD_C_CONFIG);          /* configure the chip */    }/********************************************************************************* eiIASetup - format and issue an interface address command*/static void eiIASetup    (    int unit    )    {    DRV_CTRL *pDrvCtrl;    pDrvCtrl = & drvCtrl [unit];    bzero ((char *)pDrvCtrl->pCfd, sizeof (CFD));       /* zero command frame */

⌨️ 快捷键说明

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