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

📄 ns83902end.c

📁 操作系统vxworks平台下end设备的驱动程序,支持多种芯片,支持多种cpu
💻 C
📖 第 1 页 / 共 5 页
字号:
* context of the netTask, which was triggered by a received packet interrupt.* It resends any packet that was in the midst of transmission when the overflow* hit.* Actual processing of the packet is done by calling ns83902Recv().** RETURNS: N/A.*/LOCAL void ns83902HandleInt    (    NS83902_END_DEVICE*	pDrvCtrl        )    {    NS83902_CLUSTER	pCluster;    /* empties the receive ring buffer of its packets */    pDrvCtrl->rxHandling = TRUE;    while ((pCluster =  ns83902ReadFrame (pDrvCtrl)) != NULL)	ns83902Recv (pDrvCtrl, pCluster);    pDrvCtrl->rxHandling = FALSE;    if (pDrvCtrl->rxOvw == TRUE)	{	/* Reset overflow bit */	NS83902_REG_SET (pDrvCtrl, NS83902_ISR, ISR_OVW, CR_RPAGE0);	NS83902_REG_SET (pDrvCtrl, NS83902_TCR, TCR_MODE0, CR_RPAGE0);	/* If resend needed, issue transmit command */	if (pDrvCtrl->txResend == TRUE)	    {	    NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_STA | CR_TXP | CR_ABORT,			     CR_RPAGE0);	    pDrvCtrl->txResend = FALSE;	    }	pDrvCtrl->rxOvw = FALSE;	}    /* Re-enable interrupts */    NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_ENABLE, CR_RPAGE0);    }/********************************************************************************* ns83902Int - The driver's interrupt handler** This function clears the cause of the device interrupt(s) and then acts* on the individual possible causes.  The primary goal of this routine is to* minimize the time spent in it.  This is accomplished by deferring processing* to the netTask via the netJobAdd() function.** Note that in case the receiver overruns, we promptly mark the interface as* "down" and leave error handling to task-level.   This is in case netTask* is in the midst of DMA activity, we must allow it to complete.  The receive* handler will give up when it discovers the interface is down, which will* then allow netTask to run our OVW handler.  This provides orderly error * recovery.** RETURNS: N/A.*/LOCAL void ns83902Int    (    NS83902_END_DEVICE*	pDrvCtrl    )    {    UINT8		isr;			/* copy of NS83902_ISR */    UINT8		cr;			/* copy of NS83902_CR */    /* Check if interface is up and running */    if ((END_FLAGS_GET(&pDrvCtrl->endObj) & (IFF_UP | IFF_RUNNING)) !=        (IFF_UP | IFF_RUNNING))	return;#ifdef	NS83902_INSTRUMENT    ns83902IntNb++;#endif    DRV_LOG (NS83902_DEBUG_INT, "Inside INT\n", 1, 2, 3, 4, 5, 6);    /* Read and clear ISR */        NS83902_REG_GET (pDrvCtrl, NS83902_ISR, isr, CR_RPAGE0);    NS83902_REG_SET (pDrvCtrl, NS83902_ISR, isr, CR_RPAGE0);    /* handle transmit interrupts */    if (isr & (ISR_PTX | ISR_TXE))	{	UINT8 tsr;	NS83902_REG_GET (pDrvCtrl, NS83902_TSR, tsr, CR_RPAGE0);	DRV_LOG (NS83902_DEBUG_TX, "ns83902Tx Interrupt TSR=%d \n", tsr,		 2, 3, 4, 5, 6);	if ((tsr & TSR_PTX) == 0)	    {	    /* PTX zero, something went wrong */		    if (tsr & TSR_ABT)		{#ifdef	NS83902_INSTRUMENT		ns83902TxTimeout++;#endif		DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit Aborted \n",			 1, 2, 3, 4, 5, 6);		}	    if (tsr & TSR_FU)		{		DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit FIFO Underrun \n",		     1, 2, 3, 4, 5, 6);		}	    /* Notify upper layers about the error */	    END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);	    pDrvCtrl->lastError.errCode = END_ERR_WARN;	    pDrvCtrl->lastError.pMesg = "Transmit error";	    netJobAdd ((FUNCPTR) muxError, (int) &pDrvCtrl->endObj,		       (int) &pDrvCtrl->lastError, 0, 0, 0);	    DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit Error\n", 0, 0, 0, 0, 0, 0);	    #ifdef	NS83902_INSTRUMENT	    ns83902TxError++;#endif	    }	if (tsr & TSR_CRS)	    {	    DRV_LOG (NS83902_DEBUG_TX, "%s%d - no carrier\n", (int)NS83902_DEV_NAME,		     pDrvCtrl->unit, 3, 4, 5, 6);	    }	#if 0   /* no collision statistics for END drivers? */	if (tsr & TSR_COL)	    {	    UINT8 ncr;	    NS83902_REG_GET (pDrvCtrl, NS83902_NCR, ncr, CR_RPAGE0);	    END_ERR_ADD (pEndObj, MIB2_COLLISIONS, ncr);	    }#endif	if (pDrvCtrl->txBlocked == TRUE)	    {	    pDrvCtrl->txBlocked = FALSE;	    netJobAdd ((FUNCPTR)muxTxRestart, (int)&pDrvCtrl->endObj, 0, 0, 0, 0);	    }	}    /* handle receiver overrun */    if (isr & ISR_OVW)	{	/* disable interrupts */	NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_DISABLE, CR_RPAGE0);	NS83902_CR_GET (pDrvCtrl, cr);        /* mark the interface down */        END_FLAGS_CLR (&pDrvCtrl->endObj, IFF_UP | IFF_RUNNING);        	ns83902Restart (pDrvCtrl, cr);        return;	}    /* handle packet received */    if (isr & ISR_PRX)        if (pDrvCtrl->rxHandling == FALSE)            {            pDrvCtrl->rxHandling = TRUE;	    /* disable receive interrupts and defer work to task context */	    NS83902_REG_SET (pDrvCtrl, NS83902_IMR, IMR_RX_DISABLE, CR_RPAGE0);	    netJobAdd ((FUNCPTR) ns83902HandleInt, (int) pDrvCtrl, 0, 0, 0, 0);            }    }/********************************************************************************* ns83902Send - the driver's actual output routine** This routine accepts outgoing packets from the snd queue, and then * gains exclusive access to the DMA (through a mutex semaphore),* then calls ns83902Transmit() to send the packet out onto the interface.** RETURNS: OK, or ERROR if the packet could not be transmitted.*/LOCAL STATUS ns83902Send    (    NS83902_END_DEVICE* pDrvCtrl,    M_BLK* pMblk    )    {    int	status;    DRV_LOG (NS83902_DEBUG_TX, "Begin ns83902Send pDrvCtrl %p pMblk %p\n", 	     (int)pDrvCtrl, (int)pMblk, 3, 4, 5, 6);    if ((END_FLAGS_GET(&pDrvCtrl->endObj) & (IFF_UP | IFF_RUNNING)) !=        (IFF_UP | IFF_RUNNING))        {        DRV_LOG (NS83902_DEBUG_TX, "Device is NOT UP and RUNNING\n",                 1, 2, 3, 4, 5, 6);        return (ERROR);        }    /* send packet out over interface */    if ((status = ns83902Transmit (pDrvCtrl, pMblk)) == OK)        {	/* Success, free the Mblk chain */	if (!NS83902_IS_IN_POLL_MODE())	    netMblkClChainFree (pMblk);        END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);	}    else        {        DRV_LOG (NS83902_DEBUG_TX, "FAILED ns83902Transmit\n", 0, 0, 0, 0, 0, 0);                /* update statistics */        END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_ERRS, +1);#ifdef	NS83902_INSTRUMENT	ns83902TxError++;#endif        }    DRV_LOG (NS83902_DEBUG_TX, "End ns83902Send \n", 0, 0, 0, 0, 0, 0);#ifdef	NS83902_INSTRUMENT    ns83902TxNb++;#endif    return status;        }/********************************************************************************* ns83902Transmit - send data over the NIC network interface** This routine transfers data to the NIC device via the remote DMA, and* then signal for a transmission.** RETURNS: OK, or ERROR if the transmitter signalled an error.*/LOCAL STATUS ns83902Transmit    (    NS83902_END_DEVICE* pDrvCtrl,        M_BLK*		pMblk    )    {    int			status = OK;    int			txLen = 0;    UINT8		cr;    LOCAL UINT8		txData[ETHERMTU + ENET_HDR_REAL_SIZ];    int			cnt;    USHORT		dummyRead;    /* Get exclusive access to DMA */    if (!NS83902_IS_IN_POLL_MODE())	NS83902_SEM_TAKE (pDrvCtrl, WAIT_FOREVER);    txLen = netMblkToBufCopy (pMblk, txData, NULL);    txLen = max (txLen, ETHERSMALL);    /* Check if we are ready to transmit */        NS83902_CR_GET (pDrvCtrl, cr);    if (cr & CR_TXP)	{	DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit: waiting for TX_IN_PROGRESS\n",		 1, 2, 3, 4, 5, 6);	/* Wait for end of TX */	cnt = 100;				/* timeout 100 mSec */	while ((cr & CR_TXP) && (cnt-- > 0))	    {	    SYS_MS_DELAY (1);	    NS83902_CR_GET (pDrvCtrl, cr);	    }	}    /* If still not ready, bail */    NS83902_CR_GET (pDrvCtrl, cr);    if (cr & CR_TXP)	{        DRV_LOG (NS83902_DEBUG_TX, "Not Ready to transmit!\n", 1, 2, 3, 4, 5, 6);	pDrvCtrl->txBlocked = TRUE;	/* transmitter not ready */	if (!NS83902_IS_IN_POLL_MODE())	    NS83902_SEM_GIVE (pDrvCtrl);        return (END_ERR_BLOCK);	}    /* Dummy read with RBCR > 1 before (see DP83902 manual) */    NS83902_REG_SET (pDrvCtrl, NS83902_RBCR0, 2, CR_RPAGE0);    NS83902_REG_SET (pDrvCtrl, NS83902_RBCR1, 0, CR_RPAGE0);    NS83902_REG_SET (pDrvCtrl, NS83902_RSAR0, 0, CR_RPAGE0);    NS83902_REG_SET (pDrvCtrl, NS83902_RSAR1, LSB(pDrvCtrl->txStartPage),		     CR_RPAGE0);    NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_RREAD, CR_RPAGE0);    if (pDrvCtrl->wide == TRUE)	{	SYS_IN_SHORT (pDrvCtrl, pDrvCtrl->ioPort, dummyRead);	}    else	{	SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->ioPort, dummyRead);	SYS_IN_BYTE (pDrvCtrl, pDrvCtrl->ioPort, dummyRead);	}    /* Set up remote DMA transfer */    NS83902_REG_SET (pDrvCtrl, NS83902_RSAR0, 0, CR_RPAGE0);    NS83902_REG_SET (pDrvCtrl, NS83902_RSAR1, LSB(pDrvCtrl->txStartPage), 		     CR_RPAGE0);    NS83902_REG_SET (pDrvCtrl, NS83902_RBCR0, LSB(txLen), CR_RPAGE0);    NS83902_REG_SET (pDrvCtrl, NS83902_RBCR1, MSB(txLen), CR_RPAGE0);    /* Start remote DMA transfer */    NS83902_REG_SET (pDrvCtrl, NS83902_CR, CR_RWRITE, CR_RPAGE0);    /* write data to the DMA port */    ns83902WritePort (pDrvCtrl, txData, txLen);    /* Se up local DMA */    NS83902_REG_SET (pDrvCtrl, NS83902_TPSR, pDrvCtrl->txStartPage, CR_RPAGE0);    NS83902_REG_SET (pDrvCtrl, NS83902_TBCR0, LSB(txLen), CR_RPAGE0);    NS83902_REG_SET (pDrvCtrl, NS83902_TBCR1, MSB(txLen), CR_RPAGE0);    DRV_LOG (NS83902_DEBUG_TX, "Sending %d bytes from %p \n", txLen,	     (int)txData, 3, 4, 5, 6);       /* Start transmission while preserving DMA command bits */    NS83902_CR_GET (pDrvCtrl, cr);    NS83902_REG_SET (pDrvCtrl, NS83902_CR, 		     CR_TXP | (cr & (CR_RWRITE | CR_RREAD | CR_ABORT)),		     CR_RPAGE0);    /* Release Semaphore */        if (!NS83902_IS_IN_POLL_MODE())	{	NS83902_SEM_GIVE (pDrvCtrl);	}    else	{	UINT8 tsr;	UINT8 isr;	FOREVER	    {	    NS83902_REG_GET (pDrvCtrl, NS83902_ISR, isr, CR_RPAGE0);	    if ((isr & (ISR_PTX | ISR_TXE)) != 0)		break;    	    }	/* Check for errors */	NS83902_REG_GET (pDrvCtrl, NS83902_TSR, tsr, CR_RPAGE0);	if ((tsr & TSR_PTX) == 0)	    {	    /* PTX zero, something went wrong */	    status = ERROR;		    if (tsr & TSR_ABT)		{#ifdef	NS83902_INSTRUMENT		ns83902TxTimeout++;#endif		DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit Aborted \n",			 1, 2, 3, 4, 5, 6);		}	    if (tsr & TSR_FU)		{		DRV_LOG (NS83902_DEBUG_TX, "ns83902Transmit FIFO Underrun \n",			 1, 2, 3, 4, 5, 6);		}	    }	if (tsr & TSR_CRS)	    {	    logMsg ("%s%d - no carrier\n", (int)NS83902_DEV_NAME, pDrvCtrl->unit, 		    3, 4, 5, 6);	    }	#if 0   /* no collision statistics for END drivers? */	if (tsr & TSR_COL)	    {	    UINT8 ncr;	    NS83902_REG_GET (pDrvCtrl, NS83902_NCR, ncr, CR_RPAGE0);	    END_ERR_ADD (pEndObj, MIB2_COLLISIONS, ncr);	    }#endif	/* Clear transmit flags in ISR */	NS83902_REG_SET (pDrvCtrl, NS83902_ISR, (ISR_PTX | ISR_TXE), CR_RPAGE0);	}    return (status);    }/********************************************************************************* ns83902Ioctl - the driver's I/O control routine** Perform device-specific commands.** RETURNS: 0, or EINVAL if the command 'cmd' is not supported.*/LOCAL int ns83902Ioctl    (    NS83902_END_DEVICE* pDrvCtrl,    int			cmd,    caddr_t		data        )    {    int 		error = 0;    long		value;    int			saveFlags;    DRV_LOG (NS83902_DEBUG_LOAD, "ns83902Ioctl Command %d\n",	    cmd, 2, 3, 4, 5, 6);        switch ((UINT)cmd)	{        case EIOCSADDR:	    if (data == NULL)		return (EINVAL);            bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->endObj),		   END_HADDR_LEN(&pDrvCtrl->endObj));            ns83902Config (pDrvCtrl);	/* HELP  Will it work? */            break;        case EIOCGADDR:	    if (data == NULL)		return (EINVAL);            bcopy ((char *)END_HADDR(&pDrvCtrl->endObj), (char *)data,		    END_HADDR_LEN(&pDrvCtrl->endObj));            break;        case EIOCSFLAGS:	    value = (long) data;	    if( value < 0 )		{		value = -value;		value--;		END_FLAGS_CLR (&pDrvCtrl->endObj, value);		}	    else		{		END_FLAGS_SET (&pDrvCtrl->endObj, value);

⌨️ 快捷键说明

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