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

📄 if_cpm.c

📁 Tornado 2.0.2 source code!vxworks的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
        default:            error = EINVAL;        }    splx (s);    return (error);    }/********************************************************************************* cpmReset - 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 sysCpmEnetDisable() to do any target specific disabling.** The complement of this rotuine is cpmInit().  Once a unit is reset in this* routine, it may be re-initialized to a running state by cpmInit().** RETURNS: N/A*/LOCAL STATUS cpmReset    (    int		unit		/* unit number */    )    {    DRV_CTRL * pDrvCtrl;    if (unit < 0 || unit >= MAX_UNITS)	/* sanity check the unit number */        return (ERROR);    pDrvCtrl = & drvCtrl[unit];    sysCpmEnetIntDisable (unit);	/* disable the SCC interrupts */    /* issue the CP graceful stop command to the transmitter if necessary */    if (pDrvCtrl->ether.pSccReg->gsmrl & SCC_GSMRL_ENT)	{	(void) sysCpmEnetCommand (unit, CPM_CR_SCC_GRSTOP);        /* wait for graceful stop to register */        /* wait for graceful stop to register */        taskDelay (sysClkRateGet ());        if (!(pDrvCtrl->ether.pSccReg->scce & SCC_ETHER_SCCX_GRA))            return (ERROR);     /* Stop not registered. */	}    /* 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) */    sysCpmEnetDisable (unit);    /* mark the driver as down */    pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);    return (OK);    }/********************************************************************************* cpmIntr - 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 cpmIntr    (    int		unit		/* unit number */    )    {    DRV_CTRL * pDrvCtrl = & drvCtrl[unit];    BOOL rxHandle = FALSE;    BOOL txHandle = FALSE;    int events;    /* identify and acknowledge all interrupt events */    events = (pDrvCtrl->ether.pSccReg->scce & pDrvCtrl->ether.pSccReg->sccm);    /* check for spurious interrupt */    if (!pDrvCtrl->attached)	{        pDrvCtrl->ether.pSccReg->scce = 0xffff;	sysCpmEnetIntClear (unit);	return;	}    /* handle receive events */    if (events & SCC_ETHER_SCCX_RXF)	{        (void) netJobAdd ((FUNCPTR) cpmHandleInt, (int) pDrvCtrl, 0, 0, 0, 0); 	/* turn off receive interrupts for now - cpmHandleInt 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) cpmTxRestart, unit, 0, 0, 0, 0);	pDrvCtrl->txStop = TRUE;	}    /* handle transmitter events - BD full condition -> ever happen ? */    if (events & SCC_ETHER_SCCX_TXB)	{#ifdef BSD43_DRIVER        (void) netJobAdd ((FUNCPTR) cpmStartOutput, unit, 0, 0, 0, 0); #else        (void) netJobAdd ((FUNCPTR) cpmStartOutput, (int)pDrvCtrl, 0, 0, 0, 0); #endif        pDrvCtrl->ether.pSccReg->sccm &= ~SCC_ETHER_SCCX_TXB;	}    /* check for input busy condition, we don't enable this interrupt       but we check for it with each interrupt. */    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;	}    /* ignore and reset all other 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));    if (rxHandle)        pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_RXF;    if (pDrvCtrl->txStop)        pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_TXE;    if (txHandle)        pDrvCtrl->ether.pSccReg->scce = SCC_ETHER_SCCX_TXB;    sysCpmEnetIntClear (unit);    }/********************************************************************************* cpmTxRestart - issue RESTART Tx command to the CP** This routine issues a RESTART transmitter command to the CP.  It is* executed by netTask (cpmIntr() did a netJobAdd).  cpmIntr() cannot do* a RESTART directly because the CPM flag must be taken before a command* can be written.  After a restart, a netJobAdd of cpmStartOutput() is* performed in order to send any packets remaining in the interface output* queue.** RETURNS: N/A*/LOCAL void cpmTxRestart    (    int		unit		/* unit number */    )    {    DRV_CTRL * pDrvCtrl = & drvCtrl[unit];    /* update error counter */    pDrvCtrl->idr.ac_if.if_oerrors++;    /* correct packet counter */    pDrvCtrl->idr.ac_if.if_opackets--;    /* restart the transmitter */    (void) sysCpmEnetCommand (unit, CPM_CR_SCC_RESTART);    /* restart transmit routine */    pDrvCtrl->txStop = FALSE;#ifdef BSD43_DRIVER    (void) netJobAdd ((FUNCPTR) cpmStartOutput, unit, 0, 0, 0, 0); #else    (void) netJobAdd ((FUNCPTR) cpmStartOutput, (int)pDrvCtrl, 0, 0, 0, 0); #endif    }/********************************************************************************* cpmHandleInt - task-level interrupt handler** This is the task-level interrupt handler, which is called from * netTask(). cpmHandleInt() gets input frames from the device and then calls * cpmRecv() to process each frame.  cpmRecv() 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 cpmIntr().* Receive interrupts are turned back on by this routine before exiting.** RETURNS: N/A*/LOCAL void cpmHandleInt    (    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)))            cpmRecv (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;    }/********************************************************************************* cpmRecv - 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 cpmRecv    (    DRV_CTRL *	pDrvCtrl,	/* pointer to DRV_CTRL structure */    SCC_BUF *	pRxBd		/* receive buffer descriptor */    )    {     MBUF *	pMbuf = NULL;	/* MBUF pointer */    UINT8 *	pData;    int		length;#ifdef BSD43_DRIVER    UINT16	type;#endif    struct ether_header * 	pEh;     /* bump input packet counter */    pDrvCtrl->idr.ac_if.if_ipackets++;    /* call hook if one is connected */    if ((etherInputHookRtn != NULL) && ((*etherInputHookRtn)	(& pDrvCtrl->idr.ac_if, pRxBd->dataPointer, pRxBd->dataLength) != 0))        return;     /* get Ethernet header */    pEh = (struct ether_header *) pRxBd->dataPointer;    /* filter frame if controller is in promiscuous mode - M bit is buggy */    if (pDrvCtrl->ether.pSccReg->psmr & SCC_ETHER_PSMR_PRO)	{	if ((bcmp ( (char *) pEh->ether_dhost,                    (char *) pDrvCtrl->idr.ac_enaddr, ENET_ADDR_SIZE)) &&	    (bcmp ((char *) pEh->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 data */    pData = ((char *)pEh) + SIZEOF_ETHERHEADER;#ifdef BSD43_DRIVER    /* save type - build_cluster trashes the type field */    type = pEh->ether_type;#endif    /* OK to loan out buffer ? -> build a mbuf cluster */    if ((pDrvCtrl->nLoanRxBd > 0) && (USE_CLUSTER (length)))	pMbuf = build_cluster (pData, length, & pDrvCtrl->idr, MC_CPM,	    pDrvCtrl->pRefCnt[(pDrvCtrl->nLoanRxBd - 1)], cpmLoanFree,	    (int) pDrvCtrl, (int) pEh,            (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 (pEh, pMbuf, & pDrvCtrl->idr, length);#endif    }/********************************************************************************* cpmLoanFree - 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 cpmLoanFree    (    DRV_CTRL *	pDrvCtrl,    UINT8 *	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 + -