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

📄 ax88796end.c

📁 操作系统vxworks
💻 C
📖 第 1 页 / 共 5 页
字号:
	len = ax88796PacketGet (pDrvCtrl, pBuf + pDrvCtrl->offset);
	if (len <= 0)
	    {
	    logMsg ("ax88796HandleRcvInt: bad packet! (len=%d)\n",
			len, 0, 0, 0, 0, 0);
	    ax88796Config (pDrvCtrl, TRUE);
	    END_ERR_ADD (&pDrvCtrl->endObj, MIB2_IN_ERRS, +1);
	    break;
	    }
	    
	pMblk = mBlkGet (pDrvCtrl->endObj.pNetPool,
			 M_DONTWAIT, MT_DATA);
	if (!pMblk)
	    {
	    ENDLOGMSG (("ax88796HandleRcvInt: 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 (("ax88796HandleRcvInt: 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, AX88796_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 (("ax88796HandleRcvInt: done (flags=%x, imask=%x)\n",
		pDrvCtrl->flags,pDrvCtrl->imask,0,0,0,0));

    intUnlock (oldLevel);
    }

/*******************************************************************************
*
* ax88796DataIn - input bytes from AX88796 memory
*
* NOMANUAL
*/

LOCAL void ax88796DataIn
    (
    AX88796END_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);
    
    delay (20);

    while (len--)
    {
    		SYS_IN_CHAR (pDrvCtrl, ENE_DATA, pData++);
    }
    
    SYS_OUT_CHAR (pDrvCtrl, ENE_INTMASK, pDrvCtrl->imask);
    }

/*******************************************************************************
*
* ax88796DataOut - output bytes to AX88796 memory
*
* NOMANUAL
*/

LOCAL void ax88796DataOut
    (
    AX88796END_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);
    
    while (len--)
    {
    		SYS_OUT_CHAR (pDrvCtrl, ENE_DATA, *(pData++));
    }
    }

/*******************************************************************************
*
* ax88796Send - 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 ax88796Send
    (
    void*	pCookie,	/* device ptr */
    M_BLK_ID	pMblk		/* data to send */
    )
    {
    int		len;
    UCHAR	cmdStat;
    AX88796END_DEVICE* pDrvCtrl = (AX88796END_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);
	}

    /* 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 (("ax88796Send: 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 (("ax88796Send: 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);
	logMsg ("ax88796Send: timeout: flags=%x cmd=%02x stat=%02x\n",
		    pDrvCtrl->flags, cmdStat, tstat, 0, 0, 0);
	ax88796Config (pDrvCtrl, TRUE);
	return (ERROR);
	
	}

    /* 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);
    ax88796DataOut (pDrvCtrl, pDrvCtrl->packetBuf, len, (AX88796_TSTART << 8));

    /* Flush the write pipe */
    
    CACHE_PIPE_FLUSH ();
    
    /* kick Transmitter */
    
    SYS_OUT_CHAR (pDrvCtrl, ENE_CMD, CMD_PAGE0);

    SYS_OUT_CHAR (pDrvCtrl, ENE_TSTART, AX88796_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);

    return (OK);
    }

/*******************************************************************************
*
* ax88796PacketGet - 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 ax88796PacketGet
    (
    AX88796END_DEVICE	*pDrvCtrl,
    char		*pData
    )
    {
    UINT        packetSize;
    UINT8       tempPage;               /* used in buffer validation */
    UINT8       pageCount;              /* used in buffer validation */
    UINT        packetLen = 0;
    AX88796_HEADER  h;

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

    ax88796DataIn (pDrvCtrl,
		  (((UINT)pDrvCtrl->nextPacket << 8) & 0x0000ffff),
		  sizeof (AX88796_HEADER), (char *) &h);
		  
/*		  
	logMsg ("rstat = %x; next = %x; lowByteCnt = %x; uppByteCnt = %x\n",
			h.rstat, h.next, h.lowByteCnt, h.uppByteCnt, 5, 6);
*/		  

    /* compute packet size excluding Ethernet checksum bytes */

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

    /* 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  + sizeof (AX88796_HEADER)
			  + (ENE_PAGESIZE - 1)) / ENE_PAGESIZE);
    tempPage = (UCHAR) (pDrvCtrl->nextPacket + pageCount);
    if (tempPage >= AX88796_PSTOP)
	tempPage -= (AX88796_PSTOP - AX88796_PSTART);
	
    if ((h.next != tempPage) ||
	(h.next < AX88796_PSTART) || (h.next >= AX88796_PSTOP))
	{
	/* can't trust anything now */
	pDrvCtrl->stats.badPacket++;
	pDrvCtrl->stats.rerror++;
	/* stop and restart the interface */
	if (!(pDrvCtrl->flags & (END_OVERWRITE|END_OVERWRITE2)))
//	    ax88796Config (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 > AX88796_BUFSIZ)
	goto doneGet;

    /* Signal that we received a good packet */
    packetLen = packetSize;

    /* copy separated frame to a temporary buffer */
    ax88796DataIn (pDrvCtrl,
		  ((UINT)pDrvCtrl->nextPacket << 8) + sizeof (AX88796_HEADER),
		  packetLen,
		  pData);

doneGet:
    pDrvCtrl->nextPacket = h.next;
    SYS_OUT_CHAR (pDrvCtrl, ENE_BOUND,
		  (pDrvCtrl->nextPacket != AX88796_PSTART ?
		   pDrvCtrl->nextPacket - 1 : AX88796_PSTOP - 1));

    return (packetLen);
    }


/******************************************************************************
*
* ax88796PollRecv - routine to receive a packet in polled mode.
*
* This routine is called by a user to try and get a packet from the
* device.
*/

LOCAL STATUS ax88796PollRecv
    (
    void*	pCookie,	/* device ptr */
    M_BLK_ID	pMblk
    )
    {
    int len;
    AX88796END_DEVICE* pDrvCtrl = (AX88796END_DEVICE *) pCookie;

    /* If no packet is available return immediately */
    pDrvCtrl->current = ax88796GetCurr (pDrvCtrl);
    if (pDrvCtrl->nextPacket == pDrvCtrl->current)
        return ((STATUS) (EAGAIN));

    /* Upper layer provides the buffer, make sure it's big enough. */
    if ((pMblk->mBlkHdr.mLen < AX88796_BUFSIZ)
	|| !(pMblk->mBlkHdr.mFlags & M_EXT))
	{
        return ((STATUS) (EAGAIN));
	}

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

    len = ax88796PacketGet (pDrvCtrl, pMblk->mBlkHdr.mData + pDrvCtrl->offset);
    if (len <= 0)
        return ((STATUS) (EAGAIN));
    pMblk->mBlkHdr.mFlags |= M_PKTHDR;
    pMblk->mBlkHdr.mLen   = len;
    pMblk->mBlkPktHdr.len = len;
    /* Adjust mData to match n23000PacketGet() above */
    pMblk->mBlkHdr.mData += pDrvCtrl->offset;

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

/*******************************************************************************
*
* ax88796PollSend - routine to send a packet in polled mode.
*
* This routine is called by a user to try and send a packet on the
* device.
*/

static STATUS ax88796PollSend
    (
    void*	pCookie,	/* device ptr */
    M_BLK_ID	pMblk
    )
    {
    char *	pBuf;
    UCHAR	cmdStat;
    int		len;
    AX88796END_DEVICE* pDrvCtrl = (AX88796END_DEVICE *) pCookie;

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

    SYS_IN_CHAR (pDrvCtrl, ENE_CMD, &cmdStat);
    while (cmdStat & CMD_TXP)
	SYS_IN_CHAR (pDrvCtrl, ENE_DATA, &cmdStat);

    /* Get the next TXD */

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

    /* Transfer to the device */

    ax88796DataOut (pDrvCtrl, pDrvCtrl->packetBuf, len, (AX88796_TSTART << 8));

    /* Flush the write pipe */

    CACHE_PIPE_FLUSH ();

    /* kick Transmitter */

    SYS_OUT_CHAR (pDrvCtrl, ENE_TSTART, AX88796_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);

    /* update statistics */

    END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);

    /* Flush the write pipe */

    CACHE_PIPE_FLUSH ();

    /* Spin until the packet has been sent */

    SYS_IN_CHAR (pDrvCtrl, ENE_CMD, &cmdStat);
    while (cmdStat & CMD_TXP)

⌨️ 快捷键说明

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