[ipxe-devel] [RFC PATCH 5/8] vmbus: factor out API to be shared with UEFI driver

Roman Kagan rkagan at virtuozzo.com
Mon Jun 11 17:28:20 UTC 2018


In preparation for the upcoming UEFI driver for VMBus, factor out the
common API that can be used by both the iPXE native VMBus implementation
and the wrapper around the UEFI VMBus protocol.

Signed-off-by: Roman Kagan <rkagan at virtuozzo.com>
---
 src/include/ipxe/vmbus.h        | 212 +----------------------
 src/include/ipxe/vmbus_device.h | 291 ++++++++++++++++++++++++++++++++
 src/drivers/net/netvsc.c        |   2 +-
 src/interface/hyperv/vmbus.c    | 291 ++++++++++++++++++--------------
 4 files changed, 464 insertions(+), 332 deletions(-)
 create mode 100644 src/include/ipxe/vmbus_device.h

diff --git a/src/include/ipxe/vmbus.h b/src/include/ipxe/vmbus.h
index 69776616..06b70672 100644
--- a/src/include/ipxe/vmbus.h
+++ b/src/include/ipxe/vmbus.h
@@ -16,6 +16,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <ipxe/uaccess.h>
 #include <ipxe/iobuf.h>
 #include <ipxe/hyperv.h>
+#include <ipxe/vmbus_device.h>
 
 /** VMBus message connection ID */
 #define VMBUS_MESSAGE_ID 1
@@ -391,105 +392,20 @@ struct vmbus {
 	const union vmbus_message *message;
 };
 
-struct vmbus_device;
-
-/** VMBus channel operations */
-struct vmbus_channel_operations {
-	/**
-	 * Handle received control packet
-	 *
-	 * @v vmdev		VMBus device
-	 * @v xid		Transaction ID
-	 * @v data		Data
-	 * @v len		Length of data
-	 * @ret rc		Return status code
-	 */
-	int ( * recv_control ) ( struct vmbus_device *vmdev, uint64_t xid,
-				 const void *data, size_t len );
-	/**
-	 * Handle received data packet
-	 *
-	 * @v vmdev		VMBus device
-	 * @v xid		Transaction ID
-	 * @v data		Data
-	 * @v len		Length of data
-	 * @v list		List of I/O buffers
-	 * @ret rc		Return status code
-	 *
-	 * This function takes ownership of the I/O buffer.  It should
-	 * eventually call vmbus_send_completion() to indicate to the
-	 * host that the buffer can be reused.
-	 */
-	int ( * recv_data ) ( struct vmbus_device *vmdev, uint64_t xid,
-			      const void *data, size_t len,
-			      struct list_head *list );
-	/**
-	 * Handle received completion packet
-	 *
-	 * @v vmdev		VMBus device
-	 * @v xid		Transaction ID
-	 * @v data		Data
-	 * @v len		Length of data
-	 * @ret rc		Return status code
-	 */
-	int ( * recv_completion ) ( struct vmbus_device *vmdev, uint64_t xid,
-				    const void *data, size_t len );
-	/**
-	 * Handle received cancellation packet
-	 *
-	 * @v vmdev		VMBus device
-	 * @v xid		Transaction ID
-	 * @ret rc		Return status code
-	 */
-	int ( * recv_cancellation ) ( struct vmbus_device *vmdev,
-				      uint64_t xid );
-};
-
-struct vmbus_xfer_pages;
-
-/** VMBus transfer page set operations */
-struct vmbus_xfer_pages_operations {
-	/**
-	 * Copy data from transfer page
-	 *
-	 * @v pages		Transfer page set
-	 * @v data		Data buffer
-	 * @v offset		Offset within page set
-	 * @v len		Length within page set
-	 * @ret rc		Return status code
-	 */
-	int ( * copy ) ( struct vmbus_xfer_pages *pages, void *data,
-			 size_t offset, size_t len );
-};
-
-/** VMBus transfer page set */
-struct vmbus_xfer_pages {
-	/** List of all transfer page sets */
-	struct list_head list;
-	/** Page set ID (in protocol byte order) */
-	uint16_t pageset;
-	/** Page set operations */
-	struct vmbus_xfer_pages_operations *op;
-};
-
-/** A VMBus device */
-struct vmbus_device {
-	/** Generic iPXE device */
-	struct device dev;
+/** A iPXE VMBus device */
+struct vmbus_ipxe_device {
+	/** Abstract VMBus device */
+	struct vmbus_device vmdev;
 	/** Hyper-V hypervisor */
 	struct hv_hypervisor *hv;
 
-	/** Channel instance */
-	union uuid instance;
-	/** Channel ID */
-	unsigned int channel;
 	/** Monitor ID */
 	unsigned int monitor;
 	/** Signal channel
 	 *
 	 * @v vmdev		VMBus device
 	 */
-	void ( * signal ) ( struct vmbus_device *vmdev );
+	void ( * signal ) ( struct vmbus_ipxe_device *vmdev );
 
 	/** Outbound ring buffer length */
 	uint32_t out_len;
@@ -502,128 +418,12 @@ struct vmbus_device {
 	/** Ring buffer GPADL ID */
 	unsigned int gpadl;
 
-	/** Channel operations */
-	struct vmbus_channel_operations *op;
 	/** Maximum expected data packet length */
 	size_t mtu;
 	/** Packet buffer */
 	void *packet;
-	/** List of transfer page sets */
-	struct list_head pages;
-
-	/** Driver */
-	struct vmbus_driver *driver;
-	/** Driver-private data */
-	void *priv;
-};
-
-/** A VMBus device driver */
-struct vmbus_driver {
-	/** Name */
-	const char *name;
-	/** Device type */
-	union uuid type;
-	/** Probe device
-	 *
-	 * @v vmdev		VMBus device
-	 * @ret rc		Return status code
-	 */
-	int ( * probe ) ( struct vmbus_device *vmdev );
-	/** Reset device
-	 *
-	 * @v vmdev		VMBus device
-	 * @ret rc		Return status code
-	 */
-	int ( * reset ) ( struct vmbus_device *vmdev );
-	/** Remove device
-	 *
-	 * @v vmdev		VMBus device
-	 */
-	void ( * remove ) ( struct vmbus_device *vmdev );
 };
 
-/** VMBus device driver table */
-#define VMBUS_DRIVERS __table ( struct vmbus_driver, "vmbus_drivers" )
-
-/** Declare a VMBus device driver */
-#define __vmbus_driver __table_entry ( VMBUS_DRIVERS, 01 )
-
-/**
- * Set VMBus device driver-private data
- *
- * @v vmdev		VMBus device
- * @v priv		Private data
- */
-static inline void vmbus_set_drvdata ( struct vmbus_device *vmdev, void *priv ){
-	vmdev->priv = priv;
-}
-
-/**
- * Get VMBus device driver-private data
- *
- * @v vmdev		VMBus device
- * @ret priv		Private data
- */
-static inline void * vmbus_get_drvdata ( struct vmbus_device *vmdev ) {
-	return vmdev->priv;
-}
-
-/** Construct VMBus type */
-#define VMBUS_TYPE( a, b, c, d, e0, e1, e2, e3, e4, e5 ) {		\
-	.canonical = {							\
-		cpu_to_le32 ( a ), cpu_to_le16 ( b ),			\
-		cpu_to_le16 ( c ), cpu_to_be16 ( d ),			\
-		{ e0, e1, e2, e3, e4, e5 }				\
-	 } }
-
-/**
- * Register transfer page set
- *
- * @v vmdev		VMBus device
- * @v pages		Transfer page set
- * @ret rc		Return status code
- */
-static inline __attribute__ (( always_inline )) int
-vmbus_register_pages ( struct vmbus_device *vmdev,
-		       struct vmbus_xfer_pages *pages ) {
-
-	list_add ( &pages->list, &vmdev->pages );
-	return 0;
-}
-
-/**
- * Unregister transfer page set
- *
- * @v vmdev		VMBus device
- * @v pages		Transfer page set
- */
-static inline __attribute__ (( always_inline )) void
-vmbus_unregister_pages ( struct vmbus_device *vmdev,
-			 struct vmbus_xfer_pages *pages ) {
-
-	list_check_contains_entry ( pages, &vmdev->pages, list );
-	list_del ( &pages->list );
-}
-
-extern int vmbus_establish_gpadl ( struct vmbus_device *vmdev, userptr_t data,
-				   size_t len );
-extern int vmbus_gpadl_teardown ( struct vmbus_device *vmdev,
-				  unsigned int gpadl );
-extern int vmbus_open ( struct vmbus_device *vmdev,
-			struct vmbus_channel_operations *op,
-			size_t out_len, size_t in_len, size_t mtu );
-extern void vmbus_close ( struct vmbus_device *vmdev );
-extern int vmbus_send_control ( struct vmbus_device *vmdev, uint64_t xid,
-				const void *data, size_t len );
-extern int vmbus_send_data ( struct vmbus_device *vmdev, uint64_t xid,
-			     const void *data, size_t len,
-			     struct io_buffer *iobuf );
-extern int vmbus_send_completion ( struct vmbus_device *vmdev, uint64_t xid,
-				   const void *data, size_t len );
-extern int vmbus_send_cancellation ( struct vmbus_device *vmdev, uint64_t xid );
-extern int vmbus_poll ( struct vmbus_device *vmdev );
-extern void vmbus_dump_channel ( struct vmbus_device *vmdev );
-
 extern int vmbus_probe ( struct hv_hypervisor *hv, struct device *parent );
 extern int vmbus_reset ( struct hv_hypervisor *hv, struct device *parent );
 extern void vmbus_remove ( struct hv_hypervisor *hv, struct device *parent );
diff --git a/src/include/ipxe/vmbus_device.h b/src/include/ipxe/vmbus_device.h
new file mode 100644
index 00000000..e41d711b
--- /dev/null
+++ b/src/include/ipxe/vmbus_device.h
@@ -0,0 +1,291 @@
+#ifndef _IPXE_VMBUS_DEVICE_H
+#define _IPXE_VMBUS_DEVICE_H
+
+/** @file
+ *
+ * Hyper-V virtual machine bus
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <byteswap.h>
+#include <ipxe/uuid.h>
+#include <ipxe/device.h>
+#include <ipxe/tables.h>
+#include <ipxe/uaccess.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/hyperv.h>
+
+struct vmbus_device;
+
+/** VMBus channel operations */
+struct vmbus_channel_operations {
+	/**
+	 * Handle received control packet
+	 *
+	 * @v vmdev		VMBus device
+	 * @v xid		Transaction ID
+	 * @v data		Data
+	 * @v len		Length of data
+	 * @ret rc		Return status code
+	 */
+	int ( * recv_control ) ( struct vmbus_device *vmdev, uint64_t xid,
+				 const void *data, size_t len );
+	/**
+	 * Handle received data packet
+	 *
+	 * @v vmdev		VMBus device
+	 * @v xid		Transaction ID
+	 * @v data		Data
+	 * @v len		Length of data
+	 * @v list		List of I/O buffers
+	 * @ret rc		Return status code
+	 *
+	 * This function takes ownership of the I/O buffer.  It should
+	 * eventually call vmbus_send_completion() to indicate to the
+	 * host that the buffer can be reused.
+	 */
+	int ( * recv_data ) ( struct vmbus_device *vmdev, uint64_t xid,
+			      const void *data, size_t len,
+			      struct list_head *list );
+	/**
+	 * Handle received completion packet
+	 *
+	 * @v vmdev		VMBus device
+	 * @v xid		Transaction ID
+	 * @v data		Data
+	 * @v len		Length of data
+	 * @ret rc		Return status code
+	 */
+	int ( * recv_completion ) ( struct vmbus_device *vmdev, uint64_t xid,
+				    const void *data, size_t len );
+	/**
+	 * Handle received cancellation packet
+	 *
+	 * @v vmdev		VMBus device
+	 * @v xid		Transaction ID
+	 * @ret rc		Return status code
+	 */
+	int ( * recv_cancellation ) ( struct vmbus_device *vmdev,
+				      uint64_t xid );
+};
+
+struct vmbus_xfer_pages;
+
+/** VMBus transfer page set operations */
+struct vmbus_xfer_pages_operations {
+	/**
+	 * Copy data from transfer page
+	 *
+	 * @v pages		Transfer page set
+	 * @v data		Data buffer
+	 * @v offset		Offset within page set
+	 * @v len		Length within page set
+	 * @ret rc		Return status code
+	 */
+	int ( * copy ) ( struct vmbus_xfer_pages *pages, void *data,
+			 size_t offset, size_t len );
+};
+
+/** VMBus transfer page set */
+struct vmbus_xfer_pages {
+	/** List of all transfer page sets */
+	struct list_head list;
+	/** Page set ID (in protocol byte order) */
+	uint16_t pageset;
+	/** Page set operations */
+	struct vmbus_xfer_pages_operations *op;
+};
+
+/** VMBus device operations */
+struct vmbus_dev_operations {
+	int ( * establish_gpadl ) ( struct vmbus_device *vmdev,
+				    userptr_t data, size_t len );
+	int ( * gpadl_teardown ) ( struct vmbus_device *vmdev,
+				   unsigned int gpadl );
+	int ( * open ) ( struct vmbus_device *vmdev,
+			 struct vmbus_channel_operations *op,
+			 size_t out_len, size_t in_len, size_t mtu );
+	void ( * close ) ( struct vmbus_device *vmdev );
+	int ( * send_control ) ( struct vmbus_device *vmdev, uint64_t xid,
+				 const void *data, size_t len );
+	int ( * send_data ) ( struct vmbus_device *vmdev, uint64_t xid,
+			      const void *data, size_t len,
+			      struct io_buffer *iobuf );
+	int ( * send_completion ) ( struct vmbus_device *vmdev, uint64_t xid,
+				    const void *data, size_t len );
+	int ( * send_cancellation ) ( struct vmbus_device *vmdev,
+				      uint64_t xid );
+	int ( * poll ) ( struct vmbus_device *vmdev );
+	void ( * dump_channel ) ( struct vmbus_device *vmdev );
+};
+
+/** A VMBus device */
+struct vmbus_device {
+	/** Generic iPXE device */
+	struct device dev;
+	/** Channel instance */
+	union uuid instance;
+	/** Channel ID */
+	unsigned int channel;
+
+	/** Device operations */
+	struct vmbus_dev_operations *dev_op;
+	/** Channel operations */
+	struct vmbus_channel_operations *op;
+	/** List of transfer page sets */
+	struct list_head pages;
+
+	/** Driver */
+	struct vmbus_driver *driver;
+	/** Driver-private data */
+	void *priv;
+};
+
+/** A VMBus device driver */
+struct vmbus_driver {
+	/** Name */
+	const char *name;
+	/** Device type */
+	union uuid type;
+	/** Probe device
+	 *
+	 * @v vmdev		VMBus device
+	 * @ret rc		Return status code
+	 */
+	int ( * probe ) ( struct vmbus_device *vmdev );
+	/** Reset device
+	 *
+	 * @v vmdev		VMBus device
+	 * @ret rc		Return status code
+	 */
+	int ( * reset ) ( struct vmbus_device *vmdev );
+	/** Remove device
+	 *
+	 * @v vmdev		VMBus device
+	 */
+	void ( * remove ) ( struct vmbus_device *vmdev );
+};
+
+/** VMBus device driver table */
+#define VMBUS_DRIVERS __table ( struct vmbus_driver, "vmbus_drivers" )
+
+/** Declare a VMBus device driver */
+#define __vmbus_driver __table_entry ( VMBUS_DRIVERS, 01 )
+
+/**
+ * Set VMBus device driver-private data
+ *
+ * @v vmdev		VMBus device
+ * @v priv		Private data
+ */
+static inline void vmbus_set_drvdata ( struct vmbus_device *vmdev, void *priv ){
+	vmdev->priv = priv;
+}
+
+/**
+ * Get VMBus device driver-private data
+ *
+ * @v vmdev		VMBus device
+ * @ret priv		Private data
+ */
+static inline void * vmbus_get_drvdata ( struct vmbus_device *vmdev ) {
+	return vmdev->priv;
+}
+
+/** Construct VMBus type */
+#define VMBUS_TYPE( a, b, c, d, e0, e1, e2, e3, e4, e5 ) {		\
+	.canonical = {							\
+		cpu_to_le32 ( a ), cpu_to_le16 ( b ),			\
+		cpu_to_le16 ( c ), cpu_to_be16 ( d ),			\
+		{ e0, e1, e2, e3, e4, e5 }				\
+	 } }
+
+/**
+ * Register transfer page set
+ *
+ * @v vmdev		VMBus device
+ * @v pages		Transfer page set
+ * @ret rc		Return status code
+ */
+static inline __attribute__ (( always_inline )) int
+vmbus_register_pages ( struct vmbus_device *vmdev,
+		       struct vmbus_xfer_pages *pages ) {
+
+	list_add ( &pages->list, &vmdev->pages );
+	return 0;
+}
+
+/**
+ * Unregister transfer page set
+ *
+ * @v vmdev		VMBus device
+ * @v pages		Transfer page set
+ */
+static inline __attribute__ (( always_inline )) void
+vmbus_unregister_pages ( struct vmbus_device *vmdev,
+			 struct vmbus_xfer_pages *pages ) {
+
+	list_check_contains_entry ( pages, &vmdev->pages, list );
+	list_del ( &pages->list );
+}
+
+static inline __attribute__ (( always_inline )) int
+vmbus_establish_gpadl ( struct vmbus_device *vmdev,
+			userptr_t data, size_t len ) {
+	return vmdev->dev_op->establish_gpadl ( vmdev, data, len );
+}
+
+static inline __attribute__ (( always_inline )) int
+vmbus_gpadl_teardown ( struct vmbus_device *vmdev, unsigned int gpadl ) {
+	return vmdev->dev_op->gpadl_teardown ( vmdev, gpadl );
+}
+
+static inline __attribute__ (( always_inline )) int
+vmbus_open ( struct vmbus_device *vmdev, struct vmbus_channel_operations *op,
+	     size_t out_len, size_t in_len, size_t mtu ) {
+	return vmdev->dev_op->open ( vmdev, op, out_len, in_len, mtu );
+}
+
+static inline __attribute__ (( always_inline )) void
+vmbus_close ( struct vmbus_device *vmdev ) {
+	vmdev->dev_op->close ( vmdev );
+}
+
+static inline __attribute__ (( always_inline )) int
+vmbus_send_control ( struct vmbus_device *vmdev, uint64_t xid,
+		     const void *data, size_t len ) {
+	return vmdev->dev_op->send_control ( vmdev, xid, data, len );
+}
+
+static inline __attribute__ (( always_inline )) int
+vmbus_send_data ( struct vmbus_device *vmdev, uint64_t xid,
+		  const void *data, size_t len, struct io_buffer *iobuf ) {
+	return vmdev->dev_op->send_data ( vmdev, xid, data, len, iobuf );
+}
+
+static inline __attribute__ (( always_inline )) int
+vmbus_send_completion ( struct vmbus_device *vmdev, uint64_t xid,
+			const void *data, size_t len ) {
+	return vmdev->dev_op->send_completion ( vmdev, xid, data, len );
+}
+
+static inline __attribute__ (( always_inline )) int
+vmbus_send_cancellation ( struct vmbus_device *vmdev, uint64_t xid ) {
+	return vmdev->dev_op->send_cancellation ( vmdev, xid );
+}
+
+static inline __attribute__ (( always_inline )) int
+vmbus_poll ( struct vmbus_device *vmdev ) {
+	return vmdev->dev_op->poll ( vmdev );
+}
+
+static inline __attribute__ (( always_inline )) void
+vmbus_dump_channel ( struct vmbus_device *vmdev ) {
+	vmdev->dev_op->dump_channel ( vmdev );
+}
+
+struct vmbus_driver * vmbus_find_driver ( const union uuid *type );
+
+#endif /* _IPXE_VMBUS_DEVICE_H */
diff --git a/src/drivers/net/netvsc.c b/src/drivers/net/netvsc.c
index ae6473d2..46c56d60 100644
--- a/src/drivers/net/netvsc.c
+++ b/src/drivers/net/netvsc.c
@@ -37,7 +37,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #include <byteswap.h>
 #include <ipxe/umalloc.h>
 #include <ipxe/rndis.h>
-#include <ipxe/vmbus.h>
+#include <ipxe/vmbus_device.h>
 #include "netvsc.h"
 
 /**
diff --git a/src/interface/hyperv/vmbus.c b/src/interface/hyperv/vmbus.c
index 4b6a9440..804a7dd8 100644
--- a/src/interface/hyperv/vmbus.c
+++ b/src/interface/hyperv/vmbus.c
@@ -288,9 +288,11 @@ static int vmbus_negotiate_version ( struct hv_hypervisor *hv ) {
  * @v len		Length of data buffer
  * @ret gpadl		GPADL ID, or negative error
  */
-int vmbus_establish_gpadl ( struct vmbus_device *vmdev, userptr_t data,
-			    size_t len ) {
-	struct hv_hypervisor *hv = vmdev->hv;
+static int vmbus_ipxe_establish_gpadl ( struct vmbus_device *vmdev,
+					userptr_t data, size_t len ) {
+	struct vmbus_ipxe_device *ipxe_vmdev =
+		container_of ( vmdev, struct vmbus_ipxe_device, vmdev );
+	struct hv_hypervisor *hv = ipxe_vmdev->hv;
 	struct vmbus *vmbus = hv->vmbus;
 	physaddr_t addr = user_to_phys ( data, 0 );
 	unsigned int pfn_count = hv_pfn_count ( addr, len );
@@ -359,8 +361,11 @@ int vmbus_establish_gpadl ( struct vmbus_device *vmdev, userptr_t data,
  * @v gpadl		GPADL ID
  * @ret rc		Return status code
  */
-int vmbus_gpadl_teardown ( struct vmbus_device *vmdev, unsigned int gpadl ) {
-	struct hv_hypervisor *hv = vmdev->hv;
+static int vmbus_ipxe_gpadl_teardown ( struct vmbus_device *vmdev,
+				       unsigned int gpadl ) {
+	struct vmbus_ipxe_device *ipxe_vmdev =
+		container_of ( vmdev, struct vmbus_ipxe_device, vmdev );
+	struct hv_hypervisor *hv = ipxe_vmdev->hv;
 	struct vmbus *vmbus = hv->vmbus;
 	struct vmbus_gpadl_teardown teardown;
 	const struct vmbus_gpadl_torndown *torndown = &vmbus->message->torndown;
@@ -415,10 +420,12 @@ int vmbus_gpadl_teardown ( struct vmbus_device *vmdev, unsigned int gpadl ) {
  * two is a policy decision taken to simplify the ring buffer indexing
  * logic.
  */
-int vmbus_open ( struct vmbus_device *vmdev,
-		 struct vmbus_channel_operations *op,
-		 size_t out_len, size_t in_len, size_t mtu ) {
-	struct hv_hypervisor *hv = vmdev->hv;
+static int vmbus_ipxe_open ( struct vmbus_device *vmdev,
+			     struct vmbus_channel_operations *op,
+			     size_t out_len, size_t in_len, size_t mtu ) {
+	struct vmbus_ipxe_device *ipxe_vmdev =
+		container_of ( vmdev, struct vmbus_ipxe_device, vmdev );
+	struct hv_hypervisor *hv = ipxe_vmdev->hv;
 	struct vmbus *vmbus = hv->vmbus;
 	struct vmbus_open_channel open;
 	const struct vmbus_open_channel_result *opened =
@@ -446,8 +453,8 @@ int vmbus_open ( struct vmbus_device *vmdev,
 	}
 
 	/* Allocate ring buffer */
-	len = ( sizeof ( *vmdev->out ) + out_len +
-		sizeof ( *vmdev->in ) + in_len );
+	len = ( sizeof ( *ipxe_vmdev->out ) + out_len +
+		sizeof ( *ipxe_vmdev->in ) + in_len );
 	assert ( ( len % PAGE_SIZE ) == 0 );
 	ring = malloc_dma ( len, PAGE_SIZE );
 	if ( ! ring ) {
@@ -470,7 +477,7 @@ int vmbus_open ( struct vmbus_device *vmdev,
 	open_id = random();
 	open.id = open_id; /* Opaque random value: endianness irrelevant */
 	open.gpadl = cpu_to_le32 ( gpadl );
-	open.out_pages = ( ( sizeof ( *vmdev->out ) / PAGE_SIZE ) +
+	open.out_pages = ( ( sizeof ( *ipxe_vmdev->out ) / PAGE_SIZE ) +
 			   ( out_len / PAGE_SIZE ) );
 
 	/* Post message */
@@ -504,25 +511,25 @@ int vmbus_open ( struct vmbus_device *vmdev,
 	}
 
 	/* Store channel parameters */
-	vmdev->out_len = out_len;
-	vmdev->in_len = in_len;
-	vmdev->out = ring;
-	vmdev->in = ( ring + sizeof ( *vmdev->out ) + out_len );
-	vmdev->gpadl = gpadl;
+	ipxe_vmdev->out_len = out_len;
+	ipxe_vmdev->in_len = in_len;
+	ipxe_vmdev->out = ring;
+	ipxe_vmdev->in = ( ring + sizeof ( *ipxe_vmdev->out ) + out_len );
+	ipxe_vmdev->gpadl = gpadl;
 	vmdev->op = op;
-	vmdev->mtu = mtu;
-	vmdev->packet = packet;
+	ipxe_vmdev->mtu = mtu;
+	ipxe_vmdev->packet = packet;
 
 	DBGC ( vmdev, "VMBUS %s channel GPADL %#08x ring "
-		"[%#08lx,%#08lx,%#08lx)\n", vmdev->dev.name, vmdev->gpadl,
-		virt_to_phys ( vmdev->out ), virt_to_phys ( vmdev->in ),
-		( virt_to_phys ( vmdev->out ) + len ) );
+		"[%#08lx,%#08lx,%#08lx)\n", vmdev->dev.name, ipxe_vmdev->gpadl,
+		virt_to_phys ( ipxe_vmdev->out ), virt_to_phys ( ipxe_vmdev->in ),
+		( virt_to_phys ( ipxe_vmdev->out ) + len ) );
 	return 0;
 
  err_check_response:
  err_wait_for_message:
  err_post_message:
-	vmbus_gpadl_teardown ( vmdev, vmdev->gpadl );
+	vmbus_gpadl_teardown ( vmdev, ipxe_vmdev->gpadl );
  err_establish:
 	free_dma ( ring, len );
  err_alloc_ring:
@@ -536,8 +543,10 @@ int vmbus_open ( struct vmbus_device *vmdev,
  *
  * @v vmdev		VMBus device
  */
-void vmbus_close ( struct vmbus_device *vmdev ) {
-	struct hv_hypervisor *hv = vmdev->hv;
+static void vmbus_ipxe_close ( struct vmbus_device *vmdev ) {
+	struct vmbus_ipxe_device *ipxe_vmdev =
+		container_of ( vmdev, struct vmbus_ipxe_device, vmdev );
+	struct hv_hypervisor *hv = ipxe_vmdev->hv;
 	struct vmbus_close_channel close;
 	size_t len;
 	int rc;
@@ -558,7 +567,7 @@ void vmbus_close ( struct vmbus_device *vmdev ) {
 	}
 
 	/* Tear down GPADL */
-	if ( ( rc = vmbus_gpadl_teardown ( vmdev, vmdev->gpadl ) ) != 0 ) {
+	if ( ( rc = vmbus_gpadl_teardown ( vmdev, ipxe_vmdev->gpadl ) ) != 0 ) {
 		DBGC ( vmdev, "VMBUS %s failed to tear down channel GPADL: "
 		       "%s\n", vmdev->dev.name, strerror ( rc ) );
 		/* We can't prevent the remote VM from continuing to
@@ -568,15 +577,15 @@ void vmbus_close ( struct vmbus_device *vmdev ) {
 	}
 
 	/* Free ring buffer */
-	len = ( sizeof ( *vmdev->out ) + vmdev->out_len +
-		sizeof ( *vmdev->in ) + vmdev->in_len );
-	free_dma ( vmdev->out, len );
-	vmdev->out = NULL;
-	vmdev->in = NULL;
+	len = ( sizeof ( *ipxe_vmdev->out ) + ipxe_vmdev->out_len +
+		sizeof ( *ipxe_vmdev->in ) + ipxe_vmdev->in_len );
+	free_dma ( ipxe_vmdev->out, len );
+	ipxe_vmdev->out = NULL;
+	ipxe_vmdev->in = NULL;
 
 	/* Free packet buffer */
-	free ( vmdev->packet );
-	vmdev->packet = NULL;
+	free ( ipxe_vmdev->packet );
+	ipxe_vmdev->packet = NULL;
 
 	DBGC ( vmdev, "VMBUS %s closed\n", vmdev->dev.name );
 }
@@ -586,7 +595,7 @@ void vmbus_close ( struct vmbus_device *vmdev ) {
  *
  * @v vmdev		VMBus device
  */
-static void vmbus_signal_monitor ( struct vmbus_device *vmdev ) {
+static void vmbus_signal_monitor ( struct vmbus_ipxe_device *vmdev ) {
 	struct hv_hypervisor *hv = vmdev->hv;
 	struct vmbus *vmbus = hv->vmbus;
 	struct hv_monitor_trigger *trigger;
@@ -605,14 +614,14 @@ static void vmbus_signal_monitor ( struct vmbus_device *vmdev ) {
  *
  * @v vmdev		VMBus device
  */
-static void vmbus_signal_event ( struct vmbus_device *vmdev ) {
+static void vmbus_signal_event ( struct vmbus_ipxe_device *vmdev ) {
 	struct hv_hypervisor *hv = vmdev->hv;
 	int rc;
 
 	/* Signal hypervisor event */
 	if ( ( rc = hv_signal_event ( hv, VMBUS_EVENT_ID, 0 ) ) != 0 ) {
 		DBGC ( vmdev, "VMBUS %s could not signal event: %s\n",
-		       vmdev->dev.name, strerror ( rc ) );
+		       vmdev->vmdev.dev.name, strerror ( rc ) );
 		return;
 	}
 }
@@ -629,7 +638,7 @@ static void vmbus_signal_event ( struct vmbus_device *vmdev ) {
  * The caller must ensure that there is sufficient space in the ring
  * buffer.
  */
-static size_t vmbus_produce ( struct vmbus_device *vmdev, size_t prod,
+static size_t vmbus_produce ( struct vmbus_ipxe_device *vmdev, size_t prod,
 			      const void *data, size_t len ) {
 	size_t first;
 	size_t second;
@@ -657,7 +666,7 @@ static size_t vmbus_produce ( struct vmbus_device *vmdev, size_t prod,
  * @v len		Length to consume
  * @ret cons		New consumer index
  */
-static size_t vmbus_consume ( struct vmbus_device *vmdev, size_t cons,
+static size_t vmbus_consume ( struct vmbus_ipxe_device *vmdev, size_t cons,
 			      void *data, size_t len ) {
 	size_t first;
 	size_t second;
@@ -692,7 +701,9 @@ static size_t vmbus_consume ( struct vmbus_device *vmdev, size_t cons,
 static int vmbus_send ( struct vmbus_device *vmdev,
 			struct vmbus_packet_header *header,
 			const void *data, size_t len ) {
-	struct hv_hypervisor *hv = vmdev->hv;
+	struct vmbus_ipxe_device *ipxe_vmdev =
+		container_of ( vmdev, struct vmbus_ipxe_device, vmdev );
+	struct hv_hypervisor *hv = ipxe_vmdev->hv;
 	struct vmbus *vmbus = hv->vmbus;
 	static uint8_t padding[ 8 - 1 ];
 	struct vmbus_packet_footer footer;
@@ -706,10 +717,10 @@ static int vmbus_send ( struct vmbus_device *vmdev,
 	size_t fill;
 
 	/* Sanity check */
-	assert ( vmdev->out != NULL );
+	assert ( ipxe_vmdev->out != NULL );
 
 	/* We're in process of being reset */
-	if ( vmbus_gpadl_is_obsolete ( vmdev->gpadl ) )
+	if ( vmbus_gpadl_is_obsolete ( ipxe_vmdev->gpadl ) )
 		return -EPIPE;
 
 	/* Calculate lengths */
@@ -719,11 +730,11 @@ static int vmbus_send ( struct vmbus_device *vmdev,
 	ring_len = ( header_len + len + pad_len + footer_len );
 
 	/* Check that we have enough room in the outbound ring buffer */
-	cons = le32_to_cpu ( vmdev->out->cons );
-	prod = le32_to_cpu ( vmdev->out->prod );
+	cons = le32_to_cpu ( ipxe_vmdev->out->cons );
+	prod = le32_to_cpu ( ipxe_vmdev->out->prod );
 	old_prod = prod;
-	fill = ( ( prod - cons ) & ( vmdev->out_len - 1 ) );
-	if ( ( fill + ring_len ) >= vmdev->out_len ) {
+	fill = ( ( prod - cons ) & ( ipxe_vmdev->out_len - 1 ) );
+	if ( ( fill + ring_len ) >= ipxe_vmdev->out_len ) {
 		DBGC ( vmdev, "VMBUS %s ring buffer full\n", vmdev->dev.name );
 		return -ENOBUFS;
 	}
@@ -733,31 +744,31 @@ static int vmbus_send ( struct vmbus_device *vmdev,
 
 	/* Construct footer */
 	footer.reserved = 0;
-	footer.prod = vmdev->out->prod;
+	footer.prod = ipxe_vmdev->out->prod;
 
 	/* Copy packet to buffer */
 	DBGC2 ( vmdev, "VMBUS %s sending:\n", vmdev->dev.name );
 	DBGC2_HDA ( vmdev, prod, header, header_len );
-	prod = vmbus_produce ( vmdev, prod, header, header_len );
+	prod = vmbus_produce ( ipxe_vmdev, prod, header, header_len );
 	DBGC2_HDA ( vmdev, prod, data, len );
-	prod = vmbus_produce ( vmdev, prod, data, len );
-	prod = vmbus_produce ( vmdev, prod, padding, pad_len );
+	prod = vmbus_produce ( ipxe_vmdev, prod, data, len );
+	prod = vmbus_produce ( ipxe_vmdev, prod, padding, pad_len );
 	DBGC2_HDA ( vmdev, prod, &footer, sizeof ( footer ) );
-	prod = vmbus_produce ( vmdev, prod, &footer, sizeof ( footer ) );
-	assert ( ( ( prod - old_prod ) & ( vmdev->out_len - 1 ) ) == ring_len );
+	prod = vmbus_produce ( ipxe_vmdev, prod, &footer, sizeof ( footer ) );
+	assert ( ( ( prod - old_prod ) & ( ipxe_vmdev->out_len - 1 ) ) == ring_len );
 
 	/* Update producer index */
 	wmb();
-	vmdev->out->prod = cpu_to_le32 ( prod );
+	ipxe_vmdev->out->prod = cpu_to_le32 ( prod );
 
 	/* Return if we do not need to signal the host.  This follows
 	 * the logic of hv_need_to_signal() in the Linux driver.
 	 */
 	mb();
-	if ( vmdev->out->intr_mask )
+	if ( ipxe_vmdev->out->intr_mask )
 		return 0;
 	rmb();
-	cons = le32_to_cpu ( vmdev->out->cons );
+	cons = le32_to_cpu ( ipxe_vmdev->out->cons );
 	if ( cons != old_prod )
 		return 0;
 
@@ -765,7 +776,7 @@ static int vmbus_send ( struct vmbus_device *vmdev,
 	set_bit ( vmdev->channel, vmbus->intr->out );
 
 	/* Signal the host */
-	vmdev->signal ( vmdev );
+	ipxe_vmdev->signal ( ipxe_vmdev );
 
 	return 0;
 }
@@ -781,9 +792,11 @@ static int vmbus_send ( struct vmbus_device *vmdev,
  *
  * Send data using a VMBUS_DATA_INBAND packet.
  */
-int vmbus_send_control ( struct vmbus_device *vmdev, uint64_t xid,
-			 const void *data, size_t len ) {
-	struct vmbus_packet_header *header = vmdev->packet;
+static int vmbus_ipxe_send_control ( struct vmbus_device *vmdev, uint64_t xid,
+				     const void *data, size_t len ) {
+	struct vmbus_ipxe_device *ipxe_vmdev =
+		container_of ( vmdev, struct vmbus_ipxe_device, vmdev );
+	struct vmbus_packet_header *header = ipxe_vmdev->packet;
 
 	/* Construct header in packet buffer */
 	assert ( header != NULL );
@@ -810,20 +823,23 @@ int vmbus_send_control ( struct vmbus_device *vmdev, uint64_t xid,
  * responsible for ensuring that the I/O buffer remains untouched
  * until the corresponding completion has been received.
  */
-int vmbus_send_data ( struct vmbus_device *vmdev, uint64_t xid,
-		      const void *data, size_t len, struct io_buffer *iobuf ) {
+static int vmbus_ipxe_send_data ( struct vmbus_device *vmdev, uint64_t xid,
+				  const void *data, size_t len,
+				  struct io_buffer *iobuf ) {
+	struct vmbus_ipxe_device *ipxe_vmdev =
+		container_of ( vmdev, struct vmbus_ipxe_device, vmdev );
 	physaddr_t addr = virt_to_phys ( iobuf->data );
 	unsigned int pfn_count = hv_pfn_count ( addr, iob_len ( iobuf ) );
 	struct {
 		struct vmbus_gpa_direct_header gpa;
 		struct vmbus_gpa_range range;
 		uint64_t pfn[pfn_count];
-	} __attribute__ (( packed )) *header = vmdev->packet;
+	} __attribute__ (( packed )) *header = ipxe_vmdev->packet;
 	unsigned int i;
 
 	/* Sanity check */
 	assert ( header != NULL );
-	assert ( sizeof ( *header ) <= vmdev->mtu );
+	assert ( sizeof ( *header ) <= ipxe_vmdev->mtu );
 
 	/* Construct header in packet buffer */
 	header->gpa.header.type = cpu_to_le16 ( VMBUS_DATA_GPA_DIRECT );
@@ -850,9 +866,12 @@ int vmbus_send_data ( struct vmbus_device *vmdev, uint64_t xid,
  *
  * Send data using a VMBUS_COMPLETION packet.
  */
-int vmbus_send_completion ( struct vmbus_device *vmdev, uint64_t xid,
-			    const void *data, size_t len ) {
-	struct vmbus_packet_header *header = vmdev->packet;
+static int vmbus_ipxe_send_completion ( struct vmbus_device *vmdev,
+					uint64_t xid,
+					const void *data, size_t len ) {
+	struct vmbus_ipxe_device *ipxe_vmdev =
+		container_of ( vmdev, struct vmbus_ipxe_device, vmdev );
+	struct vmbus_packet_header *header = ipxe_vmdev->packet;
 
 	/* Construct header in packet buffer */
 	assert ( header != NULL );
@@ -873,8 +892,11 @@ int vmbus_send_completion ( struct vmbus_device *vmdev, uint64_t xid,
  *
  * Send data using a VMBUS_CANCELLATION packet.
  */
-int vmbus_send_cancellation ( struct vmbus_device *vmdev, uint64_t xid ) {
-	struct vmbus_packet_header *header = vmdev->packet;
+static int vmbus_ipxe_send_cancellation ( struct vmbus_device *vmdev,
+					  uint64_t xid ) {
+	struct vmbus_ipxe_device *ipxe_vmdev =
+		container_of ( vmdev, struct vmbus_ipxe_device, vmdev );
+	struct vmbus_packet_header *header = ipxe_vmdev->packet;
 
 	/* Construct header in packet buffer */
 	assert ( header != NULL );
@@ -988,8 +1010,10 @@ static int vmbus_xfer_page_iobufs ( struct vmbus_device *vmdev,
  * @v vmdev		VMBus device
  * @ret rc		Return status code
  */
-int vmbus_poll ( struct vmbus_device *vmdev ) {
-	struct vmbus_packet_header *header = vmdev->packet;
+static int vmbus_ipxe_poll ( struct vmbus_device *vmdev ) {
+	struct vmbus_ipxe_device *ipxe_vmdev =
+		container_of ( vmdev, struct vmbus_ipxe_device, vmdev );
+	struct vmbus_packet_header *header = ipxe_vmdev->packet;
 	struct list_head list;
 	void *data;
 	size_t header_len;
@@ -1002,21 +1026,21 @@ int vmbus_poll ( struct vmbus_device *vmdev ) {
 	int rc;
 
 	/* Sanity checks */
-	assert ( vmdev->packet != NULL );
-	assert ( vmdev->in != NULL );
+	assert ( ipxe_vmdev->packet != NULL );
+	assert ( ipxe_vmdev->in != NULL );
 
 	/* We're in process of being reset */
-	if ( vmbus_gpadl_is_obsolete ( vmdev->gpadl ) )
+	if ( vmbus_gpadl_is_obsolete ( ipxe_vmdev->gpadl ) )
 		return -EPIPE;
 
 	/* Return immediately if buffer is empty */
-	if ( vmdev->in->prod == vmdev->in->cons )
+	if ( ipxe_vmdev->in->prod == ipxe_vmdev->in->cons )
 		return -EAGAIN;
-	cons = le32_to_cpu ( vmdev->in->cons );
+	cons = le32_to_cpu ( ipxe_vmdev->in->cons );
 	old_cons = cons;
 
 	/* Consume (start of) header */
-	cons = vmbus_consume ( vmdev, cons, header, sizeof ( *header ) );
+	cons = vmbus_consume ( ipxe_vmdev, cons, header, sizeof ( *header ) );
 
 	/* Parse and sanity check header */
 	header_len = ( le16_to_cpu ( header->hdr_qlen ) * 8 );
@@ -1028,7 +1052,7 @@ int vmbus_poll ( struct vmbus_device *vmdev ) {
 	len = ( ( le16_to_cpu ( header->qlen ) * 8 ) - header_len );
 	footer_len = sizeof ( struct vmbus_packet_footer );
 	ring_len = ( header_len + len + footer_len );
-	if ( ring_len > vmdev->mtu ) {
+	if ( ring_len > ipxe_vmdev->mtu ) {
 		DBGC ( vmdev, "VMBUS %s received overlength packet (%zd "
 		       "bytes)\n", vmdev->dev.name, ring_len );
 		return -ERANGE;
@@ -1036,12 +1060,12 @@ int vmbus_poll ( struct vmbus_device *vmdev ) {
 	xid = le64_to_cpu ( header->xid );
 
 	/* Consume remainder of packet */
-	cons = vmbus_consume ( vmdev, cons,
+	cons = vmbus_consume ( ipxe_vmdev, cons,
 			       ( ( ( void * ) header ) + sizeof ( *header ) ),
 			       ( ring_len - sizeof ( *header ) ) );
 	DBGC2 ( vmdev, "VMBUS %s received:\n", vmdev->dev.name );
 	DBGC2_HDA ( vmdev, old_cons, header, ring_len );
-	assert ( ( ( cons - old_cons ) & ( vmdev->in_len - 1 ) ) == ring_len );
+	assert ( ( ( cons - old_cons ) & ( ipxe_vmdev->in_len - 1 ) ) == ring_len );
 
 	/* Allocate I/O buffers, if applicable */
 	INIT_LIST_HEAD ( &list );
@@ -1053,7 +1077,7 @@ int vmbus_poll ( struct vmbus_device *vmdev ) {
 
 	/* Update producer index */
 	rmb();
-	vmdev->in->cons = cpu_to_le32 ( cons );
+	ipxe_vmdev->in->cons = cpu_to_le32 ( cons );
 
 	/* Handle packet */
 	data = ( ( ( void * ) header ) + header_len );
@@ -1109,41 +1133,56 @@ int vmbus_poll ( struct vmbus_device *vmdev ) {
  *
  * @v vmdev		VMBus device
  */
-void vmbus_dump_channel ( struct vmbus_device *vmdev ) {
-	size_t out_prod = le32_to_cpu ( vmdev->out->prod );
-	size_t out_cons = le32_to_cpu ( vmdev->out->cons );
-	size_t in_prod = le32_to_cpu ( vmdev->in->prod );
-	size_t in_cons = le32_to_cpu ( vmdev->in->cons );
+static void vmbus_ipxe_dump_channel ( struct vmbus_device *vmdev ) {
+	struct vmbus_ipxe_device *ipxe_vmdev =
+		container_of ( vmdev, struct vmbus_ipxe_device, vmdev );
+	size_t out_prod = le32_to_cpu ( ipxe_vmdev->out->prod );
+	size_t out_cons = le32_to_cpu ( ipxe_vmdev->out->cons );
+	size_t in_prod = le32_to_cpu ( ipxe_vmdev->in->prod );
+	size_t in_cons = le32_to_cpu ( ipxe_vmdev->in->cons );
 	size_t in_len;
 	size_t first;
 	size_t second;
 
 	/* Dump ring status */
-	DBGC ( vmdev, "VMBUS %s out %03zx:%03zx%s in %03zx:%03zx%s\n",
+	DBGC ( ipxe_vmdev, "VMBUS %s out %03zx:%03zx%s in %03zx:%03zx%s\n",
 	       vmdev->dev.name, out_prod, out_cons,
-	       ( vmdev->out->intr_mask ? "(m)" : "" ), in_prod, in_cons,
-	       ( vmdev->in->intr_mask ? "(m)" : "" ) );
+	       ( ipxe_vmdev->out->intr_mask ? "(m)" : "" ), in_prod, in_cons,
+	       ( ipxe_vmdev->in->intr_mask ? "(m)" : "" ) );
 
 	/* Dump inbound ring contents, if any */
 	if ( in_prod != in_cons ) {
 		in_len = ( ( in_prod - in_cons ) &
-			   ( vmdev->in_len - 1 ) );
-		first = ( vmdev->in_len - in_cons );
+			   ( ipxe_vmdev->in_len - 1 ) );
+		first = ( ipxe_vmdev->in_len - in_cons );
 		if ( first > in_len )
 			first = in_len;
 		second = ( in_len - first );
-		DBGC_HDA ( vmdev, in_cons, &vmdev->in->data[in_cons], first );
-		DBGC_HDA ( vmdev, 0, &vmdev->in->data[0], second );
+		DBGC_HDA ( ipxe_vmdev, in_cons, &ipxe_vmdev->in->data[in_cons], first );
+		DBGC_HDA ( ipxe_vmdev, 0, &ipxe_vmdev->in->data[0], second );
 	}
 }
 
+static struct vmbus_dev_operations vmbus_ipxe_dev_operations = {
+	.establish_gpadl = vmbus_ipxe_establish_gpadl,
+	.gpadl_teardown = vmbus_ipxe_gpadl_teardown,
+	.open = vmbus_ipxe_open,
+	.close = vmbus_ipxe_close,
+	.send_control = vmbus_ipxe_send_control,
+	.send_data = vmbus_ipxe_send_data,
+	.send_completion = vmbus_ipxe_send_completion,
+	.send_cancellation = vmbus_ipxe_send_cancellation,
+	.poll = vmbus_ipxe_poll,
+	.dump_channel = vmbus_ipxe_dump_channel,
+};
+
 /**
  * Find driver for VMBus device
  *
  * @v vmdev		VMBus device
  * @ret driver		Driver, or NULL
  */
-static struct vmbus_driver * vmbus_find_driver ( const union uuid *type ) {
+struct vmbus_driver * vmbus_find_driver ( const union uuid *type ) {
 	struct vmbus_driver *vmdrv;
 
 	for_each_table_entry ( vmdrv, VMBUS_DRIVERS ) {
@@ -1168,8 +1207,8 @@ static int vmbus_probe_channels ( struct hv_hypervisor *hv,
 	const union uuid *type;
 	union uuid instance;
 	struct vmbus_driver *driver;
-	struct vmbus_device *vmdev;
-	struct vmbus_device *tmp;
+	struct vmbus_ipxe_device *vmdev;
+	struct vmbus_ipxe_device *tmp;
 	unsigned int channel;
 	int rc;
 
@@ -1214,27 +1253,29 @@ static int vmbus_probe_channels ( struct hv_hypervisor *hv,
 			memcpy ( &instance, &offer->instance,
 				 sizeof ( instance ) );
 			uuid_mangle ( &instance );
-			snprintf ( vmdev->dev.name, sizeof ( vmdev->dev.name ),
+			snprintf ( vmdev->vmdev.dev.name,
+				   sizeof ( vmdev->vmdev.dev.name ),
 				   "{%s}", uuid_ntoa ( &instance ) );
-			vmdev->dev.desc.bus_type = BUS_TYPE_HV;
-			vmdev->dev.desc.location = channel;
-			INIT_LIST_HEAD ( &vmdev->dev.children );
-			list_add_tail ( &vmdev->dev.siblings,
+			vmdev->vmdev.dev.desc.bus_type = BUS_TYPE_HV;
+			vmdev->vmdev.dev.desc.location = channel;
+			INIT_LIST_HEAD ( &vmdev->vmdev.dev.children );
+			list_add_tail ( &vmdev->vmdev.dev.siblings,
 					&parent->children );
-			vmdev->dev.parent = parent;
+			vmdev->vmdev.dev.parent = parent;
 			vmdev->hv = hv;
-			memcpy ( &vmdev->instance, &offer->instance,
-				 sizeof ( vmdev->instance ) );
-			vmdev->channel = channel;
+			memcpy ( &vmdev->vmdev.instance, &offer->instance,
+				 sizeof ( vmdev->vmdev.instance ) );
+			vmdev->vmdev.channel = channel;
 			vmdev->monitor = offer->monitor;
 			vmdev->signal = ( offer->monitored ?
 					  vmbus_signal_monitor :
 					  vmbus_signal_event );
-			INIT_LIST_HEAD ( &vmdev->pages );
-			vmdev->driver = driver;
-			vmdev->dev.driver_name = driver->name;
+			INIT_LIST_HEAD ( &vmdev->vmdev.pages );
+			vmdev->vmdev.driver = driver;
+			vmdev->vmdev.dev.driver_name = driver->name;
+			vmdev->vmdev.dev_op = &vmbus_ipxe_dev_operations;
 			DBGC ( vmdev, "VMBUS %s has driver \"%s\"\n",
-			       vmdev->dev.name, vmdev->driver->name );
+			       vmdev->vmdev.dev.name, vmdev->vmdev.driver->name );
 
 		} else if ( header->type ==
 			    cpu_to_le32 ( VMBUS_ALL_OFFERS_DELIVERED ) ) {
@@ -1254,10 +1295,10 @@ static int vmbus_probe_channels ( struct hv_hypervisor *hv,
 	 * enumeration since devices will need to send and receive
 	 * VMBus messages.
 	 */
-	list_for_each_entry ( vmdev, &parent->children, dev.siblings ) {
-		if ( ( rc = vmdev->driver->probe ( vmdev ) ) != 0 ) {
+	list_for_each_entry ( vmdev, &parent->children, vmdev.dev.siblings ) {
+		if ( ( rc = vmdev->vmdev.driver->probe ( &vmdev->vmdev ) ) != 0 ) {
 			DBGC ( vmdev, "VMBUS %s could not probe: %s\n",
-			       vmdev->dev.name, strerror ( rc ) );
+			       vmdev->vmdev.dev.name, strerror ( rc ) );
 			goto err_probe;
 		}
 	}
@@ -1267,16 +1308,16 @@ static int vmbus_probe_channels ( struct hv_hypervisor *hv,
  err_probe:
 	/* Remove driver from each device that was already probed */
 	list_for_each_entry_continue_reverse ( vmdev, &parent->children,
-					       dev.siblings ) {
-		vmdev->driver->remove ( vmdev );
+					       vmdev.dev.siblings ) {
+		vmdev->vmdev.driver->remove ( &vmdev->vmdev );
 	}
  err_unexpected_offer:
  err_alloc_vmdev:
  err_wait_for_any_message:
 	/* Free any devices allocated (but potentially not yet probed) */
 	list_for_each_entry_safe ( vmdev, tmp, &parent->children,
-				   dev.siblings ) {
-		list_del ( &vmdev->dev.siblings );
+				   vmdev.dev.siblings ) {
+		list_del ( &vmdev->vmdev.dev.siblings );
 		free ( vmdev );
 	}
  err_post_message:
@@ -1297,7 +1338,7 @@ static int vmbus_reset_channels ( struct hv_hypervisor *hv,
 	const struct vmbus_message_header *header = &vmbus->message->header;
 	const struct vmbus_offer_channel *offer = &vmbus->message->offer;
 	const union uuid *type;
-	struct vmbus_device *vmdev;
+	struct vmbus_ipxe_device *vmdev;
 	unsigned int channel;
 	int rc;
 
@@ -1342,10 +1383,10 @@ static int vmbus_reset_channels ( struct hv_hypervisor *hv,
 	}
 
 	/* Reset all devices */
-	list_for_each_entry ( vmdev, &parent->children, dev.siblings ) {
-		if ( ( rc = vmdev->driver->reset ( vmdev ) ) != 0 ) {
+	list_for_each_entry ( vmdev, &parent->children, vmdev.dev.siblings ) {
+		if ( ( rc = vmdev->vmdev.driver->reset ( &vmdev->vmdev ) ) != 0 ) {
 			DBGC ( vmdev, "VMBUS %s could not reset: %s\n",
-			       vmdev->dev.name, strerror ( rc ) );
+			       vmdev->vmdev.dev.name, strerror ( rc ) );
 			/* Continue attempting to reset other devices */
 			continue;
 		}
@@ -1362,19 +1403,19 @@ static int vmbus_reset_channels ( struct hv_hypervisor *hv,
  */
 static void vmbus_remove_channels ( struct hv_hypervisor *hv __unused,
 				    struct device *parent ) {
-	struct vmbus_device *vmdev;
-	struct vmbus_device *tmp;
+	struct vmbus_ipxe_device *vmdev;
+	struct vmbus_ipxe_device *tmp;
 
 	/* Remove devices */
 	list_for_each_entry_safe ( vmdev, tmp, &parent->children,
-				   dev.siblings ) {
-		vmdev->driver->remove ( vmdev );
-		assert ( list_empty ( &vmdev->dev.children ) );
+				   vmdev.dev.siblings ) {
+		vmdev->vmdev.driver->remove ( &vmdev->vmdev );
+		assert ( list_empty ( &vmdev->vmdev.dev.children ) );
 		assert ( vmdev->out == NULL );
 		assert ( vmdev->in == NULL );
 		assert ( vmdev->packet == NULL );
-		assert ( list_empty ( &vmdev->pages ) );
-		list_del ( &vmdev->dev.siblings );
+		assert ( list_empty ( &vmdev->vmdev.pages ) );
+		list_del ( &vmdev->vmdev.dev.siblings );
 		free ( vmdev );
 	}
 }
-- 
2.17.1




More information about the ipxe-devel mailing list