/*
 * Send a data block via Ethernet
 */
static int
ftmac100_send (struct eth_device *dev, volatile void *packet, int length)
{
	struct ftmac100 *ftmac100 = (struct ftmac100 *)dev->iobase;
	struct ftmac100_data *priv = dev->priv;
	volatile struct ftmac100_txdes *curr_des = priv->txdes;
	int tmo;

	if (curr_des->txdes0 & FTMAC100_TXDES0_TXDMA_OWN) {
		debug ("%s(): no TX descriptor available\n", __func__);
		return -1;
	}

	debug ("%s(%x, %x)\n", __func__, (int)packet, length);

	length = (length < ETH_ZLEN) ? ETH_ZLEN : length;

	/* initiate a transmit sequence */

	curr_des->txdes2 = (unsigned int)packet;	/* TXBUF_BADR */

	curr_des->txdes1 &= FTMAC100_TXDES1_EDOTR;
	curr_des->txdes1 |= FTMAC100_TXDES1_FTS |
			    FTMAC100_TXDES1_LTS |
			    FTMAC100_TXDES1_TXBUF_SIZE (length);

	curr_des->txdes0 = FTMAC100_TXDES0_TXDMA_OWN;

	/* start transmit */

	writel (1, &ftmac100->txpd);

	/* wait for transfer to succeed */

	tmo = get_timer (0) + 5 * CONFIG_SYS_HZ;
	while (curr_des->txdes0 & FTMAC100_TXDES0_TXDMA_OWN) {
		if (get_timer (0) >= tmo) {
			debug ("%s(): timed out\n", __func__);
			return -1;
		}
	}

	debug ("%s(): packet sent\n", __func__);

	return 0;
}
Beispiel #2
0
static void ftmac100_txdes_set_buffer_size(struct ftmac100_txdes *txdes,
					   unsigned int len)
{
	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXBUF_SIZE(len));
}
Beispiel #3
0
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;
	unsigned char *pucBuffer = tx_buf;
	unsigned char *pucChar;
	u16_t usTotalLength = p->tot_len - ETH_PAD_SIZE;
	err_t xReturn = ERR_OK;
	long x;
	struct ftmac100_txdes *txdes;

	( void ) pxNetIf;

	#if defined(LWIP_DEBUG) && LWIP_NETIF_TX_SINGLE_PBUF
	LWIP_ASSERT("p->next == NULL && p->len == p->tot_len", p->next == NULL && p->len == p->tot_len);
	#endif

	/* Initiate transfer. */
	if( p->len == p->tot_len )
	{
		memcpy( pucBuffer, &( ( unsigned char * ) p->payload )[ ETH_PAD_SIZE ], usTotalLength );
	}
	else
	{
		/* pbuf chain, copy into contiguous tx_buf. */
		if( p->tot_len >= sizeof( tx_buf ) )
		{
#if LINK_STATS
			LINK_STATS_INC( link.lenerr );
			LINK_STATS_INC( link.drop );
#endif
			xReturn = ERR_BUF;
		}
		else
		{
			pucChar = tx_buf;

			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;
				}
			}
		}
	}

	if( xReturn == ERR_OK )
	{
		sys_sem_wait( &pgMac100If->tx_sem );

		xReturn = ERR_BUF;

#if 0 /* Only has 1 tx descriptor */
		txdes = &gTxDes[0];
#else
		txdes = &gTxDes[pgMac100If->tx_pointer];
		pgMac100If->tx_pointer = (pgMac100If->tx_pointer + 1) & (TX_QUEUE_ENTRIES - 1);;
#endif
		/* setup TX descriptor */
		txdes->txdes2 = (int) pucBuffer;

		txdes->txdes1 &= FTMAC100_TXDES1_EDOTR;

		if (usTotalLength < 64)
			usTotalLength = 64;
		txdes->txdes1 |= ( FTMAC100_TXDES1_FTS | FTMAC100_TXDES1_LTS |
				   FTMAC100_TXDES1_TXBUF_SIZE( usTotalLength ) );

		/* Descriptor owned by FTMAC */
		txdes->txdes0 = FTMAC100_TXDES0_TXDMA_OWN;

		/* start transmit */
		FTMAC100_OFFSET_TXPD = 1;
		for( x = 0; x < netifMAX_TX_ATTEMPTS; x++ )
		{
			if( !(txdes->txdes0 & FTMAC100_TXDES0_TXDMA_OWN) )
			{
				xReturn = ERR_OK;
#if LINK_STATS
				LINK_STATS_INC( link.xmit );
#endif
				break;
			}
			else
			{
				vTaskDelay( netifTX_BUFFER_FREE_WAIT );
			}
		}

		if( xReturn != ERR_OK )
		{
#if LINK_STATS
			LINK_STATS_INC( link.memerr );
			LINK_STATS_INC( link.drop );
#endif
		}

		/* reset the descriptor */
		txdes->txdes1 &= ~( FTMAC100_TXDES1_FTS | FTMAC100_TXDES1_LTS |
				    FTMAC100_TXDES1_TXBUF_SIZE( 0x7ff ) );
		sys_sem_signal( &pgMac100If->tx_sem );
	}

	return xReturn;
}