portBASE_TYPE xNetworkInterfaceOutput( xNetworkBufferDescriptor_t * const pxNetworkBuffer )
{
portBASE_TYPE xReturn = pdFAIL;
int32_t x;
extern void EMAC_StartTransmitNextBuffer( uint32_t ulLength );
extern void EMAC_SetNextPacketToSend( uint8_t * pucBuffer );


	/* Attempt to obtain access to a Tx buffer. */
	for( x = 0; x < niMAX_TX_ATTEMPTS; x++ )
	{
		if( EMAC_CheckTransmitIndex() == TRUE )
		{
			/* Will the data fit in the Tx buffer? */
			if( pxNetworkBuffer->xDataLength < EMAC_ETH_MAX_FLEN ) /*_RB_ The size needs to come from FreeRTOSIPConfig.h. */
			{
				/* Assign the buffer to the Tx descriptor that is now known to
				be free. */
				EMAC_SetNextPacketToSend( pxNetworkBuffer->pucEthernetBuffer );

				/* The EMAC now owns the buffer. */
				pxNetworkBuffer->pucEthernetBuffer = NULL;

				/* Initiate the Tx. */
				EMAC_StartTransmitNextBuffer( pxNetworkBuffer->xDataLength );
				iptraceNETWORK_INTERFACE_TRANSMIT();

				/* The Tx has been initiated. */
				xReturn = pdPASS;
			}
			break;
		}
		else
		{
			vTaskDelay( niTX_BUFFER_FREE_WAIT );
		}
	}

	/* Finished with the network buffer. */
	vNetworkBufferRelease( pxNetworkBuffer );

	return xReturn;
}
Esempio n. 2
0
BaseType_t xNetworkInterfaceOutput( xNetworkBufferDescriptor_t * const pxNetworkBuffer )
{
BaseType_t xReturn = pdFAIL;
int32_t x;

	/* Attempt to obtain access to a Tx descriptor. */
	for( x = 0; x < niMAX_TX_ATTEMPTS; x++ )
	{
		if( EMAC_CheckTransmitIndex() == TRUE )
		{
			/* Assign the buffer being transmitted to the Tx descriptor. */
			EMAC_SetNextPacketToSend( pxNetworkBuffer->pucEthernetBuffer );

			/* The EMAC now owns the buffer and will free it when it has been
			transmitted.  Set pucBuffer to NULL to ensure the buffer is not
			freed when the network buffer structure is returned to the pool
			of network buffers. */
			pxNetworkBuffer->pucEthernetBuffer = NULL;

			/* Initiate the Tx. */
			EMAC_StartTransmitNextBuffer( pxNetworkBuffer->xDataLength );
			iptraceNETWORK_INTERFACE_TRANSMIT();

			/* The Tx has been initiated. */
			xReturn = pdPASS;

			break;
		}
		else
		{
			iptraceWAITING_FOR_TX_DMA_DESCRIPTOR();
			vTaskDelay( niTX_BUFFER_FREE_WAIT );
		}
	}

	/* Finished with the network buffer. */
	vNetworkBufferRelease( pxNetworkBuffer );

	return xReturn;
}
Esempio n. 3
0
/**
 * This function should do the actual transmission of the packet. The packet is
 * contained in the pbuf that is passed to the function. This pbuf
 * might be chained.
 *
 * @param pxNetIf the lwip network interface structure for this etherpxNetIf
 * @param p the MAC packet to send (e.g. IP packet including MAC addresses and type)
 * @return ERR_OK if the packet could be sent
 *		 an err_t value if the packet couldn't be sent
 *
 * @note Returning ERR_MEM here if a DMA queue of your MAC is full can lead to
 *	   strange results. You might consider waiting for space in the DMA queue
 *	   to become available since the stack doesn't retry to send a packet
 *	   dropped because of memory failure (except for the TCP timers).
 */
static err_t prvLowLevelOutput( struct netif *pxNetIf, struct pbuf *p )
{

	/* This is taken from lwIP example code and therefore does not conform
	to the FreeRTOS coding standard. */

struct pbuf *q;
uint8_t *pucChar;
struct eth_hdr *pxHeader;
err_t xReturn = ERR_BUF;
int32_t x;
extern uint8_t *EMAC_NextPacketToSend( void );
void EMAC_StartTransmitNextBuffer( uint32_t ulLength );

	( void ) pxNetIf;

	/* Attempt to obtain access to a Tx buffer. */
	for( x = 0; x < netifMAX_TX_ATTEMPTS; x++ )
	{
		if( EMAC_CheckTransmitIndex() == TRUE )
		{
			/* Will the data fit in the Tx buffer? */
			if( p->tot_len < EMAC_ETH_MAX_FLEN )
			{
				/* Get a pointer to the Tx buffer that is now known to be free. */
				pucChar = EMAC_NextPacketToSend();

				/* Copy the data into the Tx buffer. */
				for( q = p; q != NULL; q = q->next )
				{
					/* Send the data from the pbuf to the interface, one pbuf at a
					time. The size of the data in each pbuf is kept in the ->len
					variable. */
					/* send data from(q->payload, q->len); */
					LWIP_DEBUGF( NETIF_DEBUG, ( "NETIF: send pucChar %p q->payload %p q->len %i q->next %p\n", pucChar, q->payload, ( int ) q->len, ( void* ) q->next ) );
					if( q == p )
					{
						memcpy( pucChar, &( ( char * ) q->payload )[ ETH_PAD_SIZE ], q->len - ETH_PAD_SIZE );
						pucChar += q->len - ETH_PAD_SIZE;
					}
					else
					{
						memcpy( pucChar, q->payload, q->len );
						pucChar += q->len;
					}
				}

				/* Initiate the Tx. */
				EMAC_StartTransmitNextBuffer( p->tot_len - ETH_PAD_SIZE );

				LINK_STATS_INC( link.xmit );
				snmp_add_ifoutoctets( pxNetIf, usTotalLength );
				pxHeader = ( struct eth_hdr * )p->payload;

				if( ( pxHeader->dest.addr[ 0 ] & 1 ) != 0 )
				{
					/* broadcast or multicast packet*/
					snmp_inc_ifoutnucastpkts( pxNetIf );
				}
				else
				{
					/* unicast packet */
					snmp_inc_ifoutucastpkts( pxNetIf );
				}

				/* The Tx has been initiated. */
				xReturn = ERR_OK;
			}
			else
			{
				configASSERT( ( volatile void * ) 0 );
			}

			break;
		}
		else
		{
			vTaskDelay( netifTX_BUFFER_FREE_WAIT );
		}
	}

	configASSERT( xReturn == ERR_OK );
	if( xReturn != ERR_OK )
	{
		LINK_STATS_INC( link.memerr );
		LINK_STATS_INC( link.drop );
		snmp_inc_ifoutdiscards( pxNetIf );
	}

	return xReturn;
}