All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH][9/17] USB virt 2.6 split driver---gateway
@ 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: 230 bytes --]

This patch implements xenidc_gateway which uses a xenidc_channel to
implement an interdomain service for sending messages and transactions
between domains bi-directionally.

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


[-- Attachment #2: p9-gateway.patch --]
[-- Type: text/x-patch, Size: 77091 bytes --]

diff -r 1786d40e66b8 -r b4eca2889318 linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile
--- a/linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile	Sun Nov 20 17:45:04 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/Makefile	Sun Nov 20 17:45:16 2005
@@ -12,3 +12,6 @@
 xenidc-objs += xenidc_vaddress.o
 xenidc-objs += xenidc_gnttab_channel.o
 xenidc-objs += xenidc_xbgt_channel.o
+xenidc-objs += xenidc_gateway.o
+xenidc-objs += xenidc_gateway_initiator_resource.o
+xenidc-objs += xenidc_gateway_target_resource.o
diff -r 1786d40e66b8 -r b4eca2889318 linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway.c
--- /dev/null	Sun Nov 20 17:45:04 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway.c	Sun Nov 20 17:45:16 2005
@@ -0,0 +1,1216 @@
+/*****************************************************************************/
+/* A communication 'gateway' object which allows the client to send messages */
+/* and transactions bi-directionally over a xenidc_channel.                  */
+/*                                                                           */
+/* 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                   */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <asm-xen/xenidc_gateway.h>
+#include <asm-xen/xenidc_vaddress.h>
+#include <linux/vmalloc.h>
+#include "xenidc_gateway_initiator_resource.h"
+#include "xenidc_gateway_target_resource.h"
+#include "xenidc_trace.h"
+
+typedef enum {
+	xenidc_gateway_stimulus_mt,	/* Message or transaction queued.            */
+	xenidc_gateway_stimulus_cc,	/* Channel connect.                          */
+	xenidc_gateway_stimulus_cm,	/* Channel message.                          */
+	xenidc_gateway_stimulus_cd,	/* Channel disconnect.                       */
+	xenidc_gateway_stimulus_km,	/* Kick messages and transactions completed. */
+	xenidc_gateway_stimulus_kc,	/* Kick channel messages completed.          */
+	xenidc_gateway_stimulus_ic,	/* Initiator resource completed.             */
+	xenidc_gateway_stimulus_ii,	/* Initiator resources idle.                 */
+	xenidc_gateway_stimulus_tc,	/* Target resource completed.                */
+	xenidc_gateway_stimulus_ti,	/* Target resources idle.                    */
+	xenidc_gateway_stimulus_lc,	/* Client connect completed.                 */
+	xenidc_gateway_stimulus_lg,	/* Client disconnect called.                 */
+	xenidc_gateway_stimulus_ld,	/* Client disconnect completed.              */
+} xenidc_gateway_stimulus;
+
+static void xenidc_gateway_handle_stimulus
+    (xenidc_gateway * gateway, xenidc_gateway_stimulus stimulus);
+
+static void xenidc_gateway_channel_connect(void *context);
+
+static void xenidc_gateway_handle_channel_message
+    (void *context, xenidc_channel_message * message);
+
+static void xenidc_gateway_channel_disconnect
+    (void *context, xenidc_callback * callback);
+
+static int xenidc_gateway_init_or_exit(xenidc_gateway * gateway, int exit);
+
+int xenidc_gateway_init
+    (xenidc_gateway * gateway,
+     xenidc_channel * channel,
+     void (*connect) (xenidc_gateway * gateway), void (*handle_message)
+      (xenidc_gateway * gateway, xenidc_gateway_message * message),
+     void (*handle_transaction)
+      (xenidc_gateway * gateway, xenidc_gateway_transaction * transaction),
+     void (*disconnect)
+      (xenidc_gateway * gateway, xenidc_callback * callback),
+     u32 initiator_quota,
+     xenidc_buffer_byte_count initiator_maximum_byte_count,
+     u32 target_quota, xenidc_buffer_byte_count target_maximum_byte_count) {
+	trace();
+
+	gateway->channel = channel;
+	gateway->connect = connect;
+	gateway->handle_message = handle_message;
+	gateway->handle_transaction = handle_transaction;
+	gateway->disconnect = disconnect;
+
+	gateway->initiator_quota = initiator_quota;
+	gateway->target_quota = target_quota;
+	gateway->target_maximum_byte_count = target_maximum_byte_count;
+
+	xenidc_channel_install_client
+	    (channel,
+	     gateway,
+	     xenidc_gateway_channel_connect,
+	     xenidc_gateway_handle_channel_message,
+	     xenidc_gateway_channel_disconnect);
+
+	return xenidc_gateway_init_or_exit(gateway, 0);
+}
+
+static void xenidc_gateway_kick_messages_and_transactions_1(void *data);
+
+static void xenidc_gateway_kick_messages_and_transactions_2
+    (xenidc_callback * callback);
+
+static void xenidc_gateway_kick_channel_messages_1(void *data);
+
+static void xenidc_gateway_kick_channel_messages_2(xenidc_callback * callback);
+
+static void xenidc_gateway_connect_client_1(void *data);
+
+static void xenidc_gateway_disconnect_client_1(void *data);
+
+static void xenidc_gateway_disconnect_client_2(xenidc_callback * callback);
+
+static int xenidc_gateway_init_or_exit(xenidc_gateway * gateway, int exit)
+{
+	trace();
+
+	{
+		int return_value = 0;
+
+		if (exit) {
+			goto EXIT;
+		}
+
+		INIT_LIST_HEAD(&gateway->initiator_resource_list);
+
+		if (gateway->initiator_quota != 0) {
+			gateway->initiator_resources = vmalloc
+			    (sizeof(xenidc_gateway_initiator_resource)
+			     * gateway->initiator_quota);
+
+			if (gateway->initiator_resources == NULL) {
+				trace0
+				    ("failed to allocate initiator resources");
+
+				return_value = -ENOMEM;
+
+				goto EXIT_NO_INITIATOR_RESOURCES;
+			}
+
+			{
+				u32 i;
+
+				for (i = 0; i < gateway->initiator_quota; i++) {
+					xenidc_gateway_initiator_resource
+					    *resource =
+					    &gateway->initiator_resources[i];
+
+					xenidc_gateway_initiator_resource_init
+					    (resource,
+					     gateway,
+					     xenidc_gateway_kick_messages_and_transactions_2,
+					     i);
+
+					list_add_tail
+					    (xenidc_gateway_initiator_resource_to_link
+					     (resource),
+					     &gateway->initiator_resource_list);
+				}
+			}
+		}
+
+		INIT_LIST_HEAD(&gateway->target_resource_list);
+
+		if (gateway->target_quota != 0) {
+			gateway->target_resources = vmalloc
+			    ((sizeof(xenidc_gateway_target_resource)
+			      * gateway->target_quota)
+			     +
+			     (gateway->target_maximum_byte_count
+			      * gateway->target_quota)
+			    );
+
+			if (gateway->target_resources == NULL) {
+				trace0("failed to allocate target resources");
+
+				return_value = -ENOMEM;
+
+				goto EXIT_NO_TARGET_RESOURCES;
+			}
+
+			{
+				xenidc_local_buffer_reference buffer_area =
+				    xenidc_vaddress_create_lbr
+				    (&gateway->target_resources
+				     [gateway->target_quota],
+				     gateway->target_maximum_byte_count *
+				     gateway->target_quota);
+
+				u32 i;
+
+				for (i = 0; i < gateway->target_quota; i++) {
+					xenidc_gateway_target_resource *resource
+					    = &gateway->target_resources[i];
+
+					xenidc_local_buffer_reference buffer =
+					    buffer_area;
+
+					xenidc_local_buffer_reference_truncate
+					    (&buffer,
+					     gateway->
+					     target_maximum_byte_count);
+
+					xenidc_gateway_target_resource_init
+					    (resource,
+					     gateway,
+					     xenidc_gateway_kick_channel_messages_2,
+					     buffer);
+
+					list_add_tail
+					    (xenidc_gateway_target_resource_to_link
+					     (resource),
+					     &gateway->target_resource_list);
+
+					xenidc_local_buffer_reference_advance
+					    (&buffer_area,
+					     gateway->
+					     target_maximum_byte_count);
+				}
+			}
+		}
+
+		spin_lock_init(&gateway->lock);
+
+		gateway->state = xenidc_gateway_state_i;
+
+		INIT_LIST_HEAD(&gateway->message_and_transaction_list);
+		INIT_LIST_HEAD(&gateway->channel_message_list);
+
+		xenidc_work_init
+		    (&gateway->kick_messages_and_transactions_1_work,
+		     xenidc_gateway_kick_messages_and_transactions_1, gateway);
+
+		xenidc_work_init
+		    (&gateway->kick_channel_messages_1_work,
+		     xenidc_gateway_kick_channel_messages_1, gateway);
+
+		xenidc_work_init
+		    (&gateway->connect_client_1_work,
+		     xenidc_gateway_connect_client_1, gateway);
+
+		xenidc_work_init
+		    (&gateway->disconnect_client_1_work,
+		     xenidc_gateway_disconnect_client_1, gateway);
+
+		xenidc_callback_init
+		    (&gateway->disconnect_client_2_callback,
+		     xenidc_gateway_disconnect_client_2);
+
+		gateway->kick_messages_and_transactions_out = 0;
+		gateway->kick_channel_messages_out = 0;
+		gateway->initiator_resources_out = 0;
+		gateway->target_resources_out = 0;
+
+		return 0;
+
+	      EXIT:
+
+		if (gateway->target_quota != 0) {
+			vfree(gateway->target_resources);
+		}
+
+	      EXIT_NO_TARGET_RESOURCES:
+
+		if (gateway->initiator_quota != 0) {
+			vfree(gateway->initiator_resources);
+		}
+
+	      EXIT_NO_INITIATOR_RESOURCES:
+
+		return return_value;
+	}
+}
+
+void xenidc_gateway_submit_message
+    (xenidc_gateway * gateway, xenidc_gateway_message * message) {
+	trace();
+
+	/* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+	{
+		unsigned long flags;
+
+		spin_lock_irqsave(&gateway->lock, flags);
+
+		list_add_tail
+		    (xenidc_gateway_message_to_link(message),
+		     &gateway->message_and_transaction_list);
+
+		xenidc_gateway_handle_stimulus
+		    (gateway, xenidc_gateway_stimulus_mt);
+
+		spin_unlock_irqrestore(&gateway->lock, flags);
+	}
+}
+
+void xenidc_gateway_submit_transaction
+    (xenidc_gateway * gateway, xenidc_gateway_transaction * transaction) {
+	trace();
+
+	/* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+	{
+		unsigned long flags;
+
+		spin_lock_irqsave(&gateway->lock, flags);
+
+		list_add_tail
+		    (xenidc_gateway_transaction_to_link(transaction),
+		     &gateway->message_and_transaction_list);
+
+		xenidc_gateway_handle_stimulus
+		    (gateway, xenidc_gateway_stimulus_mt);
+
+		spin_unlock_irqrestore(&gateway->lock, flags);
+	}
+}
+
+void xenidc_gateway_exit(xenidc_gateway * gateway)
+{
+	trace();
+
+	(void)xenidc_gateway_init_or_exit(gateway, 1);
+}
+
+static void xenidc_gateway_channel_connect(void *context)
+{
+	trace();
+
+	{
+		xenidc_gateway *gateway = (xenidc_gateway *) context;
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&gateway->lock, flags);
+
+		xenidc_gateway_handle_stimulus
+		    (gateway, xenidc_gateway_stimulus_cc);
+
+		spin_unlock_irqrestore(&gateway->lock, flags);
+	}
+}
+
+static void xenidc_gateway_handle_channel_message
+    (void *context, xenidc_channel_message * message) {
+	trace();
+
+	/* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+	{
+		xenidc_gateway *gateway = (xenidc_gateway *) context;
+
+		xenidc_gateway_ring_element_header header;
+
+		if (xenidc_local_buffer_reference_copy_out
+		    (&message->message_lbr, &header, sizeof(header))
+		    != sizeof(header)
+		    ) {
+			goto PROTOCOL_ERROR;
+		}
+
+		if (header.type == XENIDC_GATEWAY_RING_ELEMENT_TYPE_STATUS) {
+			xenidc_local_buffer_reference status_lbr =
+			    message->message_lbr;
+
+			xenidc_gateway_status_ring_element status_element;
+
+			if (xenidc_local_buffer_reference_copy_out
+			    (&status_lbr, &status_element,
+			     sizeof(status_element))
+			    != sizeof(status_element)
+			    ) {
+				goto PROTOCOL_ERROR;
+			}
+
+			xenidc_local_buffer_reference_advance
+			    (&status_lbr, sizeof(status_element));
+
+			if (status_element.id >= gateway->initiator_quota) {
+				goto PROTOCOL_ERROR;
+			}
+
+			{
+				xenidc_gateway_initiator_resource *resource =
+				    &gateway->
+				    initiator_resources[status_element.id];
+
+				if (xenidc_gateway_initiator_resource_handle_status(resource, status_element.error, status_lbr)
+				    != 0) {
+					goto PROTOCOL_ERROR;
+				}
+			}
+
+			xenidc_callback_success
+			    (xenidc_channel_message_to_callback(message));
+		} else {
+			unsigned long flags;
+
+			spin_lock_irqsave(&gateway->lock, flags);
+
+			list_add_tail
+			    (xenidc_channel_message_to_link(message),
+			     &gateway->channel_message_list);
+
+			xenidc_gateway_handle_stimulus
+			    (gateway, xenidc_gateway_stimulus_cm);
+
+			spin_unlock_irqrestore(&gateway->lock, flags);
+		}
+	}
+
+	return;
+
+      PROTOCOL_ERROR:
+
+	xenidc_callback_complete
+	    (xenidc_channel_message_to_callback(message),
+	     XENIDC_ERROR_INVALID_PROTOCOL);
+}
+
+static void xenidc_gateway_channel_disconnect
+    (void *context, xenidc_callback * callback) {
+	trace();
+
+	{
+		xenidc_gateway *gateway = (xenidc_gateway *) context;
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&gateway->lock, flags);
+
+		gateway->channel_disconnect_callback = callback;
+
+		xenidc_gateway_handle_stimulus
+		    (gateway, xenidc_gateway_stimulus_cd);
+
+		spin_unlock_irqrestore(&gateway->lock, flags);
+	}
+}
+
+void xenidc_gateway_submit_channel_message
+    (xenidc_gateway * gateway, xenidc_channel_message * message) {
+	trace();
+
+	/* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+	xenidc_channel_submit_message(gateway->channel, message);
+}
+
+void xenidc_gateway_submit_message_to_client
+    (xenidc_gateway * gateway, xenidc_gateway_message * message) {
+	trace();
+
+	/* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+	gateway->handle_message(gateway, message);
+}
+
+void xenidc_gateway_submit_transaction_to_client
+    (xenidc_gateway * gateway, xenidc_gateway_transaction * transaction) {
+	trace();
+
+	/* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+	gateway->handle_transaction(gateway, transaction);
+}
+
+static void xenidc_gateway_invalid_stimulus
+    (xenidc_gateway * gateway, xenidc_gateway_stimulus stimulus);
+
+static void xenidc_gateway_kick_messages_and_transactions
+    (xenidc_gateway * gateway);
+
+static void xenidc_gateway_fail_out_messages_and_transactions
+    (xenidc_gateway * gateway);
+
+static void xenidc_gateway_kick_channel_messages(xenidc_gateway * gateway);
+
+static void xenidc_gateway_complete_channel_messages(xenidc_gateway * gateway);
+
+static void xenidc_gateway_connect_client(xenidc_gateway * gateway);
+
+static void xenidc_gateway_disconnect_client(xenidc_gateway * gateway);
+
+static void xenidc_gateway_abort_initiator_resources(xenidc_gateway * gateway);
+
+static void xenidc_gateway_test_initiator_resources(xenidc_gateway * gateway);
+
+static void xenidc_gateway_test_target_resources(xenidc_gateway * gateway);
+
+static void xenidc_gateway_complete_channel_disconnect
+    (xenidc_gateway * gateway);
+
+static void xenidc_gateway_handle_stimulus
+    (xenidc_gateway * gateway, xenidc_gateway_stimulus stimulus) {
+	trace3
+	    ("gateway %p in state %d received stimulus %d",
+	     gateway, gateway->state, stimulus);
+
+	switch (gateway->state) {
+	case xenidc_gateway_state_i:
+		/* Channel disconnected.               */
+		/* Client disconnected.                */
+		/* No messages or transactions queued. */
+		/* No channel messages queued.         */
+		/* Initiator resources idle.           */
+		/* Target resources idle.              */
+		/* Not kicking m/t.                    */
+		/* Not kicking cm.                     */
+		switch (stimulus) {
+		case xenidc_gateway_stimulus_cc:
+			gateway->state = xenidc_gateway_state_i_cc;
+			xenidc_gateway_connect_client(gateway);
+			break;
+		default:
+			xenidc_gateway_invalid_stimulus(gateway, stimulus);
+			break;
+		}
+		break;
+	case xenidc_gateway_state_i_cc:
+		/* Channel connected.                     */
+		/* Client connecting.                     */
+		/* Maybe messages or transactions queued. */
+		/* Maybe channel messages queued.         */
+		/* Initiator resources idle.              */
+		/* Target resources idle.                 */
+		/* Not kicking m/t.                       */
+		/* Not kicking cm.                        */
+		switch (stimulus) {
+		case xenidc_gateway_stimulus_mt:
+		case xenidc_gateway_stimulus_cm:
+			break;
+		case xenidc_gateway_stimulus_cd:
+			gateway->state = xenidc_gateway_state_i_cc_cd;
+			xenidc_gateway_complete_channel_messages(gateway);
+			break;
+		case xenidc_gateway_stimulus_lc:
+			gateway->state = xenidc_gateway_state_i_cc_lc;
+			xenidc_gateway_kick_messages_and_transactions(gateway);
+			xenidc_gateway_kick_channel_messages(gateway);
+			break;
+		default:
+			xenidc_gateway_invalid_stimulus(gateway, stimulus);
+			break;
+		}
+		break;
+	case xenidc_gateway_state_i_cc_cd:
+		/* Channel disconnecting.                 */
+		/* Client connecting.                     */
+		/* Maybe messages or transactions queued. */
+		/* No channel messages queued.            */
+		/* Initiator resources idle.              */
+		/* Target resources idle.                 */
+		/* Not kicking m/t.                       */
+		/* Not kicking cm.                        */
+		switch (stimulus) {
+		case xenidc_gateway_stimulus_mt:
+			break;
+		case xenidc_gateway_stimulus_lc:
+			gateway->state = xenidc_gateway_state_i_cc_cd_lc;
+			xenidc_gateway_disconnect_client(gateway);
+			break;
+		default:
+			xenidc_gateway_invalid_stimulus(gateway, stimulus);
+			break;
+		}
+		break;
+	case xenidc_gateway_state_i_cc_lc:
+		/* Channel connected.                     */
+		/* Client connected.                      */
+		/* Maybe messages or transactions queued. */
+		/* Maybe channel messages queued.         */
+		/* Maybe initiator resources busy.        */
+		/* Maybe target resources busy.           */
+		/* Maybe kicking m/t.                     */
+		/* Maybe kicking cm.                      */
+		switch (stimulus) {
+		case xenidc_gateway_stimulus_mt:
+			xenidc_gateway_kick_messages_and_transactions(gateway);
+			break;
+		case xenidc_gateway_stimulus_cm:
+			xenidc_gateway_kick_channel_messages(gateway);
+			break;
+		case xenidc_gateway_stimulus_cd:
+			gateway->state = xenidc_gateway_state_i_cc_lc_cd;
+			xenidc_gateway_complete_channel_messages(gateway);
+			xenidc_gateway_kick_messages_and_transactions(gateway);
+			xenidc_gateway_kick_channel_messages(gateway);
+			break;
+		case xenidc_gateway_stimulus_km:
+		case xenidc_gateway_stimulus_kc:
+			break;
+		case xenidc_gateway_stimulus_ic:
+		case xenidc_gateway_stimulus_ii:
+			xenidc_gateway_kick_messages_and_transactions(gateway);
+			break;
+		case xenidc_gateway_stimulus_tc:
+		case xenidc_gateway_stimulus_ti:
+			xenidc_gateway_kick_channel_messages(gateway);
+			break;
+		default:
+			xenidc_gateway_invalid_stimulus(gateway, stimulus);
+			break;
+		}
+		break;
+	case xenidc_gateway_state_i_cc_lc_cd:
+		/* Channel disconnecting.                 */
+		/* Client connected.                      */
+		/* Maybe messages or transactions queued. */
+		/* No channel messages queued.            */
+		/* Maybe initiator resources busy.        */
+		/* Maybe target resources busy.           */
+		/* Kicking m/t.                           */
+		/* Kicking cm.                            */
+		switch (stimulus) {
+		case xenidc_gateway_stimulus_mt:
+			break;
+		case xenidc_gateway_stimulus_km:
+		case xenidc_gateway_stimulus_kc:
+			gateway->state = xenidc_gateway_state_i_cc_lc_cd_km;
+			break;
+		case xenidc_gateway_stimulus_ic:
+		case xenidc_gateway_stimulus_ii:
+		case xenidc_gateway_stimulus_tc:
+		case xenidc_gateway_stimulus_ti:
+			break;
+		default:
+			xenidc_gateway_invalid_stimulus(gateway, stimulus);
+			break;
+		}
+		break;
+	case xenidc_gateway_state_i_cc_lc_cd_km:
+		/* Channel disconnecting.                 */
+		/* Client connected.                      */
+		/* Maybe messages or transactions queued. */
+		/* No channel messages queued.            */
+		/* Maybe initiator resources busy.        */
+		/* Maybe target resources busy.           */
+		/* One of kicking m/t or cm.              */
+		switch (stimulus) {
+		case xenidc_gateway_stimulus_mt:
+			break;
+		case xenidc_gateway_stimulus_km:
+		case xenidc_gateway_stimulus_kc:
+			gateway->state = xenidc_gateway_state_i_cc_cd_lc;
+			xenidc_gateway_disconnect_client(gateway);
+			break;
+		case xenidc_gateway_stimulus_ic:
+		case xenidc_gateway_stimulus_ii:
+		case xenidc_gateway_stimulus_tc:
+		case xenidc_gateway_stimulus_ti:
+			break;
+		default:
+			xenidc_gateway_invalid_stimulus(gateway, stimulus);
+			break;
+		}
+		break;
+	case xenidc_gateway_state_i_cc_cd_lc:
+		/* Channel disconnecting.                 */
+		/* Calling client disconnect.             */
+		/* Maybe messages or transactions queued. */
+		/* No channel messages queued.            */
+		/* Maybe initiator resources busy.        */
+		/* Maybe target resources busy.           */
+		/* Not kicking m/t.                       */
+		/* Not kicking cm.                        */
+		switch (stimulus) {
+		case xenidc_gateway_stimulus_mt:
+			break;
+		case xenidc_gateway_stimulus_ic:
+		case xenidc_gateway_stimulus_ii:
+		case xenidc_gateway_stimulus_tc:
+		case xenidc_gateway_stimulus_ti:
+			break;
+		case xenidc_gateway_stimulus_lg:
+			gateway->state = xenidc_gateway_state_i_cc_cd_lc_lg;
+			xenidc_gateway_fail_out_messages_and_transactions
+			    (gateway);
+			xenidc_gateway_abort_initiator_resources(gateway);
+			break;
+		case xenidc_gateway_stimulus_ld:
+			gateway->state = xenidc_gateway_state_i_cc_cd_lc_ld;
+			break;
+		default:
+			xenidc_gateway_invalid_stimulus(gateway, stimulus);
+			break;
+		}
+		break;
+	case xenidc_gateway_state_i_cc_cd_lc_lg:
+		/* Channel disconnecting.              */
+		/* Client disconnecting.               */
+		/* No messages or transactions queued. */
+		/* No channel messages queued.         */
+		/* Maybe initiator resources busy.     */
+		/* Maybe target resources busy.        */
+		/* Not kicking m/t.                    */
+		/* Not kicking cm.                     */
+		switch (stimulus) {
+		case xenidc_gateway_stimulus_mt:
+			break;
+		case xenidc_gateway_stimulus_ic:
+		case xenidc_gateway_stimulus_ii:
+		case xenidc_gateway_stimulus_tc:
+		case xenidc_gateway_stimulus_ti:
+			break;
+		case xenidc_gateway_stimulus_ld:
+			gateway->state = xenidc_gateway_state_i_cc_cd_lc_lg_ld;
+			xenidc_gateway_test_target_resources(gateway);
+			break;
+		default:
+			xenidc_gateway_invalid_stimulus(gateway, stimulus);
+			break;
+		}
+		break;
+	case xenidc_gateway_state_i_cc_cd_lc_ld:
+		/* Channel disconnecting.                          */
+		/* Client disconnected but call still in progress. */
+		/* No messages or transactions queued.             */
+		/* No channel messages queued.                     */
+		/* Maybe initiator resources busy.                 */
+		/* Maybe target resources busy.                    */
+		/* Not kicking m/t.                                */
+		/* Not kicking cm.                                 */
+		switch (stimulus) {
+		case xenidc_gateway_stimulus_ic:
+		case xenidc_gateway_stimulus_ii:
+		case xenidc_gateway_stimulus_tc:
+		case xenidc_gateway_stimulus_ti:
+			break;
+		case xenidc_gateway_stimulus_lg:
+			gateway->state = xenidc_gateway_state_i_cc_cd_lc_lg_ld;
+			xenidc_gateway_test_target_resources(gateway);
+			break;
+		default:
+			xenidc_gateway_invalid_stimulus(gateway, stimulus);
+			break;
+		}
+		break;
+	case xenidc_gateway_state_i_cc_cd_lc_lg_ld:
+		/* Channel disconnecting.                          */
+		/* Client disconnected.                            */
+		/* No messages or transactions queued.             */
+		/* No channel messages queued.                     */
+		/* Maybe initiator resources busy.                 */
+		/* Test target resources or target resources busy. */
+		/* Not kicking m/t.                                */
+		/* Not kicking cm.                                 */
+		switch (stimulus) {
+		case xenidc_gateway_stimulus_ic:
+		case xenidc_gateway_stimulus_ii:
+		case xenidc_gateway_stimulus_tc:
+			break;
+		case xenidc_gateway_stimulus_ti:
+			gateway->state =
+			    xenidc_gateway_state_i_cc_cd_lc_lg_ld_ti;
+			xenidc_gateway_test_initiator_resources(gateway);
+			break;
+		default:
+			xenidc_gateway_invalid_stimulus(gateway, stimulus);
+			break;
+		}
+		break;
+	case xenidc_gateway_state_i_cc_cd_lc_lg_ld_ti:
+		/* Channel disconnecting.                                */
+		/* Client disconnected.                                  */
+		/* No messages or transactions queued.                   */
+		/* No channel messages queued.                           */
+		/* Test initiator resources or initiator resources busy. */
+		/* Target resources idle.                                */
+		/* Not kicking m/t.                                      */
+		/* Not kicking cm.                                       */
+		switch (stimulus) {
+		case xenidc_gateway_stimulus_ic:
+			break;
+		case xenidc_gateway_stimulus_ii:
+			gateway->state = xenidc_gateway_state_i;
+			xenidc_gateway_complete_channel_disconnect(gateway);
+			break;
+		default:
+			xenidc_gateway_invalid_stimulus(gateway, stimulus);
+			break;
+		}
+		break;
+	default:
+		xenidc_gateway_invalid_stimulus(gateway, stimulus);
+		break;
+	}
+}
+
+static void xenidc_gateway_invalid_stimulus
+    (xenidc_gateway * gateway, xenidc_gateway_stimulus stimulus) {
+	trace();
+
+	printk
+	    (KERN_ERR "xenidc: gateway %p in state %d"
+	     "received invalid stimulus %d", gateway, gateway->state, stimulus);
+}
+
+static void xenidc_gateway_kick_messages_and_transactions
+    (xenidc_gateway * gateway) {
+	trace();
+
+	/* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+	if (!gateway->kick_messages_and_transactions_out) {
+		gateway->kick_messages_and_transactions_out = 1;
+
+		(void)xenidc_work_schedule
+		    (&gateway->kick_messages_and_transactions_1_work);
+	}
+}
+
+static void xenidc_gateway_kick_messages_and_transactions_1(void *data)
+{
+	trace();
+
+	{
+		xenidc_gateway *gateway = (xenidc_gateway *) data;
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&gateway->lock, flags);
+
+		while ((!list_empty(&gateway->message_and_transaction_list))
+		       && (!list_empty(&gateway->initiator_resource_list))
+		    ) {
+			xenidc_gateway_message_and_transaction_header *header =
+			    list_entry(gateway->message_and_transaction_list.
+				       next,
+				       xenidc_gateway_message_and_transaction_header,
+				       XENIDC_GATEWAY_MESSAGE_AND_TRANSACTION_HEADER_LINK);
+
+			xenidc_gateway_initiator_resource *resource = list_entry
+			    (gateway->initiator_resource_list.next,
+			     xenidc_gateway_initiator_resource,
+			     XENIDC_GATEWAY_INITIATOR_RESOURCE_LINK);
+
+			list_del_init
+			    (xenidc_gateway_message_and_transaction_header_to_link
+			     (header)
+			    );
+
+			list_del_init
+			    (xenidc_gateway_initiator_resource_to_link
+			     (resource));
+
+			gateway->initiator_resources_out++;
+
+			spin_unlock_irqrestore(&gateway->lock, flags);
+
+			xenidc_gateway_initiator_resource_start(resource,
+								header);
+
+			spin_lock_irqsave(&gateway->lock, flags);
+		}
+
+		gateway->kick_messages_and_transactions_out = 0;
+
+		xenidc_gateway_handle_stimulus(gateway,
+					       xenidc_gateway_stimulus_km);
+
+		spin_unlock_irqrestore(&gateway->lock, flags);
+	}
+}
+
+static void xenidc_gateway_kick_messages_and_transactions_2
+    (xenidc_callback * callback) {
+	trace();
+
+	{
+		xenidc_gateway_initiator_resource *resource =
+		    xenidc_gateway_initiator_resource_callback_to(callback);
+
+		xenidc_gateway *gateway =
+		    xenidc_gateway_initiator_resource_query_gateway(resource);
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&gateway->lock, flags);
+
+		list_add_tail
+		    (xenidc_gateway_initiator_resource_to_link(resource),
+		     &gateway->initiator_resource_list);
+
+		if (--gateway->initiator_resources_out != 0) {
+			xenidc_gateway_handle_stimulus
+			    (gateway, xenidc_gateway_stimulus_ic);
+		} else {
+			xenidc_gateway_handle_stimulus
+			    (gateway, xenidc_gateway_stimulus_ii);
+		}
+
+		spin_unlock_irqrestore(&gateway->lock, flags);
+	}
+}
+
+static void xenidc_gateway_fail_out_messages_and_transactions
+    (xenidc_gateway * gateway) {
+	trace();
+
+	while (!list_empty(&gateway->message_and_transaction_list)) {
+		xenidc_gateway_message_and_transaction_header *header =
+		    list_entry(gateway->message_and_transaction_list.next,
+			       xenidc_gateway_message_and_transaction_header,
+			       XENIDC_GATEWAY_MESSAGE_AND_TRANSACTION_HEADER_LINK);
+
+		list_del_init
+		    (xenidc_gateway_message_and_transaction_header_to_link
+		     (header));
+
+		xenidc_callback_complete
+		    (xenidc_gateway_message_and_transaction_header_to_callback
+		     (header), XENIDC_ERROR_DISCONNECT);
+	}
+}
+
+static void xenidc_gateway_kick_channel_messages(xenidc_gateway * gateway)
+{
+	trace();
+
+	/* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+	if (!gateway->kick_channel_messages_out) {
+		gateway->kick_channel_messages_out = 1;
+
+		(void)xenidc_work_schedule(&gateway->
+					   kick_channel_messages_1_work);
+	}
+}
+
+static void xenidc_gateway_kick_channel_messages_1(void *data)
+{
+	trace();
+
+	/* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+	{
+		xenidc_gateway *gateway = (xenidc_gateway *) data;
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&gateway->lock, flags);
+
+		while ((!list_empty(&gateway->channel_message_list))
+		       && (!list_empty(&gateway->target_resource_list))
+		    ) {
+			xenidc_channel_message *message = list_entry
+			    (gateway->channel_message_list.next,
+			     xenidc_channel_message,
+			     XENIDC_CHANNEL_MESSAGE_LINK);
+
+			xenidc_gateway_target_resource *resource = list_entry
+			    (gateway->target_resource_list.next,
+			     xenidc_gateway_target_resource,
+			     XENIDC_GATEWAY_TARGET_RESOURCE_LINK);
+
+			list_del_init(xenidc_channel_message_to_link(message));
+
+			{
+				xenidc_gateway_ring_element_header header;
+
+				if (xenidc_local_buffer_reference_copy_out
+				    (&message->message_lbr, &header,
+				     sizeof(header))
+				    != sizeof(header)
+				    ) {
+					goto PROTOCOL_ERROR;
+				}
+
+				if (header.type ==
+				    XENIDC_GATEWAY_RING_ELEMENT_TYPE_MESSAGE) {
+					xenidc_local_buffer_reference
+					    message_lbr = message->message_lbr;
+
+					xenidc_local_buffer_reference_advance
+					    (&message_lbr,
+					     sizeof
+					     (xenidc_gateway_message_ring_element)
+					    );
+
+					list_del_init
+					    (xenidc_gateway_target_resource_to_link
+					     (resource));
+
+					gateway->target_resources_out++;
+
+					spin_unlock_irqrestore(&gateway->lock,
+							       flags);
+
+					xenidc_gateway_target_resource_start_message
+					    (resource, message_lbr);
+
+					spin_lock_irqsave(&gateway->lock,
+							  flags);
+
+					xenidc_callback_success
+					    (xenidc_channel_message_to_callback
+					     (message));
+				} else if (header.type ==
+					   XENIDC_GATEWAY_RING_ELEMENT_TYPE_PARAMETERS)
+				{
+					xenidc_local_buffer_reference
+					    parameters_lbr =
+					    message->message_lbr;
+
+					xenidc_gateway_parameters_ring_element
+					    parameters_element;
+
+					if (xenidc_local_buffer_reference_copy_out(&parameters_lbr, &parameters_element, sizeof(parameters_element)
+					    )
+					    != sizeof(parameters_element)
+					    ) {
+						goto PROTOCOL_ERROR;
+					}
+
+					xenidc_local_buffer_reference_advance
+					    (&parameters_lbr,
+					     sizeof(parameters_element));
+
+					list_del_init
+					    (xenidc_gateway_target_resource_to_link
+					     (resource));
+
+					gateway->target_resources_out++;
+
+					spin_unlock_irqrestore(&gateway->lock,
+							       flags);
+
+					xenidc_gateway_target_resource_start_transaction
+					    (resource,
+					     parameters_element.id,
+					     parameters_lbr,
+					     parameters_element.
+					     status_byte_count);
+
+					spin_lock_irqsave(&gateway->lock,
+							  flags);
+
+					xenidc_callback_success
+					    (xenidc_channel_message_to_callback
+					     (message));
+				} else {
+				      PROTOCOL_ERROR:
+
+					xenidc_callback_complete
+					    (xenidc_channel_message_to_callback
+					     (message),
+					     XENIDC_ERROR_INVALID_PROTOCOL);
+				}
+			}
+		}
+
+		gateway->kick_channel_messages_out = 0;
+
+		xenidc_gateway_handle_stimulus(gateway,
+					       xenidc_gateway_stimulus_kc);
+
+		spin_unlock_irqrestore(&gateway->lock, flags);
+	}
+}
+
+static void xenidc_gateway_kick_channel_messages_2(xenidc_callback * callback) {
+	trace();
+
+	{
+		xenidc_gateway_target_resource *resource =
+		    xenidc_gateway_target_resource_callback_to(callback);
+
+		xenidc_gateway *gateway =
+		    xenidc_gateway_target_resource_query_gateway(resource);
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&gateway->lock, flags);
+
+		list_add_tail
+		    (xenidc_gateway_target_resource_to_link(resource),
+		     &gateway->target_resource_list);
+
+		if (--gateway->target_resources_out != 0) {
+			xenidc_gateway_handle_stimulus
+			    (gateway, xenidc_gateway_stimulus_tc);
+		} else {
+			xenidc_gateway_handle_stimulus
+			    (gateway, xenidc_gateway_stimulus_ti);
+		}
+
+		spin_unlock_irqrestore(&gateway->lock, flags);
+	}
+}
+
+static void xenidc_gateway_complete_channel_messages(xenidc_gateway * gateway) {
+	trace();
+
+	while (!list_empty(&gateway->channel_message_list)) {
+		xenidc_channel_message *message = list_entry
+		    (gateway->channel_message_list.next,
+		     xenidc_channel_message,
+		     XENIDC_CHANNEL_MESSAGE_LINK);
+
+		list_del_init(xenidc_channel_message_to_link(message));
+
+		xenidc_callback_success
+		    (xenidc_channel_message_to_callback(message));
+	}
+}
+
+static void xenidc_gateway_connect_client(xenidc_gateway * gateway)
+{
+	trace();
+
+	(void)xenidc_work_schedule(&gateway->connect_client_1_work);
+}
+
+static void xenidc_gateway_connect_client_1(void *data)
+{
+	trace();
+
+	{
+		xenidc_gateway *gateway = (xenidc_gateway *) data;
+
+		gateway->connect(gateway);
+
+		{
+			unsigned long flags;
+
+			spin_lock_irqsave(&gateway->lock, flags);
+
+			xenidc_gateway_handle_stimulus
+			    (gateway, xenidc_gateway_stimulus_lc);
+
+			spin_unlock_irqrestore(&gateway->lock, flags);
+		}
+	}
+}
+
+static void xenidc_gateway_disconnect_client(xenidc_gateway * gateway)
+{
+	trace();
+
+	(void)xenidc_work_schedule(&gateway->disconnect_client_1_work);
+}
+
+static void xenidc_gateway_disconnect_client_1(void *data)
+{
+	trace();
+
+	{
+		xenidc_gateway *gateway = (xenidc_gateway *) data;
+
+		gateway->disconnect(gateway,
+				    &gateway->disconnect_client_2_callback);
+
+		{
+			unsigned long flags;
+
+			spin_lock_irqsave(&gateway->lock, flags);
+
+			xenidc_gateway_handle_stimulus
+			    (gateway, xenidc_gateway_stimulus_lg);
+
+			spin_unlock_irqrestore(&gateway->lock, flags);
+		}
+	}
+}
+
+static void xenidc_gateway_disconnect_client_2(xenidc_callback * callback)
+{
+	trace();
+
+	{
+		xenidc_gateway *gateway = container_of
+		    (callback, xenidc_gateway, disconnect_client_2_callback);
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&gateway->lock, flags);
+
+		xenidc_gateway_handle_stimulus
+		    (gateway, xenidc_gateway_stimulus_ld);
+
+		spin_unlock_irqrestore(&gateway->lock, flags);
+	}
+}
+
+static void xenidc_gateway_abort_initiator_resources(xenidc_gateway * gateway) {
+	trace();
+
+	{
+		u32 i;
+
+		for (i = 0; i < gateway->initiator_quota; i++) {
+			xenidc_gateway_initiator_resource_abort
+			    (&gateway->initiator_resources[i],
+			     XENIDC_ERROR_DISCONNECT);
+		}
+	}
+}
+
+static void xenidc_gateway_test_initiator_resources(xenidc_gateway * gateway) {
+	trace();
+
+	if (gateway->initiator_resources_out == 0) {
+		xenidc_gateway_handle_stimulus
+		    (gateway, xenidc_gateway_stimulus_ii);
+	}
+}
+
+static void xenidc_gateway_test_target_resources(xenidc_gateway * gateway) {
+	trace();
+
+	if (gateway->target_resources_out == 0) {
+		xenidc_gateway_handle_stimulus
+		    (gateway, xenidc_gateway_stimulus_ti);
+	}
+}
+
+static void xenidc_gateway_complete_channel_disconnect(xenidc_gateway * gateway) {
+	trace();
+
+	xenidc_callback_success(gateway->channel_disconnect_callback);
+}
diff -r 1786d40e66b8 -r b4eca2889318 linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_initiator_resource.c
--- /dev/null	Sun Nov 20 17:45:04 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_initiator_resource.c	Sun Nov 20 17:45:16 2005
@@ -0,0 +1,382 @@
+/*****************************************************************************/
+/* The xenidc_gateway_initiator_resource object performs the initiator-side  */
+/* part of the processing of a client message or transaction sent across the */
+/* gateway.                                                                  */
+/*                                                                           */
+/* 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                   */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <asm-xen/xenidc_vaddress.h>
+#include "xenidc_gateway_initiator_resource.h"
+#include "xenidc_trace.h"
+
+extern void xenidc_gateway_submit_channel_message
+    (xenidc_gateway * gateway, xenidc_channel_message * message);
+
+static void xenidc_gateway_initiator_resource_handle_stimulus
+    (xenidc_gateway_initiator_resource * resource,
+     xenidc_gateway_initiator_resource_stimulus stimulus);
+
+static void xenidc_gateway_initiator_resource_channel_message_callback
+    (xenidc_callback * callback);
+
+void xenidc_gateway_initiator_resource_init
+    (xenidc_gateway_initiator_resource * resource,
+     xenidc_gateway * gateway, xenidc_callback_function callback, int id) {
+	trace();
+
+	xenidc_callback_init(&resource->callback, callback);
+
+	resource->gateway = gateway;
+
+	resource->id = id;
+
+	spin_lock_init(&resource->lock);
+
+	resource->state = xenidc_gateway_initiator_resource_state_i;
+
+	xenidc_callback_init
+	    (xenidc_channel_message_to_callback(&resource->channel_message),
+	     xenidc_gateway_initiator_resource_channel_message_callback);
+}
+
+void xenidc_gateway_initiator_resource_start
+    (xenidc_gateway_initiator_resource * resource,
+     xenidc_gateway_message_and_transaction_header * header) {
+	trace();
+
+	/* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+	resource->header = header;
+
+	resource->error = XENIDC_ERROR_SUCCESS;
+
+	{
+		xenidc_gateway_initiator_resource_stimulus stimulus;
+
+		if (header->transaction_not_message) {
+			xenidc_gateway_transaction *transaction =
+			    xenidc_gateway_transaction_header_to(header);
+
+			resource->element_lbr = xenidc_vaddress_create_lbr
+			    (&resource->parameters_element,
+			     sizeof(resource->parameters_element)
+			    );
+
+			resource->channel_message.message_lbr =
+			    xenidc_concatenate_create_lbr
+			    (&resource->base,
+			     &resource->element_lbr,
+			     &transaction->parameters_lbr);
+
+			memset
+			    (&resource->parameters_element,
+			     0, sizeof(resource->parameters_element)
+			    );
+
+			resource->parameters_element.header.type =
+			    XENIDC_GATEWAY_RING_ELEMENT_TYPE_PARAMETERS;
+
+			resource->parameters_element.id = resource->id;
+
+			resource->parameters_element.status_byte_count =
+			    xenidc_local_buffer_reference_query_byte_count
+			    (&transaction->status_lbr);
+
+			stimulus =
+			    xenidc_gateway_initiator_resource_stimulus_st;
+		} else {
+			xenidc_gateway_message *message =
+			    xenidc_gateway_message_header_to(header);
+
+			resource->element_lbr = xenidc_vaddress_create_lbr
+			    (&resource->message_element,
+			     sizeof(resource->message_element)
+			    );
+
+			resource->channel_message.message_lbr =
+			    xenidc_concatenate_create_lbr
+			    (&resource->base,
+			     &resource->element_lbr, &message->message_lbr);
+
+			memset
+			    (&resource->message_element,
+			     0, sizeof(resource->message_element)
+			    );
+
+			resource->parameters_element.header.type =
+			    XENIDC_GATEWAY_RING_ELEMENT_TYPE_MESSAGE;
+
+			stimulus =
+			    xenidc_gateway_initiator_resource_stimulus_sm;
+		}
+
+		{
+			unsigned long flags;
+
+			spin_lock_irqsave(&resource->lock, flags);
+
+			xenidc_gateway_initiator_resource_handle_stimulus
+			    (resource, stimulus);
+
+			spin_unlock_irqrestore(&resource->lock, flags);
+		}
+
+		xenidc_gateway_submit_channel_message
+		    (resource->gateway, &resource->channel_message);
+	}
+}
+
+void xenidc_gateway_initiator_resource_abort
+    (xenidc_gateway_initiator_resource * resource, xenidc_error error) {
+	trace();
+
+	{
+		unsigned long flags;
+
+		spin_lock_irqsave(&resource->lock, flags);
+
+		resource->aborted_error = error;
+
+		xenidc_gateway_initiator_resource_handle_stimulus
+		    (resource, xenidc_gateway_initiator_resource_stimulus_ab);
+
+		spin_unlock_irqrestore(&resource->lock, flags);
+	}
+}
+
+static void xenidc_gateway_initiator_resource_channel_message_callback
+    (xenidc_callback * callback) {
+	trace();
+
+	{
+		xenidc_gateway_initiator_resource *resource = container_of
+		    (callback,
+		     xenidc_gateway_initiator_resource,
+		     channel_message.callback);
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&resource->lock, flags);
+
+		xenidc_gateway_initiator_resource_handle_stimulus
+		    (resource, xenidc_gateway_initiator_resource_stimulus_sc);
+
+		spin_unlock_irqrestore(&resource->lock, flags);
+	}
+}
+
+int xenidc_gateway_initiator_resource_handle_status
+    (xenidc_gateway_initiator_resource * resource,
+     xenidc_error error, xenidc_local_buffer_reference status_lbr) {
+	trace();
+
+	{
+		int return_value = -1;
+
+		unsigned long flags;
+
+		spin_lock_irqsave(&resource->lock, flags);
+
+		if ((resource->state
+		     == xenidc_gateway_initiator_resource_state_i_st)
+		    ||
+		    (resource->state
+		     == xenidc_gateway_initiator_resource_state_i_st_sc)
+		    ) {
+			xenidc_gateway_transaction *transaction =
+			    xenidc_gateway_transaction_header_to(resource->
+								 header);
+
+			if (xenidc_local_buffer_reference_query_byte_count
+			    (&status_lbr)
+			    ==
+			    xenidc_local_buffer_reference_query_byte_count
+			    (&transaction->status_lbr)
+			    ) {
+				xenidc_local_buffer_reference_copy
+				    (&transaction->status_lbr, &status_lbr);
+
+				resource->error = error;
+
+				xenidc_gateway_initiator_resource_handle_stimulus
+				    (resource,
+				     xenidc_gateway_initiator_resource_stimulus_ts);
+
+				return_value = 0;
+			}
+		}
+
+		spin_unlock_irqrestore(&resource->lock, flags);
+
+		return return_value;
+	}
+}
+
+static void xenidc_gateway_initiator_resource_invalid_stimulus
+    (xenidc_gateway_initiator_resource * resource,
+     xenidc_gateway_initiator_resource_stimulus stimulus);
+
+static void xenidc_gateway_initiator_resource_set_aborted
+    (xenidc_gateway_initiator_resource * resource);
+
+static void xenidc_gateway_initiator_resource_complete
+    (xenidc_gateway_initiator_resource * resource);
+
+static void xenidc_gateway_initiator_resource_handle_stimulus
+    (xenidc_gateway_initiator_resource * resource,
+     xenidc_gateway_initiator_resource_stimulus stimulus) {
+	trace3
+	    ("gateway initiator resource %p in state %d received stimulus %d",
+	     resource, resource->state, stimulus);
+
+	switch (resource->state) {
+	case xenidc_gateway_initiator_resource_state_i:
+		switch (stimulus) {
+		case xenidc_gateway_initiator_resource_stimulus_sm:
+			resource->state =
+			    xenidc_gateway_initiator_resource_state_i_sm;
+			break;
+		case xenidc_gateway_initiator_resource_stimulus_st:
+			resource->state =
+			    xenidc_gateway_initiator_resource_state_i_st;
+			break;
+		case xenidc_gateway_initiator_resource_stimulus_ab:
+			break;
+		default:
+			xenidc_gateway_initiator_resource_invalid_stimulus
+			    (resource, stimulus);
+			break;
+		}
+		break;
+	case xenidc_gateway_initiator_resource_state_i_sm:
+		switch (stimulus) {
+		case xenidc_gateway_initiator_resource_stimulus_ab:
+			break;
+		case xenidc_gateway_initiator_resource_stimulus_sc:
+			resource->state =
+			    xenidc_gateway_initiator_resource_state_i;
+			xenidc_gateway_initiator_resource_complete(resource);
+			break;
+		default:
+			xenidc_gateway_initiator_resource_invalid_stimulus
+			    (resource, stimulus);
+			break;
+		}
+		break;
+	case xenidc_gateway_initiator_resource_state_i_st:
+		switch (stimulus) {
+		case xenidc_gateway_initiator_resource_stimulus_ab:
+			resource->state =
+			    xenidc_gateway_initiator_resource_state_i_st_ab;
+			break;
+		case xenidc_gateway_initiator_resource_stimulus_sc:
+			resource->state =
+			    xenidc_gateway_initiator_resource_state_i_st_sc;
+			break;
+		case xenidc_gateway_initiator_resource_stimulus_ts:
+			resource->state =
+			    xenidc_gateway_initiator_resource_state_i_st_ts;
+			break;
+		default:
+			xenidc_gateway_initiator_resource_invalid_stimulus
+			    (resource, stimulus);
+			break;
+		}
+		break;
+	case xenidc_gateway_initiator_resource_state_i_st_ab:
+		switch (stimulus) {
+		case xenidc_gateway_initiator_resource_stimulus_sc:
+			resource->state =
+			    xenidc_gateway_initiator_resource_state_i;
+			xenidc_gateway_initiator_resource_set_aborted(resource);
+			xenidc_gateway_initiator_resource_complete(resource);
+			break;
+		default:
+			xenidc_gateway_initiator_resource_invalid_stimulus
+			    (resource, stimulus);
+			break;
+		}
+		break;
+	case xenidc_gateway_initiator_resource_state_i_st_sc:
+		switch (stimulus) {
+		case xenidc_gateway_initiator_resource_stimulus_ab:
+			resource->state =
+			    xenidc_gateway_initiator_resource_state_i;
+			xenidc_gateway_initiator_resource_set_aborted(resource);
+			xenidc_gateway_initiator_resource_complete(resource);
+			break;
+		case xenidc_gateway_initiator_resource_stimulus_ts:
+			resource->state =
+			    xenidc_gateway_initiator_resource_state_i;
+			xenidc_gateway_initiator_resource_complete(resource);
+			break;
+		default:
+			xenidc_gateway_initiator_resource_invalid_stimulus
+			    (resource, stimulus);
+			break;
+		}
+		break;
+	case xenidc_gateway_initiator_resource_state_i_st_ts:
+		switch (stimulus) {
+		case xenidc_gateway_initiator_resource_stimulus_ab:
+			break;
+		case xenidc_gateway_initiator_resource_stimulus_sc:
+			resource->state =
+			    xenidc_gateway_initiator_resource_state_i;
+			xenidc_gateway_initiator_resource_complete(resource);
+			break;
+		default:
+			xenidc_gateway_initiator_resource_invalid_stimulus
+			    (resource, stimulus);
+			break;
+		}
+		break;
+	default:
+		xenidc_gateway_initiator_resource_invalid_stimulus
+		    (resource, stimulus);
+		break;
+	}
+}
+
+static void xenidc_gateway_initiator_resource_invalid_stimulus
+    (xenidc_gateway_initiator_resource * resource,
+     xenidc_gateway_initiator_resource_stimulus stimulus) {
+	trace();
+
+	printk
+	    (KERN_ERR "xenidc: gateway initiator resource %p in state %d"
+	     "received invalid stimulus %d",
+	     resource, resource->state, stimulus);
+}
+
+static void xenidc_gateway_initiator_resource_set_aborted
+    (xenidc_gateway_initiator_resource * resource) {
+	trace();
+
+	resource->error = resource->aborted_error;
+}
+
+static void xenidc_gateway_initiator_resource_complete
+    (xenidc_gateway_initiator_resource * resource) {
+	trace();
+
+	xenidc_callback_complete(&resource->header->callback, resource->error);
+
+	xenidc_callback_success(&resource->callback);
+}
diff -r 1786d40e66b8 -r b4eca2889318 linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_initiator_resource.h
--- /dev/null	Sun Nov 20 17:45:04 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_initiator_resource.h	Sun Nov 20 17:45:16 2005
@@ -0,0 +1,78 @@
+#ifndef _XENIDC_GATEWAY_INITIATOR_RESOURCE_H
+#define _XENIDC_GATEWAY_INITIATOR_RESOURCE_H
+
+#include <asm-xen/xenidc_concatenate.h>
+#include <asm-xen/xenidc_channel.h>
+#include <asm-xen/xenidc_gateway.h>
+#include "xenidc_gateway_ring.h"
+
+typedef enum {
+	xenidc_gateway_initiator_resource_state_i,
+	xenidc_gateway_initiator_resource_state_i_sm,
+	xenidc_gateway_initiator_resource_state_i_st,
+	xenidc_gateway_initiator_resource_state_i_st_ab,
+	xenidc_gateway_initiator_resource_state_i_st_sc,
+	xenidc_gateway_initiator_resource_state_i_st_ts
+} xenidc_gateway_initiator_resource_state;
+
+typedef enum {
+	xenidc_gateway_initiator_resource_stimulus_sm,	/* Start message      */
+	xenidc_gateway_initiator_resource_stimulus_st,	/* Start transaction  */
+	xenidc_gateway_initiator_resource_stimulus_ab,	/* Abort              */
+	xenidc_gateway_initiator_resource_stimulus_sc,	/* Send complete      */
+	xenidc_gateway_initiator_resource_stimulus_ts,	/* Transaction status */
+} xenidc_gateway_initiator_resource_stimulus;
+
+struct xenidc_gateway_initiator_resource_struct {
+	xenidc_callback callback;
+	xenidc_gateway *gateway;
+	int id;
+	spinlock_t lock;
+	xenidc_gateway_initiator_resource_state state;
+	xenidc_gateway_message_and_transaction_header *header;
+	xenidc_error aborted_error;
+	xenidc_error error;
+	xenidc_channel_message channel_message;
+	xenidc_local_buffer_reference element_lbr;
+	xenidc_concatenate_base base;
+	union {
+		xenidc_gateway_parameters_ring_element parameters_element;
+		xenidc_gateway_message_ring_element message_element;
+	};
+};
+
+#define XENIDC_GATEWAY_INITIATOR_RESOURCE_LINK callback.XENIDC_CALLBACK_LINK
+
+static inline struct list_head *xenidc_gateway_initiator_resource_to_link
+    (xenidc_gateway_initiator_resource * resource) {
+	return &resource->XENIDC_GATEWAY_INITIATOR_RESOURCE_LINK;
+}
+
+static inline xenidc_gateway_initiator_resource
+    *xenidc_gateway_initiator_resource_callback_to(xenidc_callback * callback)
+{
+	return container_of
+	    (callback, xenidc_gateway_initiator_resource, callback);
+}
+
+static inline xenidc_gateway *xenidc_gateway_initiator_resource_query_gateway
+    (xenidc_gateway_initiator_resource * resource) {
+	return resource->gateway;
+}
+
+void xenidc_gateway_initiator_resource_init
+    (xenidc_gateway_initiator_resource * resource,
+     xenidc_gateway * gateway, xenidc_callback_function callback, int id);
+
+void xenidc_gateway_initiator_resource_start
+    (xenidc_gateway_initiator_resource * resource,
+     xenidc_gateway_message_and_transaction_header * header);
+
+void xenidc_gateway_initiator_resource_abort
+    (xenidc_gateway_initiator_resource * resource, xenidc_error error);
+
+int xenidc_gateway_initiator_resource_handle_status
+    (xenidc_gateway_initiator_resource * resource,
+     xenidc_error error, xenidc_local_buffer_reference status);
+
+#endif
diff -r 1786d40e66b8 -r b4eca2889318 linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_ring.h
--- /dev/null	Sun Nov 20 17:45:04 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_ring.h	Sun Nov 20 17:45:16 2005
@@ -0,0 +1,65 @@
+/*****************************************************************************/
+/* Xen inter-domain communication gateway ring structure definitions.        */
+/*                                                                           */
+/* 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_GATEWAY_RING_H
+#define _XENIDC_GATEWAY_RING_H
+
+#include <asm-xen/xenidc_error.h>
+
+typedef struct xenidc_gateway_ring_element_header_struct
+ xenidc_gateway_ring_element_header;
+
+struct xenidc_gateway_ring_element_header_struct {
+	u8 type;
+	u8 reserved[7];
+};
+
+#define XENIDC_GATEWAY_RING_ELEMENT_TYPE_MESSAGE    0
+#define XENIDC_GATEWAY_RING_ELEMENT_TYPE_PARAMETERS 1
+#define XENIDC_GATEWAY_RING_ELEMENT_TYPE_STATUS     2
+
+typedef struct xenidc_gateway_message_ring_element_struct
+ xenidc_gateway_message_ring_element;
+
+struct xenidc_gateway_message_ring_element_struct {
+	xenidc_gateway_ring_element_header header;
+};
+
+typedef struct xenidc_gateway_parameters_ring_element_struct
+ xenidc_gateway_parameters_ring_element;
+
+struct xenidc_gateway_parameters_ring_element_struct {
+	xenidc_gateway_ring_element_header header;
+	u32 id;
+	u16 status_byte_count;
+	u16 reserved;
+};
+
+typedef struct xenidc_gateway_status_ring_element_struct
+ xenidc_gateway_status_ring_element;
+
+struct xenidc_gateway_status_ring_element_struct {
+	xenidc_gateway_ring_element_header header;
+	u32 id;
+	xenidc_error error;
+};
+
+#endif
diff -r 1786d40e66b8 -r b4eca2889318 linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_target_resource.c
--- /dev/null	Sun Nov 20 17:45:04 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_target_resource.c	Sun Nov 20 17:45:16 2005
@@ -0,0 +1,190 @@
+/*****************************************************************************/
+/* The xenidc_gateway_target_resource object performs the target-side part   */
+/* of the processing of a client message or transaction sent across the      */
+/* gateway.                                                                  */
+/*                                                                           */
+/* 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                   */
+/*                                                                           */
+/*****************************************************************************/
+
+#include <asm-xen/xenidc_vaddress.h>
+#include "xenidc_gateway_target_resource.h"
+#include "xenidc_trace.h"
+
+extern void xenidc_gateway_submit_channel_message
+    (xenidc_gateway * gateway, xenidc_channel_message * message);
+
+extern void xenidc_gateway_submit_message_to_client
+    (xenidc_gateway * gateway, xenidc_gateway_message * message);
+
+extern void xenidc_gateway_submit_transaction_to_client
+    (xenidc_gateway * gateway, xenidc_gateway_transaction * transaction);
+
+static void xenidc_gateway_target_resource_channel_message_callback
+    (xenidc_callback * callback);
+
+void xenidc_gateway_target_resource_init
+    (xenidc_gateway_target_resource * resource,
+     xenidc_gateway * gateway,
+     xenidc_callback_function callback, xenidc_local_buffer_reference buffer) {
+	trace();
+
+	xenidc_callback_init(&resource->callback, callback);
+
+	resource->gateway = gateway;
+
+	resource->buffer = buffer;
+
+	xenidc_callback_init
+	    (xenidc_channel_message_to_callback(&resource->channel_message),
+	     xenidc_gateway_target_resource_channel_message_callback);
+
+	resource->element_lbr = xenidc_vaddress_create_lbr
+	    (&resource->status_element, sizeof(resource->status_element));
+
+	memset(&resource->status_element, 0, sizeof(resource->status_element));
+
+	resource->status_element.header.type =
+	    XENIDC_GATEWAY_RING_ELEMENT_TYPE_STATUS;
+}
+
+static void xenidc_gateway_target_resource_message_callback
+    (xenidc_callback * callback);
+
+void xenidc_gateway_target_resource_start_message
+    (xenidc_gateway_target_resource * resource,
+     xenidc_local_buffer_reference message_lbr) {
+	trace();
+
+	/* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+	xenidc_gateway_message_init
+	    (&resource->message,
+	     xenidc_gateway_target_resource_message_callback);
+
+	{
+		xenidc_local_buffer_reference lbr = resource->buffer;
+
+		xenidc_local_buffer_reference_truncate
+		    (&lbr,
+		     xenidc_local_buffer_reference_copy(&lbr, &message_lbr)
+		    );
+
+		resource->message.message_lbr = lbr;
+	}
+
+	xenidc_gateway_submit_message_to_client
+	    (resource->gateway, &resource->message);
+}
+
+static void xenidc_gateway_target_resource_message_callback
+    (xenidc_callback * callback) {
+	trace();
+
+	{
+		xenidc_gateway_target_resource *resource = container_of
+		    (xenidc_gateway_message_callback_to(callback),
+		     xenidc_gateway_target_resource,
+		     message);
+
+		xenidc_callback_success(&resource->callback);
+	}
+}
+
+static void xenidc_gateway_target_resource_transaction_callback
+    (xenidc_callback * callback);
+
+void xenidc_gateway_target_resource_start_transaction
+    (xenidc_gateway_target_resource * resource,
+     u32 id,
+     xenidc_local_buffer_reference parameters_lbr,
+     xenidc_buffer_byte_count status_byte_count) {
+	trace();
+
+	/* MUST MAINTAIN RELATIVE REQUEST ORDER ON THE SUBMISSION PATH */
+
+	xenidc_gateway_transaction_init
+	    (&resource->transaction,
+	     xenidc_gateway_target_resource_transaction_callback);
+
+	{
+		xenidc_local_buffer_reference lbr = resource->buffer;
+
+		xenidc_local_buffer_reference_truncate
+		    (&lbr,
+		     xenidc_local_buffer_reference_copy(&lbr, &parameters_lbr)
+		    );
+
+		resource->transaction.parameters_lbr = lbr;
+	}
+
+	{
+		xenidc_local_buffer_reference lbr = resource->buffer;
+
+		xenidc_local_buffer_reference_subrange
+		    (&lbr,
+		     xenidc_local_buffer_reference_query_byte_count
+		     (&parameters_lbr), status_byte_count);
+
+		xenidc_local_buffer_reference_zero(&lbr);
+
+		resource->transaction.status_lbr = lbr;
+	}
+
+	resource->status_element.id = id;
+
+	xenidc_gateway_submit_transaction_to_client
+	    (resource->gateway, &resource->transaction);
+}
+
+static void xenidc_gateway_target_resource_transaction_callback
+    (xenidc_callback * callback) {
+	trace();
+
+	{
+		xenidc_gateway_target_resource *resource = container_of
+		    (xenidc_gateway_transaction_callback_to(callback),
+		     xenidc_gateway_target_resource,
+		     transaction);
+
+		resource->status_element.error =
+		    xenidc_callback_query_error(callback);
+
+		resource->channel_message.message_lbr =
+		    xenidc_concatenate_create_lbr(&resource->base,
+						  &resource->element_lbr,
+						  &resource->transaction.
+						  status_lbr);
+
+		xenidc_gateway_submit_channel_message
+		    (resource->gateway, &resource->channel_message);
+	}
+}
+
+static void xenidc_gateway_target_resource_channel_message_callback
+    (xenidc_callback * callback) {
+	trace();
+
+	{
+		xenidc_gateway_target_resource *resource = container_of
+		    (callback,
+		     xenidc_gateway_target_resource,
+		     channel_message.callback);
+
+		xenidc_callback_success(&resource->callback);
+	}
+}
diff -r 1786d40e66b8 -r b4eca2889318 linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_target_resource.h
--- /dev/null	Sun Nov 20 17:45:04 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/xenidc/xenidc_gateway_target_resource.h	Sun Nov 20 17:45:16 2005
@@ -0,0 +1,79 @@
+/*****************************************************************************/
+/* The xenidc_gateway_target_resource object performs the target-side part   */
+/* of the processing of a client message or transaction sent across the      */
+/* gateway.                                                                  */
+/*                                                                           */
+/* 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_GATEWAY_TARGET_RESOURCE_H
+#define _XENIDC_GATEWAY_TARGET_RESOURCE_H
+
+#include <asm-xen/xenidc_channel.h>
+#include <asm-xen/xenidc_concatenate.h>
+#include <asm-xen/xenidc_gateway.h>
+#include "xenidc_gateway_ring.h"
+
+struct xenidc_gateway_target_resource_struct {
+	xenidc_callback callback;
+	xenidc_gateway *gateway;
+	xenidc_local_buffer_reference buffer;
+	union {
+		xenidc_gateway_message message;
+		xenidc_gateway_transaction transaction;
+	};
+	xenidc_channel_message channel_message;
+	xenidc_local_buffer_reference element_lbr;
+	xenidc_concatenate_base base;
+	xenidc_gateway_status_ring_element status_element;
+};
+
+#define XENIDC_GATEWAY_TARGET_RESOURCE_LINK callback.XENIDC_CALLBACK_LINK
+
+static inline struct list_head *xenidc_gateway_target_resource_to_link
+    (xenidc_gateway_target_resource * resource) {
+	return &resource->XENIDC_GATEWAY_TARGET_RESOURCE_LINK;
+}
+
+static inline xenidc_gateway_target_resource
+    *xenidc_gateway_target_resource_callback_to(xenidc_callback * callback)
+{
+	return container_of(callback, xenidc_gateway_target_resource, callback);
+}
+
+static inline xenidc_gateway *xenidc_gateway_target_resource_query_gateway
+    (xenidc_gateway_target_resource * resource) {
+	return resource->gateway;
+}
+
+extern void xenidc_gateway_target_resource_init
+    (xenidc_gateway_target_resource * resource,
+     xenidc_gateway * gateway,
+     xenidc_callback_function callback, xenidc_local_buffer_reference buffer);
+
+extern void xenidc_gateway_target_resource_start_message
+    (xenidc_gateway_target_resource * resource,
+     xenidc_local_buffer_reference message_lbr);
+
+extern void xenidc_gateway_target_resource_start_transaction
+    (xenidc_gateway_target_resource * resource,
+     u32 id,
+     xenidc_local_buffer_reference parameters_lbr,
+     xenidc_buffer_byte_count status_byte_count);
+
+#endif
diff -r 1786d40e66b8 -r b4eca2889318 linux-2.6-xen-sparse/include/asm-xen/xenidc_gateway.h
--- /dev/null	Sun Nov 20 17:45:04 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/xenidc_gateway.h	Sun Nov 20 17:45:16 2005
@@ -0,0 +1,254 @@
+/*****************************************************************************/
+/* Xen inter-domain communication gateway class. This class uses the message */
+/* channel service provided by a xenidc_channel to implement a gateway       */
+/* service which allows the client to send both messages and transactions    */
+/* (consisting of parameters and status) between domains.                    */
+/*                                                                           */
+/* 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_GATEWAY_H
+#define _XENIDC_GATEWAY_H
+
+#include <asm-xen/xenidc_callback.h>
+#include <asm-xen/xenidc_channel.h>
+#include <asm-xen/xenidc_local_buffer_reference.h>
+
+typedef struct xenidc_gateway_initiator_resource_struct
+ xenidc_gateway_initiator_resource;
+
+typedef struct xenidc_gateway_target_resource_struct
+ xenidc_gateway_target_resource;
+
+/* Messages and transactions share a common header because relative order is */
+/* preserved on submission and so they are queued on the same list.          */
+
+typedef struct xenidc_gateway_message_and_transaction_header_struct
+ xenidc_gateway_message_and_transaction_header;
+
+struct xenidc_gateway_message_and_transaction_header_struct {
+	xenidc_callback callback;
+	int transaction_not_message;
+};
+
+#define XENIDC_GATEWAY_MESSAGE_AND_TRANSACTION_HEADER_LINK \
+callback.XENIDC_CALLBACK_LINK
+
+static inline struct list_head
+    *xenidc_gateway_message_and_transaction_header_to_link
+    (xenidc_gateway_message_and_transaction_header * header) {
+	return xenidc_callback_to_link(&header->callback);
+}
+
+static inline xenidc_callback
+    *xenidc_gateway_message_and_transaction_header_to_callback
+    (xenidc_gateway_message_and_transaction_header * header) {
+	return &header->callback;
+}
+
+/* A xenidc_gateway_message is used to send a message from the local domain  */
+/* to the remote domain using the gateway.  This is also the structure used  */
+/* by the gateway to pass a message to the client.  The receiver gets to     */
+/* hold onto the message as long as necessary and completes the callback to  */
+/* return it when finished with it.                                          */
+
+typedef struct xenidc_gateway_message_struct xenidc_gateway_message;
+
+struct xenidc_gateway_message_struct {
+	xenidc_gateway_message_and_transaction_header header;
+	xenidc_local_buffer_reference message_lbr;
+};
+
+static inline xenidc_callback *xenidc_gateway_message_to_callback
+    (xenidc_gateway_message * message) {
+	return &message->header.callback;
+}
+
+static inline xenidc_gateway_message *xenidc_gateway_message_callback_to
+    (xenidc_callback * callback) {
+	return container_of(callback, xenidc_gateway_message, header.callback);
+}
+
+static inline struct list_head *xenidc_gateway_message_to_link
+    (xenidc_gateway_message * message) {
+	return xenidc_callback_to_link(&message->header.callback);
+}
+
+static inline xenidc_gateway_message *xenidc_gateway_message_link_to
+    (struct list_head *link) {
+	return xenidc_gateway_message_callback_to
+	    (xenidc_callback_link_to(link));
+}
+
+static inline xenidc_gateway_message *xenidc_gateway_message_header_to
+    (xenidc_gateway_message_and_transaction_header * header) {
+	return container_of(header, xenidc_gateway_message, header);
+}
+
+static inline void xenidc_gateway_message_init
+    (xenidc_gateway_message * message, xenidc_callback_function * callback) {
+	xenidc_callback_init
+	    (xenidc_gateway_message_to_callback(message), callback);
+
+	message->header.transaction_not_message = 0;
+}
+
+/* A xenidc_gateway_transaction is used to send a transaction to the remote  */
+/* domain from the local domain.  The transaction passes parameters to the   */
+/* remote domain and gets status back from the remote domain.                */
+/* The structure is used for both sending transactions and when inbound      */
+/* transactions are received.  The target domain completes the transaction   */
+/* with a xenidc_error which is returned to the transaction initiator as the */
+/* error of the callback of the initiators transaction.                      */
+
+typedef struct xenidc_gateway_transaction_struct xenidc_gateway_transaction;
+
+struct xenidc_gateway_transaction_struct {
+	xenidc_gateway_message_and_transaction_header header;
+	xenidc_local_buffer_reference parameters_lbr;
+	xenidc_local_buffer_reference status_lbr;
+};
+
+#define XENIDC_GATEWAY_TRANSACTION_LINK header.callback.XENIDC_CALLBACK_LINK
+
+static inline xenidc_callback *xenidc_gateway_transaction_to_callback
+    (xenidc_gateway_transaction * transaction) {
+	return &transaction->header.callback;
+}
+
+static inline xenidc_gateway_transaction
+    *xenidc_gateway_transaction_callback_to(xenidc_callback * callback)
+{
+	return container_of
+	    (callback, xenidc_gateway_transaction, header.callback);
+}
+
+static inline struct list_head *xenidc_gateway_transaction_to_link
+    (xenidc_gateway_transaction * transaction) {
+	return xenidc_callback_to_link
+	    (xenidc_gateway_transaction_to_callback(transaction));
+}
+
+static inline xenidc_gateway_transaction *xenidc_gateway_transaction_link_to
+    (struct list_head *link) {
+	return xenidc_gateway_transaction_callback_to
+	    (xenidc_callback_link_to(link));
+}
+
+static inline xenidc_gateway_transaction *xenidc_gateway_transaction_header_to
+    (xenidc_gateway_message_and_transaction_header * header) {
+	return container_of(header, xenidc_gateway_transaction, header);
+}
+
+static inline void xenidc_gateway_transaction_init
+    (xenidc_gateway_transaction * transaction,
+     xenidc_callback_function * callback) {
+	xenidc_callback_init
+	    (xenidc_gateway_transaction_to_callback(transaction), callback);
+
+	transaction->header.transaction_not_message = 1;
+}
+
+typedef enum {
+	xenidc_gateway_state_i,
+	xenidc_gateway_state_i_cc,
+	xenidc_gateway_state_i_cc_cd,
+	xenidc_gateway_state_i_cc_lc,
+	xenidc_gateway_state_i_cc_cd_lc,
+	xenidc_gateway_state_i_cc_lc_cd,
+	xenidc_gateway_state_i_cc_lc_cd_km,
+	xenidc_gateway_state_i_cc_cd_lc_lg,
+	xenidc_gateway_state_i_cc_cd_lc_ld,
+	xenidc_gateway_state_i_cc_cd_lc_lg_ld,
+	xenidc_gateway_state_i_cc_cd_lc_lg_ld_ti
+} xenidc_gateway_state;
+
+typedef struct xenidc_gateway_struct xenidc_gateway;
+
+struct xenidc_gateway_struct {
+	xenidc_channel *channel;
+	void (*connect) (xenidc_gateway * gateway);
+	void (*handle_message)
+	 (xenidc_gateway * gateway, xenidc_gateway_message * message);
+	void (*handle_transaction)
+	 (xenidc_gateway * gateway, xenidc_gateway_transaction * transaction);
+	void (*disconnect)
+	 (xenidc_gateway * gateway, xenidc_callback * callback);
+
+	u32 initiator_quota;
+	u32 target_quota;
+	xenidc_buffer_byte_count target_maximum_byte_count;
+
+	struct list_head initiator_resource_list;
+	xenidc_gateway_initiator_resource *initiator_resources;
+
+	struct list_head target_resource_list;
+	xenidc_gateway_target_resource *target_resources;
+
+	spinlock_t lock;
+
+	xenidc_gateway_state state;
+
+	struct list_head message_and_transaction_list;
+	struct list_head channel_message_list;
+
+	xenidc_work kick_messages_and_transactions_1_work;
+	xenidc_work kick_channel_messages_1_work;
+	xenidc_work connect_client_1_work;
+	xenidc_work disconnect_client_1_work;
+	xenidc_callback disconnect_client_2_callback;
+
+	int kick_messages_and_transactions_out:1;
+	int kick_channel_messages_out:1;
+	u32 initiator_resources_out;
+	u32 target_resources_out;
+
+	xenidc_callback *channel_disconnect_callback;
+};
+
+/* Initialised with underlying channel to use to send inter-domain messages  */
+/* and client's callbacks and required quotas.                               */
+
+extern int xenidc_gateway_init
+    (xenidc_gateway * gateway,
+     xenidc_channel * channel,
+     void (*connect) (xenidc_gateway * gateway), void (*handle_message)
+      (xenidc_gateway * gateway, xenidc_gateway_message * message),
+     void (*handle_transaction)
+      (xenidc_gateway * gateway, xenidc_gateway_transaction * transaction),
+     void (*disconnect)
+      (xenidc_gateway * gateway, xenidc_callback * callback),
+     u32 initiator_quota,
+     xenidc_buffer_byte_count initiator_maximum_byte_count,
+     u32 target_quota, xenidc_buffer_byte_count target_maximum_byte_count);
+
+/* Called by client between connect and disconnect callback to submit a      */
+/* message.                                                                  */
+
+extern void xenidc_gateway_submit_message
+    (xenidc_gateway * gateway, xenidc_gateway_message * message);
+
+/* Called by client between connect and disconnect callback to submit a      */
+/* transaction.                                                              */
+
+extern void xenidc_gateway_submit_transaction
+    (xenidc_gateway * gateway, xenidc_gateway_transaction * transaction);
+
+extern void xenidc_gateway_exit(xenidc_gateway * gateway);
+
+#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][9/17] USB virt 2.6 split driver---gateway 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.