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

📄 ne2000end.c

📁 vxworks下44B0X的BSP
💻 C
📖 第 1 页 / 共 5 页
字号:
            {
	    /* Disable RX int */
	    pDrvCtrl->imask &= ~IM_PRXE;
	    SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);

            pDrvCtrl->flags |= END_RECV_HANDLING_FLAG;
            (void)netJobAdd ((FUNCPTR)ne2000HandleRcvInt, (int)pDrvCtrl,
                              0,0,0,0);
            }
        }

    /* Check for transmit complete */

    if ((intStat & (ISTAT_TXE | ISTAT_PTX)) != 0)
	{
	pDrvCtrl->flags &= ~END_TX_IN_PROGRESS;
	ENDLOGMSG (("ne2000Int: Tx complete, blocked=%d\n",
		    (pDrvCtrl->flags & END_TX_BLOCKED) ? 1 : 0,0,0,0,0,0));
	if (pDrvCtrl->flags & END_TX_BLOCKED)
	    {
	    /* Disable TX ints */
	    pDrvCtrl->imask &= ~(IM_TXEE | IM_PTXE);
	    SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);

	    pDrvCtrl->flags &= ~END_TX_BLOCKED;
	    netJobAdd ((FUNCPTR)muxTxRestart, (int)&pDrvCtrl->endObj,
		       0, 0, 0, 0);
	    }
	}

    /* Flush the write pipe */

    CACHE_PIPE_FLUSH ();
    }


/*******************************************************************************
*
* ne2000HandleRcvInt - 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.
*
* RETURNS: N/A.
*/

LOCAL void ne2000HandleRcvInt
    (
    NE2000END_DEVICE *pDrvCtrl
    )
    {
    int oldLevel;
    char *pBuf;

    /* END_RECV_HANDLING_FLAG set by ISR */

    ENDLOGMSG (("ne2000HandleRcvInt(%x): enter (flags=%x)\n",
		pDrvCtrl,pDrvCtrl->flags,0,0,0,0));
    pBuf = NULL;
    while (pDrvCtrl->flags & END_RECV_HANDLING_FLAG)
	{
	int	len;
	CL_BLK_ID	pClBlk;
	M_BLK_ID	pMblk;      /* MBLK to send upstream */

	ENDLOGMSG (("ne2000HandleRcvInt: flags=%x imask=%x cur=%d next=%d\n",
		    pDrvCtrl->flags, pDrvCtrl->imask,
		    pDrvCtrl->current, pDrvCtrl->nextPacket,
		    0, 0));
	/* check if all packets removed */
	if (pDrvCtrl->nextPacket == pDrvCtrl->current)
	    break;

	/* Break out if we get an overwrite condition */
	if (pDrvCtrl->flags & END_OVERWRITE)
	    break;

	/* Allocate an MBLK, and a replacement buffer */
	if (!pBuf)
	    {
	    pBuf = netClusterGet (pDrvCtrl->endObj.pNetPool,
				  pDrvCtrl->clPoolId);
	    if (!pBuf)
		{
		ENDLOGMSG (("ne2000HandleRcvInt: Out of clusters!\n",
			    0, 0, 0, 0, 0, 0));
		break;
		}
	    }
	/* Read packet in offset so IP header is long-aligned */
	len = ne2000PacketGet (pDrvCtrl, pBuf + pDrvCtrl->offset);
	if (len <= 0)
	    {
	    ENDLOGMSG (("ne2000HandleRcvInt: bad packet! (len=%d)\n",
			len, 0, 0, 0, 0, 0));
	    END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
	    break;
	    }
	pMblk = mBlkGet (pDrvCtrl->endObj.pNetPool,
			 M_DONTWAIT, MT_DATA);
	if (!pMblk)
	    {
	    ENDLOGMSG (("ne2000HandleRcvInt: Out of M Blocks!\n",
			0, 0, 0, 0, 0, 0));
	    END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
	    break;
	    }
	pClBlk = netClBlkGet (pDrvCtrl->endObj.pNetPool, M_DONTWAIT);
	if (!pClBlk)
	    {
	    ENDLOGMSG (("ne2000HandleRcvInt: Out of CL Blocks!\n",
			0, 0, 0, 0, 0, 0));
	    netMblkFree (pDrvCtrl->endObj.pNetPool, (M_BLK_ID)pMblk);
	    break;
	    }
	/* Associate the data pointer with the MBLK */
	netClBlkJoin (pClBlk, pBuf, NE2000_BUFSIZ, NULL, 0, 0, 0);

	/* Associate the data pointer with the MBLK */
	netMblkClJoin (pMblk, pClBlk);

	pMblk->mBlkHdr.mFlags |= M_PKTHDR;
	pMblk->mBlkHdr.mLen    = len;
	pMblk->mBlkPktHdr.len  = len;
	/* Adjust mData to match n23000PacketGet() above */
	pMblk->mBlkHdr.mData   += pDrvCtrl->offset;

	/* record received packet */
	END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_UCAST, +1);


	/* Call the upper layer's receive routine. */
	END_RCV_RTN_CALL (&pDrvCtrl->endObj, pMblk);

	/* buffer was used, will need another next time around */
	pBuf = NULL;
	}

    /* If we still have an unused buffer, free it */
    if (pBuf)
	netClFree (pDrvCtrl->endObj.pNetPool, (UCHAR *) pBuf);

    /* Re-enable the receive interrupt */
    oldLevel = intLock ();
    pDrvCtrl->flags &= ~END_RECV_HANDLING_FLAG;
    pDrvCtrl->imask |= IM_PRXE;
    SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);

    ENDLOGMSG (("ne2000HandleRcvInt: done (flags=%x, imask=%x)\n",
		pDrvCtrl->flags,pDrvCtrl->imask,0,0,0,0));

    intUnlock (oldLevel);
    }

/*******************************************************************************
*
* ne2000DataIn - input bytes from NE2000 memory
*
* NOMANUAL
*/

LOCAL void ne2000DataIn
    (
    NE2000END_DEVICE *	pDrvCtrl,
    int			eneAddress,
    int			len,
    char *		pData
    )
    {
    if (len == 0)
	return;

    SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, 0);
    SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START);
    SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR0, eneAddress & 0xff);
    SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR1, eneAddress >> 8);
    SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, len & 0xff);
    SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, len >> 8);
    SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_RREAD | CMD_START);

    SYS_IN_WORD_STRING (pDrvCtrl, ENE_DATA, pData, len/2);
    if (len & 1)
	SYS_IN_CHAR (pDrvCtrl, ENE_DATA, (pData + (len - 1)));
    SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
    }

/*******************************************************************************
*
* ne2000DataOut - output bytes to NE2000 memory
*
* NOMANUAL
*/

LOCAL void ne2000DataOut
    (
    NE2000END_DEVICE *	pDrvCtrl,
    char *		pData,
    int			len,
    int			eneAddress
    )
    {
    if (len == 0)
        return;

    SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, (char)0xff);
    SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_NODMA | CMD_PAGE0 | CMD_START);
    SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR0, eneAddress & 0xff);
    SYS_OUT_CHAR (pDrvCtrl, ENE_RSAR1, eneAddress >> 8);
    SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR0, len & 0xff);
    SYS_OUT_CHAR (pDrvCtrl, ENE_RBCR1, len >> 8);
    SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_RWRITE | CMD_START);

    SYS_OUT_WORD_STRING (pDrvCtrl, ENE_DATA, pData, len/2);
    if (len & 1)
        SYS_OUT_CHAR (pDrvCtrl, ENE_DATA, *(pData + (len - 1)));
    }

/*******************************************************************************
*
* ne2000Send - the driver send routine
*
* This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
* The buffer must already have the addressing information properly installed
* in it.  This is done by a higher layer.  The last arguments are a free
* routine to be called when the device is done with the buffer and a pointer
* to the argument to pass to the free routine.  
*
* RETURNS: OK or ERROR.
*/

LOCAL STATUS ne2000Send
    (
    void*	pCookie,	/* device ptr */
    M_BLK_ID	pMblk		/* data to send */
    )
    {
    int		len;
    UCHAR	cmdStat;
    NE2000END_DEVICE* pDrvCtrl = (NE2000END_DEVICE *) pCookie;
    
    /*
     * Obtain exclusive access to transmitter.  This is necessary because
     * we might have more than one stack transmitting at once.
     */


    if (pDrvCtrl->flags & (END_OVERWRITE | END_OVERWRITE2))
	{
	return (END_ERR_BLOCK);
	}

    ENDLOGMSG (("ne2000Send: enter: (flags=%x, imask=%x)\n",
		pDrvCtrl->flags, pDrvCtrl->imask, 0, 0, 0, 0));

    /* Note device receive interrupts may still be enabled */

    END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);
    pDrvCtrl->flags |= END_TX_BLOCKED;

    if (pDrvCtrl->flags & END_TX_IN_PROGRESS)
	{
	int cnt;

	ENDLOGMSG (("ne2000Send: waiting for TX_IN_PROGRESS\n",
		    0,0,0,0,0,0));

	/* Wait up to 1 second */
	cnt = sysClkRateGet ();
	while ((pDrvCtrl->flags & END_TX_IN_PROGRESS) && (cnt-- > 0))
	    taskDelay (1);
	}

    /* Disable device interrupts and check for overwrite detected */
    SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, 0);
    if (pDrvCtrl->flags & (END_OVERWRITE | END_OVERWRITE2))
	{
	ENDLOGMSG (("ne2000Send: overwrite detected (timeout)\n",
		    0, 0, 0, 0, 0, 0));
	pDrvCtrl->flags &= ~END_TX_BLOCKED;
	END_TX_SEM_GIVE (&pDrvCtrl->endObj);
	return (END_ERR_BLOCK);
	}

    /* If TX still in progress, re-configure chip */
    if (pDrvCtrl->flags & END_TX_IN_PROGRESS)
	{
	UCHAR tstat;

	SYS_IN_CHAR (pDrvCtrl, ENE_TSTAT, &tstat);
	SYS_IN_CHAR (pDrvCtrl, ENE_CMD, &cmdStat);
	ENDLOGMSG (("ne2000Send: timeout: flags=%x cmd=%02x stat=%02x\n",
		    pDrvCtrl->flags, cmdStat, tstat, 0, 0, 0));
	ne2000Config (pDrvCtrl, FALSE);
	}

    /* Copy and free the MBLK */

    len = netMblkToBufCopy (pMblk, pDrvCtrl->packetBuf, NULL);
    netMblkClChainFree (pMblk);
    len = max (len, ETHERSMALL);

    /* Transfer to the device */

    SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, 0x00);
    ne2000DataOut (pDrvCtrl, pDrvCtrl->packetBuf, len, (NE2000_TSTART << 8));

    /* Flush the write pipe */
    
    CACHE_PIPE_FLUSH ();
    
    /* kick Transmitter */

    SYS_OUT_CHAR (pDrvCtrl, ENE_TSTART, NE2000_TSTART);
    SYS_OUT_CHAR (pDrvCtrl, ENE_TCNTH, len >> 8);
    SYS_OUT_CHAR (pDrvCtrl, ENE_TCNTL, len & 0xff);
    SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_TXP | CMD_START);

    /* mark tx as in progress */

    pDrvCtrl->flags |= END_TX_IN_PROGRESS;

    /* Re-enable device TX interrupts */

    pDrvCtrl->imask |= (IM_TXEE | IM_PTXE);
    SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);

    END_TX_SEM_GIVE (&pDrvCtrl->endObj);

    /* update statistics */
    END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);


    ENDLOGMSG (("ne2000Send: done: imask=%02x\n",
		pDrvCtrl->imask, 0, 0, 0, 0, 0));
    return (OK);
    }

/*******************************************************************************
*
* ne2000PacketGet - get next received message
*
* Get next received message.  Returns NULL if none are
* ready.
*
* RETURNS: ptr to next packet, or NULL if none ready.
*/

LOCAL int ne2000PacketGet
    (
    NE2000END_DEVICE	*pDrvCtrl,
    char		*pData
    )
    {
    UINT        packetSize;
    UCHAR	uppByteCnt;
    UINT8       tempPage;               /* used in buffer validation */
    UINT8       pageCount;              /* used in buffer validation */
    UINT        packetLen = 0;
    NE2000_HEADER  h;

    if (pDrvCtrl->nextPacket == pDrvCtrl->current)
	return (0);

    ne2000DataIn (pDrvCtrl,
		  (((UINT)pDrvCtrl->nextPacket << 8) & 0x0000ffff),
		  sizeof (NE2000_HEADER), (char *) &h);

    /*
     * Calculate upper byte count in case it's corrupted,
     * though this supposedly happens only in StarLAN applications
     * with bus clock frequence greater than 4 mHz.
     */
    if (h.next > pDrvCtrl->nextPacket)
	uppByteCnt = (UCHAR) (h.next - pDrvCtrl->nextPacket);
    else
	uppByteCnt = (UCHAR) ((NE2000_PSTOP - pDrvCtrl->nextPacket)
			      + (h.next - NE2000_PSTART));
    if (h.lowByteCnt > 0xfc)
	uppByteCnt -= 2;
    else
	uppByteCnt -= 1;
    h.uppByteCnt = uppByteCnt;

    /* compute packet size excluding Ethernet checksum bytes */

    packetSize = (((UINT)h.uppByteCnt << 8) + h.lowByteCnt) - 4;

    /* Check for packet (and header) shifted in memory (by heavy load).
     * The method and solution are recommended by 3Com in their
     * EtherLink II Adapter Technical Manual, with the addition of
     * a reasonableness check on the next-page link.
     */
    pageCount = (UCHAR) ((packetSize + 4 + sizeof (NE2000_HEADER)
			  + (ENE_PAGESIZE - 1)) / ENE_PAGESIZE);
    tempPage = (UCHAR) (pDrvCtrl->nextPacket + pageCount);
    if (tempPage >= NE2000_PSTOP)
	tempPage -= (NE2000_PSTOP - NE2000_PSTART);
    if ((h.next != tempPage) ||
	(h.next < NE2000_PSTART) || (h.next >= NE2000_PSTOP))
	{
	/* can't trust anything now */
	pDrvCtrl->stats.badPacket++;
	pDrvCtrl->stats.rerror++;
	/* stop and restart the interface */
	if (!(pDrvCtrl->flags & (END_OVERWRITE|END_OVERWRITE2)))
	    ne2000Config (pDrvCtrl, TRUE);
	return (-1);
	}

    /* reject runts, although we are configured to reject them */
    if (packetSize < 60)
	{
	pDrvCtrl->stats.shortPacket++;
	goto doneGet;
	}

    /* reject packets larger than our scratch buffer */
    if (packetSize > NE2000_BUFSIZ)
	goto doneGet;

    if (h.rstat & RSTAT_PRX)
	{
	/* 3Com says this status marks a packet bit-shifted in memory;
	 * the data cannot be trusted but the NIC header is OK.
	 */
	if (h.rstat & (RSTAT_DFR | RSTAT_DIS))
	    {
	    pDrvCtrl->stats.badPacket++;
	    pDrvCtrl->stats.rerror++;
	    goto doneGet;
	    }
	pDrvCtrl->stats.rnoerror++;
	}
    else
	{
	if (h.rstat & RSTAT_DFR)
	    pDrvCtrl->stats.jabber++;
	pDrvCtrl->stats.rerror++;
	goto doneGet;
	}

    /* Signal that we received a good packet */

⌨️ 快捷键说明

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