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

📄 if_eitp.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    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. */			/* Disable system interrupts (NOTE #1) */			intLevel = intLock ();            pTfd = (TFD*) eiQGet ((EI_LIST *)&pDrvCtrl->cleanQueue);			/* Re-enable system interrupts */    		intUnlock (intLevel);            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 */#ifdef BSD43_DRIVER            eiTxStartup (unit);#else            eiTxStartup (pDrvCtrl);#endif        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;#ifdef BSD43_DRIVER    UINT16      etherType;#endif    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;#ifdef BSD43_DRIVER    etherType = ntohs (pEh->ether_type);#endif    /* 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) && (USE_CLUSTER (len)) &&        ((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    else        pDrvCtrl->idr.ac_if.if_ierrors++;       /* bump error counter */    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 */	unsigned long loopy;    /* 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.     */	/* Delay here for ample time.  Can not use taskDelay() because all	 * interrupts have been enabled, and thus no clock ticks.	 */	for ( loopy = 0x00100000; loopy--; )		;    if ( pIscp->iscpBusy == 1 )        return (ERROR);    return (OK);    }/********************************************************************************* eiDiag - format and issue a diagnostic command*/static STATUS 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))        return (ERROR);	return (OK);    }/********************************************************************************* 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 */    bcopy   (            (char *)pDrvCtrl->idr.ac_enaddr,            (char *)pDrvCtrl->pCfd->cfdIASetup.ciAddress,            6            );    eiAction (unit, CFD_C_IASETUP);         /* setup the address */    }/********************************************************************************* eiRxStartup - start up the Receive Unit** Starts up the Receive Unit.  Assumes that the receive structures are set up.*/static void eiRxStartup    (    DRV_CTRL *pDrvCtrl    )    {    SCB *pScb = pDrvCtrl->pScb;    void * pTemp;	int intLevel;    if (pScb->scbStatus & SCB_S_RUREADY)        /* already running */        return;    pTemp = CACHE_DRV_VIRT_TO_PHYS (&pDrvCtrl->cacheFuncs, pDrvCtrl->pFreeRfd);    LINK_WR (&pScb->pRF, pTemp);            /* point to free Rfd */

⌨️ 快捷键说明

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