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

📄 if_qu.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 3 页
字号:
            /* set promiscuous bit according to flags */	    if (pDrvCtrl->idr.ac_if.if_flags & IFF_PROMISC)                pDrvCtrl->ether.pSccReg->psmr |= SCC_ETHER_PSMR_PRO;            else                pDrvCtrl->ether.pSccReg->psmr &= ~SCC_ETHER_PSMR_PRO;            break;        default:            error = EINVAL;        }    splx (s);    return (error);    }/********************************************************************************* quReset - network interface reset routine** This routine marks the interface as down and resets the device.  This* includes disabling interrupts, stopping the transmitter and receiver,* and calling sys360EnetDisable() to do any target specific disabling.** The complement of this rotuine is quInit().  Once a unit is reset in this* routine, it may be re-initialized to a running state by quInit().** RETURNS: N/A*/LOCAL void quReset    (    int		unit		/* unit number */    )    {    DRV_CTRL * pDrvCtrl;    int counter = 0xffff;    if (unit < 0 || unit >= MAX_UNITS)	/* sanity check the unit number */        return;		      pDrvCtrl = & drvCtrl[unit];    /* disable the SCC interrupts */    *M360_CPM_CIMR(pDrvCtrl->regBase) &= ~pDrvCtrl->ether.intMask;    /* issue the CP graceful stop command to the transmitter if necessary */    if (pDrvCtrl->ether.pSccReg->gsmrl & SCC_GSMRL_ENT)	{        while (*M360_CPM_CR(pDrvCtrl->regBase) & CPM_CR_FLG);        *M360_CPM_CR(pDrvCtrl->regBase) = ((pDrvCtrl->ether.sccNum - 1) << 6) |                                          CPM_CR_SCC_GRSTOP | CPM_CR_FLG;        while (*M360_CPM_CR(pDrvCtrl->regBase) & CPM_CR_FLG);        /* wait for graceful stop to register */        while ((counter--) && (!(pDrvCtrl->ether.pSccReg->scce &			         SCC_ETHER_SCCX_GRA)));	}    /* disable the SCC receiver and transmitter */    pDrvCtrl->ether.pSccReg->gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);    /* call the BSP to do any other disabling (e.g., *TENA) */    sys360EnetDisable (unit, pDrvCtrl->regBase);    /* mark the driver as down */    pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);    /* mark the driver as no longer initialized */    pDrvCtrl->initialized = FALSE;    }/********************************************************************************* quIntr - network interface interrupt handler** This routine gets called at interrupt level. It handles work that * requires minimal processing. Interrupt processing that is more * extensive gets handled at task level. The network task, netTask(), is * provided for this function. Routines get added to the netTask() work * queue via the netJobAdd() command.** RETURNS: N/A*/LOCAL void quIntr    (    int		unit		/* unit number */    )    {    DRV_CTRL * pDrvCtrl = & drvCtrl[unit];    BOOL rxHandle = FALSE;    BOOL txbHandle = FALSE;    /* check for spurious interrupt -> attached & initialized ? */    if ((!pDrvCtrl->attached) || (!pDrvCtrl->initialized))	{        pDrvCtrl->ether.pSccReg->scce = 0xffff;        *M360_CPM_CISR(pDrvCtrl->regBase) = pDrvCtrl->ether.intMask;	return;	}    /* handle receive events */    if ((pDrvCtrl->ether.pSccReg->sccm & SCC_ETHER_SCCX_RXF) &&        (pDrvCtrl->ether.pSccReg->scce & SCC_ETHER_SCCX_RXF))	{        (void) netJobAdd ((FUNCPTR) quHandleInt, (int) pDrvCtrl, 0, 0, 0, 0); 	/* turn off receive interrupts for now - quHandleInt turns back on */        pDrvCtrl->ether.pSccReg->sccm &= ~SCC_ETHER_SCCX_RXF;	rxHandle = TRUE;        }    /* check for output errors */    if (pDrvCtrl->ether.pSccReg->scce & SCC_ETHER_SCCX_TXE)	{	/* NOTE: HBC error not supported -> always RESTART Tx here */        (void) netJobAdd ((FUNCPTR) quTxRestart, (int) pDrvCtrl, 0, 0, 0, 0);	pDrvCtrl->txStop = TRUE;	}    /* handle transmitter events - BD full condition -> ever happen ? */    if ((pDrvCtrl->ether.pSccReg->sccm & SCC_ETHER_SCCX_TXB) &&        (pDrvCtrl->ether.pSccReg->scce & SCC_ETHER_SCCX_TXB))	{#ifdef BSD43_DRIVER        (void) netJobAdd ((FUNCPTR) quStartOutput, unit, 0, 0, 0, 0); #else        (void) netJobAdd ((FUNCPTR) quStartOutput, (int)pDrvCtrl, 0, 0, 0, 0); #endif /* BSD43_DRIVER */        pDrvCtrl->ether.pSccReg->sccm &= ~SCC_ETHER_SCCX_TXB;	txbHandle = TRUE;	}    /* check for input busy condition */    if (pDrvCtrl->ether.pSccReg->scce & SCC_ETHER_SCCX_BSY)	{        pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_BSY;         /* count discarded frames as errors */        pDrvCtrl->idr.ac_if.if_ierrors +=	    ((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->disfc;	((SCC_ETHER_PROTO *)pDrvCtrl->ether.pScc->prot)->disfc = 0;	}    /* acknowledge all other interrupts - ignore events */    pDrvCtrl->ether.pSccReg->scce = (pDrvCtrl->ether.pSccReg->scce &				    ~(SCC_ETHER_SCCX_RXF |				      SCC_ETHER_SCCX_TXE |				      SCC_ETHER_SCCX_TXB |				      SCC_ETHER_SCCX_BSY));    /* acknowledge interrupts */    if (rxHandle)        pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_RXF;     if (pDrvCtrl->txStop)        pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_TXE;     if (txbHandle)        pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_TXB;     *M360_CPM_CISR(pDrvCtrl->regBase) = pDrvCtrl->ether.intMask;    }/********************************************************************************* quTxRestart - issue RESTART Tx command to the CP** This routine issues a RESTART transmitter command to the CP.  It is* executed by netTask (quIntr() did a netJobAdd).  quIntr() cannot do* a RESTART directly because the CPM flag must be taken before a command* can be written.  After a restart, a netJobAdd of quStartOutput() is* performed in order to send any packets remaining in the interface output* queue.** RETURNS: N/A*/LOCAL void quTxRestart    (    DRV_CTRL *	pDrvCtrl	/* pointer to DRV_CTRL structure */    )    {    /* update error counter */    pDrvCtrl->idr.ac_if.if_oerrors++;    /* restart transmitter */    while (*M360_CPM_CR(pDrvCtrl->regBase) & CPM_CR_FLG);    *M360_CPM_CR(pDrvCtrl->regBase) = ((pDrvCtrl->ether.sccNum - 1) << 6) |                                      CPM_CR_SCC_RESTART | CPM_CR_FLG;    while (*M360_CPM_CR(pDrvCtrl->regBase) & CPM_CR_FLG);    /* restart transmit routine */    pDrvCtrl->txStop = FALSE;#ifdef 	BSD43_DRIVER    (void) netJobAdd ((FUNCPTR) quStartOutput, pDrvCtrl->idr.ac_if.if_unit,		      0, 0, 0, 0); #else    (void) netJobAdd ((FUNCPTR) quStartOutput, (int)pDrvCtrl, 0, 0, 0, 0); #endif	/* BSD43_DRIVER */    }/********************************************************************************* quHandleInt - task-level interrupt handler** This is the task-level interrupt handler, which is called from * netTask(). quHandleInt() gets input frames from the device and then calls * quRecv() to process each frame.  quRecv() only gets called if no error* stats were reported in the buffer descriptor.  Data chaining is not* supported.** This routine should be called with SCC receive interrupts masked so that* more netJobAdds of this routine are not performed by quIntr().* Receive interrupts are turned back on by this routine before exiting.** RETURNS: N/A*/LOCAL void quHandleInt    (    DRV_CTRL *	pDrvCtrl	/* pointer to DRV_CTRL structure */    )    {    SCC_BUF *	pRxBd = & pDrvCtrl->ether.rxBdBase[pDrvCtrl->ether.rxBdNext];    while (!(pRxBd->statusMode & SCC_ETHER_RX_BD_E))        {        /* data chaining is not supported  - check all error conditions */        if (((pRxBd->statusMode & (SCC_ETHER_RX_BD_F  | SCC_ETHER_RX_BD_L))	                       == (SCC_ETHER_RX_BD_F  | SCC_ETHER_RX_BD_L))	                      && !(pRxBd->statusMode & (SCC_ETHER_RX_BD_CL |		                   SCC_ETHER_RX_BD_OV | SCC_ETHER_RX_BD_CR |				   SCC_ETHER_RX_BD_SH | SCC_ETHER_RX_BD_NO |				   SCC_ETHER_RX_BD_LG)))            quRecv (pDrvCtrl, pRxBd);        else            pDrvCtrl->idr.ac_if.if_ierrors++;        /* reset buffer descriptor as empty */	if (pRxBd->statusMode & SCC_ETHER_RX_BD_W)            pRxBd->statusMode = SCC_ETHER_RX_BD_E | SCC_ETHER_RX_BD_I |                                SCC_ETHER_RX_BD_W;        else            pRxBd->statusMode = SCC_ETHER_RX_BD_E | SCC_ETHER_RX_BD_I;        /* incr BD count */        pDrvCtrl->ether.rxBdNext = (pDrvCtrl->ether.rxBdNext + 1) %				    pDrvCtrl->ether.rxBdNum;        pRxBd = & pDrvCtrl->ether.rxBdBase[pDrvCtrl->ether.rxBdNext];        /* clear Rx events */        pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_RXF;        }    /* re-enable Rx interrupts */    pDrvCtrl->ether.pSccReg->sccm |= SCC_ETHER_SCCX_RXF;    }/********************************************************************************* quRecv - process an input frame** This routine processes an input frame, then passes it up to the higher * level in a form it expects.  Buffer loaning, promiscuous mode, and* etherInputHookRtns are all supported.  Trailer protocols is not supported.** RETURNS: N/A*/LOCAL void quRecv    (    DRV_CTRL *	pDrvCtrl,	/* pointer to DRV_CTRL structure */    SCC_BUF *	pRxBd		/* receive buffer descriptor */    )    {     FAST ETH_HDR *	pEtherHdr;	/* pointer to the ethernet header */    MBUF *		pMbuf = NULL;	/* MBUF pointer */    u_char *		pData;    int			length;#ifdef BSD43_DRIVER    UINT16		type;#endif /* BSD43_DRIVER */    /* call hook if one is connected */    if ((etherInputHookRtn != NULL) && ((*etherInputHookRtn)	(& pDrvCtrl->idr.ac_if, pRxBd->dataPointer, pRxBd->dataLength) != 0))        return;     /* filter frame if controller is in promiscuous mode - M bit is buggy */    if (pDrvCtrl->ether.pSccReg->psmr & SCC_ETHER_PSMR_PRO)	{	if ((bcmp ((char *) ((ETH_HDR *) pRxBd->dataPointer)->ether_dhost,	     (char *) pDrvCtrl->idr.ac_enaddr, ENET_ADDR_SIZE)) &&	    (bcmp ((char *) ((ETH_HDR *) pRxBd->dataPointer)->ether_dhost,	     (char *) etherbroadcastaddr, ENET_ADDR_SIZE)))           return;	}    /* adjust length to data only */    length = pRxBd->dataLength - SIZEOF_ETHERHEADER;    if (length <= 0)	{         pDrvCtrl->idr.ac_if.if_ierrors++;	return;	}    /* point to ethernet header */        pEtherHdr = (ETH_HDR *) pRxBd->dataPointer;     /* point to data */        pData = (u_char *)pEtherHdr + SIZEOF_ETHERHEADER;#ifdef BSD43_DRIVER    /* save type - build_cluster trashes the type field */    type = ((ETH_HDR *) pRxBd->dataPointer)->ether_type;#endif /* BSD43_DRIVER */        /* OK to loan out buffer ? -> build a mbuf cluster */    if ((pDrvCtrl->nLoanRxBd > 0) && (USE_CLUSTER (length)))	pMbuf = build_cluster (        		       pData,                               length,                               & pDrvCtrl->idr.ac_if,                               MC_QU,                               pDrvCtrl->pRefCnt [(pDrvCtrl->nLoanRxBd - 1)],                               (FUNCPTR)quLoanFree,                               (int) pDrvCtrl,                               (int) pRxBd->dataPointer,                               (int) pDrvCtrl->pRefCnt [(pDrvCtrl->nLoanRxBd -                                                         1)]                               );    /* if buffer was successfully turned into mbuf cluster */    if (pMbuf != NULL)	pRxBd->dataPointer = pDrvCtrl->lPool[--pDrvCtrl->nLoanRxBd];    else        {	/* else do same ol' copy to mbuf */        pMbuf = copy_to_mbufs (pData, length, 0, & pDrvCtrl->idr.ac_if);        if (pMbuf == NULL)	    {            pDrvCtrl->idr.ac_if.if_ierrors++;            return;	    }        }    /* send up to protocol */#ifdef BSD43_DRIVER    do_protocol_with_type (type, pMbuf, & pDrvCtrl->idr, length);#else    do_protocol (pEtherHdr, pMbuf, &pDrvCtrl->idr, length);#endif    /* bump input packet counter */    pDrvCtrl->idr.ac_if.if_ipackets++;    }/********************************************************************************* quLoanFree - return the given buffer to loaner pool** This routine returns <pRxBuf> to the pool of available loaner buffers.* It also returns <pRef> to the pool of available loaner reference counters,* then zeroes the reference count.** RETURNS: N/A*/LOCAL void quLoanFree    (    DRV_CTRL *	pDrvCtrl,    u_char *	pRxBuf,    UINT8 *	pRef    )    {    /* return loaned buffer to pool */    pDrvCtrl->lPool[pDrvCtrl->nLoanRxBd] = pRxBuf;    /* return loaned reference count to pool */    pDrvCtrl->pRefCnt[pDrvCtrl->nLoanRxBd++] = pRef;    /* reset reference count - should have been done from above, but... */    *pRef = 0;    }

⌨️ 快捷键说明

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