예제 #1
0
파일: snpnet.c 프로젝트: eatnumber1/ipxe
/**
 * Poll for completed packets
 *
 * @v netdev		Network device
 */
static void snpnet_poll_tx ( struct net_device *netdev ) {
    struct snp_nic *snp = netdev->priv;
    struct io_buffer *iobuf;
    UINT32 irq;
    VOID *txbuf;
    EFI_STATUS efirc;
    int rc;

    /* Get status */
    if ( ( efirc = snp->snp->GetStatus ( snp->snp, &irq, &txbuf ) ) != 0 ) {
        rc = -EEFI ( efirc );
        DBGC ( snp, "SNP %s could not get status: %s\n",
               netdev->name, strerror ( rc ) );
        netdev_rx_err ( netdev, NULL, rc );
        return;
    }

    /* Do nothing unless we have a completion */
    if ( ! txbuf )
        return;

    /* Sanity check */
    if ( ! snp->txbuf ) {
        DBGC ( snp, "SNP %s reported spurious TX completion\n",
               netdev->name );
        netdev_tx_err ( netdev, NULL, -EPIPE );
        return;
    }

    /* Complete transmission */
    iobuf = snp->txbuf;
    snp->txbuf = NULL;
    netdev_tx_complete ( netdev, iobuf );
}
예제 #2
0
파일: af_packet.c 프로젝트: antonym/ipxe
/**
 * Transmit an ethernet packet.
 *
 * The packet can be written to the socket and marked as complete immediately.
 */
static int af_packet_nic_transmit ( struct net_device *netdev,
				    struct io_buffer *iobuf )
{
	struct af_packet_nic * nic = netdev->priv;
	struct sockaddr_ll socket_address;
	const struct ethhdr * eh;
	int rc;

	memset(&socket_address, 0, sizeof(socket_address));
	socket_address.sll_family = LINUX_AF_PACKET;
	socket_address.sll_ifindex = nic->ifindex;
	socket_address.sll_halen = ETH_ALEN;

	eh = iobuf->data;
	memcpy(socket_address.sll_addr, eh->h_dest, ETH_ALEN);

	rc = linux_sendto(nic->fd, iobuf->data, iobuf->tail - iobuf->data,
			  0, (struct sockaddr *)&socket_address,
			  sizeof(socket_address));

	DBGC2(nic, "af_packet %p wrote %d bytes\n", nic, rc);
	netdev_tx_complete(netdev, iobuf);

	return 0;
}
예제 #3
0
파일: vxge_main.c 프로젝트: 42wim/ipxe
/*
 * vxge_xmit_compl
 *
 * If an interrupt was raised to indicate DMA complete of the Tx packet,
 * this function is called. It identifies the last TxD whose buffer was
 * freed and frees all skbs whose data have already DMA'ed into the NICs
 * internal memory.
 */
enum vxge_hw_status
vxge_xmit_compl(struct __vxge_hw_fifo *fifo_hw,
		struct vxge_hw_fifo_txd *txdp, enum vxge_hw_fifo_tcode tcode)
{
	struct net_device *netdev;
	struct io_buffer *tx_iob = NULL;

	vxge_trace();

	netdev = fifo_hw->vpathh->hldev->ndev;

	tx_iob = (struct io_buffer *)(intptr_t)txdp->host_control;

	if (tcode == VXGE_HW_FIFO_T_CODE_OK) {
		netdev_tx_complete(netdev, tx_iob);
	} else {
		netdev_tx_complete_err(netdev, tx_iob, -EINVAL);
		vxge_debug(VXGE_ERR, "%s: transmit failed, tcode %d\n",
				netdev->name, tcode);
	}

	memset(txdp, 0, sizeof(struct vxge_hw_fifo_txd));

	return VXGE_HW_OK;
}
예제 #4
0
파일: netfront.c 프로젝트: pipcet/ipxe
/**
 * Poll for completed packets
 *
 * @v netdev		Network device
 */
static void netfront_poll_tx ( struct net_device *netdev ) {
	struct netfront_nic *netfront = netdev->priv;
	struct xen_device *xendev = netfront->xendev;
	struct netif_tx_response *response;
	struct io_buffer *iobuf;
	unsigned int status;
	int rc;

	/* Consume any unconsumed responses */
	while ( RING_HAS_UNCONSUMED_RESPONSES ( &netfront->tx_fring ) ) {

		/* Get next response */
		response = RING_GET_RESPONSE ( &netfront->tx_fring,
					       netfront->tx_fring.rsp_cons++ );

		/* Retrieve from descriptor ring */
		iobuf = netfront_pull ( netfront, &netfront->tx, response->id );
		status = response->status;
		if ( status == NETIF_RSP_OKAY ) {
			DBGC2 ( netfront, "NETFRONT %s TX id %d complete\n",
				xendev->key, response->id );
			netdev_tx_complete ( netdev, iobuf );
		} else {
			rc = -EIO_NETIF_RSP ( status );
			DBGC2 ( netfront, "NETFRONT %s TX id %d error %d: %s\n",
				xendev->key, response->id, status,
				strerror ( rc ) );
			netdev_tx_complete_err ( netdev, iobuf, rc );
		}
	}
}
예제 #5
0
파일: legacy.c 프로젝트: B-Rich/serialice
static int legacy_transmit ( struct net_device *netdev, struct io_buffer *iobuf ) {
    struct nic *nic = netdev->priv;
    struct ethhdr *ethhdr;

    DBG ( "Transmitting %zd bytes\n", iob_len ( iobuf ) );
    iob_pad ( iobuf, ETH_ZLEN );
    ethhdr = iobuf->data;
    iob_pull ( iobuf, sizeof ( *ethhdr ) );
    nic->nic_op->transmit ( nic, ( const char * ) ethhdr->h_dest,
                            ntohs ( ethhdr->h_protocol ),
                            iob_len ( iobuf ), iobuf->data );
    netdev_tx_complete ( netdev, iobuf );
    return 0;
}
예제 #6
0
파일: e1000e_main.c 프로젝트: CSU-GH/gpxe
/**
 * e1000_process_tx_packets - process transmitted packets
 *
 * @v netdev	network interface device structure
 **/
static void e1000e_process_tx_packets ( struct net_device *netdev )
{
	struct e1000_adapter *adapter = netdev_priv ( netdev );
	uint32_t i;
	uint32_t tx_status;
	struct e1000_tx_desc *tx_curr_desc;

	/* Check status of transmitted packets
	 */
	DBG ( "process_tx_packets: tx_head = %d, tx_tail = %d\n", adapter->tx_head,
	      adapter->tx_tail );

	while ( ( i = adapter->tx_head ) != adapter->tx_tail ) {

		tx_curr_desc = ( void * )  ( adapter->tx_base ) +
					   ( i * sizeof ( *adapter->tx_base ) );

		tx_status = tx_curr_desc->upper.data;

		DBG ( "	 tx_curr_desc = %#08lx\n", virt_to_bus ( tx_curr_desc ) );
		DBG ( "	 tx_status = %#08x\n", tx_status );

		/* if the packet at tx_head is not owned by hardware it is for us */
		if ( ! ( tx_status & E1000_TXD_STAT_DD ) )
			break;

		DBG ( "Sent packet. tx_head: %d tx_tail: %d tx_status: %#08x\n",
		      adapter->tx_head, adapter->tx_tail, tx_status );

		if ( tx_status & ( E1000_TXD_STAT_EC | E1000_TXD_STAT_LC |
				   E1000_TXD_STAT_TU ) ) {
			netdev_tx_complete_err ( netdev, adapter->tx_iobuf[i], -EINVAL );
			DBG ( "Error transmitting packet, tx_status: %#08x\n",
			      tx_status );
		} else {
			netdev_tx_complete ( netdev, adapter->tx_iobuf[i] );
			DBG ( "Success transmitting packet, tx_status: %#08x\n",
			      tx_status );
		}

		/* Decrement count of used descriptors, clear this descriptor
		 */
		adapter->tx_fill_ctr--;
		memset ( tx_curr_desc, 0, sizeof ( *tx_curr_desc ) );

		adapter->tx_head = ( adapter->tx_head + 1 ) % NUM_TX_DESC;
	}
}
예제 #7
0
파일: nii.c 프로젝트: baloo/ipxe
/**
 * Poll for completed packets
 *
 * @v netdev		Network device
 * @v stat		Status flags
 */
static void nii_poll_tx ( struct net_device *netdev, unsigned int stat ) {
	struct nii_nic *nii = netdev->priv;
	struct io_buffer *iobuf;

	/* Do nothing unless we have a completion */
	if ( stat & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN )
		return;

	/* Sanity check */
	assert ( nii->txbuf != NULL );

	/* Complete transmission */
	iobuf = nii->txbuf;
	nii->txbuf = NULL;
	netdev_tx_complete ( netdev, iobuf );
}
예제 #8
0
파일: b44.c 프로젝트: 1stMaster/syslinux
/** Recycles sent TX descriptors and notifies network stack
 *
 * @v bp Driver state
 */
static void b44_tx_complete(struct b44_private *bp)
{
	u32 cur, i;

	cur = pending_tx_index(bp);

	for (i = bp->tx_dirty; i != cur; i = ring_next(i)) {
		/* Free finished frame */
		netdev_tx_complete(bp->netdev, bp->tx_iobuf[i]);
		bp->tx_iobuf[i] = NULL;

		/* Clear TX descriptor */
		bp->tx[i].ctrl = 0;
		bp->tx[i].addr = 0;
	}
	bp->tx_dirty = cur;
}
예제 #9
0
파일: undinet.c 프로젝트: Phlogistique/iPXE
/**
 * Transmit packet
 *
 * @v netdev		Network device
 * @v iobuf		I/O buffer
 * @ret rc		Return status code
 */
static int undinet_transmit ( struct net_device *netdev,
			      struct io_buffer *iobuf ) {
	struct s_PXENV_UNDI_TRANSMIT undi_transmit;
	size_t len = iob_len ( iobuf );
	int rc;

	/* Technically, we ought to make sure that the previous
	 * transmission has completed before we re-use the buffer.
	 * However, many PXE stacks (including at least some Intel PXE
	 * stacks and Etherboot 5.4) fail to generate TX completions.
	 * In practice this won't be a problem, since our TX datapath
	 * has a very low packet volume and we can get away with
	 * assuming that a TX will be complete by the time we want to
	 * transmit the next packet.
	 */

	/* Copy packet to UNDI I/O buffer */
	if ( len > sizeof ( basemem_packet ) )
		len = sizeof ( basemem_packet );
	memcpy ( &basemem_packet, iobuf->data, len );

	/* Create PXENV_UNDI_TRANSMIT data structure */
	memset ( &undi_transmit, 0, sizeof ( undi_transmit ) );
	undi_transmit.DestAddr.segment = rm_ds;
	undi_transmit.DestAddr.offset = __from_data16 ( &undinet_tbd );
	undi_transmit.TBD.segment = rm_ds;
	undi_transmit.TBD.offset = __from_data16 ( &undinet_tbd );

	/* Create PXENV_UNDI_TBD data structure */
	undinet_tbd.ImmedLength = len;
	undinet_tbd.Xmit.segment = rm_ds;
	undinet_tbd.Xmit.offset = __from_data16 ( basemem_packet );

	/* Issue PXE API call */
	if ( ( rc = pxeparent_call ( undinet_entry, PXENV_UNDI_TRANSMIT,
				     &undi_transmit,
				     sizeof ( undi_transmit ) ) ) != 0 )
		goto done;

	/* Free I/O buffer */
	netdev_tx_complete ( netdev, iobuf );

 done:
	return rc;
}
예제 #10
0
파일: e1000.c 프로젝트: 1stMaster/syslinux
/** 
 * e1000_poll - Poll for received packets
 *
 * @v netdev	Network device
 */
static void
e1000_poll ( struct net_device *netdev )
{
	struct e1000_adapter *adapter = netdev_priv( netdev );
	struct e1000_hw *hw = &adapter->hw;

	uint32_t icr;
	uint32_t tx_status;
	uint32_t rx_status;
	uint32_t rx_len;
	uint32_t rx_err;
	struct e1000_tx_desc *tx_curr_desc;
	struct e1000_rx_desc *rx_curr_desc;
	uint32_t i;

	DBGP ( "e1000_poll\n" );

	/* Acknowledge interrupts */
	icr = E1000_READ_REG ( hw, ICR );
	if ( ! icr )
		return;
		
        DBG ( "e1000_poll: intr_status = %#08x\n", icr );

	/* Check status of transmitted packets
	 */
	while ( ( i = adapter->tx_head ) != adapter->tx_tail ) {
			
		tx_curr_desc = ( void * )  ( adapter->tx_base ) + 
					   ( i * sizeof ( *adapter->tx_base ) ); 
					    		
		tx_status = tx_curr_desc->upper.data;

		/* if the packet at tx_head is not owned by hardware it is for us */
		if ( ! ( tx_status & E1000_TXD_STAT_DD ) )
			break;
		
		DBG ( "Sent packet. tx_head: %d tx_tail: %d tx_status: %#08x\n",
	    	      adapter->tx_head, adapter->tx_tail, tx_status );

		if ( tx_status & ( E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | 
				   E1000_TXD_STAT_TU ) ) {
			netdev_tx_complete_err ( netdev, adapter->tx_iobuf[i], -EINVAL );
			DBG ( "Error transmitting packet, tx_status: %#08x\n",
			      tx_status );
		} else {
			netdev_tx_complete ( netdev, adapter->tx_iobuf[i] );
			DBG ( "Success transmitting packet, tx_status: %#08x\n",
			      tx_status );
		}

		/* Decrement count of used descriptors, clear this descriptor 
		 */
		adapter->tx_fill_ctr--;
		memset ( tx_curr_desc, 0, sizeof ( *tx_curr_desc ) );
		
		adapter->tx_head = ( adapter->tx_head + 1 ) % NUM_TX_DESC;		
	}
	
	/* Process received packets 
	 */
	while ( 1 ) {
	
		i = adapter->rx_curr;
		
		rx_curr_desc = ( void * )  ( adapter->rx_base ) + 
			          ( i * sizeof ( *adapter->rx_base ) ); 
		rx_status = rx_curr_desc->status;
		
		DBG2 ( "Before DD Check RX_status: %#08x\n", rx_status );
	
		if ( ! ( rx_status & E1000_RXD_STAT_DD ) )
			break;

		if ( adapter->rx_iobuf[i] == NULL )
			break;

		DBG ( "RCTL = %#08x\n", E1000_READ_REG ( &adapter->hw, RCTL ) );
	
		rx_len = rx_curr_desc->length;

                DBG ( "Received packet, rx_curr: %d  rx_status: %#08x  rx_len: %d\n",
                      i, rx_status, rx_len );

                rx_err = rx_curr_desc->errors;

		iob_put ( adapter->rx_iobuf[i], rx_len );

		if ( rx_err & E1000_RXD_ERR_FRAME_ERR_MASK ) {
		
			netdev_rx_err ( netdev, adapter->rx_iobuf[i], -EINVAL );
			DBG ( "e1000_poll: Corrupted packet received!"
			      " rx_err: %#08x\n", rx_err );
		} else 	{
			/* Add this packet to the receive queue. */
			netdev_rx ( netdev, adapter->rx_iobuf[i] );
		}
		adapter->rx_iobuf[i] = NULL;

		memset ( rx_curr_desc, 0, sizeof ( *rx_curr_desc ) );

		adapter->rx_curr = ( adapter->rx_curr + 1 ) % NUM_RX_DESC;
	}
	e1000_refill_rx_ring(adapter);
}