All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH][8/17] USB virt 2.6 split driver---xbgt channel
@ 2005-11-21 13:19 harry
  0 siblings, 0 replies; only message in thread
From: harry @ 2005-11-21 13:19 UTC (permalink / raw)
  To: xen-devel

[-- Attachment #1: Type: text/plain, Size: 399 bytes --]

This patch implements the xenidc_xbgt_channel or xenbus grant-table
channel which is an interdomain message channel based on grant-tables
(this bit implemented by composition using a xenidc_gnttab_channel from
a previous patch) with bring up and tear down implemented using xenbus
(this bit implemented in this patch by xenidc_xbgt_channel).

Signed-off-by: Harry Butterworth <butterwo@uk.ibm.com>


[-- Attachment #2: p8-xbgt-channel.patch --]
[-- Type: text/x-patch, Size: 63290 bytes --]

diff -r 47edf571a62d -r 1786d40e66b8 linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile	Sun Nov 20 17:44:51 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile	Sun Nov 20 17:45:04 2005
@@ -11,3 +11,4 @@
 xenidc-objs += xenidc_grant_table.o
 xenidc-objs += xenidc_vaddress.o
 xenidc-objs += xenidc_gnttab_channel.o
+xenidc-objs += xenidc_xbgt_channel.o
diff -r 47edf571a62d -r 1786d40e66b8 linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_xbgt_channel.c
--- /dev/null	Sun Nov 20 17:44:51 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_xbgt_channel.c	Sun Nov 20 17:45:04 2005
@@ -0,0 +1,1607 @@
+/*****************************************************************************/
+/* This is a class which uses a xenidc_gnttab_channel (grant-tables based    */
+/* message channel class) and xenbus to implement an interdomain message     */
+/* channel with grant-tables based message transfer and xenbus based         */
+/* bring-up and tear-down handshaking.                                       */
+/* This class is used in the implementation of the xenidc_endpoint class.    */
+/*                                                                           */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation                      */
+/*                                                                           */
+/* This program is free software; you can redistribute it and/or modify it   */
+/* under the terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2 of the License, or (at your    */
+/* option) any later version.                                                */
+/*                                                                           */
+/* This program is distributed in the hope that it will be useful, but       */
+/* WITHOUT ANY WARRANTY; without even the implied warranty of                */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General */
+/* Public License for more details.                                          */
+/*                                                                           */
+/* You should have received a copy of the GNU General Public License along   */
+/* with this program; if not, write to the Free Software Foundation, Inc.,   */
+/* 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                   */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/* The state machine below makes the following assumptions:                  */
+/*                                                                           */
+/* 1) The store might contain some stale cruft from the last time our device */
+/* driver failed.  This is a handy assumption for testing new versions of    */
+/* the driver but isn't strictly necessary.                                  */
+/*                                                                           */
+/* 2) If the other side generates a protocol error on the inter-domain       */
+/* connection then we attempt to disconnect and reconnect.  An alternative   */
+/* behaviour would be to wait for our interface to be called to disconnect   */
+/* and then reconnect before retrying.                                       */
+/*                                                                           */
+/* 3) If we experience an internal failure (fail to register watch for       */
+/* example) then we attempt to disconnect and wait for our interface to be   */
+/* called to disconnect (by module unload for example) and reconnect before  */
+/* retrying.                                                                 */
+/*                                                                           */
+/* 4) Connection and disconnection of the channel is done in two phases: the */
+/* first phase makes the local resources available to the remote side, the   */
+/* second phase uses the resources of the remote side to complete the        */
+/* connection.                                                               */
+/*                                                                           */
+/* The key for the stimuli is as follows:                                    */
+/*                                                                           */
+/* cn: interface called to connect the channel when interface state is       */
+/* disconnected (for example on module load).                                */
+/*                                                                           */
+/* pe: protocol error detected when channel is in a state between phase two  */
+/* connected and the completion of the phase two disconnect callback.        */
+/*                                                                           */
+/* dn: interface called to disconnect the channel when the interface state   */
+/* is connected (for example on module unload).                              */
+/*                                                                           */
+/* ou: a synchronous stimulus from the response test_other_state which       */
+/* indicates that the other state is still unknown because the watch         */
+/* callback hasn't happened yet. Can only happen when making the response    */
+/* test_other_state.                                                         */
+/*                                                                           */
+/* od: other state is disconnected.  This is both a synchronous stimulus     */
+/* from test_other_state and an asynchronous stimulus from the watch         */
+/* function. Disconnected means that we can't read at least the other side's */
+/* ready node from the store.                                                */
+/*                                                                           */
+/* or: other state is ready. This is both a synchronous stimulus from        */
+/* test_other_state and an asynchronous stimulus from the watch function.    */
+/* Ready means that we can see the other side's ready node but not the       */
+/* ring-reference and event-channel information.                             */
+/*                                                                           */
+/* oc: other state is connected.  This is both a synchronous stimulus from   */
+/* test_other_state and an asynchronous stimulus from the watch function.    */
+/* Connected means that we found both the ready node and the connected       */
+/* information in the store.                                                 */
+/*                                                                           */
+/* If the values of the connected information change when the other side is  */
+/* connected then we generate the 'oc' stimulus again which forces a         */
+/* reconnect.                                                                */
+/*                                                                           */
+/* rs: An asynchronous response was successful (we only make one response at */
+/* a time so all asynchronous responses have the same completion stimuli).   */
+/*                                                                           */
+/* rf: An asynchronous response failed.  Only register_watch, clear_store,   */
+/* write_ready, write_connected, phase_two_connect can fail.  Only           */
+/* phase_two_connect has a good reason for failure: the other side might     */
+/* have passed bogus parameters; the other failures are poor API design and  */
+/* ought to be promoted to domain failures.                                  */
+/*                                                                           */
+/* The state machine responses are as follows:                               */
+/*                                                                           */
+/* test_other_state:  what state do we currently think the other side is in  */
+/* as reflected by the last watch event.  Synchronous (called with the lock  */
+/* held) completes with ou/od/or/oc.                                         */
+/*                                                                           */
+/* register_watch: register a watch on the other side.                       */
+/*                                                                           */
+/* unregister_watch: unregister the watch.                                   */
+/*                                                                           */
+/* clear_store: remove the ready node and connected information.             */
+/*                                                                           */
+/* write_ready: write the ready node to the store.                           */
+/*                                                                           */
+/* write_connected: write the connected information to the store.            */
+/*                                                                           */
+/* phase_one_connect: grant the remote side access to the local page etc.    */
+/*                                                                           */
+/* phase_two_connect: map the remote page etc.                               */
+/*                                                                           */
+/* phase_two_disconnect: unmap the remote page.                              */
+/*                                                                           */
+/* phase_one_disconnect: revoke the access of the remote side.               */
+/*                                                                           */
+/* complete_disconnect: When our interface is called to get us to disconnect */
+/* the channel we quiesce and disconnect and then call this to indicate we   */
+/* are done.                                                                 */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <asm-xen/xenidc_xbgt_channel.h>
+#include <linux/err.h>
+#include "xenidc_trace.h"
+
+typedef enum {
+	xenidc_xbgt_channel_stimulus_cn,	/* Connect:  disconnected               */
+	xenidc_xbgt_channel_stimulus_pe,	/* Protocol error: ph2c->ph2dc inclusive */
+	xenidc_xbgt_channel_stimulus_dn,	/* Disconnect: connected                */
+	xenidc_xbgt_channel_stimulus_ou,	/* Other unknown: test other state only */
+	xenidc_xbgt_channel_stimulus_od,	/* Other disconnected: watch / test     */
+	xenidc_xbgt_channel_stimulus_or,	/* Other ready: watch / test            */
+	xenidc_xbgt_channel_stimulus_oc,	/* Other connected: watch / test        */
+	xenidc_xbgt_channel_stimulus_rs,	/* Response successful: making response */
+	xenidc_xbgt_channel_stimulus_rf	/* Response failed: r. watch, tra, ph2c */
+} xenidc_xbgt_channel_stimulus;
+
+static void xenidc_xbgt_channel_handle_stimulus
+    (xenidc_xbgt_channel * channel, xenidc_xbgt_channel_stimulus stimulus);
+
+static int xenidc_xbgt_channel_init_or_exit
+    (xenidc_xbgt_channel * channel, int exit);
+
+int xenidc_xbgt_channel_init(xenidc_xbgt_channel * channel)
+{
+	return xenidc_xbgt_channel_init_or_exit(channel, 0);
+}
+
+void xenidc_xbgt_channel_connect
+    (xenidc_xbgt_channel * channel,
+     const char *local_path,
+     const char *remote_path, domid_t remote_domain_id) {
+	trace();
+
+	{
+		unsigned long flags;
+
+		spin_lock_irqsave(&channel->lock, flags);
+
+		channel->local_path = local_path;
+		channel->remote_path = remote_path;
+		channel->remote_domain_id = remote_domain_id;
+
+		xenidc_xbgt_channel_handle_stimulus
+		    (channel, xenidc_xbgt_channel_stimulus_cn);
+
+		spin_unlock_irqrestore(&channel->lock, flags);
+	}
+}
+
+static void xenidc_xbgt_channel_watch
+    (struct xenbus_watch *watch, const char **vec, unsigned int len) {
+	trace();
+
+	{
+		xenidc_xbgt_channel *channel =
+		    container_of(watch, xenidc_xbgt_channel, watch);
+
+		struct xenbus_transaction *transaction =
+		    xenbus_transaction_start();
+
+		if (IS_ERR(transaction)) {
+			trace0("error starting transaction");
+
+			goto DISCONNECTED;
+		}
+
+		{
+			unsigned int event_channel;
+			unsigned int ring_reference;
+			unsigned int ready;
+
+			int error = xenbus_gather(transaction,
+						  watch->node,
+						  "ready", "%u", &ready,
+						  "event-channel", "%u",
+						  &event_channel,
+						  "ring-reference", "%u",
+						  &ring_reference,
+						  NULL);
+
+			if (error == 0) {
+				unsigned long flags;
+
+				spin_lock_irqsave(&channel->lock, flags);
+
+				if ((channel->other_state
+				     !=
+				     xenidc_xbgt_channel_other_state_connected)
+				    ||
+				    (channel->ready_event_channel !=
+				     event_channel)
+				    || (channel->ready_ring_reference !=
+					ring_reference)
+				    ) {
+					channel->other_state =
+					    xenidc_xbgt_channel_other_state_connected;
+
+					channel->ready_event_channel =
+					    event_channel;
+					channel->ready_ring_reference =
+					    ring_reference;
+
+					xenidc_xbgt_channel_handle_stimulus
+					    (channel,
+					     xenidc_xbgt_channel_stimulus_oc);
+				}
+
+				spin_unlock_irqrestore(&channel->lock, flags);
+
+				xenbus_transaction_end(transaction,
+						       1 /* abort */ );
+
+				return;
+			}
+		}
+
+		{
+			unsigned int ready;
+
+			int error = xenbus_gather(transaction,
+						  watch->node,
+						  "ready", "%u", &ready,
+						  NULL);
+
+			if (error == 0) {
+				unsigned long flags;
+
+				spin_lock_irqsave(&channel->lock, flags);
+
+				if ((channel->other_state
+				     != xenidc_xbgt_channel_other_state_ready)
+				    ) {
+					channel->other_state =
+					    xenidc_xbgt_channel_other_state_ready;
+
+					xenidc_xbgt_channel_handle_stimulus
+					    (channel,
+					     xenidc_xbgt_channel_stimulus_or);
+				}
+
+				spin_unlock_irqrestore(&channel->lock, flags);
+
+				xenbus_transaction_end(transaction,
+						       1 /* abort */ );
+
+				return;
+			}
+		}
+
+		xenbus_transaction_end(transaction, 1 /* abort */ );
+
+	      DISCONNECTED:
+
+		{
+			unsigned long flags;
+
+			spin_lock_irqsave(&channel->lock, flags);
+
+			if (channel->other_state
+			    != xenidc_xbgt_channel_other_state_disconnected) {
+				channel->other_state =
+				    xenidc_xbgt_channel_other_state_disconnected;
+
+				xenidc_xbgt_channel_handle_stimulus
+				    (channel, xenidc_xbgt_channel_stimulus_od);
+			}
+
+			spin_unlock_irqrestore(&channel->lock, flags);
+		}
+	}
+}
+
+static void xenidc_xbgt_channel_protocol_error
+    (xenidc_gnttab_channel * gnttab_channel) {
+	trace();
+
+	{
+		xenidc_xbgt_channel *channel =
+		    xenidc_xbgt_channel_gnttab_channel_to(gnttab_channel);
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&channel->lock, flags);
+
+		xenidc_xbgt_channel_handle_stimulus
+		    (channel, xenidc_xbgt_channel_stimulus_pe);
+
+		spin_unlock_irqrestore(&channel->lock, flags);
+	}
+}
+
+void xenidc_xbgt_channel_disconnect
+    (xenidc_xbgt_channel * channel, xenidc_callback * callback) {
+	trace();
+
+	{
+		unsigned long flags;
+
+		spin_lock_irqsave(&channel->lock, flags);
+
+		channel->disconnect_callback = callback;
+
+		xenidc_xbgt_channel_handle_stimulus
+		    (channel, xenidc_xbgt_channel_stimulus_dn);
+
+		spin_unlock_irqrestore(&channel->lock, flags);
+	}
+}
+
+void xenidc_xbgt_channel_exit(xenidc_xbgt_channel * channel)
+{
+	trace();
+
+	(void)xenidc_xbgt_channel_init_or_exit(channel, 1);
+}
+
+static void xenidc_xbgt_channel_register_watch_1(void *data);
+static void xenidc_xbgt_channel_unregister_watch_1(void *data);
+static void xenidc_xbgt_channel_clear_store_1(void *data);
+static void xenidc_xbgt_channel_write_ready_1(void *data);
+static void xenidc_xbgt_channel_write_connected_1(void *data);
+static void xenidc_xbgt_channel_phase_one_connect_1(void *data);
+static void xenidc_xbgt_channel_phase_one_connect_2(xenidc_callback * callback);
+static void xenidc_xbgt_channel_phase_two_connect_1(void *data);
+static void xenidc_xbgt_channel_phase_two_connect_2(xenidc_callback * callback);
+static void xenidc_xbgt_channel_phase_two_disconnect_1(void *data);
+static void xenidc_xbgt_channel_phase_two_disconnect_2
+    (xenidc_callback * callback);
+static void xenidc_xbgt_channel_phase_one_disconnect_1(void *data);
+static void xenidc_xbgt_channel_phase_one_disconnect_2
+    (xenidc_callback * callback);
+
+static int xenidc_xbgt_channel_init_or_exit
+    (xenidc_xbgt_channel * channel, int exit) {
+	trace();
+
+	{
+		int return_value = 0;
+
+		if (exit) {
+			goto EXIT;
+		}
+
+		if ((return_value = xenidc_gnttab_channel_init
+		     (&channel->channel, xenidc_xbgt_channel_protocol_error)
+		    )
+		    != 0) {
+			goto EXIT_NO_GNTTAB_CHANNEL;
+		}
+
+		spin_lock_init(&channel->lock);
+
+		channel->state = xenidc_xbgt_channel_state_i;
+
+		xenidc_work_init
+		    (&channel->register_watch_1_work,
+		     xenidc_xbgt_channel_register_watch_1, channel);
+
+		xenidc_work_init
+		    (&channel->unregister_watch_1_work,
+		     xenidc_xbgt_channel_unregister_watch_1, channel);
+
+		xenidc_work_init
+		    (&channel->clear_store_1_work,
+		     xenidc_xbgt_channel_clear_store_1, channel);
+
+		xenidc_work_init
+		    (&channel->write_ready_1_work,
+		     xenidc_xbgt_channel_write_ready_1, channel);
+
+		xenidc_work_init
+		    (&channel->write_connected_1_work,
+		     xenidc_xbgt_channel_write_connected_1, channel);
+
+		xenidc_work_init
+		    (&channel->phase_one_connect_1_work,
+		     xenidc_xbgt_channel_phase_one_connect_1, channel);
+
+		xenidc_work_init
+		    (&channel->phase_two_connect_1_work,
+		     xenidc_xbgt_channel_phase_two_connect_1, channel);
+
+		xenidc_work_init
+		    (&channel->phase_two_disconnect_1_work,
+		     xenidc_xbgt_channel_phase_two_disconnect_1, channel);
+
+		xenidc_work_init
+		    (&channel->phase_one_disconnect_1_work,
+		     xenidc_xbgt_channel_phase_one_disconnect_1, channel);
+
+		xenidc_callback_init
+		    (&channel->phase_one_connect_request.callback,
+		     xenidc_xbgt_channel_phase_one_connect_2);
+
+		xenidc_callback_init
+		    (&channel->phase_two_connect_request.callback,
+		     xenidc_xbgt_channel_phase_two_connect_2);
+
+		xenidc_callback_init
+		    (&channel->phase_two_disconnect_callback,
+		     xenidc_xbgt_channel_phase_two_disconnect_2);
+
+		xenidc_callback_init
+		    (&channel->phase_one_disconnect_callback,
+		     xenidc_xbgt_channel_phase_one_disconnect_2);
+
+		return 0;
+
+	      EXIT:
+
+		xenidc_gnttab_channel_exit(&channel->channel);
+
+	      EXIT_NO_GNTTAB_CHANNEL:
+
+		return return_value;
+	}
+}
+
+static void xenidc_xbgt_channel_invalid_stimulus
+    (xenidc_xbgt_channel * channel, xenidc_xbgt_channel_stimulus stimulus);
+
+static void xenidc_xbgt_channel_test_other_state(xenidc_xbgt_channel * channel);
+
+static void xenidc_xbgt_channel_register_watch(xenidc_xbgt_channel * channel);
+
+static void xenidc_xbgt_channel_unregister_watch(xenidc_xbgt_channel * channel);
+
+static void xenidc_xbgt_channel_clear_store(xenidc_xbgt_channel * channel);
+
+static void xenidc_xbgt_channel_write_ready(xenidc_xbgt_channel * channel);
+
+static void xenidc_xbgt_channel_write_connected(xenidc_xbgt_channel * channel);
+
+static void xenidc_xbgt_channel_phase_one_connect
+    (xenidc_xbgt_channel * channel);
+
+static void xenidc_xbgt_channel_phase_two_connect
+    (xenidc_xbgt_channel * channel);
+
+static void xenidc_xbgt_channel_phase_two_disconnect
+    (xenidc_xbgt_channel * channel);
+
+static void xenidc_xbgt_channel_phase_one_disconnect
+    (xenidc_xbgt_channel * channel);
+
+static void xenidc_xbgt_channel_complete_disconnect
+    (xenidc_xbgt_channel * channel);
+
+static void xenidc_xbgt_channel_handle_stimulus
+    (xenidc_xbgt_channel * channel, xenidc_xbgt_channel_stimulus stimulus) {
+	trace3
+	    ("xbgt channel %p in state %d received stimulus %d",
+	     channel, channel->state, stimulus);
+
+	switch (channel->state) {
+	case xenidc_xbgt_channel_state_i:
+		/* Interface disconnected.      */
+		/* Gnttab channel disconnected. */
+		/* Local store unknown.         */
+		/* Watch not registered.        */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_cn:
+			channel->state = xenidc_xbgt_channel_state_i_cn;
+			xenidc_xbgt_channel_phase_one_connect(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn:
+		/* Interface connected.                 */
+		/* Gnttab channel phase one connecting. */
+		/* Local store unknown.                 */
+		/* Watch not registered.                */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_dn:
+			channel->state = xenidc_xbgt_channel_state_i_cn_dn;
+			break;
+		case xenidc_xbgt_channel_stimulus_rs:
+			channel->state = xenidc_xbgt_channel_state_i_cn_rs;
+			xenidc_xbgt_channel_register_watch(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_dn:
+		/* Interface disconnecting.            */
+		/* Gnttab channel phase one connecting */
+		/* Local store unknown.                */
+		/* Watch not registered.               */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_rs:
+			channel->state = xenidc_xbgt_channel_state_i_cn_dn_rs;
+			xenidc_xbgt_channel_clear_store(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs:
+		/* Interface connected.                                        */
+		/* Gnttab channel phase one connected and registering watch or */
+		/* Watch registered and gnttab channel phase two disconnecting */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_pe:
+			break;
+		case xenidc_xbgt_channel_stimulus_dn:
+			channel->state = xenidc_xbgt_channel_state_i_cn_rs_dn;
+			break;
+		case xenidc_xbgt_channel_stimulus_od:
+		case xenidc_xbgt_channel_stimulus_or:
+		case xenidc_xbgt_channel_stimulus_oc:
+			break;
+		case xenidc_xbgt_channel_stimulus_rs:
+			channel->state = xenidc_xbgt_channel_state_i_cn_rs_rs;
+			xenidc_xbgt_channel_clear_store(channel);
+			break;
+		case xenidc_xbgt_channel_stimulus_rf:
+			channel->state = xenidc_xbgt_channel_state_i_cn_rs_rf;
+			xenidc_xbgt_channel_clear_store(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_dn_rs:
+		/* Interface disconnecting.           */
+		/* Gnttab channel phase one connected */
+		/* Clearing store.                    */
+		/* Watch not registered.              */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_rs:
+		case xenidc_xbgt_channel_stimulus_rf:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_dn_rs_rs;
+			xenidc_xbgt_channel_phase_one_disconnect(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_dn:
+		/* Interface disconnecting.            */
+		/* Gnttab channel phase one connected. */
+		/* Local store unknown.                */
+		/* Registering watch.                  */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_od:
+		case xenidc_xbgt_channel_stimulus_or:
+		case xenidc_xbgt_channel_stimulus_oc:
+			break;
+		case xenidc_xbgt_channel_stimulus_rs:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_dn_rs;
+			xenidc_xbgt_channel_unregister_watch(channel);
+			break;
+		case xenidc_xbgt_channel_stimulus_rf:
+			channel->state = xenidc_xbgt_channel_state_i_cn_dn_rs;
+			xenidc_xbgt_channel_clear_store(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_rs:
+		/* Interface connected.                */
+		/* Gnttab channel phase one connected. */
+		/* Clearing Store.                     */
+		/* Watch Registered.                   */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_dn:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_dn;
+			break;
+		case xenidc_xbgt_channel_stimulus_od:
+		case xenidc_xbgt_channel_stimulus_or:
+		case xenidc_xbgt_channel_stimulus_oc:
+			break;
+		case xenidc_xbgt_channel_stimulus_rs:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_rs;
+			xenidc_xbgt_channel_test_other_state(channel);
+			break;
+		case xenidc_xbgt_channel_stimulus_rf:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_rf;
+			xenidc_xbgt_channel_unregister_watch(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_rf:
+		/* Interface connected.                */
+		/* Gnttab channel phase one connected. */
+		/* Clearing store.                     */
+		/* Something failed.                   */
+		/* Watch not registered.               */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_dn:
+			channel->state = xenidc_xbgt_channel_state_i_cn_dn_rs;
+			break;
+		case xenidc_xbgt_channel_stimulus_rs:
+		case xenidc_xbgt_channel_stimulus_rf:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rf_rs;
+			xenidc_xbgt_channel_phase_one_disconnect(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_dn_rs_rs:
+		/* Interface disconnecting.               */
+		/* Gnttab channel phase one disconnecting */
+		/* Attempted to clear store.              */
+		/* Watch not registered.                  */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_rs:
+			channel->state = xenidc_xbgt_channel_state_i;
+			xenidc_xbgt_channel_complete_disconnect(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_dn_rs:
+		/* Interface disconnecting.            */
+		/* Gnttab channel phase one connected. */
+		/* Local store unknown.                */
+		/* Unregistering watch.                */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_od:
+		case xenidc_xbgt_channel_stimulus_or:
+		case xenidc_xbgt_channel_stimulus_oc:
+			break;
+		case xenidc_xbgt_channel_stimulus_rs:
+			channel->state = xenidc_xbgt_channel_state_i_cn_dn_rs;
+			xenidc_xbgt_channel_clear_store(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_rs_dn:
+		/* Interface disconnecting.                                          */
+		/* Gnttab channel phase one connected unless ph2 disconnecting below. */
+		/* Clearing Store / writing ready / writing connected / ...          */
+		/* ... ph2 disconnecting                                             */
+		/* Watch Registered.                                                 */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_pe:
+		case xenidc_xbgt_channel_stimulus_od:
+		case xenidc_xbgt_channel_stimulus_or:
+		case xenidc_xbgt_channel_stimulus_oc:
+			break;
+		case xenidc_xbgt_channel_stimulus_rs:
+		case xenidc_xbgt_channel_stimulus_rf:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_dn_rs;
+			xenidc_xbgt_channel_unregister_watch(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_rs_rs:
+		/* Interface connected.                                */
+		/* Gnttab channel phase one connected.                 */
+		/* Store clear.                                        */
+		/* Watch Registered.                                   */
+		/* Testing other state / other state unknown/connected */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_dn:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_dn_rs;
+			xenidc_xbgt_channel_unregister_watch(channel);
+			break;
+		case xenidc_xbgt_channel_stimulus_ou:
+			break;
+		case xenidc_xbgt_channel_stimulus_od:
+		case xenidc_xbgt_channel_stimulus_or:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od;
+			xenidc_xbgt_channel_write_ready(channel);
+			break;
+		case xenidc_xbgt_channel_stimulus_oc:
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_rs_rf:
+		/* Interface connected.                */
+		/* Gnttab channel phase one connected. */
+		/* Unregistering watch.                */
+		/* Something failed.                   */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_dn:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_dn_rs;
+			break;
+		case xenidc_xbgt_channel_stimulus_od:
+		case xenidc_xbgt_channel_stimulus_or:
+		case xenidc_xbgt_channel_stimulus_oc:
+			break;
+		case xenidc_xbgt_channel_stimulus_rs:
+			channel->state = xenidc_xbgt_channel_state_i_cn_rs_rf;
+			xenidc_xbgt_channel_clear_store(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_rf_rs:
+		/* Interface connected.                    */
+		/* Gnttab channel phase one disconnecting. */
+		/* Attempted to clear store.               */
+		/* Something failed.                       */
+		/* Watch not registered.                   */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_dn:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_dn_rs_rs;
+			break;
+		case xenidc_xbgt_channel_stimulus_rs:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rf_rs_rs;
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od:
+		/* Interface connected.                                */
+		/* Gnttab channel phase one connected.                 */
+		/* Writing Ready.                                      */
+		/* Watch Registered.                                   */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_dn:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_dn;
+			break;
+		case xenidc_xbgt_channel_stimulus_od:
+		case xenidc_xbgt_channel_stimulus_or:
+		case xenidc_xbgt_channel_stimulus_oc:
+			break;
+		case xenidc_xbgt_channel_stimulus_rs:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs;
+			xenidc_xbgt_channel_test_other_state(channel);
+			break;
+		case xenidc_xbgt_channel_stimulus_rf:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_rf;
+			xenidc_xbgt_channel_unregister_watch(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_rf_rs_rs:
+		/* Interface connected.                   */
+		/* Gnttab channel phase one disconnected. */
+		/* Attempted to clear store.              */
+		/* Something failed.                      */
+		/* Watch not registered.                  */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_dn:
+			channel->state = xenidc_xbgt_channel_state_i;
+			xenidc_xbgt_channel_complete_disconnect(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs:
+		/* Interface connected.                            */
+		/* Gnttab channel phase one connected.             */
+		/* Ready.                                          */
+		/* Watch registered.                               */
+		/* Testing other state or other state disconnected */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_dn:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_dn_rs;
+			xenidc_xbgt_channel_unregister_watch(channel);
+			break;
+		case xenidc_xbgt_channel_stimulus_od:
+			break;
+		case xenidc_xbgt_channel_stimulus_or:
+		case xenidc_xbgt_channel_stimulus_oc:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or;
+			xenidc_xbgt_channel_write_connected(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or:
+		/* Interface connected.                            */
+		/* Gnttab channel phase one connected.             */
+		/* Writing Connected.                              */
+		/* Watch registered.                               */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_dn:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_dn;
+			break;
+		case xenidc_xbgt_channel_stimulus_od:
+		case xenidc_xbgt_channel_stimulus_or:
+		case xenidc_xbgt_channel_stimulus_oc:
+			break;
+		case xenidc_xbgt_channel_stimulus_rs:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs;
+			xenidc_xbgt_channel_test_other_state(channel);
+			break;
+		case xenidc_xbgt_channel_stimulus_rf:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_rf;
+			xenidc_xbgt_channel_unregister_watch(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs:
+		/* Interface connected.                            */
+		/* Gnttab channel phase one connected.             */
+		/* Connected.                                      */
+		/* Watch registered.                               */
+		/* Testing other state / other state ready.        */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_dn:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_dn_rs;
+			xenidc_xbgt_channel_unregister_watch(channel);
+			break;
+		case xenidc_xbgt_channel_stimulus_od:
+			channel->state = xenidc_xbgt_channel_state_i_cn_rs_rs;
+			xenidc_xbgt_channel_clear_store(channel);
+			break;
+		case xenidc_xbgt_channel_stimulus_or:
+			break;
+		case xenidc_xbgt_channel_stimulus_oc:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs_oc;
+			xenidc_xbgt_channel_phase_two_connect(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs_oc:
+		/* Interface connected.                 */
+		/* Gnttab channel phase two connecting. */
+		/* Connected.                           */
+		/* Watch registered.                    */
+		/* Other side connected.                */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_pe:
+			/* Phase two disconnect then go around. */
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs_oc_pe;
+			break;
+		case xenidc_xbgt_channel_stimulus_dn:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs_oc_dn;
+			break;
+		case xenidc_xbgt_channel_stimulus_od:
+		case xenidc_xbgt_channel_stimulus_or:
+		case xenidc_xbgt_channel_stimulus_oc:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs_oc_pe;
+			break;
+		case xenidc_xbgt_channel_stimulus_rs:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs_oc_rs;
+			break;
+		case xenidc_xbgt_channel_stimulus_rf:
+			/* Maybe we picked up stale state from the store. Go around. */
+			channel->state = xenidc_xbgt_channel_state_i_cn_rs_rs;
+			xenidc_xbgt_channel_clear_store(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs_oc_pe:
+		/* Interface connected.                 */
+		/* Gnttab channel phase two connecting. */
+		/* Connected.                           */
+		/* Watch registered.                    */
+		/* Protocol error or glitch.            */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_pe:
+			break;
+		case xenidc_xbgt_channel_stimulus_dn:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs_oc_dn;
+			break;
+		case xenidc_xbgt_channel_stimulus_od:
+		case xenidc_xbgt_channel_stimulus_or:
+		case xenidc_xbgt_channel_stimulus_oc:
+			break;
+		case xenidc_xbgt_channel_stimulus_rs:
+			channel->state = xenidc_xbgt_channel_state_i_cn_rs;
+			xenidc_xbgt_channel_phase_two_disconnect(channel);
+			break;
+		case xenidc_xbgt_channel_stimulus_rf:
+			channel->state = xenidc_xbgt_channel_state_i_cn_rs_rs;
+			xenidc_xbgt_channel_clear_store(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs_oc_dn:
+		/* Interface disconnecting.             */
+		/* Gnttab channel phase two connecting. */
+		/* Connected.                           */
+		/* Watch registered.                    */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_pe:
+		case xenidc_xbgt_channel_stimulus_od:
+		case xenidc_xbgt_channel_stimulus_or:
+		case xenidc_xbgt_channel_stimulus_oc:
+			break;
+		case xenidc_xbgt_channel_stimulus_rs:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_dn;
+			xenidc_xbgt_channel_phase_two_disconnect(channel);
+			break;
+		case xenidc_xbgt_channel_stimulus_rf:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_dn_rs;
+			xenidc_xbgt_channel_unregister_watch(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	case xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs_oc_rs:
+		/* Interface connected.                */
+		/* Gnttab channel phase two connected. */
+		/* Connected.                          */
+		/* Watch registered.                   */
+		/* Other side connected.               */
+		/* Totally happy.                      */
+		switch (stimulus) {
+		case xenidc_xbgt_channel_stimulus_pe:
+			channel->state = xenidc_xbgt_channel_state_i_cn_rs;
+			xenidc_xbgt_channel_phase_two_disconnect(channel);
+			break;
+		case xenidc_xbgt_channel_stimulus_dn:
+			channel->state =
+			    xenidc_xbgt_channel_state_i_cn_rs_rs_dn;
+			xenidc_xbgt_channel_phase_two_disconnect(channel);
+			break;
+		case xenidc_xbgt_channel_stimulus_od:
+		case xenidc_xbgt_channel_stimulus_or:
+		case xenidc_xbgt_channel_stimulus_oc:
+			channel->state = xenidc_xbgt_channel_state_i_cn_rs;
+			xenidc_xbgt_channel_phase_two_disconnect(channel);
+			break;
+		default:
+			xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+			break;
+		}
+		break;
+	default:
+		xenidc_xbgt_channel_invalid_stimulus(channel, stimulus);
+		break;
+	}
+}
+
+static void xenidc_xbgt_channel_invalid_stimulus
+    (xenidc_xbgt_channel * channel, xenidc_xbgt_channel_stimulus stimulus) {
+	trace();
+
+	printk
+	    (KERN_ERR "xenidc: xbgt channel %p in state %d"
+	     "received invalid stimulus %d", channel, channel->state, stimulus);
+}
+
+static void xenidc_xbgt_channel_test_other_state(xenidc_xbgt_channel * channel) {
+	trace();
+
+	switch (channel->other_state) {
+	case xenidc_xbgt_channel_other_state_unknown:
+		xenidc_xbgt_channel_handle_stimulus
+		    (channel, xenidc_xbgt_channel_stimulus_ou);
+		break;
+	case xenidc_xbgt_channel_other_state_disconnected:
+		xenidc_xbgt_channel_handle_stimulus
+		    (channel, xenidc_xbgt_channel_stimulus_od);
+		break;
+	case xenidc_xbgt_channel_other_state_ready:
+		xenidc_xbgt_channel_handle_stimulus
+		    (channel, xenidc_xbgt_channel_stimulus_or);
+		break;
+	case xenidc_xbgt_channel_other_state_connected:
+		xenidc_xbgt_channel_handle_stimulus
+		    (channel, xenidc_xbgt_channel_stimulus_oc);
+		break;
+	}
+}
+
+static void xenidc_xbgt_channel_register_watch(xenidc_xbgt_channel * channel) {
+	trace();
+
+	channel->other_state = xenidc_xbgt_channel_other_state_unknown;
+
+	(void)xenidc_work_schedule(&channel->register_watch_1_work);
+}
+
+static void xenidc_xbgt_channel_register_watch_1(void *data)
+{
+	trace();
+
+	{
+		xenidc_xbgt_channel *channel = (xenidc_xbgt_channel *) data;
+
+		channel->watch.node = channel->remote_path;
+		channel->watch.callback = xenidc_xbgt_channel_watch;
+
+		{
+			int return_value =
+			    register_xenbus_watch(&channel->watch);
+
+			unsigned long flags;
+
+			spin_lock_irqsave(&channel->lock, flags);
+
+			if (return_value == 0) {
+				xenidc_xbgt_channel_handle_stimulus
+				    (channel, xenidc_xbgt_channel_stimulus_rs);
+			} else {
+				xenidc_xbgt_channel_handle_stimulus
+				    (channel, xenidc_xbgt_channel_stimulus_rf);
+			}
+
+			spin_unlock_irqrestore(&channel->lock, flags);
+		}
+	}
+}
+
+static void xenidc_xbgt_channel_unregister_watch(xenidc_xbgt_channel * channel) {
+	trace();
+
+	(void)xenidc_work_schedule(&channel->unregister_watch_1_work);
+}
+
+static void xenidc_xbgt_channel_unregister_watch_1(void *data)
+{
+	trace();
+
+	{
+		xenidc_xbgt_channel *channel = (xenidc_xbgt_channel *) data;
+
+		unregister_xenbus_watch(&channel->watch);
+
+		{
+			unsigned long flags;
+
+			spin_lock_irqsave(&channel->lock, flags);
+
+			xenidc_xbgt_channel_handle_stimulus
+			    (channel, xenidc_xbgt_channel_stimulus_rs);
+
+			spin_unlock_irqrestore(&channel->lock, flags);
+		}
+	}
+}
+
+static void xenidc_xbgt_channel_clear_store(xenidc_xbgt_channel * channel)
+{
+	trace();
+
+	(void)xenidc_work_schedule(&channel->clear_store_1_work);
+}
+
+static void xenidc_xbgt_channel_clear_store_1(void *data)
+{
+	trace();
+
+	{
+		xenidc_xbgt_channel *channel = (xenidc_xbgt_channel *) data;
+
+		struct xenbus_transaction *transaction;
+
+	      AGAIN:
+
+		transaction = xenbus_transaction_start();
+
+		if (IS_ERR(transaction)) {
+			trace0("error starting transaction");
+
+			goto ERROR;
+		}
+
+		{
+			int error =
+			    xenbus_rm(transaction, channel->local_path,
+				      "ready");
+
+			if (error) {
+				trace0("error removing ready field from store");
+
+				goto ABORT_TRANSACTION;
+			}
+		}
+
+		{
+			int error =
+			    xenbus_rm(transaction, channel->local_path,
+				      "event-channel");
+
+			if (error) {
+				trace0
+				    ("error removing event-channel field from store");
+
+				goto ABORT_TRANSACTION;
+			}
+		}
+
+		{
+			int error =
+			    xenbus_rm(transaction, channel->local_path,
+				      "ring-reference");
+
+			if (error) {
+				trace0
+				    ("error removing ring-reference field from store");
+
+				goto ABORT_TRANSACTION;
+			}
+		}
+
+		{
+			int error =
+			    xenbus_transaction_end(transaction,
+						   0 /* commit */ );
+
+			if (error != 0) {
+				if (error == -EAGAIN) {
+					goto AGAIN;
+				} else {
+					trace0("error committing transaction");
+
+					goto ERROR;
+				}
+			}
+		}
+
+		{
+			unsigned long flags;
+
+			spin_lock_irqsave(&channel->lock, flags);
+
+			xenidc_xbgt_channel_handle_stimulus
+			    (channel, xenidc_xbgt_channel_stimulus_rs);
+
+			spin_unlock_irqrestore(&channel->lock, flags);
+		}
+
+		return;
+
+	      ABORT_TRANSACTION:
+
+		xenbus_transaction_end(transaction, 1 /* abort */ );
+
+	      ERROR:
+
+		{
+			unsigned long flags;
+
+			spin_lock_irqsave(&channel->lock, flags);
+
+			xenidc_xbgt_channel_handle_stimulus
+			    (channel, xenidc_xbgt_channel_stimulus_rf);
+
+			spin_unlock_irqrestore(&channel->lock, flags);
+		}
+	}
+}
+
+static void xenidc_xbgt_channel_write_ready(xenidc_xbgt_channel * channel)
+{
+	trace();
+
+	(void)xenidc_work_schedule(&channel->write_ready_1_work);
+}
+
+static void xenidc_xbgt_channel_write_ready_1(void *data)
+{
+	trace();
+
+	{
+		xenidc_xbgt_channel *channel = (xenidc_xbgt_channel *) data;
+
+		struct xenbus_transaction *transaction;
+
+	      AGAIN:
+
+		transaction = xenbus_transaction_start();
+
+		if (IS_ERR(transaction)) {
+			trace0("error starting transaction");
+
+			goto ERROR;
+		}
+
+		{
+			int error = xenbus_write(transaction,
+						 channel->local_path,
+						 "ready",
+						 "1");
+
+			if (error) {
+				trace0("error writing ready to store");
+
+				goto ABORT_TRANSACTION;
+			}
+		}
+
+		{
+			int error =
+			    xenbus_transaction_end(transaction,
+						   0 /* commit */ );
+
+			if (error != 0) {
+				if (error == -EAGAIN) {
+					goto AGAIN;
+				} else {
+					trace0("error committing transaction");
+
+					goto ERROR;
+				}
+			}
+		}
+
+		{
+			unsigned long flags;
+
+			spin_lock_irqsave(&channel->lock, flags);
+
+			xenidc_xbgt_channel_handle_stimulus
+			    (channel, xenidc_xbgt_channel_stimulus_rs);
+
+			spin_unlock_irqrestore(&channel->lock, flags);
+		}
+
+		return;
+
+	      ABORT_TRANSACTION:
+
+		xenbus_transaction_end(transaction, 1 /* abort */ );
+
+	      ERROR:
+
+		{
+			unsigned long flags;
+
+			spin_lock_irqsave(&channel->lock, flags);
+
+			xenidc_xbgt_channel_handle_stimulus
+			    (channel, xenidc_xbgt_channel_stimulus_rf);
+
+			spin_unlock_irqrestore(&channel->lock, flags);
+		}
+	}
+}
+
+static void xenidc_xbgt_channel_write_connected(xenidc_xbgt_channel * channel) {
+	trace();
+
+	(void)xenidc_work_schedule(&channel->write_connected_1_work);
+}
+
+static void xenidc_xbgt_channel_write_connected_1(void *data)
+{
+	trace();
+
+	{
+		xenidc_xbgt_channel *channel = (xenidc_xbgt_channel *) data;
+
+		struct xenbus_transaction *transaction;
+
+		xenidc_gnttab_channel_reset_ring(&channel->channel);
+
+	      AGAIN:
+
+		transaction = xenbus_transaction_start();
+
+		if (IS_ERR(transaction)) {
+			trace0("error starting transaction");
+
+			goto ERROR;
+		}
+
+		{
+			int error = xenbus_printf(transaction,
+						  channel->local_path,
+						  "ring-reference",
+						  "%u",
+						  channel->
+						  phase_one_connect_request.
+						  send_ring_ref);
+
+			if (error) {
+				trace0("error writing ring-reference to store");
+
+				goto ABORT_TRANSACTION;
+			}
+		}
+
+		{
+			int error = xenbus_printf(transaction,
+						  channel->local_path,
+						  "event-channel",
+						  "%u",
+						  channel->
+						  phase_one_connect_request.
+						  send_event_channel);
+
+			if (error) {
+				trace0("error writing event-channel to store");
+
+				goto ABORT_TRANSACTION;
+			}
+		}
+
+		{
+			int error =
+			    xenbus_transaction_end(transaction,
+						   0 /* commit */ );
+
+			if (error != 0) {
+				if (error == -EAGAIN) {
+					goto AGAIN;
+				} else {
+					trace0("error committing transaction");
+
+					goto ERROR;
+				}
+			}
+		}
+
+		{
+			unsigned long flags;
+
+			spin_lock_irqsave(&channel->lock, flags);
+
+			xenidc_xbgt_channel_handle_stimulus
+			    (channel, xenidc_xbgt_channel_stimulus_rs);
+
+			spin_unlock_irqrestore(&channel->lock, flags);
+		}
+
+		return;
+
+	      ABORT_TRANSACTION:
+
+		xenbus_transaction_end(transaction, 1 /* abort */ );
+
+	      ERROR:
+
+		{
+			unsigned long flags;
+
+			spin_lock_irqsave(&channel->lock, flags);
+
+			xenidc_xbgt_channel_handle_stimulus
+			    (channel, xenidc_xbgt_channel_stimulus_rf);
+
+			spin_unlock_irqrestore(&channel->lock, flags);
+		}
+	}
+}
+
+static void xenidc_xbgt_channel_phase_one_connect(xenidc_xbgt_channel * channel) {
+	trace();
+
+	channel->phase_one_connect_request.remote_domain_id =
+	    channel->remote_domain_id;
+
+	(void)xenidc_work_schedule(&channel->phase_one_connect_1_work);
+}
+
+static void xenidc_xbgt_channel_phase_one_connect_1(void *data)
+{
+	trace();
+
+	{
+		xenidc_xbgt_channel *channel = (xenidc_xbgt_channel *) data;
+
+		xenidc_gnttab_channel_phase_one_connect
+		    (&channel->channel, &channel->phase_one_connect_request);
+	}
+}
+
+static void xenidc_xbgt_channel_phase_one_connect_2(xenidc_callback * callback) {
+	trace();
+
+	{
+		xenidc_xbgt_channel *channel = container_of
+		    (xenidc_gnttab_channel_phase_one_connect_request_callback_to
+		     (callback),
+		     xenidc_xbgt_channel,
+		     phase_one_connect_request);
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&channel->lock, flags);
+
+		xenidc_xbgt_channel_handle_stimulus
+		    (channel, xenidc_xbgt_channel_stimulus_rs);
+
+		spin_unlock_irqrestore(&channel->lock, flags);
+	}
+}
+
+static void xenidc_xbgt_channel_phase_two_connect(xenidc_xbgt_channel * channel) {
+	trace();
+
+	channel->phase_two_connect_request.remote_domain_id =
+	    channel->remote_domain_id;
+	channel->phase_two_connect_request.recv_ring_ref =
+	    channel->ready_ring_reference;
+	channel->phase_two_connect_request.recv_event_channel =
+	    channel->ready_event_channel;
+
+	(void)xenidc_work_schedule(&channel->phase_two_connect_1_work);
+}
+
+static void xenidc_xbgt_channel_phase_two_connect_1(void *data)
+{
+	trace();
+
+	{
+		xenidc_xbgt_channel *channel = (xenidc_xbgt_channel *) data;
+
+		xenidc_gnttab_channel_phase_two_connect
+		    (&channel->channel, &channel->phase_two_connect_request);
+	}
+}
+
+static void xenidc_xbgt_channel_phase_two_connect_2(xenidc_callback * callback) {
+	trace();
+
+	{
+		xenidc_xbgt_channel *channel = container_of
+		    (xenidc_gnttab_channel_phase_two_connect_request_callback_to
+		     (callback),
+		     xenidc_xbgt_channel,
+		     phase_two_connect_request);
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&channel->lock, flags);
+
+		if (xenidc_callback_query_error(callback) ==
+		    XENIDC_ERROR_SUCCESS) {
+			xenidc_xbgt_channel_handle_stimulus(channel,
+							    xenidc_xbgt_channel_stimulus_rs);
+		} else {
+			xenidc_xbgt_channel_handle_stimulus
+			    (channel, xenidc_xbgt_channel_stimulus_rf);
+		}
+
+		spin_unlock_irqrestore(&channel->lock, flags);
+	}
+}
+
+static void xenidc_xbgt_channel_phase_two_disconnect
+    (xenidc_xbgt_channel * channel) {
+	trace();
+
+	(void)xenidc_work_schedule(&channel->phase_two_disconnect_1_work);
+}
+
+static void xenidc_xbgt_channel_phase_two_disconnect_1(void *data)
+{
+	trace();
+
+	{
+		xenidc_xbgt_channel *channel = (xenidc_xbgt_channel *) data;
+
+		xenidc_gnttab_channel_phase_two_disconnect
+		    (&channel->channel,
+		     &channel->phase_two_disconnect_callback);
+	}
+}
+
+static void xenidc_xbgt_channel_phase_two_disconnect_2
+    (xenidc_callback * callback) {
+	trace();
+
+	{
+		xenidc_xbgt_channel *channel = container_of
+		    (callback, xenidc_xbgt_channel,
+		     phase_two_disconnect_callback);
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&channel->lock, flags);
+
+		xenidc_xbgt_channel_handle_stimulus
+		    (channel, xenidc_xbgt_channel_stimulus_rs);
+
+		spin_unlock_irqrestore(&channel->lock, flags);
+	}
+}
+
+static void xenidc_xbgt_channel_phase_one_disconnect
+    (xenidc_xbgt_channel * channel) {
+	trace();
+
+	(void)xenidc_work_schedule(&channel->phase_one_disconnect_1_work);
+}
+
+static void xenidc_xbgt_channel_phase_one_disconnect_1(void *data)
+{
+	trace();
+
+	{
+		xenidc_xbgt_channel *channel = (xenidc_xbgt_channel *) data;
+
+		xenidc_gnttab_channel_phase_one_disconnect
+		    (&channel->channel,
+		     &channel->phase_one_disconnect_callback);
+	}
+}
+
+static void xenidc_xbgt_channel_phase_one_disconnect_2
+    (xenidc_callback * callback) {
+	trace();
+
+	{
+		xenidc_xbgt_channel *channel = container_of
+		    (callback, xenidc_xbgt_channel,
+		     phase_one_disconnect_callback);
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&channel->lock, flags);
+
+		xenidc_xbgt_channel_handle_stimulus
+		    (channel, xenidc_xbgt_channel_stimulus_rs);
+
+		spin_unlock_irqrestore(&channel->lock, flags);
+	}
+}
+
+static void xenidc_xbgt_channel_complete_disconnect
+    (xenidc_xbgt_channel * channel) {
+	trace();
+
+	xenidc_callback_success(channel->disconnect_callback);
+}
diff -r 47edf571a62d -r 1786d40e66b8 linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_xbgt_channel_enumeration.dot
--- /dev/null	Sun Nov 20 17:44:51 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_xbgt_channel_enumeration.dot	Sun Nov 20 17:45:04 2005
@@ -0,0 +1,109 @@
+digraph enumeration {
+size="7,7"
+
+i[style=filled,fillcolor=green]
+i->i_cn[label="cn\nphase_one_connect"];
+
+i_cn[style=filled,fillcolor=green]
+i_cn->i_cn_dn[label="dn"];
+i_cn->i_cn_rs[label="rs\nregister_watch"];
+
+i_cn_dn[style=filled,fillcolor=orange]
+i_cn_dn->i_cn_dn_rs[label="rs\nclear_store"];
+
+i_cn_rs[style=filled,fillcolor=green]
+i_cn_rs->i_cn_rs_dn[label="dn"];
+i_cn_rs->i_cn_rs[label="pe/od/or/oc"];
+i_cn_rs->i_cn_rs_rs[label="rs\nclear_store"];
+i_cn_rs->i_cn_rs_rf[label="rf\nclear_store"];
+
+i_cn_dn_rs[style=filled,fillcolor=orange]
+i_cn_dn_rs->i_cn_dn_rs_rs[label="rs/rf\nphase_one_disconnect"];
+
+i_cn_rs_dn[style=filled,fillcolor=orange]
+i_cn_rs_dn->i_cn_rs_dn[label="od/or/oc"];
+i_cn_rs_dn->i_cn_rs_dn_rs[label="rs\nunregister_watch"];
+i_cn_rs_dn->i_cn_dn_rs[label="rf\nclear_store"];
+
+i_cn_rs_rs[style=filled,fillcolor=green]
+i_cn_rs_rs->i_cn_rs_rs_dn[label="dn"];
+i_cn_rs_rs->i_cn_rs_rs[label="od/or/oc"];
+i_cn_rs_rs->i_cn_rs_rs_rs[label="rs\ntest_other_state"];
+i_cn_rs_rs->i_cn_rs_rs_rf[label="rf\nunregister_watch"];
+
+i_cn_rs_rf[style=filled,fillcolor=red]
+i_cn_rs_rf->i_cn_dn_rs[label="dn"];
+i_cn_rs_rf->i_cn_rs_rf_rs[label="rs/rf\nphase_one_disconnect"];
+
+i_cn_dn_rs_rs[style=filled,fillcolor=orange]
+i_cn_dn_rs_rs->i[label="rs\ncomplete_disconnect"];
+
+i_cn_rs_dn_rs[style=filled,fillcolor=orange]
+i_cn_rs_dn_rs->i_cn_rs_dn_rs[label="od/or/oc"];
+i_cn_rs_dn_rs->i_cn_dn_rs[label="rs\nclear_store"];
+
+i_cn_rs_rs_dn[style=filled,fillcolor=orange]
+i_cn_rs_rs_dn->i_cn_rs_rs_dn[label="od/or/oc"];
+i_cn_rs_rs_dn->i_cn_rs_dn_rs[label="rs/rf\nunregister_watch"];
+
+i_cn_rs_rs_rs[style=filled,fillcolor=green]
+i_cn_rs_rs_rs->i_cn_rs_dn_rs[label="dn\nunregister_watch"];
+i_cn_rs_rs_rs->i_cn_rs_rs_rs[label="ou/oc"];
+i_cn_rs_rs_rs->i_cn_rs_rs_rs_od[label="od/or\nwrite_ready"];
+
+i_cn_rs_rs_rf[style=filled,fillcolor=red]
+i_cn_rs_rs_rf->i_cn_rs_dn_rs[label="dn"];
+i_cn_rs_rs_rf->i_cn_rs_rs_rf[label="od/or/oc"];
+i_cn_rs_rs_rf->i_cn_rs_rf[label="rs\nclear_store"];
+
+i_cn_rs_rf_rs[style=filled,fillcolor=red]
+i_cn_rs_rf_rs->i_cn_dn_rs_rs[label="dn"];
+i_cn_rs_rf_rs->i_cn_rs_rf_rs_rs[label="rs"];
+
+i_cn_rs_rs_rs_od[style=filled,fillcolor=green]
+i_cn_rs_rs_rs_od->i_cn_rs_rs_dn[label="dn"];
+i_cn_rs_rs_rs_od->i_cn_rs_rs_rs_od[label="od/or/oc"];
+i_cn_rs_rs_rs_od->i_cn_rs_rs_rs_od_rs[label="rs\ntest_other_state"];
+i_cn_rs_rs_rs_od->i_cn_rs_rs_rf[label="rf\nunregister_watch"];
+
+i_cn_rs_rf_rs_rs[style=filled,fillcolor=red]
+i_cn_rs_rf_rs_rs->i[label="dn\ncomplete_disconnect"];
+
+i_cn_rs_rs_rs_od_rs[style=filled,fillcolor=green]
+i_cn_rs_rs_rs_od_rs->i_cn_rs_dn_rs[label="dn\nunregister_watch"];
+i_cn_rs_rs_rs_od_rs->i_cn_rs_rs_rs_od_rs[label="od"];
+i_cn_rs_rs_rs_od_rs->i_cn_rs_rs_rs_od_rs_or[label="or/oc\nwrite_connected"];
+
+i_cn_rs_rs_rs_od_rs_or[style=filled,fillcolor=green]
+i_cn_rs_rs_rs_od_rs_or->i_cn_rs_rs_dn[label="dn"];
+i_cn_rs_rs_rs_od_rs_or->i_cn_rs_rs_rs_od_rs_or[label="od/or/oc"];
+i_cn_rs_rs_rs_od_rs_or->i_cn_rs_rs_rs_od_rs_or_rs[label="rs\ntest_other_state"];
+i_cn_rs_rs_rs_od_rs_or->i_cn_rs_rs_rf[label="rf\nunregister_watch"];
+
+i_cn_rs_rs_rs_od_rs_or_rs[style=filled,fillcolor=green]
+i_cn_rs_rs_rs_od_rs_or_rs->i_cn_rs_dn_rs[label="dn\nunregister_watch"];
+i_cn_rs_rs_rs_od_rs_or_rs->i_cn_rs_rs[label="od\nclear_store"];
+i_cn_rs_rs_rs_od_rs_or_rs->i_cn_rs_rs_rs_od_rs_or_rs[label="or"];
+i_cn_rs_rs_rs_od_rs_or_rs->i_cn_rs_rs_rs_od_rs_or_rs_oc[label="oc\nphase_two_connect"];
+
+i_cn_rs_rs_rs_od_rs_or_rs_oc[style=filled,fillcolor=green]
+i_cn_rs_rs_rs_od_rs_or_rs_oc->i_cn_rs_rs_rs_od_rs_or_rs_oc_pe[label="pe/od/or/oc"];
+i_cn_rs_rs_rs_od_rs_or_rs_oc->i_cn_rs_rs_rs_od_rs_or_rs_oc_dn[label="dn"];
+i_cn_rs_rs_rs_od_rs_or_rs_oc->i_cn_rs_rs_rs_od_rs_or_rs_oc_rs[label="rs"];
+i_cn_rs_rs_rs_od_rs_or_rs_oc->i_cn_rs_rs[label="rf\nclear_store"];
+
+i_cn_rs_rs_rs_od_rs_or_rs_oc_pe[style=filled,fillcolor=blue]
+i_cn_rs_rs_rs_od_rs_or_rs_oc_pe->i_cn_rs_rs_rs_od_rs_or_rs_oc_pe[label="pe/od/or/oc"]
+i_cn_rs_rs_rs_od_rs_or_rs_oc_pe->i_cn_rs_rs_rs_od_rs_or_rs_oc_dn[label="dn"]
+i_cn_rs_rs_rs_od_rs_or_rs_oc_pe->i_cn_rs[label="rs\nphase_two_disconnect"]
+i_cn_rs_rs_rs_od_rs_or_rs_oc_pe->i_cn_rs_rs[label="rf\nclear_store"]
+
+i_cn_rs_rs_rs_od_rs_or_rs_oc_dn[style=filled,fillcolor=orange]
+i_cn_rs_rs_rs_od_rs_or_rs_oc_dn->i_cn_rs_rs_rs_od_rs_or_rs_oc_dn[label="pe/od/or/oc"]
+i_cn_rs_rs_rs_od_rs_or_rs_oc_dn->i_cn_rs_rs_dn[label="rs\nphase_two_disconnect"]
+i_cn_rs_rs_rs_od_rs_or_rs_oc_dn->i_cn_rs_dn_rs[label="rf\nunregister_watch"]
+
+i_cn_rs_rs_rs_od_rs_or_rs_oc_rs[style=filled,fillcolor=green]
+i_cn_rs_rs_rs_od_rs_or_rs_oc_rs->i_cn_rs[label="pe/od/or/oc\nphase_two_disconnect"]
+i_cn_rs_rs_rs_od_rs_or_rs_oc_rs->i_cn_rs_rs_dn[label="dn\nphase_two_disconnect"]
+}
diff -r 47edf571a62d -r 1786d40e66b8 linux-2.6-xen-sparse/include/asm-xen/xenidc_xbgt_channel.h
--- /dev/null	Sun Nov 20 17:44:51 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenidc_xbgt_channel.h	Sun Nov 20 17:45:04 2005
@@ -0,0 +1,144 @@
+/*****************************************************************************/
+/* This is a class which uses a xenidc_gnttab_channel (grant-tables based    */
+/* message channel class) and xenbus to implement an interdomain message     */
+/* channel with grant-tables based message transfer and xenbus based         */
+/* bring-up and tear-down handshaking.                                       */
+/* This class is used in the implementation of the xenidc_endpoint class.    */
+/*                                                                           */
+/* Copyright (c) 2005 Harry Butterworth IBM Corporation                      */
+/*                                                                           */
+/* This program is free software; you can redistribute it and/or modify it   */
+/* under the terms of the GNU General Public License as published by the     */
+/* Free Software Foundation; either version 2 of the License, or (at your    */
+/* option) any later version.                                                */
+/*                                                                           */
+/* This program is distributed in the hope that it will be useful, but       */
+/* WITHOUT ANY WARRANTY; without even the implied warranty of                */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General */
+/* Public License for more details.                                          */
+/*                                                                           */
+/* You should have received a copy of the GNU General Public License along   */
+/* with this program; if not, write to the Free Software Foundation, Inc.,   */
+/* 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                   */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef _XENIDC_XBGT_CHANNEL_H
+#define _XENIDC_XBGT_CHANNEL_H
+
+#include <asm-xen/xenbus.h>
+#include <asm-xen/xenidc_gnttab_channel.h>
+
+typedef struct xenidc_xbgt_channel_struct xenidc_xbgt_channel;
+
+typedef enum {
+	xenidc_xbgt_channel_state_i,
+	xenidc_xbgt_channel_state_i_cn,
+	xenidc_xbgt_channel_state_i_cn_dn,
+	xenidc_xbgt_channel_state_i_cn_rs,
+	xenidc_xbgt_channel_state_i_cn_dn_rs,
+	xenidc_xbgt_channel_state_i_cn_rs_dn,
+	xenidc_xbgt_channel_state_i_cn_rs_rs,
+	xenidc_xbgt_channel_state_i_cn_rs_rf,
+	xenidc_xbgt_channel_state_i_cn_dn_rs_rs,
+	xenidc_xbgt_channel_state_i_cn_rs_dn_rs,
+	xenidc_xbgt_channel_state_i_cn_rs_rs_dn,
+	xenidc_xbgt_channel_state_i_cn_rs_rs_rs,
+	xenidc_xbgt_channel_state_i_cn_rs_rs_rf,
+	xenidc_xbgt_channel_state_i_cn_rs_rf_rs,
+	xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od,
+	xenidc_xbgt_channel_state_i_cn_rs_rf_rs_rs,
+	xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs,
+	xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or,
+	xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs,
+	xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs_oc,
+	xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs_oc_pe,
+	xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs_oc_dn,
+	xenidc_xbgt_channel_state_i_cn_rs_rs_rs_od_rs_or_rs_oc_rs
+} xenidc_xbgt_channel_state;
+
+typedef enum {
+	xenidc_xbgt_channel_other_state_unknown,
+	xenidc_xbgt_channel_other_state_disconnected,
+	xenidc_xbgt_channel_other_state_ready,
+	xenidc_xbgt_channel_other_state_connected
+} xenidc_xbgt_channel_other_state;
+
+struct xenidc_xbgt_channel_struct {
+	xenidc_gnttab_channel channel;
+
+	struct xenbus_watch watch;
+
+	spinlock_t lock;
+
+	xenidc_xbgt_channel_state state;
+	xenidc_xbgt_channel_other_state other_state;
+
+	const char *local_path;
+	const char *remote_path;
+	domid_t remote_domain_id;
+
+	xenidc_callback *disconnect_callback;
+
+	int ready_ring_reference;
+	int ready_event_channel;
+
+	xenidc_work register_watch_1_work;
+	xenidc_work unregister_watch_1_work;
+	xenidc_work clear_store_1_work;
+	xenidc_work write_ready_1_work;
+	xenidc_work write_connected_1_work;
+	xenidc_work phase_one_connect_1_work;
+	xenidc_work phase_two_connect_1_work;
+	xenidc_work phase_two_disconnect_1_work;
+	xenidc_work phase_one_disconnect_1_work;
+
+	xenidc_gnttab_channel_phase_one_connect_request
+	    phase_one_connect_request;
+	xenidc_gnttab_channel_phase_two_connect_request
+	    phase_two_connect_request;
+
+	xenidc_callback phase_two_disconnect_callback;
+	xenidc_callback phase_one_disconnect_callback;
+};
+
+/* This class implements the xenidc_channel interface. */
+
+static inline xenidc_channel *xenidc_xbgt_channel_to_channel
+    (xenidc_xbgt_channel * channel) {
+	return xenidc_gnttab_channel_to_channel(&channel->channel);
+}
+
+/* Cast from base class. */
+
+static inline xenidc_xbgt_channel *xenidc_xbgt_channel_gnttab_channel_to
+    (xenidc_gnttab_channel * gnttab_channel) {
+	return container_of(gnttab_channel, xenidc_xbgt_channel, channel);
+}
+
+/* Cast from base class. */
+
+static inline xenidc_xbgt_channel *xenidc_xbgt_channel_channel_to
+    (xenidc_channel * channel) {
+	return xenidc_xbgt_channel_gnttab_channel_to
+	    (xenidc_gnttab_channel_channel_to(channel));
+}
+
+extern int xenidc_xbgt_channel_init(xenidc_xbgt_channel * channel);
+
+/* xenidc_xbgt_channel_connect called to connect the channel.  Passed the    */
+/* xenbus specific addressing information of the remote domain and device.   */
+
+extern void xenidc_xbgt_channel_connect
+    (xenidc_xbgt_channel * channel,
+     const char *local_path, const char *remote_path, domid_t remote_domain_id);
+
+/* Called to disconnect.  Callback completes after base channel class has    */
+/* disconnected its client.                                                  */
+
+extern void xenidc_xbgt_channel_disconnect
+    (xenidc_xbgt_channel * channel, xenidc_callback * callback);
+
+extern void xenidc_xbgt_channel_exit(xenidc_xbgt_channel * channel);
+
+#endif

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-11-21 13:19 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-11-21 13:19 [PATCH][8/17] USB virt 2.6 split driver---xbgt channel harry

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.