Ejemplo n.º 1
0
/**
 * Complete interrupt transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void acm_intr_complete ( struct usb_endpoint *ep,
				struct io_buffer *iobuf, int rc ) {
	struct acm_device *acm = container_of ( ep, struct acm_device,
						usbnet.intr );
	struct rndis_device *rndis = acm->rndis;
	struct usb_setup_packet *message;

	/* Profile completions */
	profile_start ( &acm_intr_profiler );

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open )
		goto ignore;

	/* Drop packets with errors */
	if ( rc != 0 ) {
		DBGC ( acm, "ACM %p interrupt failed: %s\n",
		       acm, strerror ( rc ) );
		DBGC_HDA ( acm, 0, iobuf->data, iob_len ( iobuf ) );
		goto error;
	}

	/* Extract message header */
	if ( iob_len ( iobuf ) < sizeof ( *message ) ) {
		DBGC ( acm, "ACM %p underlength interrupt:\n", acm );
		DBGC_HDA ( acm, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EINVAL;
		goto error;
	}
	message = iobuf->data;

	/* Parse message header */
	switch ( message->request ) {

	case cpu_to_le16 ( CDC_RESPONSE_AVAILABLE ) :
	case cpu_to_le16 ( 0x0001 ) : /* qemu seems to use this value */
		acm->responded = 1;
		break;

	default:
		DBGC ( acm, "ACM %p unrecognised interrupt:\n", acm );
		DBGC_HDA ( acm, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -ENOTSUP;
		goto error;
	}

	/* Free I/O buffer */
	free_iob ( iobuf );
	profile_stop ( &acm_intr_profiler );

	return;

 error:
	rndis_rx_err ( rndis, iob_disown ( iobuf ), rc );
 ignore:
	free_iob ( iobuf );
	return;
}
Ejemplo n.º 2
0
Archivo: iobuf.c Proyecto: 42wim/ipxe
/**
 * Concatenate I/O buffers into a single buffer
 *
 * @v list	List of I/O buffers
 * @ret iobuf	Concatenated I/O buffer, or NULL on allocation failure
 *
 * After a successful concatenation, the list will be empty.
 */
struct io_buffer * iob_concatenate ( struct list_head *list ) {
	struct io_buffer *iobuf;
	struct io_buffer *tmp;
	struct io_buffer *concatenated;
	size_t len = 0;

	/* If the list contains only a single entry, avoid an
	 * unnecessary additional allocation.
	 */
	if ( list_is_singular ( list ) ) {
		iobuf = list_first_entry ( list, struct io_buffer, list );
		INIT_LIST_HEAD ( list );
		return iobuf;
	}

	/* Calculate total length */
	list_for_each_entry ( iobuf, list, list )
		len += iob_len ( iobuf );

	/* Allocate new I/O buffer */
	concatenated = alloc_iob_raw ( len, __alignof__ ( *iobuf ), 0 );
	if ( ! concatenated )
		return NULL;

	/* Move data to new I/O buffer */
	list_for_each_entry_safe ( iobuf, tmp, list, list ) {
		list_del ( &iobuf->list );
		memcpy ( iob_put ( concatenated, iob_len ( iobuf ) ),
			 iobuf->data, iob_len ( iobuf ) );
		free_iob ( iobuf );
	}
Ejemplo n.º 3
0
/**
 * Handle SRP login rejection
 *
 * @v srp		SRP device
 * @v iobuf		I/O buffer
 * @ret rc		Return status code
 */
static int srp_login_rej ( struct srp_device *srp, struct io_buffer *iobuf ) {
	struct srp_login_rej *login_rej = iobuf->data;
	int rc;

	DBGC2 ( srp, "SRP %p RX login rejection tag %08x%08x\n",
		srp, ntohl ( login_rej->tag.dwords[0] ),
		ntohl ( login_rej->tag.dwords[1] ) );

	/* Sanity check */
	if ( iob_len ( iobuf ) < sizeof ( *login_rej ) ) {
		DBGC ( srp, "SRP %p RX login rejection too short (%zd "
		       "bytes)\n", srp, iob_len ( iobuf ) );
		rc = -EINVAL;
		goto out;
	}

	/* Login rejection always indicates an error */
	DBGC ( srp, "SRP %p login rejected (reason %08x)\n",
	       srp, ntohl ( login_rej->reason ) );
	rc = -EPERM;

 out:
	free_iob ( iobuf );
	return rc;
}
Ejemplo n.º 4
0
/**
 * Handle received data
 *
 * @v downloader	Downloader
 * @v iobuf		Datagram I/O buffer
 * @v meta		Data transfer metadata
 * @ret rc		Return status code
 */
static int downloader_xfer_deliver ( struct downloader *downloader,
				     struct io_buffer *iobuf,
				     struct xfer_metadata *meta ) {
	size_t len;
	size_t max;
	int rc;

	/* Calculate new buffer position */
	if ( meta->flags & XFER_FL_ABS_OFFSET )
		downloader->pos = 0;
	downloader->pos += meta->offset;

	/* Ensure that we have enough buffer space for this data */
	len = iob_len ( iobuf );
	max = ( downloader->pos + len );
	if ( ( rc = downloader_ensure_size ( downloader, max ) ) != 0 )
		goto done;

	/* Copy data to buffer */
	copy_to_user ( downloader->image->data, downloader->pos,
		       iobuf->data, len );

	/* Update current buffer position */
	downloader->pos += len;

 done:
	free_iob ( iobuf );
	if ( rc != 0 )
		downloader_finished ( downloader, rc );
	return rc;
}
Ejemplo n.º 5
0
Archivo: xfer.c Proyecto: baloo/ipxe
/**
 * Deliver datagram
 *
 * @v intf		Data transfer interface
 * @v iobuf		Datagram I/O buffer
 * @v meta		Data transfer metadata
 * @ret rc		Return status code
 */
int xfer_deliver ( struct interface *intf,
		   struct io_buffer *iobuf,
		   struct xfer_metadata *meta ) {
	struct interface *dest;
	xfer_deliver_TYPE ( void * ) *op =
		intf_get_dest_op ( intf, xfer_deliver, &dest );
	void *object = intf_object ( dest );
	int rc;

	DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT " deliver %zd\n",
	       INTF_INTF_DBG ( intf, dest ), iob_len ( iobuf ) );

	if ( op ) {
		rc = op ( object, iobuf, meta );
	} else {
		/* Default is to discard the I/O buffer */
		free_iob ( iobuf );
		rc = -EPIPE;
	}

	if ( rc != 0 ) {
		DBGC ( INTF_COL ( intf ), "INTF " INTF_INTF_FMT
		       " deliver failed: %s\n",
		       INTF_INTF_DBG ( intf, dest ), strerror ( rc ) );
	}

	intf_put ( dest );
	return rc;
}
Ejemplo n.º 6
0
/**
 * Handle SRP login response
 *
 * @v srp		SRP device
 * @v iobuf		I/O buffer
 * @ret rc		Return status code
 */
static int srp_login_rsp ( struct srp_device *srp, struct io_buffer *iobuf ) {
	struct srp_login_rsp *login_rsp = iobuf->data;
	int rc;

	DBGC2 ( srp, "SRP %p RX login response tag %08x%08x\n",
		srp, ntohl ( login_rsp->tag.dwords[0] ),
		ntohl ( login_rsp->tag.dwords[1] ) );

	/* Sanity check */
	if ( iob_len ( iobuf ) < sizeof ( *login_rsp ) ) {
		DBGC ( srp, "SRP %p RX login response too short (%zd bytes)\n",
		       srp, iob_len ( iobuf ) );
		rc = -EINVAL;
		goto out;
	}

	DBGC ( srp, "SRP %p logged in\n", srp );

	/* Mark as logged in */
	srp->state |= SRP_STATE_LOGGED_IN;

	/* Reset error counter */
	srp->retry_count = 0;

	/* Issue pending command */
	srp_cmd ( srp );

	rc = 0;
 out:
	free_iob ( iobuf );
	return rc;
}
Ejemplo n.º 7
0
/**
 * Close network device
 *
 * @v netdev		Network device
 */
static void snpnet_close ( struct net_device *netdev ) {
    struct snp_nic *snp = netdev->priv;
    EFI_STATUS efirc;
    int rc;

    /* Shut down NIC */
    if ( ( efirc = snp->snp->Shutdown ( snp->snp ) ) != 0 ) {
        rc = -EEFI ( efirc );
        DBGC ( snp, "SNP %s could not shut down: %s\n",
               netdev->name, strerror ( rc ) );
        /* Nothing we can do about this */
    }

    /* Discard transmit buffer, if applicable */
    if ( snp->txbuf ) {
        netdev_tx_complete_err ( netdev, snp->txbuf, -ECANCELED );
        snp->txbuf = NULL;
    }

    /* Discard receive buffer, if applicable */
    if ( snp->rxbuf ) {
        free_iob ( snp->rxbuf );
        snp->rxbuf = NULL;
    }
}
Ejemplo n.º 8
0
/**
 * Add received data to data transfer buffer
 *
 * @v xferbuf		Data transfer buffer
 * @v iobuf		I/O buffer
 * @v meta		Data transfer metadata
 * @ret rc		Return status code
 */
int xferbuf_deliver ( struct xfer_buffer *xferbuf, struct io_buffer *iobuf,
		      struct xfer_metadata *meta ) {
	size_t len = iob_len ( iobuf );
	size_t pos;
	int rc;

	/* Start profiling */
	profile_start ( &xferbuf_deliver_profiler );

	/* Calculate new buffer position */
	pos = xferbuf->pos;
	if ( meta->flags & XFER_FL_ABS_OFFSET )
		pos = 0;
	pos += meta->offset;

	/* Write data to buffer */
	if ( ( rc = xferbuf_write ( xferbuf, pos, iobuf->data, len ) ) != 0 )
		goto done;

	/* Update current buffer position */
	xferbuf->pos = ( pos + len );

 done:
	free_iob ( iobuf );
	profile_stop ( &xferbuf_deliver_profiler );
	return rc;
}
Ejemplo n.º 9
0
/**
 * Process received data
 *
 * @v file		Data transfer file
 * @v iobuf		I/O buffer
 * @v meta		Data transfer metadata
 * @ret rc		Return status code
 */
static int efi_download_deliver_iob ( struct efi_download_file *file,
				      struct io_buffer *iobuf,
				      struct xfer_metadata *meta ) {
	EFI_STATUS efirc;
	size_t len = iob_len ( iobuf );
	int rc;

	/* Calculate new buffer position */
	if ( meta->flags & XFER_FL_ABS_OFFSET )
		file->pos = 0;
	file->pos += meta->offset;

	/* Call out to the data handler */
	if ( ( efirc = file->data_callback ( file->context, iobuf->data,
					     len, file->pos ) ) != 0 ) {
		rc = -EEFI ( efirc );
		goto err_callback;
	}

	/* Update current buffer position */
	file->pos += len;

	/* Success */
	rc = 0;

 err_callback:
	free_iob ( iobuf );
	return rc;
}
Ejemplo n.º 10
0
/**
 * Complete bulk IN transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void acm_in_complete ( struct usb_endpoint *ep, struct io_buffer *iobuf,
			      int rc ) {
	struct acm_device *acm = container_of ( ep, struct acm_device,
						usbnet.in );
	struct rndis_device *rndis = acm->rndis;

	/* Profile receive completions */
	profile_start ( &acm_in_profiler );

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open )
		goto ignore;

	/* Record USB errors against the RNDIS device */
	if ( rc != 0 ) {
		DBGC ( acm, "ACM %p bulk IN failed: %s\n",
		       acm, strerror ( rc ) );
		goto error;
	}

	/* Hand off to RNDIS */
	rndis_rx ( rndis, iob_disown ( iobuf ) );

	profile_stop ( &acm_in_profiler );
	return;

 error:
	rndis_rx_err ( rndis, iob_disown ( iobuf ), rc );
 ignore:
	free_iob ( iobuf );
}
Ejemplo n.º 11
0
/**
 * Complete bulk IN transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void smsc95xx_in_complete ( struct usb_endpoint *ep,
				   struct io_buffer *iobuf, int rc ) {
	struct smsc95xx_device *smsc95xx =
		container_of ( ep, struct smsc95xx_device, usbnet.in );
	struct net_device *netdev = smsc95xx->netdev;
	struct smsc95xx_rx_header *header;

	/* Profile completions */
	profile_start ( &smsc95xx_in_profiler );

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open ) {
		free_iob ( iobuf );
		return;
	}

	/* Record USB errors against the network device */
	if ( rc != 0 ) {
		DBGC ( smsc95xx, "SMSC95XX %p bulk IN failed: %s\n",
		       smsc95xx, strerror ( rc ) );
		goto err;
	}

	/* Sanity check */
	if ( iob_len ( iobuf ) < ( sizeof ( *header ) + 4 /* CRC */ ) ) {
		DBGC ( smsc95xx, "SMSC95XX %p underlength bulk IN\n",
		       smsc95xx );
		DBGC_HDA ( smsc95xx, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EINVAL;
		goto err;
	}

	/* Strip header and CRC */
	header = iobuf->data;
	iob_pull ( iobuf, sizeof ( *header ) );
	iob_unput ( iobuf, 4 /* CRC */ );

	/* Check for errors */
	if ( header->command & cpu_to_le32 ( SMSC95XX_RX_RUNT |
					     SMSC95XX_RX_LATE |
					     SMSC95XX_RX_CRC ) ) {
		DBGC ( smsc95xx, "SMSC95XX %p receive error (%08x):\n",
		       smsc95xx, le32_to_cpu ( header->command ) );
		DBGC_HDA ( smsc95xx, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EIO;
		goto err;
	}

	/* Hand off to network stack */
	netdev_rx ( netdev, iob_disown ( iobuf ) );

	profile_stop ( &smsc95xx_in_profiler );
	return;

 err:
	/* Hand off to network stack */
	netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
}
Ejemplo n.º 12
0
/**
 * Handle SRP unrecognised response
 *
 * @v srp		SRP device
 * @v iobuf		I/O buffer
 * @ret rc		Returns status code
 */
static int srp_unrecognised ( struct srp_device *srp,
			      struct io_buffer *iobuf ) {
	struct srp_common *common = iobuf->data;

	DBGC ( srp, "SRP %p RX unrecognised IU tag %08x%08x type %02x\n",
	       srp, ntohl ( common->tag.dwords[0] ),
	       ntohl ( common->tag.dwords[1] ), common->type );

	free_iob ( iobuf );
	return -ENOTSUP;
}
Ejemplo n.º 13
0
static void e1000e_free_rx_resources ( struct e1000_adapter *adapter )
{
	int i;

	DBGP ( "e1000_free_rx_resources\n" );

	free_dma ( adapter->rx_base, adapter->rx_ring_size );

	for ( i = 0; i < NUM_RX_DESC; i++ ) {
		free_iob ( adapter->rx_iobuf[i] );
	}
}
Ejemplo n.º 14
0
static void b44_free_rx_ring(struct b44_private *bp)
{
	u32 i;

	if (bp->rx) {
		for (i = 0; i < B44_RING_SIZE; i++) {
			free_iob(bp->rx_iobuf[i]);
			bp->rx_iobuf[i] = NULL;
		}
		free_dma(bp->rx, B44_RX_RING_LEN_BYTES);
		bp->rx = NULL;
	}
}
Ejemplo n.º 15
0
static void rtl818x_free_rx_ring(struct net80211_device *dev)
{
	struct rtl818x_priv *priv = dev->priv;
	int i;

	for (i = 0; i < RTL818X_RX_RING_SIZE; i++) {
		free_iob(priv->rx_buf[i]);
		priv->rx_buf[i] = NULL;
	}

	free_dma(priv->rx_ring, sizeof(*priv->rx_ring) * RTL818X_RX_RING_SIZE);
	priv->rx_ring = NULL;
}
Ejemplo n.º 16
0
/**
 * Complete bulk IN transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void dm96xx_in_complete ( struct usb_endpoint *ep,
				 struct io_buffer *iobuf, int rc ) {
	struct dm96xx_device *dm96xx = container_of ( ep, struct dm96xx_device,
						      usbnet.in );
	struct net_device *netdev = dm96xx->netdev;
	struct dm96xx_rx_header *header;

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open ) {
		free_iob ( iobuf );
		return;
	}

	/* Record USB errors against the network device */
	if ( rc != 0 ) {
		DBGC ( dm96xx, "DM96XX %p bulk IN failed: %s\n",
		       dm96xx, strerror ( rc ) );
		goto err;
	}

	/* Sanity check */
	if ( iob_len ( iobuf ) < ( sizeof ( *header ) + 4 /* CRC */ ) ) {
		DBGC ( dm96xx, "DM96XX %p underlength bulk IN\n", dm96xx );
		DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EINVAL;
		goto err;
	}

	/* Strip header and CRC */
	header = iobuf->data;
	iob_pull ( iobuf, sizeof ( *header ) );
	iob_unput ( iobuf, 4 /* CRC */ );

	/* Check status */
	if ( header->rsr & ~DM96XX_RSR_MF ) {
		DBGC ( dm96xx, "DM96XX %p receive error %02x:\n",
		       dm96xx, header->rsr );
		DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
		rc = -EIO;
		goto err;
	}

	/* Hand off to network stack */
	netdev_rx ( netdev, iob_disown ( iobuf ) );
	return;

 err:
	/* Hand off to network stack */
	netdev_rx_err ( netdev, iob_disown ( iobuf ), rc );
}
Ejemplo n.º 17
0
/**
 * Transmit a TCP/IP packet
 *
 * @v iobuf		I/O buffer
 * @v tcpip_protocol	Transport-layer protocol
 * @v st_src		Source address, or NULL to use route default
 * @v st_dest		Destination address
 * @v netdev		Network device to use if no route found, or NULL
 * @v trans_csum	Transport-layer checksum to complete, or NULL
 * @ret rc		Return status code
 */
int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol,
	       struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest,
	       struct net_device *netdev, uint16_t *trans_csum ) {
	struct tcpip_net_protocol *tcpip_net;

	/* Hand off packet to the appropriate network-layer protocol */
	tcpip_net = tcpip_net_protocol ( st_dest->st_family );
	if ( tcpip_net ) {
		DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
		return tcpip_net->tx ( iobuf, tcpip_protocol, st_src, st_dest,
				       netdev, trans_csum );
	}

	free_iob ( iobuf );
	return -EAFNOSUPPORT;
}
Ejemplo n.º 18
0
/**
 * Handle SRP SCSI response
 *
 * @v srp		SRP device
 * @v iobuf		I/O buffer
 * @ret rc		Returns status code
 */
static int srp_rsp ( struct srp_device *srp, struct io_buffer *iobuf ) {
	struct srp_rsp *rsp = iobuf->data;
	int rc;

	DBGC2 ( srp, "SRP %p RX SCSI response tag %08x%08x\n", srp,
		ntohl ( rsp->tag.dwords[0] ), ntohl ( rsp->tag.dwords[1] ) );

	/* Sanity check */
	if ( iob_len ( iobuf ) < sizeof ( *rsp ) ) {
		DBGC ( srp, "SRP %p RX SCSI response too short (%zd bytes)\n",
		       srp, iob_len ( iobuf ) );
		rc = -EINVAL;
		goto out;
	}

	/* Report SCSI errors */
	if ( rsp->status != 0 ) {
		DBGC ( srp, "SRP %p response status %02x\n",
		       srp, rsp->status );
		if ( srp_rsp_sense_data ( rsp ) ) {
			DBGC ( srp, "SRP %p sense data:\n", srp );
			DBGC_HDA ( srp, 0, srp_rsp_sense_data ( rsp ),
				   srp_rsp_sense_data_len ( rsp ) );
		}
	}
	if ( rsp->valid & ( SRP_RSP_VALID_DOUNDER | SRP_RSP_VALID_DOOVER ) ) {
		DBGC ( srp, "SRP %p response data-out %srun by %#x bytes\n",
		       srp, ( ( rsp->valid & SRP_RSP_VALID_DOUNDER )
			      ? "under" : "over" ),
		       ntohl ( rsp->data_out_residual_count ) );
	}
	if ( rsp->valid & ( SRP_RSP_VALID_DIUNDER | SRP_RSP_VALID_DIOVER ) ) {
		DBGC ( srp, "SRP %p response data-in %srun by %#x bytes\n",
		       srp, ( ( rsp->valid & SRP_RSP_VALID_DIUNDER )
			      ? "under" : "over" ),
		       ntohl ( rsp->data_in_residual_count ) );
	}
	srp->command->status = rsp->status;

	/* Mark SCSI command as complete */
	srp_scsi_done ( srp, 0 );

	rc = 0;
 out:
	free_iob ( iobuf );
	return rc;
}
Ejemplo n.º 19
0
/**
 * Receive control packet
 *
 * @v acm		USB RNDIS device
 * @ret rc		Return status code
 */
static int acm_control_receive ( struct acm_device *acm ) {
	struct rndis_device *rndis = acm->rndis;
	struct usb_device *usb = acm->usb;
	struct io_buffer *iobuf;
	struct rndis_header *header;
	size_t mtu = ACM_RESPONSE_MTU;
	size_t len;
	int rc;

	/* Allocate I/O buffer */
	iobuf = alloc_iob ( mtu );
	if ( ! iobuf ) {
		rc = -ENOMEM;
		goto err_alloc;
	}

	/* Get encapsulated response */
	if ( ( rc = cdc_get_encapsulated_response ( usb, acm->usbnet.comms,
						    iobuf->data, mtu ) ) != 0 ){
		DBGC ( acm, "ACM %p could not get encapsulated response: %s\n",
		       acm, strerror ( rc ) );
		goto err_get_response;
	}

	/* Fix up buffer length */
	header = iobuf->data;
	len = le32_to_cpu ( header->len );
	if ( len > mtu ) {
		DBGC ( acm, "ACM %p overlength encapsulated response\n", acm );
		DBGC_HDA ( acm, 0, iobuf->data, mtu );
		rc = -EPROTO;
		goto err_len;
	}
	iob_put ( iobuf, len );

	/* Hand off to RNDIS */
	rndis_rx ( rndis, iob_disown ( iobuf ) );

	return 0;

 err_len:
 err_get_response:
	free_iob ( iobuf );
 err_alloc:
	return rc;
}
Ejemplo n.º 20
0
static void legacy_poll ( struct net_device *netdev ) {
    struct nic *nic = netdev->priv;
    struct io_buffer *iobuf;

    iobuf = alloc_iob ( ETH_FRAME_LEN );
    if ( ! iobuf )
        return;

    nic->packet = iobuf->data;
    if ( nic->nic_op->poll ( nic, 1 ) ) {
        DBG ( "Received %d bytes\n", nic->packetlen );
        iob_put ( iobuf, nic->packetlen );
        netdev_rx ( netdev, iobuf );
    } else {
        free_iob ( iobuf );
    }
}
Ejemplo n.º 21
0
/**
 * Receive PXE UDP data
 *
 * @v pxe_udp			PXE UDP connection
 * @v iobuf			I/O buffer
 * @v meta			Data transfer metadata
 * @ret rc			Return status code
 *
 * Receives a packet as part of the current pxenv_udp_read()
 * operation.
 */
static int pxe_udp_deliver ( struct pxe_udp_connection *pxe_udp,
			     struct io_buffer *iobuf,
			     struct xfer_metadata *meta ) {
	struct s_PXENV_UDP_READ *pxenv_udp_read = pxe_udp->pxenv_udp_read;
	struct sockaddr_in *sin_src;
	struct sockaddr_in *sin_dest;
	userptr_t buffer;
	size_t len;
	int rc = 0;

	if ( ! pxenv_udp_read ) {
		DBG ( "PXE discarded UDP packet\n" );
		rc = -ENOBUFS;
		goto done;
	}

	/* Copy packet to buffer and record length */
	buffer = real_to_user ( pxenv_udp_read->buffer.segment,
				pxenv_udp_read->buffer.offset );
	len = iob_len ( iobuf );
	if ( len > pxenv_udp_read->buffer_size )
		len = pxenv_udp_read->buffer_size;
	copy_to_user ( buffer, 0, iobuf->data, len );
	pxenv_udp_read->buffer_size = len;

	/* Fill in source/dest information */
	assert ( meta );
	sin_src = ( struct sockaddr_in * ) meta->src;
	assert ( sin_src );
	assert ( sin_src->sin_family == AF_INET );
	pxenv_udp_read->src_ip = sin_src->sin_addr.s_addr;
	pxenv_udp_read->s_port = sin_src->sin_port;
	sin_dest = ( struct sockaddr_in * ) meta->dest;
	assert ( sin_dest );
	assert ( sin_dest->sin_family == AF_INET );
	pxenv_udp_read->dest_ip = sin_dest->sin_addr.s_addr;
	pxenv_udp_read->d_port = sin_dest->sin_port;

	/* Mark as received */
	pxe_udp->pxenv_udp_read = NULL;

 done:
	free_iob ( iobuf );
	return rc;
}
Ejemplo n.º 22
0
/**
 * e1000_setup_rx_resources - allocate Rx resources (Descriptors)
 *
 * @v adapter	e1000 private structure
 *
 * @ret rc       Returns 0 on success, negative on failure
 **/
static int
e1000_setup_rx_resources ( struct e1000_adapter *adapter )
{
	int i, j;
	struct e1000_rx_desc *rx_curr_desc;
	
	DBG ( "e1000_setup_rx_resources\n" );
	
	/* Allocate receive descriptor ring memory.
	   It must not cross a 64K boundary because of hardware errata
	 */

        adapter->rx_base = 
        	malloc_dma ( adapter->rx_ring_size, adapter->rx_ring_size );
        		     
       	if ( ! adapter->rx_base ) {
       		return -ENOMEM;
	}
	memset ( adapter->rx_base, 0, adapter->rx_ring_size );

	for ( i = 0; i < NUM_RX_DESC; i++ ) {
	
		adapter->rx_iobuf[i] = alloc_iob ( MAXIMUM_ETHERNET_VLAN_SIZE );
		
		/* If unable to allocate all iobufs, free any that
		 * were successfully allocated, and return an error 
		 */
		if ( ! adapter->rx_iobuf[i] ) {
			for ( j = 0; j < i; j++ ) {
				free_iob ( adapter->rx_iobuf[j] );
			}
			return -ENOMEM;
		}

		rx_curr_desc = ( void * ) ( adapter->rx_base ) + 
					  ( i * sizeof ( *adapter->rx_base ) ); 
			
		rx_curr_desc->buffer_addr = virt_to_bus ( adapter->rx_iobuf[i]->data );	

		DBG ( "i = %d  rx_curr_desc->buffer_addr = %#16llx\n", 
		      i, rx_curr_desc->buffer_addr );
		
	}	
	return 0;
}
Ejemplo n.º 23
0
Archivo: nii.c Proyecto: baloo/ipxe
/**
 * Close network device
 *
 * @v netdev		Network device
 */
static void nii_close ( struct net_device *netdev ) {
	struct nii_nic *nii = netdev->priv;

	/* Shut down NIC */
	nii_shutdown ( nii );

	/* Discard transmit buffer, if applicable */
	if ( nii->txbuf ) {
		netdev_tx_complete_err ( netdev, nii->txbuf, -ECANCELED );
		nii->txbuf = NULL;
	}

	/* Discard receive buffer, if applicable */
	if ( nii->rxbuf ) {
		free_iob ( nii->rxbuf );
		nii->rxbuf = NULL;
	}
}
Ejemplo n.º 24
0
/** Transmit a TCP/IP packet
 *
 * @v iobuf		I/O buffer
 * @v tcpip_protocol	Transport-layer protocol
 * @v st_src		Source address, or NULL to use route default
 * @v st_dest		Destination address
 * @v netdev		Network device to use if no route found, or NULL
 * @v trans_csum	Transport-layer checksum to complete, or NULL
 * @ret rc		Return status code
 */
int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol,
	       struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest,
	       struct net_device *netdev, uint16_t *trans_csum ) {
	struct tcpip_net_protocol *tcpip_net;

	/* Hand off packet to the appropriate network-layer protocol */
	for_each_table_entry ( tcpip_net, TCPIP_NET_PROTOCOLS ) {
		if ( tcpip_net->sa_family == st_dest->st_family ) {
			DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
			return tcpip_net->tx ( iobuf, tcpip_protocol, st_src,
					       st_dest, netdev, trans_csum );
		}
	}
	
	DBG ( "Unrecognised TCP/IP address family %d\n", st_dest->st_family );
	free_iob ( iobuf );
	return -EAFNOSUPPORT;
}
Ejemplo n.º 25
0
/** Process a received TCP/IP packet
 *
 * @v iobuf		I/O buffer
 * @v tcpip_proto	Transport-layer protocol number
 * @v st_src		Partially-filled source address
 * @v st_dest		Partially-filled destination address
 * @v pshdr_csum	Pseudo-header checksum
 * @ret rc		Return status code
 *
 * This function expects a transport-layer segment from the network
 * layer.  The network layer should fill in as much as it can of the
 * source and destination addresses (i.e. it should fill in the
 * address family and the network-layer addresses, but leave the ports
 * and the rest of the structures as zero).
 */
int tcpip_rx ( struct io_buffer *iobuf, uint8_t tcpip_proto, 
	       struct sockaddr_tcpip *st_src,
	       struct sockaddr_tcpip *st_dest,
	       uint16_t pshdr_csum ) {
	struct tcpip_protocol *tcpip;

	/* Hand off packet to the appropriate transport-layer protocol */
	for_each_table_entry ( tcpip, TCPIP_PROTOCOLS ) {
		if ( tcpip->tcpip_proto == tcpip_proto ) {
			DBG ( "TCP/IP received %s packet\n", tcpip->name );
			return tcpip->rx ( iobuf, st_src, st_dest, pshdr_csum );
		}
	}

	DBG ( "Unrecognised TCP/IP protocol %d\n", tcpip_proto );
	free_iob ( iobuf );
	return -EPROTONOSUPPORT;
}
Ejemplo n.º 26
0
/**
 * Process incoming marker packet
 *
 * @v iobuf		I/O buffer
 * @v netdev		Network device
 * @ret rc		Return status code
 */
static int eth_slow_marker_rx ( struct io_buffer *iobuf,
				struct net_device *netdev ) {
	union eth_slow_packet *eth_slow = iobuf->data;
	struct eth_slow_marker *marker = &eth_slow->marker;

	eth_slow_marker_dump ( iobuf, netdev, "RX" );

	if ( marker->marker.tlv.type == ETH_SLOW_TLV_MARKER_REQUEST ) {
		/* Send marker response */
		marker->marker.tlv.type = ETH_SLOW_TLV_MARKER_RESPONSE;
		eth_slow_marker_dump ( iobuf, netdev, "TX" );
		return net_tx ( iobuf, netdev, &eth_slow_protocol,
				eth_slow_address, netdev->ll_addr );
	} else {
		/* Discard all other marker packets */
		free_iob ( iobuf );
		return -EINVAL;
	}
}
Ejemplo n.º 27
0
/**
 * Complete interrupt transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void smsc95xx_intr_complete ( struct usb_endpoint *ep,
				     struct io_buffer *iobuf, int rc ) {
	struct smsc95xx_device *smsc95xx =
		container_of ( ep, struct smsc95xx_device, usbnet.intr );
	struct net_device *netdev = smsc95xx->netdev;
	struct smsc95xx_interrupt *intr;

	/* Profile completions */
	profile_start ( &smsc95xx_intr_profiler );

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open )
		goto done;

	/* Record USB errors against the network device */
	if ( rc != 0 ) {
		DBGC ( smsc95xx, "SMSC95XX %p interrupt failed: %s\n",
		       smsc95xx, strerror ( rc ) );
		DBGC_HDA ( smsc95xx, 0, iobuf->data, iob_len ( iobuf ) );
		netdev_rx_err ( netdev, NULL, rc );
		goto done;
	}

	/* Extract interrupt data */
	if ( iob_len ( iobuf ) != sizeof ( *intr ) ) {
		DBGC ( smsc95xx, "SMSC95XX %p malformed interrupt\n",
		       smsc95xx );
		DBGC_HDA ( smsc95xx, 0, iobuf->data, iob_len ( iobuf ) );
		netdev_rx_err ( netdev, NULL, rc );
		goto done;
	}
	intr = iobuf->data;

	/* Record interrupt status */
	smsc95xx->int_sts = le32_to_cpu ( intr->int_sts );
	profile_stop ( &smsc95xx_intr_profiler );

 done:
	/* Free I/O buffer */
	free_iob ( iobuf );
}
Ejemplo n.º 28
0
/** Poll for new packets */
static void af_packet_nic_poll ( struct net_device *netdev )
{
	struct af_packet_nic * nic = netdev->priv;
	struct pollfd pfd;
	struct io_buffer * iobuf;
	int r;

	pfd.fd = nic->fd;
	pfd.events = POLLIN;
	if (linux_poll(&pfd, 1, 0) == -1) {
		DBGC(nic, "af_packet %p poll failed (%s)\n",
		     nic, linux_strerror(linux_errno));
		return;
	}
	if ((pfd.revents & POLLIN) == 0)
		return;

	/* At this point we know there is at least one new packet to be read */

	iobuf = alloc_iob(RX_BUF_SIZE);
	if (! iobuf)
		goto allocfail;

	while ((r = linux_read(nic->fd, iobuf->data, RX_BUF_SIZE)) > 0) {
		DBGC2(nic, "af_packet %p read %d bytes\n", nic, r);

		iob_put(iobuf, r);
		netdev_rx(netdev, iobuf);

		iobuf = alloc_iob(RX_BUF_SIZE);
		if (! iobuf)
			goto allocfail;
	}

	free_iob(iobuf);
	return;

allocfail:
	DBGC(nic, "af_packet %p alloc_iob failed\n", nic);
}
Ejemplo n.º 29
0
/**
 * Close network device
 *
 * @v netdev		Network device
 */
static void myson_close ( struct net_device *netdev ) {
	struct myson_nic *myson = netdev->priv;
	unsigned int i;

	/* Disable receiver and transmitter */
	writel ( 0, myson->regs + MYSON_TCR_RCR );

	/* Allow time for receiver and transmitter to become idle */
	myson_wait_idle ( myson );

	/* Destroy receive descriptor ring */
	myson_destroy_ring ( myson, &myson->rx );

	/* Discard any unused receive buffers */
	for ( i = 0 ; i < MYSON_NUM_RX_DESC ; i++ ) {
		if ( myson->rx_iobuf[i] )
			free_iob ( myson->rx_iobuf[i] );
		myson->rx_iobuf[i] = NULL;
	}

	/* Destroy transmit descriptor ring */
	myson_destroy_ring ( myson, &myson->tx );
}
Ejemplo n.º 30
0
/**
 * Complete interrupt transfer
 *
 * @v ep		USB endpoint
 * @v iobuf		I/O buffer
 * @v rc		Completion status code
 */
static void dm96xx_intr_complete ( struct usb_endpoint *ep,
				   struct io_buffer *iobuf, int rc ) {
	struct dm96xx_device *dm96xx = container_of ( ep, struct dm96xx_device,
						      usbnet.intr );
	struct net_device *netdev = dm96xx->netdev;
	struct dm96xx_interrupt *intr;
	size_t len = iob_len ( iobuf );

	/* Ignore packets cancelled when the endpoint closes */
	if ( ! ep->open )
		goto done;

	/* Record USB errors against the network device */
	if ( rc != 0 ) {
		DBGC ( dm96xx, "DM96XX %p interrupt failed: %s\n",
		       dm96xx, strerror ( rc ) );
		DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
		netdev_rx_err ( netdev, NULL, rc );
		goto done;
	}

	/* Extract message header */
	if ( len < sizeof ( *intr ) ) {
		DBGC ( dm96xx, "DM96XX %p underlength interrupt:\n", dm96xx );
		DBGC_HDA ( dm96xx, 0, iobuf->data, iob_len ( iobuf ) );
		netdev_rx_err ( netdev, NULL, -EINVAL );
		goto done;
	}
	intr = iobuf->data;

	/* Update link status */
	dm96xx_link_nsr ( dm96xx, intr->nsr );

 done:
	/* Free I/O buffer */
	free_iob ( iobuf );
}