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

📄 at91emacend.c

📁 atmel9200 vxworks bsp
💻 C
📖 第 1 页 / 共 4 页
字号:
LOCAL STATUS at91EndSend
    (
    at91end_device *pDrvCtrl,	/* device ptr */
    M_BLK_ID pNBuff		/* data to send */
    )
{
	EMAC_S* pemac = (EMAC_S*)EMAC_BASE_ADDR;
    BOOL        freeNow = TRUE;
	UINT32		curtailptr, txdelta;
	UINT32 oldlevel;
	char *txbuf;

/*
	ENDLOGMSG ((" Enter  at91EndSend routine...\n", 1, 2, 3, 4, 5, 6));
*/


	oldlevel = intLock ();

	curtailptr = pDrvCtrl ->TxTailPtr;
	txdelta = TX_FD_NUM - curtailptr + (pDrvCtrl ->TxPtr);
	if( txdelta >= TX_FD_NUM )
		txdelta -= TX_FD_NUM;

	if( (txdelta < 3) && ( pDrvCtrl ->TXFifoStat != TXFIFOEMPTY ) )
	{
		intUnlock( oldlevel );
		return ERROR;
	}

	intUnlock( oldlevel );

    /*
     * Obtain exclusive access to transmitter.  This is necessary because
     * we might have more than one stack transmitting at once.
     */
	END_TX_SEM_TAKE ( &pDrvCtrl->end, WAIT_FOREVER );

	/*
	 *	fifo now have space for new packet
	 */

	txbuf = (pDrvCtrl ->pTxBufStart)[curtailptr].bufaddr;
	(pDrvCtrl ->pTxBufStart)[curtailptr].len = pNBuff->mBlkPktHdr.len;
	

    /* Set pointers in local structures to point to data. */
	netMblkToBufCopy( pNBuff, (void *)txbuf, NULL ) ;


    /* place a transmit request */

    oldlevel = intLock ();   /* now at91EndInt won't get confused */
	
	if( pDrvCtrl ->TxTailPtr == (TX_FD_NUM-1) )
		pDrvCtrl ->TxTailPtr = 0;
	else
		pDrvCtrl ->TxTailPtr ++;
	
	if( pDrvCtrl ->TxTailPtr == pDrvCtrl ->TxPtr )
		pDrvCtrl ->TXFifoStat = TXFIFOFULL;
	else
		pDrvCtrl ->TXFifoStat = TXFIFONORMAL;

	if( (pemac ->EMAC_TSR) & EMAC_TSR_BNQ ) 
	{
		/*
		 *	TxPtr ->next ready to send package
		 *	TxTailPtr ->Next to accept transmit package
		 */
		TranNextPackage( pDrvCtrl );
	}	
	
    intUnlock (oldlevel);   /* now at91EndInt won't get confused */
    

	END_TX_SEM_GIVE (&pDrvCtrl->end);
    
    /* Bump the statistic counter. */

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

    /*
     * Cleanup.  The driver must either free the packet now or
     * set up a structure so it can be freed later after a transmit
     * interrupt occurs.
     */

    if (freeNow)
        netMblkClChainFree (pNBuff);

/*
	ENDLOGMSG ((" Leave  at91EndSend routine...\n", 1, 2, 3, 4, 5, 6));
*/
	

    return (OK);
}

/*******************************************************************************
*
* at91EndIoctl - the driver I/O control routine
*
* Process an ioctl request.
*
* RETURNS: A command specific response, usually OK or ERROR.
*/

LOCAL int at91EndIoctl
    (
    at91end_device *pDrvCtrl,	/* device receiving command */
    int cmd,			/* ioctl command code */
    caddr_t data		/* command argument */
    )
{

    int error = 0;
    long value;
/*
	ENDLOGMSG ((" Enter   at91EndIoctl routine...\n", 1, 2, 3, 4, 5, 6));
*/
	
    switch (cmd)
	{
	case EIOCSADDR:
		if (data == NULL)
			return (EINVAL);
		bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end),
			END_HADDR_LEN(&pDrvCtrl->end));
		break;
		
	case EIOCGADDR:
		if (data == NULL)
			return (EINVAL);
		bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *)data,
			END_HADDR_LEN(&pDrvCtrl->end));
		break;
		
	case EIOCSFLAGS:
		value = (long)data;
		if (value < 0)
		{
			value = ~value;
			END_FLAGS_CLR (&pDrvCtrl->end, value);
		}
		else
		{
			END_FLAGS_SET (&pDrvCtrl->end, value);
		}
		at91EndConfig (pDrvCtrl);
		break;
		
	case EIOCGFLAGS:
		*(int *)data = END_FLAGS_GET(&pDrvCtrl->end);
		break;
		
	case EIOCPOLLSTART:
		at91EndPollStart (pDrvCtrl);
		break;
		
	case EIOCPOLLSTOP:
		at91EndPollStop (pDrvCtrl);
		break;
		
    case EIOCGMIB2:
		if (data == NULL)
            return (EINVAL);
		bcopy((char *)&pDrvCtrl->end.mib2Tbl, (char *)data,
            sizeof(pDrvCtrl->end.mib2Tbl));
		break;
		
    case EIOCGFBUF:
		if (data == NULL)
			return (EINVAL);
		*(int *)data = 0;	/**END_MIN_FBUF;**/
		break;
		
    default:
		error = EINVAL;
	}
/*
	ENDLOGMSG ((" Leave   at91EndIoctl routine...\n", 1, 2, 3, 4, 5, 6));
*/
    return (error);
}

/******************************************************************************
*
* at91EndConfig - reconfigure the interface under us.
*
* Reconfigure the interface setting promiscuous mode
*
* RETURNS: N/A.
*/

LOCAL void at91EndConfig
    (
    at91end_device *pDrvCtrl	/* device to be re-configured */
    )
{
	at91EmacReset(pDrvCtrl);	/* reset the chip */

    /* Set up address filter for multicasting. */
	
    if ( END_MULTI_LST_CNT( &pDrvCtrl->end ) > 0 )
		at91EndAddrFilterSet ( pDrvCtrl );

	at91EndFdFree(pDrvCtrl);	/* Free the FDs */
	at91EndFdInitialize(pDrvCtrl);	/* Reinitialize FDs */
	
	at91EndMacInitialize( pDrvCtrl );	/* Initialize MAC */

	/* Was started before in interrupt mode? */
	if ( (END_FLAGS_GET(&pDrvCtrl->end) & IFF_RUNNING) &&
			((pDrvCtrl->flags & LS_POLLING) == 0) )
			at91EndStart(pDrvCtrl);	/* Start again */

    return;
    }

/*******************************************************************************
*
* at91EndPollStart - start polled mode operations
*
* RETURNS: OK or ERROR.
*/

LOCAL STATUS at91EndPollStart
    (
    at91end_device* pDrvCtrl	/* device to be polled */
    )
{

    int         oldLevel;
	EMAC_S* pemac = (EMAC_S*)EMAC_BASE_ADDR;
	
    oldLevel = intLock ();          /* disable ints during update */

	intDisable (pDrvCtrl->level);

    pDrvCtrl->flags |= LS_POLLING;

    intUnlock (oldLevel);   /* now at91EndInt won't get confused */

    ENDLOGMSG (( "POLLing STARTED\n", 1, 2, 3, 4, 5, 6 ));

    at91EndConfig (pDrvCtrl);	/* reconfigure device */

	/*
	 *	enable receive
	 */
	pemac ->EMAC_CTL = EMAC_CTL_RE | EMAC_CTL_TE;

	/* Set the flags to indicate that the device is up */
	END_FLAGS_SET (&pDrvCtrl->end, IFF_UP | IFF_RUNNING);

    return (OK);
    }

/*******************************************************************************
*
* at91EndPollStop - stop polled mode operations
*
* This function terminates polled mode operation.  The device returns to
* interrupt mode.
*
* The device interrupts are enabled, the current mode flag is switched
* to indicate interrupt mode and the device is then reconfigured for
* interrupt operation.
*
* RETURNS: OK or ERROR.
*/

LOCAL STATUS at91EndPollStop
    (
    at91end_device* pDrvCtrl	/* device to be changed */
    )
{
	EMAC_S* pemac = (EMAC_S*)EMAC_BASE_ADDR;
	int         oldLevel;

	/*
	 *	stop all
	 */
	pemac ->EMAC_CTL = 0;

    oldLevel = intLock ();	/* disable ints during register updates */

    pDrvCtrl->flags &= ~LS_POLLING;

    intUnlock (oldLevel);

	/*
	 * Restart in interrupt mode.  Calling at91EndConfig without clearing
	 * IFF_RUNNING flag will result in calling at91EndStart automatically
	 */
    at91EndConfig (pDrvCtrl);

    ENDLOGMSG (("END POLLing STOPPED\n", 1, 2, 3, 4, 5, 6));
	return (OK);
}

/*******************************************************************************
*
* at91EndPollRcv - routine to receive a packet in polled mode.
*
* This routine is called by a user to try and get a packet from the
* device.
*
* RETURNS: OK upon success.  EAGAIN is returned when no packet is available.
*/

LOCAL STATUS at91EndPollRcv
    (
    at91end_device *pDrvCtrl,	/* device to be polled */
    M_BLK_ID pMblk		/* ptr to buffer */
	)
{

	EMAC_S* pemac = (EMAC_S*)EMAC_BASE_ADDR;
    int len;
	UINT32 rxptr;
	STATUS retVal = EAGAIN;

	ENDLOGMSG (( "entering at91EndPollRcv\n", 1, 2, 3, 4, 5, 6 ));
	
	rxptr = pDrvCtrl ->rxBufPtr;
	
	if( ( (pDrvCtrl ->RecvBufDesc[rxptr].bufaddr) & EMAC_RECV_DESC_HAVE_DATA ) == 0 )
		return EAGAIN;

	/* Upper layer must provide a valid buffer. */
	len =  pDrvCtrl ->RecvBufDesc[rxptr].recvstatus & (0x7FF) ;

    if ((pMblk->mBlkHdr.mLen < len) || (!(pMblk->mBlkHdr.mFlags & M_EXT)))
	{
		ENDLOGMSG( ( "END: poll receive buffer too small to fit received buffer\n", 1,2,3,4,5,6 ) );
		goto pollRcvExit;
	}

    END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);

	bcopy ( (char*)(pDrvCtrl ->RecvBufDesc[rxptr].bufaddr&0xFFFFFFFC), pMblk->m_data, len );
    pMblk->m_len = len;
	/*pMblk->mBlkHdr.mData += OFFSET;*/
    pMblk->mBlkHdr.mFlags |= M_PKTHDR;
    pMblk->mBlkPktHdr.len = len;

	retVal = OK;

	ENDLOGMSG ((" proces at91EndPollRcv OK\n", 1, 2, 3, 4, 5, 6));

pollRcvExit:

	pDrvCtrl ->RecvBufDesc[rxptr].bufaddr &= 0xFFFFFFFE;
	if( rxptr == (RX_FD_NUM-1) )
		pDrvCtrl ->rxBufPtr = 0;
	else
		pDrvCtrl ->rxBufPtr ++;

	return retVal;
	
}

/*******************************************************************************
*
* at91EndPollSend - routine to send a packet in polled mode.
*
* This routine is called by a user to try and send a packet on the
* device.
*
* RETURNS: OK upon success.  EAGAIN if device is busy.
*/

LOCAL STATUS at91EndPollSend
    (
    at91end_device* pDrvCtrl,	/* device to be polled */
    M_BLK_ID pMblk		/* packet to send */
    )
{
	EMAC_S* pemac = (EMAC_S*)EMAC_BASE_ADDR;
	UINT32 curTxptr = pDrvCtrl ->TxPtr;

    int         len;
	ENDLOGMSG ((" enter at91EndPollSend\n", 1, 2, 3, 4, 5, 6 ));

	if( !(pemac ->EMAC_TSR&EMAC_TSR_TXIDLE ) )
	{
		return EAGAIN;
	}

	len = pMblk->mBlkPktHdr.len;
    /* Set pointers in local structures to point to data. */
	netMblkToBufCopy(pMblk, (void *)pDrvCtrl ->pTxBufStart[curTxptr].bufaddr, NULL) ;
	pDrvCtrl ->pTxBufStart[curTxptr].len = len;

	/*
	 *	start transmit
	 */
	pemac ->EMAC_TAR = (UINT32)pDrvCtrl ->pTxBufStart[curTxptr].bufaddr;
	pemac ->EMAC_TCR = len&(0x7FF);


    /* Bump the statistic counter. */

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


    /*
     * Cleanup.  The driver must either free the packet now or
     * set up a structure so it can be freed later after a transmit
     * interrupt occurs.
     */
	netMblkClChainFree (pMblk);

	ENDLOGMSG (("leaving at91EndPollSend\n", 1, 2, 3, 4, 5, 6));

    return (OK);
}

/******************************************************************************
*
* at91EndAddrFilterSet - set the address filter for multicast addresses
*
* This routine goes through all of the multicast addresses on the list
* of addresses (added with the endAddrAdd() routine) and sets the
* device's filter correctly.
*
* RETURNS: N/A.
*/

LOCAL void at91EndAddrFilterSet
    (
    at91end_device *pDrvCtrl	/* device to be updated */
	)
{
    ETHER_MULTI* pCurr;
    UINT32 count;

	ENDLOGMSG ((" Enter   at91EndAddrFilterSet routine...\n", 1, 2, 3, 4, 5, 6));

	for ( count = 0; count < (AT91EMAC_MAX_MULTI+1); count++ )
	{
		pDrvCtrl->addrListLow[count] =	/* Zero the addresses */
			pDrvCtrl->addrListHigh[count] = 0;
	}

	pDrvCtrl->mcastAddrCount = 0;		/* Init the multi count */
	
    pCurr = END_MULTI_LST_FIRST ( &pDrvCtrl->end );

	/*
	 * Now copy the addresses from ether_multi_list to our own array.  In our
	 * array, the first 6 bytes are for our own MAC address.  This array is
	 * an exact replica of the internal CAM registers of Ethernet controller.
	 * The CAM registers will be updated in at91EndMacInitialize() function
	 */
    while ( pCurr != NULL )
	{
		if (pDrvCtrl->mcastAddrCount > AT91EMAC_MAX_MULTI )
			break;
		FormatETHSpecialAddrWord( &( pDrvCtrl ->addrListHigh[ pDrvCtrl ->mcastAddrCount + 1 ] ), 
			&(pDrvCtrl ->addrListLow[ pDrvCtrl ->mcastAddrCount + 1 ]), (BYTE*)(pCurr->addr) );
		

		pDrvCtrl ->mcastAddrCount++;		/* Bump the multicast address count */
	
		pCurr = END_MULTI_LST_NEXT(pCurr);	/* Get the next address in the list */
	}
	ENDLOGMSG ((" Leave   at91EndAddrFilterSet routine...\n", 1, 2, 3, 4, 5, 6));
	
}

/*****************************************************************************
*
* at91EndMCastAdd - add a multicast address for the device

⌨️ 快捷键说明

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