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

📄 if_nicevb.c

📁 IXP425的BSP代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    if  ((isr & OVW) && (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)))	{	cr = nicReadReg (pNic, &pNic->Cr, RPAGE0);	nicWriteReg(pNic, &pNic->Imr, 0, RPAGE0); /* disable all interrupts */        pDrvCtrl->idr.ac_if.if_flags &= ~(IFF_UP | IFF_RUNNING);	netJobAdd ((FUNCPTR) nicRestart, (int) pDrvCtrl, cr, 0, 0, 0);        return;	}    /* handle packet received */    if  ((isr & PRX) && (pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)))	netJobAdd ((FUNCPTR) nicHandleInt, (int) pDrvCtrl, 0, 0, 0, 0);    }/********************************************************************************* nicRestart - restart chip after receive ring buffer overflow** This routine is the task-level handler that deals with a receive DMA* overflow condition.  It gets access to the remote DMA, cleans up NIC* registers, empties the receive ring buffers, and then resends any* packet that was in the midst of transmission when the overflow hit.** RETURNS: N/A.*/LOCAL void nicRestart    (    DRV_CTRL *		pDrvCtrl,    UINT8		cr    )    {    NIC_DEVICE *	pNic = pDrvCtrl->nicAddr;	/* NIC registers */    BOOL		resend = FALSE;#ifdef	NIC_INSTRUMENT    nicRestartNb++;#endif    nicWriteCr (pNic, STP);    nicResetDelay ();				/* wait at least 1.6 mSec */    if (semTake(pDrvCtrl->dmaSem, 100) == ERROR)	{#ifdef NIC_DEBUG	if (_func_logMsg != NULL)	    _func_logMsg ("nicRestart: can't obtain dmaSem\n", 0, 0, 0, 0, 0,0);#endif        semTake (pDrvCtrl->dmaSem, WAIT_FOREVER);        }    nicWriteReg (pNic, &pNic->Rbcr0, 0, RPAGE0);    nicWriteReg (pNic, &pNic->Rbcr1, 0, RPAGE0);    if ((cr & TXP) && (!(nicReadReg (pNic, &pNic->Isr, RPAGE0) & (TXE | PTX))))	resend = TRUE;    nicWriteReg (pNic, &pNic->Tcr, MODE1, RPAGE0);    nicWriteCr (pNic, RPAGE0 | ABORT | STA);		/* back to page 0 */    pDrvCtrl->idr.ac_if.if_flags |= IFF_UP | IFF_RUNNING | IFF_NOTRAILERS;    while (nicRead (pDrvCtrl))	;    nicWriteReg(pNic, &pNic->Isr, OVW, RPAGE0);    nicWriteReg (pNic, &pNic->Tcr, MODE0, RPAGE0);    if (resend)        nicWriteCr (pNic, RPAGE0 | STA | TXP | ABORT);    semGive(pDrvCtrl->dmaSem);    nicWriteReg (pNic, &pNic->Imr, PRXE | OVWE, RPAGE0);    }/********************************************************************************* nicHandleInt - deferred receive interrupt handler** This function handles the received frames from the device.  It runs in the* context of the netTask, which was triggered by a received packet interrupt.* Actual processing of the packet is done by calling nicRead().** RETURNS: N/A.*/LOCAL void nicHandleInt    (    DRV_CTRL *		pDrvCtrl    )    {    /* empties the receive ring buffer of its packets */    while (nicRead (pDrvCtrl));    }/********************************************************************************* nicRead - read a packet off the interface ring buffer** nicRead copies packets from local memory into an mbuf and hands it to* the next higher layer (IP or etherInputHook).** RETURNS: TRUE, or FALSE if the packet reception encountered errors.*/LOCAL BOOL nicRead    (    DRV_CTRL *		pDrvCtrl    )    {    NIC_DEVICE *	pNic = pDrvCtrl->nicAddr;/* NIC registers */    RX_FRAME *		pRx = pDrvCtrl->pRxFrame;/* free Rx buffer */    MBUF *		pMbuf = NULL;    UINT32		len;			/* len of Rx pkt */#ifdef BSD43_DRIVER    UINT16		type;			/* packet type - saved */#endif    int			cur;    if (!(pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) ||        (pDrvCtrl->nextPkt == (cur = nicReadReg (pNic, &pNic->Curr, RPAGE1))))	return (FALSE);    /*     * OK, there is work to be done.     * First we copy the NIC receive status header from the NIC buffer     * into our local area. This is done so that we can obtain the length     * of the packet before copying out the rest of it. Note that the length     * field in the NIC header includes the Ethernet header, the data, and     * the 4 byte FCS field.     */    if (nicPktBufRead (pDrvCtrl, pDrvCtrl->nextPkt << 8, (RX_HDR_SIZ),	(char *) &pRx->rxHdr) == ERROR)        {#ifdef	NIC_DEBUG	if (_func_logMsg != NULL)	    _func_logMsg("nicRead could not read packet header\n",0,0,0,0,0,0);#endif	return (FALSE);	}    len = pRx->rxHdr.cntL + (pRx->rxHdr.cntH << 8) - 4 /* FCS */;    /* valid frame checks */    /*     * NOTE: if the packet's receive status byte indicates an error     * the packet is discarded and the receive page pointers are updated to     * point to the next packet.     */#ifdef	NIC_INSTRUMENT    nicLen = len;    nicHdrStat = pRx->rxHdr.status;    nicNextPage = pRx->rxHdr.nextRxPage;    nicCurrentPage = cur;#endif    if ((len < 60) || (len > 1514) || ((pRx->rxHdr.status & ~PHY) != PRX))	{	pDrvCtrl->idr.ac_if.if_ierrors++;#ifdef	NIC_DEBUG	if (_func_logMsg != NULL)	    _func_logMsg ("nicRead receive error: statusHeader=0x%x nextRxPage=%d currentPage=%d len=%d IntNb=%d\n",pRx->rxHdr.status, pRx->rxHdr.nextRxPage, cur,len,nicIntNb);#endif  	if (nicPagePtrUpdate (pDrvCtrl))	    return (TRUE);	else	    return (FALSE);	}    /* copy Ethernet packet section of the frame */    if (nicPktBufRead(pDrvCtrl, (pDrvCtrl->nextPkt << 8) + RX_HDR_SIZ, len,	(char *) &pRx->enetHdr) == ERROR)	{#ifdef	NIC_DEBUG	if (_func_logMsg != NULL)	    _func_logMsg ("nicRead: Could not read packet data\n",0,0,0,0,0,0);#endif	if (nicPagePtrUpdate(pDrvCtrl))	    return (TRUE);	else	    return (FALSE);	}    /* update ring buffer/page pointers */    if (!nicPagePtrUpdate (pDrvCtrl))	{	return (FALSE);	}    pDrvCtrl->idr.ac_if.if_ipackets++;    if ((etherInputHookRtn != NULL) &&		/* call hook if installed */        ((* etherInputHookRtn) (&pDrvCtrl->idr.ac_if, (char *) &pRx->enetHdr,        len)))        return (TRUE);    len -= sizeof (ETH_HDR);            /* now equals length of data only */#ifdef BSD43_DRIVER    type = pRx->enetHdr.ether_type;	/* build_cluster trashes type field */#endif    if ((pDrvCtrl->lIndex) && (USE_CLUSTER (len)))	/* use loaning ? */	{	pRx->refCnt = 0;        pMbuf = build_cluster (pRx->data, len, &pDrvCtrl->idr, MC_NIC_EVB,            &pRx->refCnt, nicLoanFree, (int) pDrvCtrl, (int) pRx, 0);	}    if (pMbuf != NULL)					/* loaning worked ? */        pDrvCtrl->pRxFrame = pDrvCtrl->lPool [--pDrvCtrl->lIndex];    else        {        pMbuf = copy_to_mbufs (pRx->data, len, 0, &pDrvCtrl->idr.ac_if);        if (pMbuf == NULL)            {            pDrvCtrl->idr.ac_if.if_ierrors++;            return (TRUE);            }        }#ifdef BSD43_DRIVER    do_protocol_with_type (type, pMbuf, &pDrvCtrl->idr, len);	/* up to IP */#else    do_protocol (&pRx->enetHdr, pMbuf, &pDrvCtrl->idr, len);#endif    return (TRUE);    }#ifdef BSD43_DRIVER/********************************************************************************* nicOutput - the driver's output routine** RETURNS: N/A.*/LOCAL int nicOutput    (    IDR  *		pIDR,    MBUF *		pMbuf,    SOCK *		pDest    )    {    return ether_output ((IFNET *) pIDR, pMbuf, pDest, (FUNCPTR) nicTxStartup,	pIDR);    }#endif/********************************************************************************* nicTxStartup - the driver's actual output routine** This routine accepts outgoing packets from the if_snd queue, and then * gains exclusive access to the DMA (through a mutex semaphore),* then calls nicTransmit() to send the packet out onto the interface.** RETURNS: OK, or ERROR if the packet could not be transmitted.*/#ifdef BSD43_DRIVERLOCAL STATUS nicTxStartup    (    int			unit    )    {    DRV_CTRL * 		pDrvCtrl = &drvCtrl [unit];#elseLOCAL STATUS nicTxStartup    (    DRV_CTRL * 	pDrvCtrl    )    {#endif    MBUF *		pMbuf;    MBUF *		mbuf;    int			status = OK;    int			length = 0;    while (pDrvCtrl->idr.ac_if.if_snd.ifq_head)	{        IF_DEQUEUE (&pDrvCtrl->idr.ac_if.if_snd, pMbuf);/* dequeue a packet */        if ((pDrvCtrl->idr.ac_if.if_flags & (IFF_UP | IFF_RUNNING)) !=            (IFF_UP | IFF_RUNNING))            return (ERROR);        if (semTake (pDrvCtrl->dmaSem, 100) == ERROR)	/* get DMA access */            {	    if (_func_logMsg != NULL)		_func_logMsg("nicTxStartup: can't obtain dmaSem\n",0,0,0,0,0,0);            semTake (pDrvCtrl->dmaSem, WAIT_FOREVER);            }	for (mbuf = pMbuf; mbuf != NULL; mbuf = mbuf->m_next)	    length += mbuf->m_len;		/* find length of chain */        if (length == 0)	    {	    m_freem (pMbuf);			/* empty mbuf chain */	    semGive (pDrvCtrl->dmaSem);	    continue;	    }#ifndef BSD43_DRIVER    /* BSD 4.4 ether_output() doesn't bump statistic */        pDrvCtrl->idr.ac_if.if_opackets++;#endif#ifdef	NIC_INSTRUMENT	nicTxNb++;#endif	/* send packet out over interface */        if ( (status = nicTransmit (pDrvCtrl, pMbuf, length, TRUE)) == ERROR)            {            pDrvCtrl->idr.ac_if.if_opackets--;            pDrvCtrl->idr.ac_if.if_oerrors++;            }        semGive (pDrvCtrl->dmaSem);	}    return status;    }/********************************************************************************* nicIoctl - the driver's I/O control routine** Perform device-specific commands.** RETURNS: 0, or EINVAL if the command 'cmd' is not supported.*/LOCAL int nicIoctl    (    IDR *		pIDR,    int			cmd,			/* command to execute */    caddr_t		data			/* command-specific data */    )    {    int			error = 0;    int			s = splimp ();    switch (cmd)	{        case SIOCSIFADDR:            ((struct arpcom *)pIDR)->ac_ipaddr = IA_SIN (data)->sin_addr;            arpwhohas (pIDR, &IA_SIN (data)->sin_addr);            break;        case SIOCSIFFLAGS:	/* no driver-dependent flags */            break;        default:            error = EINVAL;	}    splx (s);    return (error);    }/********************************************************************************* nicEnetAddrGet - get the Ethernet address.** Get ethernet address from the BSP.** RETURNS: N/A.*/LOCAL void nicEnetAddrGet    (    int			unit    )    {    DRV_CTRL *		pDrvCtrl = & drvCtrl [unit];    UINT8		enetAdrs[6];    UINT8		count;    sysEnetAddrGet (unit, enetAdrs);    for (count=0; count<6; count++)        pDrvCtrl->idr.ac_enaddr[count] = enetAdrs[5-count];            }/********************************************************************************* nicConfig - configure the NIC chip and program address** This routine follows the algorythm in the ST-NIC manual for enabling* a NIC device on an active network.  Essentially, this routine initializes* the NIC device.** RETURNS: N/A.*/LOCAL void nicConfig    (    int			unit    )    {    DRV_CTRL *		pDrvCtrl = &drvCtrl [unit];    NIC_DEVICE *	pNic= pDrvCtrl->nicAddr;        nicWriteCr (pNic, RPAGE0 | STP | ABORT);    nicResetDelay ();    nicWriteReg (pNic, &pNic->Dcr, NOTLS | FIFO8, RPAGE0);    /* clear remote DMA byte count registers */    nicWriteReg (pNic, &pNic->Rbcr0, 0, RPAGE0);                 nicWriteReg (pNic, &pNic->Rbcr1, 0, RPAGE0);    /* accept broadcast, but not runt or multicast */    nicWriteReg (pNic, &pNic->Rcr, AB, RPAGE0);             nicWriteReg (pNic, &pNic->Tcr, MODE1, RPAGE0);	/* int loopback mode */    nicWriteReg (pNic, &pNic->Pstart, PSTART, RPAGE0);    nicWriteReg (pNic, &pNic->Pstop, PSTOP, RPAGE0);    nicWriteReg (pNic, &pNic->Bnry, BNRY, RPAGE0);    nicWriteReg (pNic, &pNic->Isr, 0xff, RPAGE0);	/* clr pending ints */    nicWriteReg (pNic, &pNic->Imr, PRXE | OVWE, RPAGE0); /* enable int */    nicEnetAddrGet (unit);			/* get enet address */    /* set up page 1 registers */    nicWriteReg (pNic, &pNic->Par0, pDrvCtrl->idr.ac_enaddr [0], RPAGE1);    nicWriteReg (pNic, &pNic->Par1, pDrvCtrl->idr.ac_enaddr [1], RPAGE1);    nicWriteReg (pNic, &pNic->Par2, pDrvCtrl->idr.ac_enaddr [2], RPAGE1);    nicWriteReg (pNic, &pNic->Par3, pDrvCtrl->idr.ac_enaddr [3], RPAGE1);    nicWriteReg (pNic, &pNic->Par4, pDrvCtrl->idr.ac_enaddr [4], RPAGE1);    nicWriteReg (pNic, &pNic->Par5, pDrvCtrl->idr.ac_enaddr [5], RPAGE1);    nicWriteReg (pNic, &pNic->nic_pg1.mar0, 0xff, RPAGE1);    nicWriteReg (pNic, &pNic->nic_pg1.mar1, 0xff, RPAGE1);    nicWriteReg (pNic, &pNic->nic_pg1.mar2, 0xff, RPAGE1);    nicWriteReg (pNic, &pNic->nic_pg1.mar3, 0xff, RPAGE1);    nicWriteReg (pNic, &pNic->nic_pg1.mar4, 0xff, RPAGE1);

⌨️ 快捷键说明

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