kernels/linux-2.4.0/drivers/net/tlan.c
/***************************************************************
	 *	TLan_StartTx
	 *  
	 *	Returns:
	 *		0 on success, non-zero on failure.
	 *	Parms:
	 *		skb	A pointer to the sk_buff containing the
	 *			frame to be sent.
	 *		dev	The device to send the data on.
	 *
	 *	This function adds a frame to the Tx list to be sent
	 *	ASAP.  First it	verifies that the adapter is ready and
	 *	there is room in the queue.  Then it sets up the next
	 *	available list, copies the frame to the	corresponding
	 *	buffer.  If the adapter Tx channel is idle, it gives
	 *	the adapter a Tx Go command on the list, otherwise it
	 *	sets the forward address of the previous list to point
	 *	to this one.  Then it frees the sk_buff.
	 *
	 **************************************************************/


0 on success, non-zero on failure.
Parms:
skb     A pointer to the sk_buff containing the
frame to be sent.
dev     The device to send the data on.

This function adds a frame to the Tx list to be sent
ASAP.  First it verifies that the adapter is ready and
there is room in the queue.  Then it sets up the next
available list, copies the frame to the corresponding
buffer.  If the adapter Tx channel is idle, it gives
the adapter a Tx Go command on the list, otherwise it
sets the forward address of the previous list to point
to this one.  Then it frees the sk_buff.
0 on success non - zero on failure . Parms : skb A pointer to the sk_buff containing the frame to be sent . dev The device to send the data on . This function adds a frame to the Tx list to be sent ASAP . First it verifies that the adapter is ready and there is room in the queue . Then it sets up the next available list copies the frame to the corresponding buffer . If the adapter Tx channel is idle it gives the adapter a Tx Go command on the list otherwise it sets the forward address of the previous list to point to this one . Then it frees the sk_buff .
static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
{
	TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
	TLanList	*tail_list;
	u8		*tail_buffer;
	int		pad;
	unsigned long	flags;
	if ( ! priv->phyOnline ) {
		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  %s PHY is not ready\n", dev->name );
		dev_kfree_skb_any(skb);
		return 0;
	}
	tail_list = priv->txList + priv->txTail;
	if ( tail_list->cStat != TLAN_CSTAT_UNUSED ) {
		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  %s is busy (Head=%d Tail=%d)\n", dev->name, priv->txHead, priv->txTail );
		netif_stop_queue(dev);
		priv->txBusyCount++;
		return 1;
	}
	tail_list->forward = 0;
	if ( bbuf ) {
		tail_buffer = priv->txBuffer + ( priv->txTail * TLAN_MAX_FRAME_SIZE );
		memcpy( tail_buffer, skb->data, skb->len );
	} else {
		tail_list->buffer[0].address = virt_to_bus( skb->data );
		tail_list->buffer[9].address = (u32) skb;
	}
	pad = TLAN_MIN_FRAME_SIZE - skb->len;
	if ( pad > 0 ) {
		tail_list->frameSize = (u16) skb->len + pad;
		tail_list->buffer[0].count = (u32) skb->len;
		tail_list->buffer[1].count = TLAN_LAST_BUFFER | (u32) pad;
		tail_list->buffer[1].address = virt_to_bus( TLanPadBuffer );
	} else {
		tail_list->frameSize = (u16) skb->len;
		tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) skb->len;
		tail_list->buffer[1].count = 0;
		tail_list->buffer[1].address = 0;
	}
	spin_lock_irqsave(&priv->lock, flags);
	tail_list->cStat = TLAN_CSTAT_READY;
	if ( ! priv->txInProgress ) {
		priv->txInProgress = 1;
		outw( 0x4, dev->base_addr + TLAN_HOST_INT );
		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Starting TX on buffer %d\n", priv->txTail );
		outl( virt_to_bus( tail_list ), dev->base_addr + TLAN_CH_PARM );
		outl( TLAN_HC_GO | TLAN_HC_ACK, dev->base_addr + TLAN_HOST_CMD );
	} else {
		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Adding buffer %d to TX channel\n", priv->txTail );
		if ( priv->txTail == 0 ) {
			( priv->txList + ( TLAN_NUM_TX_LISTS - 1 ) )->forward = virt_to_bus( tail_list );
		} else {
			( priv->txList + ( priv->txTail - 1 ) )->forward = virt_to_bus( tail_list );
		}
	}
	spin_unlock_irqrestore(&priv->lock, flags);
	CIRC_INC( priv->txTail, TLAN_NUM_TX_LISTS );
	if ( bbuf )
		dev_kfree_skb_any(skb);
	dev->trans_start = jiffies;
	return 0;
}
static int TLan_StartTx ( struct sk_buff * skb , struct net_device * dev ) { TLanPrivateInfo * priv = ( TLanPrivateInfo * ) dev -> priv ; TLanList * tail_list ; u8 * tail_buffer ; int pad ; unsigned long flags ; if ( ! priv -> phyOnline ) { TLAN_DBG ( TLAN_DEBUG_TX , " \n " , dev -> name ) ; dev_kfree_skb_any ( skb ) ; return 0 ; } tail_list = priv -> txList + priv -> txTail ; if ( tail_list -> cStat != TLAN_CSTAT_UNUSED ) { TLAN_DBG ( TLAN_DEBUG_TX , " \n " , dev -> name , priv -> txHead , priv -> txTail ) ; netif_stop_queue ( dev ) ; priv -> txBusyCount ++ ; return 1 ; } tail_list -> forward = 0 ; if ( bbuf ) { tail_buffer = priv -> txBuffer + ( priv -> txTail * TLAN_MAX_FRAME_SIZE ) ; memcpy ( tail_buffer , skb -> data , skb -> len ) ; } else { tail_list -> buffer [ 0 ] . address = virt_to_bus ( skb -> data ) ; tail_list -> buffer [ 9 ] . address = ( u32 ) skb ; } pad = TLAN_MIN_FRAME_SIZE - skb -> len ; if ( pad > 0 ) { tail_list -> frameSize = ( u16 ) skb -> len + pad ; tail_list -> buffer [ 0 ] . count = ( u32 ) skb -> len ; tail_list -> buffer [ 1 ] . count = TLAN_LAST_BUFFER | ( u32 ) pad ; tail_list -> buffer [ 1 ] . address = virt_to_bus ( TLanPadBuffer ) ; } else { tail_list -> frameSize = ( u16 ) skb -> len ; tail_list -> buffer [ 0 ] . count = TLAN_LAST_BUFFER | ( u32 ) skb -> len ; tail_list -> buffer [ 1 ] . count = 0 ; tail_list -> buffer [ 1 ] . address = 0 ; } spin_lock_irqsave ( & priv -> lock , flags ) ; tail_list -> cStat = TLAN_CSTAT_READY ; if ( ! priv -> txInProgress ) { priv -> txInProgress = 1 ; outw ( 0x4 , dev -> base_addr + TLAN_HOST_INT ) ; TLAN_DBG ( TLAN_DEBUG_TX , " \n " , priv -> txTail ) ; outl ( virt_to_bus ( tail_list ) , dev -> base_addr + TLAN_CH_PARM ) ; outl ( TLAN_HC_GO | TLAN_HC_ACK , dev -> base_addr + TLAN_HOST_CMD ) ; } else { TLAN_DBG ( TLAN_DEBUG_TX , " \n " , priv -> txTail ) ; if ( priv -> txTail == 0 ) { ( priv -> txList + ( TLAN_NUM_TX_LISTS - 1 ) ) -> forward = virt_to_bus ( tail_list ) ; } else { ( priv -> txList + ( priv -> txTail - 1 ) ) -> forward = virt_to_bus ( tail_list ) ; } } spin_unlock_irqrestore ( & priv -> lock , flags ) ; CIRC_INC ( priv -> txTail , TLAN_NUM_TX_LISTS ) ; if ( bbuf ) dev_kfree_skb_any ( skb ) ; dev -> trans_start = jiffies ; return 0 ; }
TLan_StartTx
TLan_StartTx