[ofa-general] Re: [PATCH 2/2] IB/iser: add backport & kernel addons for open-iscsi over iSER support for RHAS4 up3 and up4

Erez Zilber erezz at voltaire.com
Sun May 20 23:28:35 PDT 2007


Michael S. Tsirkin wrote:
>> Quoting Erez Zilber <erezz at voltaire.com>:
>> Subject: [PATCH 2/2] IB/iser: add backport & kernel addons for open-iscsi over iSER support for RHAS4 up3 and up4
>>
>>
>> Add the required backport patches & kernel addons for open-iscsi
>> over iSER in RHAS4 up3 and up4.
>>
>> Signed-off-by: Erez Zilber <erezz at voltaire.com>
> 
> In addition to posting patches, could you pls publish a git tree to pull from,
> please? This makes it easy to test-build the patch as our build system
> knows how to do git checkout.

Added a git tree:

http://www.openfabrics.org/git/?p=~erezz/ofed_1_2_iser_rh4.git;a=summary

> 
> ---
> 
> Two comments, generally
> A: Please move code from kernel_patches to kernel_addons as much
>    as possible. There are many places where you just add new headers,
>    or add #include directives, or change the function called or
>    remove extra parameters, all this can and should be done through addons.
> 

Done

> B: Please do not add code to core unless there is more than 1 user -
>    add it to the iser module instead. This way if there is
>    compilation failure there, you do not break core for people.

Done

> 
> Some specifics below:
> ....
> 
>> 
>> diff --git a/kernel_patches/backport/2.6.9_U3/add_open_iscsi.patch b/kernel_patches/backport/2.6.9_U3/add_open_iscsi.patch
>> new file mode 100644
>> index 0000000..d77c663
>> --- /dev/null
>> +++ b/kernel_patches/backport/2.6.9_U3/add_open_iscsi.patch
>> @@ -0,0 +1,504 @@
>> +diff -rup linux-2.6.20/drivers/scsi/iscsi_tcp.c linux-2.6.20-backport-rh4-u3/drivers/scsi/iscsi_tcp.c
>> +--- linux-2.6.20/drivers/scsi/iscsi_tcp.c	2007-02-04 20:44:54.000000000 +0200
>> ++++ linux-2.6.20-backport-rh4-u3/drivers/scsi/iscsi_tcp.c	2007-04-01 13:11:17.000000000 +0300
> 
> ...
>> +@@ -108,7 +108,7 @@ iscsi_hdr_digest(struct iscsi_conn *conn
>> + {
>> + 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
>> + 
>> +-	crypto_hash_digest(&tcp_conn->tx_hash, &buf->sg, buf->sg.length, crc);
>> ++	crypto_digest_digest(tcp_conn->tx_tfm, &buf->sg, 1, crc);
>> + 	buf->sg.length = tcp_conn->hdr_size;
>> + }
>> + 
> 
> You could make it a macro in addons if you had named the new field tx_hash.

I fixed that and other crypto function calls whenever possible.

>> + 
>> + struct iscsi_internal {
>> + 	int daemon_pid;
>> +@@ -65,6 +69,8 @@ static DEFINE_SPINLOCK(iscsi_transport_l
>> + #define cdev_to_iscsi_internal(_cdev) \
>> + 	container_of(_cdev, struct iscsi_internal, cdev)
>> + 
>> ++extern int attribute_container_init(void);
>> ++
> 
> This does not look scsi-related. Why does this belong here?

This is a hack. In 2.6.20, attribute_container_init is called from drivers/base/init.c. Since I cannot do that, I'm calling it from the init function in scsi_transport_iscsi (because scsi_transport_iscsi uses the attribute container). Do you have a better suggestion?

> 
>> diff --git a/kernel_patches/backport/2.6.9_U3/fix_inclusion_order_iscsi_iser.patch b/kernel_patches/backport/2.6.9_U3/fix_inclusion_order_iscsi_iser.patch
>> new file mode 100644
>> index 0000000..3c2a969
>> --- /dev/null
>> +++ b/kernel_patches/backport/2.6.9_U3/fix_inclusion_order_iscsi_iser.patch
>> @@ -0,0 +1,13 @@
>> +--- linux-2.6.20-rc7-orig/drivers/infiniband/ulp/iser/iscsi_iser.c	2007-02-08 09:13:43.000000000 +0200
>> ++++ linux-2.6.20-rc7/drivers/infiniband/ulp/iser/iscsi_iser.c	2007-02-08 09:14:31.000000000 +0200
>> +@@ -70,9 +70,8 @@
>> + #include <scsi/scsi_tcq.h>
>> + #include <scsi/scsi_host.h>
>> + #include <scsi/scsi.h>
>> +-#include <scsi/scsi_transport_iscsi.h>
>> +-
>> + #include "iscsi_iser.h"
>> ++#include <scsi/scsi_transport_iscsi.h>
>> + 
>> + static unsigned int iscsi_max_lun = 512;
>> + module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
> 
> Looks like the right thing to do anyway.
> So put it in fixes instead, and post upstream.

It is not required in newer kernels: mutex.h is included from include/scsi/scsi_host.h. Therefore, I don't want to post a patch upstream. Maybe we can add this inclusion to kernel_addons/backport/2.6.9_U4/include/scsi/scsi_host.h. What do you think?

> 
>> diff --git a/kernel_patches/backport/2.6.9_U3/linux_stuff_to_2_6_17.patch b/kernel_patches/backport/2.6.9_U3/linux_stuff_to_2_6_17.patch
>> index e84b964..52c0136 100644
>> --- a/kernel_patches/backport/2.6.9_U3/linux_stuff_to_2_6_17.patch
>> +++ b/kernel_patches/backport/2.6.9_U3/linux_stuff_to_2_6_17.patch
>> @@ -19,6 +19,62 @@ index 0000000..58cf933
>>  +++ b/drivers/infiniband/core/kfifo.c
>>  @@ -0,0 +1 @@
>>  +#include "src/kfifo.c"
>> +diff --git a/drivers/infiniband/core/init.c b/drivers/infiniband/core/init.c
>> +new file mode 100644
>> +index 0000000..58cf933
>> +--- /dev/null
>> ++++ b/drivers/infiniband/core/init.c
>> +@@ -0,0 +1 @@
>> ++#include "src/init.c"
>> +diff --git a/drivers/infiniband/core/attribute_container.c b/drivers/infiniband/core/attribute_container.c
>> +new file mode 100644
>> +index 0000000..58cf933
>> +--- /dev/null
>> ++++ b/drivers/infiniband/core/attribute_container.c
>> +@@ -0,0 +1 @@
>> ++#include "src/attribute_container.c"
...
>> +diff --git a/drivers/infiniband/core/kref_new.c b/drivers/infiniband/core/kref_new.c
>> +new file mode 100644
>> +index 0000000..58cf933
>> +--- /dev/null
>> ++++ b/drivers/infiniband/core/kref_new.c
>> +@@ -0,0 +1 @@
>> ++#include "src/kref_new.c"
>>  diff --git a/drivers/infiniband/core/Makefile b/drivers/infiniband/core/Makefile
>>  index 50fb1cd..456bfd0 100644
>>  --- a/drivers/infiniband/core/Makefile
>> @@ -28,4 +84,4 @@ index 50fb1cd..456bfd0 100644
>>   ib_uverbs-y :=			uverbs_main.o uverbs_cmd.o uverbs_mem.o \
>>   				uverbs_marshall.o
>>  +
>> -+ib_core-y +=			genalloc.o netevent.o kfifo.o
>> ++ib_core-y +=			genalloc.o netevent.o kfifo.o scsi.o scsi_lib.o scsi_scan.o init.o attribute_container.o transport_class.o klist.o kref_new.o
> 
> Can we make these part of iser place?
> Linking scsi stuff into core does not look right.

Moved that into open-iscsi modules. This code is required for open-iscsi over any transport (not just iSER).

Here's the fixed patch (also available on my git tree):

diff --git a/kernel_addons/backport/2.6.9_U3/include/linux/attribute_container.h b/kernel_addons/backport/2.6.9_U3/include/linux/attribute_container.h
new file mode 100644
index 0000000..93bfb0b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/linux/attribute_container.h
@@ -0,0 +1,71 @@
+/*
+ * class_container.h - a generic container for all classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ */
+
+#ifndef _ATTRIBUTE_CONTAINER_H_
+#define _ATTRIBUTE_CONTAINER_H_
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/klist.h>
+#include <linux/spinlock.h>
+
+struct attribute_container {
+	struct list_head	node;
+	struct klist		containers;
+	struct class		*class;
+	struct class_device_attribute **attrs;
+	int (*match)(struct attribute_container *, struct device *);
+#define	ATTRIBUTE_CONTAINER_NO_CLASSDEVS	0x01
+	unsigned long		flags;
+};
+
+static inline int
+attribute_container_no_classdevs(struct attribute_container *atc)
+{
+	return atc->flags & ATTRIBUTE_CONTAINER_NO_CLASSDEVS;
+}
+
+static inline void
+attribute_container_set_no_classdevs(struct attribute_container *atc)
+{
+	atc->flags |= ATTRIBUTE_CONTAINER_NO_CLASSDEVS;
+}
+
+int attribute_container_register(struct attribute_container *cont);
+int attribute_container_unregister(struct attribute_container *cont);
+void attribute_container_create_device(struct device *dev,
+				       int (*fn)(struct attribute_container *,
+						 struct device *,
+						 struct class_device *));
+void attribute_container_add_device(struct device *dev,
+				    int (*fn)(struct attribute_container *,
+					      struct device *,
+					      struct class_device *));
+void attribute_container_remove_device(struct device *dev,
+				       void (*fn)(struct attribute_container *,
+						  struct device *,
+						  struct class_device *));
+void attribute_container_device_trigger(struct device *dev, 
+					int (*fn)(struct attribute_container *,
+						  struct device *,
+						  struct class_device *));
+void attribute_container_trigger(struct device *dev, 
+				 int (*fn)(struct attribute_container *,
+					   struct device *));
+int attribute_container_add_attrs(struct class_device *classdev);
+int attribute_container_add_class_device(struct class_device *classdev);
+int attribute_container_add_class_device_adapter(struct attribute_container *cont,
+						 struct device *dev,
+						 struct class_device *classdev);
+void attribute_container_remove_attrs(struct class_device *classdev);
+void attribute_container_class_device_del(struct class_device *classdev);
+struct attribute_container *attribute_container_classdev_to_container(struct class_device *);
+struct class_device *attribute_container_find_class_device(struct attribute_container *, struct device *);
+struct class_device_attribute **attribute_container_classdev_to_attrs(const struct class_device *classdev);
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U3/include/linux/crypto.h b/kernel_addons/backport/2.6.9_U3/include/linux/crypto.h
new file mode 100644
index 0000000..aecccde
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/linux/crypto.h
@@ -0,0 +1,11 @@
+#ifndef LINUX_CRYPTO_BACKPORT_H
+#define LINUX_CRYPTO_BACKPORT_H
+
+#include_next <linux/crypto.h>
+
+#define crypto_hash_init(desc) crypto_digest_init(*desc)
+#define crypto_hash_digest(desc, sg, nbytes, out) crypto_digest_digest(*desc, sg, 1, out)
+#define crypto_hash_update(desc, sg, nbytes) crypto_digest_update(*desc, sg, 1)
+#define crypto_hash_final(desc, out) crypto_digest_final(*desc, out)
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U3/include/linux/kernel.h b/kernel_addons/backport/2.6.9_U3/include/linux/kernel.h
index a37dcd5..02a5907 100644
--- a/kernel_addons/backport/2.6.9_U3/include/linux/kernel.h
+++ b/kernel_addons/backport/2.6.9_U3/include/linux/kernel.h
@@ -4,4 +4,7 @@ #define BACKPORT_KERNEL_H_2_6_19
 #include_next <linux/kernel.h>
 #include <linux/log2.h>
 
+#define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+#define NIPQUAD_FMT "%u.%u.%u.%u"
+
 #endif
diff --git a/kernel_addons/backport/2.6.9_U3/include/linux/kfifo.h b/kernel_addons/backport/2.6.9_U3/include/linux/kfifo.h
index 48eccd8..2b94461 100644
--- a/kernel_addons/backport/2.6.9_U3/include/linux/kfifo.h
+++ b/kernel_addons/backport/2.6.9_U3/include/linux/kfifo.h
@@ -25,6 +25,7 @@ #ifdef __KERNEL__
 
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
+#include <linux/gfp.h>
 
 struct kfifo {
 	unsigned char *buffer;	/* the buffer holding the data */
diff --git a/kernel_addons/backport/2.6.9_U3/include/linux/klist.h b/kernel_addons/backport/2.6.9_U3/include/linux/klist.h
new file mode 100644
index 0000000..7407125
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/linux/klist.h
@@ -0,0 +1,61 @@
+/*
+ *	klist.h - Some generic list helpers, extending struct list_head a bit.
+ *
+ *	Implementations are found in lib/klist.c
+ *
+ *
+ *	Copyright (C) 2005 Patrick Mochel
+ *
+ *	This file is rleased under the GPL v2.
+ */
+
+#ifndef _LINUX_KLIST_H
+#define _LINUX_KLIST_H
+
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/kref.h>
+#include <linux/list.h>
+
+struct klist_node;
+struct klist {
+	spinlock_t		k_lock;
+	struct list_head	k_list;
+	void			(*get)(struct klist_node *);
+	void			(*put)(struct klist_node *);
+};
+
+
+extern void klist_init(struct klist * k, void (*get)(struct klist_node *),
+		       void (*put)(struct klist_node *));
+
+struct klist_node {
+	struct klist		* n_klist;
+	struct list_head	n_node;
+	struct kref		n_ref;
+	struct completion	n_removed;
+};
+
+extern void klist_add_tail(struct klist_node * n, struct klist * k);
+extern void klist_add_head(struct klist_node * n, struct klist * k);
+
+extern void klist_del(struct klist_node * n);
+extern void klist_remove(struct klist_node * n);
+
+extern int klist_node_attached(struct klist_node * n);
+
+
+struct klist_iter {
+	struct klist		* i_klist;
+	struct list_head	* i_head;
+	struct klist_node	* i_cur;
+};
+
+
+extern void klist_iter_init(struct klist * k, struct klist_iter * i);
+extern void klist_iter_init_node(struct klist * k, struct klist_iter * i, 
+				 struct klist_node * n);
+extern void klist_iter_exit(struct klist_iter * i);
+extern struct klist_node * klist_next(struct klist_iter * i);
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U3/include/linux/memory.h b/kernel_addons/backport/2.6.9_U3/include/linux/memory.h
new file mode 100644
index 0000000..654ef55
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/linux/memory.h
@@ -0,0 +1,89 @@
+/*
+ * include/linux/memory.h - generic memory definition
+ *
+ * This is mainly for topological representation. We define the
+ * basic "struct memory_block" here, which can be embedded in per-arch
+ * definitions or NUMA information.
+ *
+ * Basic handling of the devices is done in drivers/base/memory.c
+ * and system devices are handled in drivers/base/sys.c.
+ *
+ * Memory block are exported via sysfs in the class/memory/devices/
+ * directory.
+ *
+ */
+#ifndef _LINUX_MEMORY_H_
+#define _LINUX_MEMORY_H_
+
+#include <linux/sysdev.h>
+#include <linux/node.h>
+#include <linux/compiler.h>
+
+#include <asm/semaphore.h>
+
+struct memory_block {
+	unsigned long phys_index;
+	unsigned long state;
+	/*
+	 * This serializes all state change requests.  It isn't
+	 * held during creation because the control files are
+	 * created long after the critical areas during
+	 * initialization.
+	 */
+	struct semaphore state_sem;
+	int phys_device;		/* to which fru does this belong? */
+	void *hw;			/* optional pointer to fw/hw data */
+	int (*phys_callback)(struct memory_block *);
+	struct sys_device sysdev;
+};
+
+/* These states are exposed to userspace as text strings in sysfs */
+#define	MEM_ONLINE		(1<<0) /* exposed to userspace */
+#define	MEM_GOING_OFFLINE	(1<<1) /* exposed to userspace */
+#define	MEM_OFFLINE		(1<<2) /* exposed to userspace */
+
+/*
+ * All of these states are currently kernel-internal for notifying
+ * kernel components and architectures.
+ *
+ * For MEM_MAPPING_INVALID, all notifier chains with priority >0
+ * are called before pfn_to_page() becomes invalid.  The priority=0
+ * entry is reserved for the function that actually makes
+ * pfn_to_page() stop working.  Any notifiers that want to be called
+ * after that should have priority <0.
+ */
+#define	MEM_MAPPING_INVALID	(1<<3)
+
+struct notifier_block;
+struct mem_section;
+
+#ifndef CONFIG_MEMORY_HOTPLUG_SPARSE
+static inline int memory_dev_init(void)
+{
+	return 0;
+}
+static inline int register_memory_notifier(struct notifier_block *nb)
+{
+	return 0;
+}
+static inline void unregister_memory_notifier(struct notifier_block *nb)
+{
+}
+#else
+extern int register_new_memory(struct mem_section *);
+extern int unregister_memory_section(struct mem_section *);
+extern int memory_dev_init(void);
+extern int remove_memory_block(unsigned long, struct mem_section *, int);
+
+#define CONFIG_MEM_BLOCK_SIZE	(PAGES_PER_SECTION<<PAGE_SHIFT)
+
+
+#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
+
+#define hotplug_memory_notifier(fn, pri) {			\
+	static struct notifier_block fn##_mem_nb =		\
+		{ .notifier_call = fn, .priority = pri };	\
+	register_memory_notifier(&fn##_mem_nb);			\
+}
+
+#endif /* _LINUX_MEMORY_H_ */
diff --git a/kernel_addons/backport/2.6.9_U3/include/linux/netlink.h b/kernel_addons/backport/2.6.9_U3/include/linux/netlink.h
new file mode 100644
index 0000000..6d69105
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/linux/netlink.h
@@ -0,0 +1,14 @@
+#ifndef BACKPORT_LINUX_NETLINK_H
+#define BACKPORT_LINUX_NETLINK_H
+
+#include_next <linux/netlink.h>
+
+#define __nlmsg_put(skb, daemon_pid, seq, type, len, flags) \
+       __nlmsg_put(skb, daemon_pid, 0, 0, len)
+
+#define netlink_kernel_create(uint, groups, input, mod) \
+       netlink_kernel_create(uint, input)
+
+#define NETLINK_ISCSI           8
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U3/include/linux/transport_class.h b/kernel_addons/backport/2.6.9_U3/include/linux/transport_class.h
new file mode 100644
index 0000000..1d6cc22
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/linux/transport_class.h
@@ -0,0 +1,100 @@
+/*
+ * transport_class.h - a generic container for all transport classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ */
+
+#ifndef _TRANSPORT_CLASS_H_
+#define _TRANSPORT_CLASS_H_
+
+#include <linux/device.h>
+#include <linux/attribute_container.h>
+
+struct transport_container;
+
+struct transport_class {
+	struct class class;
+	int (*setup)(struct transport_container *, struct device *,
+		     struct class_device *);
+	int (*configure)(struct transport_container *, struct device *,
+			 struct class_device *);
+	int (*remove)(struct transport_container *, struct device *,
+		      struct class_device *);
+};
+
+#define DECLARE_TRANSPORT_CLASS(cls, nm, su, rm, cfg)			\
+struct transport_class cls = {						\
+	.class = {							\
+		.name = nm,						\
+	},								\
+	.setup = su,							\
+	.remove = rm,							\
+	.configure = cfg,						\
+}
+
+
+struct anon_transport_class {
+	struct transport_class tclass;
+	struct attribute_container container;
+};
+
+#define DECLARE_ANON_TRANSPORT_CLASS(cls, mtch, cfg)		\
+struct anon_transport_class cls = {				\
+	.tclass = {						\
+		.configure = cfg,				\
+	},							\
+	. container = {						\
+		.match = mtch,					\
+	},							\
+}
+
+#define class_to_transport_class(x) \
+	container_of(x, struct transport_class, class)
+
+struct transport_container {
+	struct attribute_container ac;
+	struct attribute_group *statistics;
+};
+
+#define attribute_container_to_transport_container(x) \
+	container_of(x, struct transport_container, ac)
+
+void transport_remove_device(struct device *);
+void transport_add_device(struct device *);
+void transport_setup_device(struct device *);
+void transport_configure_device(struct device *);
+void transport_destroy_device(struct device *);
+
+static inline void
+transport_register_device(struct device *dev)
+{
+	transport_setup_device(dev);
+	transport_add_device(dev);
+}
+
+static inline void
+transport_unregister_device(struct device *dev)
+{
+	transport_remove_device(dev);
+	transport_destroy_device(dev);
+}
+
+static inline int transport_container_register(struct transport_container *tc)
+{
+	return attribute_container_register(&tc->ac);
+}
+
+static inline int transport_container_unregister(struct transport_container *tc)
+{
+	return attribute_container_unregister(&tc->ac);
+}
+
+int transport_class_register(struct transport_class *);
+int anon_transport_class_register(struct anon_transport_class *);
+void transport_class_unregister(struct transport_class *);
+void anon_transport_class_unregister(struct anon_transport_class *);
+
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U3/include/scsi/iscsi_proto.h b/kernel_addons/backport/2.6.9_U3/include/scsi/iscsi_proto.h
new file mode 100644
index 0000000..02f6e4b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/scsi/iscsi_proto.h
@@ -0,0 +1,587 @@
+/*
+ * RFC 3720 (iSCSI) protocol data types
+ *
+ * Copyright (C) 2005 Dmitry Yusupov
+ * Copyright (C) 2005 Alex Aizman
+ * maintained by open-iscsi at googlegroups.com
+ *
+ * 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.
+ *
+ * See the file COPYING included with this distribution for more details.
+ */
+
+#ifndef ISCSI_PROTO_H
+#define ISCSI_PROTO_H
+
+#define ISCSI_DRAFT20_VERSION	0x00
+
+/* default iSCSI listen port for incoming connections */
+#define ISCSI_LISTEN_PORT	3260
+
+/* Padding word length */
+#define PAD_WORD_LEN		4
+
+/*
+ * useful common(control and data pathes) macro
+ */
+#define ntoh24(p) (((p)[0] << 16) | ((p)[1] << 8) | ((p)[2]))
+#define hton24(p, v) { \
+        p[0] = (((v) >> 16) & 0xFF); \
+        p[1] = (((v) >> 8) & 0xFF); \
+        p[2] = ((v) & 0xFF); \
+}
+#define zero_data(p) {p[0]=0;p[1]=0;p[2]=0;}
+
+/*
+ * iSCSI Template Message Header
+ */
+struct iscsi_hdr {
+	uint8_t		opcode;
+	uint8_t		flags;		/* Final bit */
+	uint8_t		rsvd2[2];
+	uint8_t		hlength;	/* AHSs total length */
+	uint8_t		dlength[3];	/* Data length */
+	uint8_t		lun[8];
+	__be32		itt;		/* Initiator Task Tag */
+	__be32		ttt;		/* Target Task Tag */
+	__be32		statsn;
+	__be32		exp_statsn;
+	__be32		max_statsn;
+	uint8_t		other[12];
+};
+
+/************************* RFC 3720 Begin *****************************/
+
+#define ISCSI_RESERVED_TAG		0xffffffff
+
+/* Opcode encoding bits */
+#define ISCSI_OP_RETRY			0x80
+#define ISCSI_OP_IMMEDIATE		0x40
+#define ISCSI_OPCODE_MASK		0x3F
+
+/* Initiator Opcode values */
+#define ISCSI_OP_NOOP_OUT		0x00
+#define ISCSI_OP_SCSI_CMD		0x01
+#define ISCSI_OP_SCSI_TMFUNC		0x02
+#define ISCSI_OP_LOGIN			0x03
+#define ISCSI_OP_TEXT			0x04
+#define ISCSI_OP_SCSI_DATA_OUT		0x05
+#define ISCSI_OP_LOGOUT			0x06
+#define ISCSI_OP_SNACK			0x10
+
+#define ISCSI_OP_VENDOR1_CMD		0x1c
+#define ISCSI_OP_VENDOR2_CMD		0x1d
+#define ISCSI_OP_VENDOR3_CMD		0x1e
+#define ISCSI_OP_VENDOR4_CMD		0x1f
+
+/* Target Opcode values */
+#define ISCSI_OP_NOOP_IN		0x20
+#define ISCSI_OP_SCSI_CMD_RSP		0x21
+#define ISCSI_OP_SCSI_TMFUNC_RSP	0x22
+#define ISCSI_OP_LOGIN_RSP		0x23
+#define ISCSI_OP_TEXT_RSP		0x24
+#define ISCSI_OP_SCSI_DATA_IN		0x25
+#define ISCSI_OP_LOGOUT_RSP		0x26
+#define ISCSI_OP_R2T			0x31
+#define ISCSI_OP_ASYNC_EVENT		0x32
+#define ISCSI_OP_REJECT			0x3f
+
+struct iscsi_ahs_hdr {
+	__be16 ahslength;
+	uint8_t ahstype;
+	uint8_t ahspec[5];
+};
+
+#define ISCSI_AHSTYPE_CDB		1
+#define ISCSI_AHSTYPE_RLENGTH		2
+
+/* iSCSI PDU Header */
+struct iscsi_cmd {
+	uint8_t opcode;
+	uint8_t flags;
+	__be16 rsvd2;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32 itt;	/* Initiator Task Tag */
+	__be32 data_length;
+	__be32 cmdsn;
+	__be32 exp_statsn;
+	uint8_t cdb[16];	/* SCSI Command Block */
+	/* Additional Data (Command Dependent) */
+};
+
+/* Command PDU flags */
+#define ISCSI_FLAG_CMD_FINAL		0x80
+#define ISCSI_FLAG_CMD_READ		0x40
+#define ISCSI_FLAG_CMD_WRITE		0x20
+#define ISCSI_FLAG_CMD_ATTR_MASK	0x07	/* 3 bits */
+
+/* SCSI Command Attribute values */
+#define ISCSI_ATTR_UNTAGGED		0
+#define ISCSI_ATTR_SIMPLE		1
+#define ISCSI_ATTR_ORDERED		2
+#define ISCSI_ATTR_HEAD_OF_QUEUE	3
+#define ISCSI_ATTR_ACA			4
+
+struct iscsi_rlength_ahdr {
+	__be16 ahslength;
+	uint8_t ahstype;
+	uint8_t reserved;
+	__be32 read_length;
+};
+
+/* SCSI Response Header */
+struct iscsi_cmd_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t response;
+	uint8_t cmd_status;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	rsvd1;
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	__be32	exp_datasn;
+	__be32	bi_residual_count;
+	__be32	residual_count;
+	/* Response or Sense Data (optional) */
+};
+
+/* Command Response PDU flags */
+#define ISCSI_FLAG_CMD_BIDI_OVERFLOW	0x10
+#define ISCSI_FLAG_CMD_BIDI_UNDERFLOW	0x08
+#define ISCSI_FLAG_CMD_OVERFLOW		0x04
+#define ISCSI_FLAG_CMD_UNDERFLOW	0x02
+
+/* iSCSI Status values. Valid if Rsp Selector bit is not set */
+#define ISCSI_STATUS_CMD_COMPLETED	0
+#define ISCSI_STATUS_TARGET_FAILURE	1
+#define ISCSI_STATUS_SUBSYS_FAILURE	2
+
+/* Asynchronous Event Header */
+struct iscsi_async {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[2];
+	uint8_t rsvd3;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	uint8_t rsvd4[8];
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	uint8_t async_event;
+	uint8_t async_vcode;
+	__be16	param1;
+	__be16	param2;
+	__be16	param3;
+	uint8_t rsvd5[4];
+};
+
+/* iSCSI Event Codes */
+#define ISCSI_ASYNC_MSG_SCSI_EVENT			0
+#define ISCSI_ASYNC_MSG_REQUEST_LOGOUT			1
+#define ISCSI_ASYNC_MSG_DROPPING_CONNECTION		2
+#define ISCSI_ASYNC_MSG_DROPPING_ALL_CONNECTIONS	3
+#define ISCSI_ASYNC_MSG_PARAM_NEGOTIATION		4
+#define ISCSI_ASYNC_MSG_VENDOR_SPECIFIC			255
+
+/* NOP-Out Message */
+struct iscsi_nopout {
+	uint8_t opcode;
+	uint8_t flags;
+	__be16	rsvd2;
+	uint8_t rsvd3;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	ttt;	/* Target Transfer Tag */
+	__be32	cmdsn;
+	__be32	exp_statsn;
+	uint8_t rsvd4[16];
+};
+
+/* NOP-In Message */
+struct iscsi_nopin {
+	uint8_t opcode;
+	uint8_t flags;
+	__be16	rsvd2;
+	uint8_t rsvd3;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	ttt;	/* Target Transfer Tag */
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	uint8_t rsvd4[12];
+};
+
+/* SCSI Task Management Message Header */
+struct iscsi_tm {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd1[2];
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	rtt;	/* Reference Task Tag */
+	__be32	cmdsn;
+	__be32	exp_statsn;
+	__be32	refcmdsn;
+	__be32	exp_datasn;
+	uint8_t rsvd2[8];
+};
+
+#define ISCSI_FLAG_TM_FUNC_MASK			0x7F
+
+/* Function values */
+#define ISCSI_TM_FUNC_ABORT_TASK		1
+#define ISCSI_TM_FUNC_ABORT_TASK_SET		2
+#define ISCSI_TM_FUNC_CLEAR_ACA			3
+#define ISCSI_TM_FUNC_CLEAR_TASK_SET		4
+#define ISCSI_TM_FUNC_LOGICAL_UNIT_RESET	5
+#define ISCSI_TM_FUNC_TARGET_WARM_RESET		6
+#define ISCSI_TM_FUNC_TARGET_COLD_RESET		7
+#define ISCSI_TM_FUNC_TASK_REASSIGN		8
+
+/* SCSI Task Management Response Header */
+struct iscsi_tm_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t response;	/* see Response values below */
+	uint8_t qualifier;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd2[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	rtt;	/* Reference Task Tag */
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	uint8_t rsvd3[12];
+};
+
+/* Response values */
+#define ISCSI_TMF_RSP_COMPLETE		0x00
+#define ISCSI_TMF_RSP_NO_TASK		0x01
+#define ISCSI_TMF_RSP_NO_LUN		0x02
+#define ISCSI_TMF_RSP_TASK_ALLEGIANT	0x03
+#define ISCSI_TMF_RSP_NO_FAILOVER	0x04
+#define ISCSI_TMF_RSP_NOT_SUPPORTED	0x05
+#define ISCSI_TMF_RSP_AUTH_FAILED	0x06
+#define ISCSI_TMF_RSP_REJECTED		0xff
+
+/* Ready To Transfer Header */
+struct iscsi_r2t_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[2];
+	uint8_t	hlength;
+	uint8_t	dlength[3];
+	uint8_t lun[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	ttt;	/* Target Transfer Tag */
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	__be32	r2tsn;
+	__be32	data_offset;
+	__be32	data_length;
+};
+
+/* SCSI Data Hdr */
+struct iscsi_data {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[2];
+	uint8_t rsvd3;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32	itt;
+	__be32	ttt;
+	__be32	rsvd4;
+	__be32	exp_statsn;
+	__be32	rsvd5;
+	__be32	datasn;
+	__be32	offset;
+	__be32	rsvd6;
+	/* Payload */
+};
+
+/* SCSI Data Response Hdr */
+struct iscsi_data_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2;
+	uint8_t cmd_status;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32	itt;
+	__be32	ttt;
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	__be32	datasn;
+	__be32	offset;
+	__be32	residual_count;
+};
+
+/* Data Response PDU flags */
+#define ISCSI_FLAG_DATA_ACK		0x40
+#define ISCSI_FLAG_DATA_OVERFLOW	0x04
+#define ISCSI_FLAG_DATA_UNDERFLOW	0x02
+#define ISCSI_FLAG_DATA_STATUS		0x01
+
+/* Text Header */
+struct iscsi_text {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[2];
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd4[8];
+	__be32	itt;
+	__be32	ttt;
+	__be32	cmdsn;
+	__be32	exp_statsn;
+	uint8_t rsvd5[16];
+	/* Text - key=value pairs */
+};
+
+#define ISCSI_FLAG_TEXT_CONTINUE	0x40
+
+/* Text Response Header */
+struct iscsi_text_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[2];
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd4[8];
+	__be32	itt;
+	__be32	ttt;
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	uint8_t rsvd5[12];
+	/* Text Response - key:value pairs */
+};
+
+/* Login Header */
+struct iscsi_login {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t max_version;	/* Max. version supported */
+	uint8_t min_version;	/* Min. version supported */
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t isid[6];	/* Initiator Session ID */
+	__be16	tsih;	/* Target Session Handle */
+	__be32	itt;	/* Initiator Task Tag */
+	__be16	cid;
+	__be16	rsvd3;
+	__be32	cmdsn;
+	__be32	exp_statsn;
+	uint8_t rsvd5[16];
+};
+
+/* Login PDU flags */
+#define ISCSI_FLAG_LOGIN_TRANSIT		0x80
+#define ISCSI_FLAG_LOGIN_CONTINUE		0x40
+#define ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK	0x0C	/* 2 bits */
+#define ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK	0x03	/* 2 bits */
+
+#define ISCSI_LOGIN_CURRENT_STAGE(flags) \
+	((flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2)
+#define ISCSI_LOGIN_NEXT_STAGE(flags) \
+	(flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK)
+
+/* Login Response Header */
+struct iscsi_login_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t max_version;	/* Max. version supported */
+	uint8_t active_version;	/* Active version */
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t isid[6];	/* Initiator Session ID */
+	__be16	tsih;	/* Target Session Handle */
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	rsvd3;
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	uint8_t status_class;	/* see Login RSP ststus classes below */
+	uint8_t status_detail;	/* see Login RSP Status details below */
+	uint8_t rsvd4[10];
+};
+
+/* Login stage (phase) codes for CSG, NSG */
+#define ISCSI_INITIAL_LOGIN_STAGE		-1
+#define ISCSI_SECURITY_NEGOTIATION_STAGE	0
+#define ISCSI_OP_PARMS_NEGOTIATION_STAGE	1
+#define ISCSI_FULL_FEATURE_PHASE		3
+
+/* Login Status response classes */
+#define ISCSI_STATUS_CLS_SUCCESS		0x00
+#define ISCSI_STATUS_CLS_REDIRECT		0x01
+#define ISCSI_STATUS_CLS_INITIATOR_ERR		0x02
+#define ISCSI_STATUS_CLS_TARGET_ERR		0x03
+
+/* Login Status response detail codes */
+/* Class-0 (Success) */
+#define ISCSI_LOGIN_STATUS_ACCEPT		0x00
+
+/* Class-1 (Redirection) */
+#define ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP	0x01
+#define ISCSI_LOGIN_STATUS_TGT_MOVED_PERM	0x02
+
+/* Class-2 (Initiator Error) */
+#define ISCSI_LOGIN_STATUS_INIT_ERR		0x00
+#define ISCSI_LOGIN_STATUS_AUTH_FAILED		0x01
+#define ISCSI_LOGIN_STATUS_TGT_FORBIDDEN	0x02
+#define ISCSI_LOGIN_STATUS_TGT_NOT_FOUND	0x03
+#define ISCSI_LOGIN_STATUS_TGT_REMOVED		0x04
+#define ISCSI_LOGIN_STATUS_NO_VERSION		0x05
+#define ISCSI_LOGIN_STATUS_ISID_ERROR		0x06
+#define ISCSI_LOGIN_STATUS_MISSING_FIELDS	0x07
+#define ISCSI_LOGIN_STATUS_CONN_ADD_FAILED	0x08
+#define ISCSI_LOGIN_STATUS_NO_SESSION_TYPE	0x09
+#define ISCSI_LOGIN_STATUS_NO_SESSION		0x0a
+#define ISCSI_LOGIN_STATUS_INVALID_REQUEST	0x0b
+
+/* Class-3 (Target Error) */
+#define ISCSI_LOGIN_STATUS_TARGET_ERROR		0x00
+#define ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE	0x01
+#define ISCSI_LOGIN_STATUS_NO_RESOURCES		0x02
+
+/* Logout Header */
+struct iscsi_logout {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd1[2];
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd2[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be16	cid;
+	uint8_t rsvd3[2];
+	__be32	cmdsn;
+	__be32	exp_statsn;
+	uint8_t rsvd4[16];
+};
+
+/* Logout PDU flags */
+#define ISCSI_FLAG_LOGOUT_REASON_MASK	0x7F
+
+/* logout reason_code values */
+
+#define ISCSI_LOGOUT_REASON_CLOSE_SESSION	0
+#define ISCSI_LOGOUT_REASON_CLOSE_CONNECTION	1
+#define ISCSI_LOGOUT_REASON_RECOVERY		2
+#define ISCSI_LOGOUT_REASON_AEN_REQUEST		3
+
+/* Logout Response Header */
+struct iscsi_logout_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t response;	/* see Logout response values below */
+	uint8_t rsvd2;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd3[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	rsvd4;
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	__be32	rsvd5;
+	__be16	t2wait;
+	__be16	t2retain;
+	__be32	rsvd6;
+};
+
+/* logout response status values */
+
+#define ISCSI_LOGOUT_SUCCESS			0
+#define ISCSI_LOGOUT_CID_NOT_FOUND		1
+#define ISCSI_LOGOUT_RECOVERY_UNSUPPORTED	2
+#define ISCSI_LOGOUT_CLEANUP_FAILED		3
+
+/* SNACK Header */
+struct iscsi_snack {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[14];
+	__be32	itt;
+	__be32	begrun;
+	__be32	runlength;
+	__be32	exp_statsn;
+	__be32	rsvd3;
+	__be32	exp_datasn;
+	uint8_t rsvd6[8];
+};
+
+/* SNACK PDU flags */
+#define ISCSI_FLAG_SNACK_TYPE_MASK	0x0F	/* 4 bits */
+
+/* Reject Message Header */
+struct iscsi_reject {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t reason;
+	uint8_t rsvd2;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd3[8];
+	__be32  ffffffff;
+	uint8_t rsvd4[4];
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	__be32	datasn;
+	uint8_t rsvd5[8];
+	/* Text - Rejected hdr */
+};
+
+/* Reason for Reject */
+#define ISCSI_REASON_CMD_BEFORE_LOGIN	1
+#define ISCSI_REASON_DATA_DIGEST_ERROR	2
+#define ISCSI_REASON_DATA_SNACK_REJECT	3
+#define ISCSI_REASON_PROTOCOL_ERROR	4
+#define ISCSI_REASON_CMD_NOT_SUPPORTED	5
+#define ISCSI_REASON_IMM_CMD_REJECT		6
+#define ISCSI_REASON_TASK_IN_PROGRESS	7
+#define ISCSI_REASON_INVALID_SNACK		8
+#define ISCSI_REASON_BOOKMARK_INVALID	9
+#define ISCSI_REASON_BOOKMARK_NO_RESOURCES	10
+#define ISCSI_REASON_NEGOTIATION_RESET	11
+
+/* Max. number of Key=Value pairs in a text message */
+#define MAX_KEY_VALUE_PAIRS	8192
+
+/* maximum length for text keys/values */
+#define KEY_MAXLEN		64
+#define VALUE_MAXLEN		255
+#define TARGET_NAME_MAXLEN	VALUE_MAXLEN
+
+#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH	8192
+
+/************************* RFC 3720 End *****************************/
+
+#endif /* ISCSI_PROTO_H */
diff --git a/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_device.h b/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_device.h
new file mode 100644
index 0000000..f353e0b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_device.h
@@ -0,0 +1,19 @@
+#ifndef _SCSI_SCSI_DEVICE_H_BACKPORT
+#define _SCSI_SCSI_DEVICE_H_BACKPORT
+
+#include_next <scsi/scsi_device.h>
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+
+struct scsi_lun;
+
+extern void int_to_scsilun(unsigned int, struct scsi_lun *);
+extern void scsi_target_block(struct device *);
+extern void scsi_target_unblock(struct device *);
+extern void starget_for_each_device(struct scsi_target *, void *,
+		     void (*fn)(struct scsi_device *, void *));
+#endif /* _SCSI_SCSI_DEVICE_H_BACKPORT */
diff --git a/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_host.h b/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_host.h
new file mode 100644
index 0000000..b7e019b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_host.h
@@ -0,0 +1,8 @@
+#ifndef _SCSI_SCSI_HOST_H_BACKPORT
+#define _SCSI_SCSI_HOST_H_BACKPORT
+
+#include_next <scsi/scsi_host.h>
+
+#define scsi_queue_work(shost, work) schedule_work(work)
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_transport.h b/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_transport.h
new file mode 100644
index 0000000..99c2b12
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/scsi/scsi_transport.h
@@ -0,0 +1,8 @@
+#ifndef _SCSI_SCSI_TRANSPORT_H_BACKPORT
+#define _SCSI_SCSI_TRANSPORT_H_BACKPORT
+
+#include_next <scsi/scsi_transport.h>
+
+#include <linux/transport_class.h>
+
+#endif /* _SCSI_SCSI_TRANSPORT_H_BACKPORT */
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/attribute_container.c b/kernel_addons/backport/2.6.9_U3/include/src/attribute_container.c
new file mode 100644
index 0000000..44948d1
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/attribute_container.c
@@ -0,0 +1,438 @@
+/*
+ * attribute_container.c - implementation of a simple container for classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ *
+ * The basic idea here is to enable a device to be attached to an
+ * aritrary numer of classes without having to allocate storage for them.
+ * Instead, the contained classes select the devices they need to attach
+ * to via a matching function.
+ */
+
+#include <linux/attribute_container.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/module.h>
+
+#include "base.h"
+
+/* This is a private structure used to tie the classdev and the
+ * container .. it should never be visible outside this file */
+struct internal_container {
+	struct klist_node node;
+	struct attribute_container *cont;
+	struct class_device classdev;
+};
+
+static void internal_container_klist_get(struct klist_node *n)
+{
+	struct internal_container *ic =
+		container_of(n, struct internal_container, node);
+	class_device_get(&ic->classdev);
+}
+
+static void internal_container_klist_put(struct klist_node *n)
+{
+	struct internal_container *ic =
+		container_of(n, struct internal_container, node);
+	class_device_put(&ic->classdev);
+}
+
+
+/**
+ * attribute_container_classdev_to_container - given a classdev, return the container
+ *
+ * @classdev: the class device created by attribute_container_add_device.
+ *
+ * Returns the container associated with this classdev.
+ */
+struct attribute_container *
+attribute_container_classdev_to_container(struct class_device *classdev)
+{
+	struct internal_container *ic =
+		container_of(classdev, struct internal_container, classdev);
+	return ic->cont;
+}
+EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container);
+
+static struct list_head attribute_container_list;
+
+static DECLARE_MUTEX(attribute_container_mutex);
+
+/**
+ * attribute_container_register - register an attribute container
+ *
+ * @cont: The container to register.  This must be allocated by the
+ *        callee and should also be zeroed by it.
+ */
+int
+attribute_container_register(struct attribute_container *cont)
+{
+	INIT_LIST_HEAD(&cont->node);
+	klist_init(&cont->containers,internal_container_klist_get,
+		   internal_container_klist_put);
+		
+	down(&attribute_container_mutex);
+	list_add_tail(&cont->node, &attribute_container_list);
+	up(&attribute_container_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(attribute_container_register);
+
+/**
+ * attribute_container_unregister - remove a container registration
+ *
+ * @cont: previously registered container to remove
+ */
+int
+attribute_container_unregister(struct attribute_container *cont)
+{
+	int retval = -EBUSY;
+	down(&attribute_container_mutex);
+	spin_lock(&cont->containers.k_lock);
+	if (!list_empty(&cont->containers.k_list))
+		goto out;
+	retval = 0;
+	list_del(&cont->node);
+ out:
+	spin_unlock(&cont->containers.k_lock);
+	up(&attribute_container_mutex);
+	return retval;
+		
+}
+EXPORT_SYMBOL_GPL(attribute_container_unregister);
+
+/* private function used as class release */
+static void attribute_container_release(struct class_device *classdev)
+{
+	struct internal_container *ic 
+		= container_of(classdev, struct internal_container, classdev);
+	struct device *dev = classdev->dev;
+
+	kfree(ic);
+	put_device(dev);
+}
+
+/**
+ * attribute_container_add_device - see if any container is interested in dev
+ *
+ * @dev: device to add attributes to
+ * @fn:	 function to trigger addition of class device.
+ *
+ * This function allocates storage for the class device(s) to be
+ * attached to dev (one for each matching attribute_container).  If no
+ * fn is provided, the code will simply register the class device via
+ * class_device_add.  If a function is provided, it is expected to add
+ * the class device at the appropriate time.  One of the things that
+ * might be necessary is to allocate and initialise the classdev and
+ * then add it a later time.  To do this, call this routine for
+ * allocation and initialisation and then use
+ * attribute_container_device_trigger() to call class_device_add() on
+ * it.  Note: after this, the class device contains a reference to dev
+ * which is not relinquished until the release of the classdev.
+ */
+void
+attribute_container_add_device(struct device *dev,
+			       int (*fn)(struct attribute_container *,
+					 struct device *,
+					 struct class_device *))
+{
+	struct attribute_container *cont;
+
+	down(&attribute_container_mutex);
+	list_for_each_entry(cont, &attribute_container_list, node) {
+		struct internal_container *ic;
+
+		if (attribute_container_no_classdevs(cont))
+			continue;
+
+		if (!cont->match(cont, dev))
+			continue;
+
+		ic = kzalloc(sizeof(*ic), GFP_KERNEL);
+		if (!ic) {
+			dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
+			continue;
+		}
+
+		ic->cont = cont;
+		class_device_initialize(&ic->classdev);
+		ic->classdev.dev = get_device(dev);
+		ic->classdev.class = cont->class;
+		cont->class->release = attribute_container_release;
+		strcpy(ic->classdev.class_id, dev->bus_id);
+		if (fn)
+			fn(cont, dev, &ic->classdev);
+		else
+			attribute_container_add_class_device(&ic->classdev);
+		klist_add_tail(&ic->node, &cont->containers);
+	}
+	up(&attribute_container_mutex);
+}
+
+/* FIXME: can't break out of this unless klist_iter_exit is also
+ * called before doing the break
+ */
+#define klist_for_each_entry(pos, head, member, iter) \
+	for (klist_iter_init(head, iter); (pos = ({ \
+		struct klist_node *n = klist_next(iter); \
+		n ? container_of(n, typeof(*pos), member) : \
+			({ klist_iter_exit(iter) ; NULL; }); \
+	}) ) != NULL; )
+			
+
+/**
+ * attribute_container_remove_device - make device eligible for removal.
+ *
+ * @dev:  The generic device
+ * @fn:	  A function to call to remove the device
+ *
+ * This routine triggers device removal.  If fn is NULL, then it is
+ * simply done via class_device_unregister (note that if something
+ * still has a reference to the classdev, then the memory occupied
+ * will not be freed until the classdev is released).  If you want a
+ * two phase release: remove from visibility and then delete the
+ * device, then you should use this routine with a fn that calls
+ * class_device_del() and then use
+ * attribute_container_device_trigger() to do the final put on the
+ * classdev.
+ */
+void
+attribute_container_remove_device(struct device *dev,
+				  void (*fn)(struct attribute_container *,
+					     struct device *,
+					     struct class_device *))
+{
+	struct attribute_container *cont;
+
+	down(&attribute_container_mutex);
+	list_for_each_entry(cont, &attribute_container_list, node) {
+		struct internal_container *ic;
+		struct klist_iter iter;
+
+		if (attribute_container_no_classdevs(cont))
+			continue;
+
+		if (!cont->match(cont, dev))
+			continue;
+
+		klist_for_each_entry(ic, &cont->containers, node, &iter) {
+			if (dev != ic->classdev.dev)
+				continue;
+			klist_del(&ic->node);
+			if (fn)
+				fn(cont, dev, &ic->classdev);
+			else {
+				attribute_container_remove_attrs(&ic->classdev);
+				class_device_unregister(&ic->classdev);
+			}
+		}
+	}
+	up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_device_trigger - execute a trigger for each matching classdev
+ *
+ * @dev:  The generic device to run the trigger for
+ * @fn	  the function to execute for each classdev.
+ *
+ * This funcion is for executing a trigger when you need to know both
+ * the container and the classdev.  If you only care about the
+ * container, then use attribute_container_trigger() instead.
+ */
+void
+attribute_container_device_trigger(struct device *dev, 
+				   int (*fn)(struct attribute_container *,
+					     struct device *,
+					     struct class_device *))
+{
+	struct attribute_container *cont;
+
+	down(&attribute_container_mutex);
+	list_for_each_entry(cont, &attribute_container_list, node) {
+		struct internal_container *ic;
+		struct klist_iter iter;
+
+		if (!cont->match(cont, dev))
+			continue;
+
+		if (attribute_container_no_classdevs(cont)) {
+			fn(cont, dev, NULL);
+			continue;
+		}
+
+		klist_for_each_entry(ic, &cont->containers, node, &iter) {
+			if (dev == ic->classdev.dev)
+				fn(cont, dev, &ic->classdev);
+		}
+	}
+	up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_trigger - trigger a function for each matching container
+ *
+ * @dev:  The generic device to activate the trigger for
+ * @fn:	  the function to trigger
+ *
+ * This routine triggers a function that only needs to know the
+ * matching containers (not the classdev) associated with a device.
+ * It is more lightweight than attribute_container_device_trigger, so
+ * should be used in preference unless the triggering function
+ * actually needs to know the classdev.
+ */
+void
+attribute_container_trigger(struct device *dev,
+			    int (*fn)(struct attribute_container *,
+				      struct device *))
+{
+	struct attribute_container *cont;
+
+	down(&attribute_container_mutex);
+	list_for_each_entry(cont, &attribute_container_list, node) {
+		if (cont->match(cont, dev))
+			fn(cont, dev);
+	}
+	up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_add_attrs - add attributes
+ *
+ * @classdev: The class device
+ *
+ * This simply creates all the class device sysfs files from the
+ * attributes listed in the container
+ */
+int
+attribute_container_add_attrs(struct class_device *classdev)
+{
+	struct attribute_container *cont =
+		attribute_container_classdev_to_container(classdev);
+	struct class_device_attribute **attrs =	cont->attrs;
+	int i, error;
+
+	if (!attrs)
+		return 0;
+
+	for (i = 0; attrs[i]; i++) {
+		error = class_device_create_file(classdev, attrs[i]);
+		if (error)
+			return error;
+	}
+
+	return 0;
+}
+
+/**
+ * attribute_container_add_class_device - same function as class_device_add
+ *
+ * @classdev:	the class device to add
+ *
+ * This performs essentially the same function as class_device_add except for
+ * attribute containers, namely add the classdev to the system and then
+ * create the attribute files
+ */
+int
+attribute_container_add_class_device(struct class_device *classdev)
+{
+	int error = class_device_add(classdev);
+	if (error)
+		return error;
+	return attribute_container_add_attrs(classdev);
+}
+
+/**
+ * attribute_container_add_class_device_adapter - simple adapter for triggers
+ *
+ * This function is identical to attribute_container_add_class_device except
+ * that it is designed to be called from the triggers
+ */
+int
+attribute_container_add_class_device_adapter(struct attribute_container *cont,
+					     struct device *dev,
+					     struct class_device *classdev)
+{
+	return attribute_container_add_class_device(classdev);
+}
+
+/**
+ * attribute_container_remove_attrs - remove any attribute files
+ *
+ * @classdev: The class device to remove the files from
+ *
+ */
+void
+attribute_container_remove_attrs(struct class_device *classdev)
+{
+	struct attribute_container *cont =
+		attribute_container_classdev_to_container(classdev);
+	struct class_device_attribute **attrs =	cont->attrs;
+	int i;
+
+	if (!attrs)
+		return;
+
+	for (i = 0; attrs[i]; i++)
+		class_device_remove_file(classdev, attrs[i]);
+}
+
+/**
+ * attribute_container_class_device_del - equivalent of class_device_del
+ *
+ * @classdev: the class device
+ *
+ * This function simply removes all the attribute files and then calls
+ * class_device_del.
+ */
+void
+attribute_container_class_device_del(struct class_device *classdev)
+{
+	attribute_container_remove_attrs(classdev);
+	class_device_del(classdev);
+}
+
+/**
+ * attribute_container_find_class_device - find the corresponding class_device
+ *
+ * @cont:	the container
+ * @dev:	the generic device
+ *
+ * Looks up the device in the container's list of class devices and returns
+ * the corresponding class_device.
+ */
+struct class_device *
+attribute_container_find_class_device(struct attribute_container *cont,
+				      struct device *dev)
+{
+	struct class_device *cdev = NULL;
+	struct internal_container *ic;
+	struct klist_iter iter;
+
+	klist_for_each_entry(ic, &cont->containers, node, &iter) {
+		if (ic->classdev.dev == dev) {
+			cdev = &ic->classdev;
+			/* FIXME: must exit iterator then break */
+			klist_iter_exit(&iter);
+			break;
+		}
+	}
+
+	return cdev;
+}
+EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
+
+int
+attribute_container_init(void)
+{
+	INIT_LIST_HEAD(&attribute_container_list);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(attribute_container_init);
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/base.h b/kernel_addons/backport/2.6.9_U3/include/src/base.h
new file mode 100644
index 0000000..a5f8936
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/base.h
@@ -0,0 +1 @@
+extern int attribute_container_init(void);
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/init.c b/kernel_addons/backport/2.6.9_U3/include/src/init.c
new file mode 100644
index 0000000..15f0bc6
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/init.c
@@ -0,0 +1,26 @@
+/*
+ *
+ * Copyright (c) 2002-3 Patrick Mochel
+ * Copyright (c) 2002-3 Open Source Development Labs
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/memory.h>
+
+#include "base.h"
+
+/**
+ *	driver_init - initialize driver model.
+ *
+ *	Call the driver model init functions to initialize their
+ *	subsystems. Called early from init/main.c.
+ */
+
+void __init driver_init(void)
+{
+	attribute_container_init();
+}
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/klist.c b/kernel_addons/backport/2.6.9_U3/include/src/klist.c
new file mode 100644
index 0000000..3b29ebc
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/klist.c
@@ -0,0 +1,287 @@
+/*
+ *	klist.c - Routines for manipulating klists.
+ *
+ *
+ *	This klist interface provides a couple of structures that wrap around 
+ *	struct list_head to provide explicit list "head" (struct klist) and 
+ *	list "node" (struct klist_node) objects. For struct klist, a spinlock
+ *	is included that protects access to the actual list itself. struct 
+ *	klist_node provides a pointer to the klist that owns it and a kref
+ *	reference count that indicates the number of current users of that node
+ *	in the list.
+ *
+ *	The entire point is to provide an interface for iterating over a list
+ *	that is safe and allows for modification of the list during the
+ *	iteration (e.g. insertion and removal), including modification of the
+ *	current node on the list.
+ *
+ *	It works using a 3rd object type - struct klist_iter - that is declared
+ *	and initialized before an iteration. klist_next() is used to acquire the
+ *	next element in the list. It returns NULL if there are no more items.
+ *	Internally, that routine takes the klist's lock, decrements the reference
+ *	count of the previous klist_node and increments the count of the next
+ *	klist_node. It then drops the lock and returns.
+ *
+ *	There are primitives for adding and removing nodes to/from a klist. 
+ *	When deleting, klist_del() will simply decrement the reference count. 
+ *	Only when the count goes to 0 is the node removed from the list. 
+ *	klist_remove() will try to delete the node from the list and block
+ *	until it is actually removed. This is useful for objects (like devices)
+ *	that have been removed from the system and must be freed (but must wait
+ *	until all accessors have finished).
+ *
+ *	Copyright (C) 2005 Patrick Mochel
+ *
+ *	This file is released under the GPL v2.
+ */
+
+#include <linux/klist.h>
+#include <linux/module.h>
+
+
+/**
+ *	klist_init - Initialize a klist structure. 
+ *	@k:	The klist we're initializing.
+ *	@get:	The get function for the embedding object (NULL if none)
+ *	@put:	The put function for the embedding object (NULL if none)
+ *
+ * Initialises the klist structure.  If the klist_node structures are
+ * going to be embedded in refcounted objects (necessary for safe
+ * deletion) then the get/put arguments are used to initialise
+ * functions that take and release references on the embedding
+ * objects.
+ */
+
+void klist_init(struct klist * k, void (*get)(struct klist_node *),
+		void (*put)(struct klist_node *))
+{
+	INIT_LIST_HEAD(&k->k_list);
+	spin_lock_init(&k->k_lock);
+	k->get = get;
+	k->put = put;
+}
+
+EXPORT_SYMBOL_GPL(klist_init);
+
+
+static void add_head(struct klist * k, struct klist_node * n)
+{
+	spin_lock(&k->k_lock);
+	list_add(&n->n_node, &k->k_list);
+	spin_unlock(&k->k_lock);
+}
+
+static void add_tail(struct klist * k, struct klist_node * n)
+{
+	spin_lock(&k->k_lock);
+	list_add_tail(&n->n_node, &k->k_list);
+	spin_unlock(&k->k_lock);
+}
+
+
+static void klist_node_init(struct klist * k, struct klist_node * n)
+{
+	INIT_LIST_HEAD(&n->n_node);
+	init_completion(&n->n_removed);
+	kref_init(&n->n_ref);
+	n->n_klist = k;
+	if (k->get)
+		k->get(n);
+}
+
+
+/**
+ *	klist_add_head - Initialize a klist_node and add it to front.
+ *	@n:	node we're adding.
+ *	@k:	klist it's going on.
+ */
+
+void klist_add_head(struct klist_node * n, struct klist * k)
+{
+	klist_node_init(k, n);
+	add_head(k, n);
+}
+
+EXPORT_SYMBOL_GPL(klist_add_head);
+
+
+/**
+ *	klist_add_tail - Initialize a klist_node and add it to back.
+ *	@n:	node we're adding.
+ *	@k:	klist it's going on.
+ */
+
+void klist_add_tail(struct klist_node * n, struct klist * k)
+{
+	klist_node_init(k, n);
+	add_tail(k, n);
+}
+
+EXPORT_SYMBOL_GPL(klist_add_tail);
+
+
+static void klist_release(struct kref * kref)
+{
+	struct klist_node * n = container_of(kref, struct klist_node, n_ref);
+
+	list_del(&n->n_node);
+	complete(&n->n_removed);
+	n->n_klist = NULL;
+}
+
+static int klist_dec_and_del(struct klist_node * n)
+{
+	return kref_put_new(&n->n_ref, klist_release);
+}
+
+
+/**
+ *	klist_del - Decrement the reference count of node and try to remove.
+ *	@n:	node we're deleting.
+ */
+
+void klist_del(struct klist_node * n)
+{
+	struct klist * k = n->n_klist;
+	void (*put)(struct klist_node *) = k->put;
+
+	spin_lock(&k->k_lock);
+	if (!klist_dec_and_del(n))
+		put = NULL;
+	spin_unlock(&k->k_lock);
+	if (put)
+		put(n);
+}
+
+EXPORT_SYMBOL_GPL(klist_del);
+
+
+/**
+ *	klist_remove - Decrement the refcount of node and wait for it to go away.
+ *	@n:	node we're removing.
+ */
+
+void klist_remove(struct klist_node * n)
+{
+	klist_del(n);
+	wait_for_completion(&n->n_removed);
+}
+
+EXPORT_SYMBOL_GPL(klist_remove);
+
+
+/**
+ *	klist_node_attached - Say whether a node is bound to a list or not.
+ *	@n:	Node that we're testing.
+ */
+
+int klist_node_attached(struct klist_node * n)
+{
+	return (n->n_klist != NULL);
+}
+
+EXPORT_SYMBOL_GPL(klist_node_attached);
+
+
+/**
+ *	klist_iter_init_node - Initialize a klist_iter structure.
+ *	@k:	klist we're iterating.
+ *	@i:	klist_iter we're filling.
+ *	@n:	node to start with.
+ *
+ *	Similar to klist_iter_init(), but starts the action off with @n, 
+ *	instead of with the list head.
+ */
+
+void klist_iter_init_node(struct klist * k, struct klist_iter * i, struct klist_node * n)
+{
+	i->i_klist = k;
+	i->i_head = &k->k_list;
+	i->i_cur = n;
+	if (n)
+		kref_get(&n->n_ref);
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_init_node);
+
+
+/**
+ *	klist_iter_init - Iniitalize a klist_iter structure.
+ *	@k:	klist we're iterating.
+ *	@i:	klist_iter structure we're filling.
+ *
+ *	Similar to klist_iter_init_node(), but start with the list head.
+ */
+
+void klist_iter_init(struct klist * k, struct klist_iter * i)
+{
+	klist_iter_init_node(k, i, NULL);
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_init);
+
+
+/**
+ *	klist_iter_exit - Finish a list iteration.
+ *	@i:	Iterator structure.
+ *
+ *	Must be called when done iterating over list, as it decrements the 
+ *	refcount of the current node. Necessary in case iteration exited before
+ *	the end of the list was reached, and always good form.
+ */
+
+void klist_iter_exit(struct klist_iter * i)
+{
+	if (i->i_cur) {
+		klist_del(i->i_cur);
+		i->i_cur = NULL;
+	}
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_exit);
+
+
+static struct klist_node * to_klist_node(struct list_head * n)
+{
+	return container_of(n, struct klist_node, n_node);
+}
+
+
+/**
+ *	klist_next - Ante up next node in list.
+ *	@i:	Iterator structure.
+ *
+ *	First grab list lock. Decrement the reference count of the previous
+ *	node, if there was one. Grab the next node, increment its reference 
+ *	count, drop the lock, and return that next node.
+ */
+
+struct klist_node * klist_next(struct klist_iter * i)
+{
+	struct list_head * next;
+	struct klist_node * lnode = i->i_cur;
+	struct klist_node * knode = NULL;
+	void (*put)(struct klist_node *) = i->i_klist->put;
+
+	spin_lock(&i->i_klist->k_lock);
+	if (lnode) {
+		next = lnode->n_node.next;
+		if (!klist_dec_and_del(lnode))
+			put = NULL;
+	} else
+		next = i->i_head->next;
+
+	if (next != i->i_head) {
+		knode = to_klist_node(next);
+		kref_get(&knode->n_ref);
+	}
+	i->i_cur = knode;
+	spin_unlock(&i->i_klist->k_lock);
+	if (put && lnode)
+		put(lnode);
+	return knode;
+}
+
+EXPORT_SYMBOL_GPL(klist_next);
+
+
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/kref_new.c b/kernel_addons/backport/2.6.9_U3/include/src/kref_new.c
new file mode 100644
index 0000000..d45bb3f
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/kref_new.c
@@ -0,0 +1,29 @@
+#include <linux/kref.h>
+#include <linux/module.h>
+
+/**
+ * kref_put - decrement refcount for object.
+ * @kref: object.
+ * @release: pointer to the function that will clean up the object when the
+ *           last reference to the object is released.
+ *           This pointer is required, and it is not acceptable to pass kfree
+ *           in as this function.
+ *
+ * Decrement the refcount, and if 0, call release().
+ * Return 1 if the object was removed, otherwise return 0.  Beware, if this
+ * function returns 0, you still can not count on the kref from remaining in
+ * memory.  Only use the return value if you want to see if the kref is now
+ * gone, not present.
+ */
+int kref_put_new(struct kref *kref, void (*release)(struct kref *kref))
+{
+        WARN_ON(release == NULL);
+        WARN_ON(release == (void (*)(struct kref *))kfree);
+
+        if (atomic_dec_and_test(&kref->refcount)) {
+                release(kref);
+                return 1;
+        }
+        return 0;
+}
+EXPORT_SYMBOL(kref_put_new);
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/scsi.c b/kernel_addons/backport/2.6.9_U3/include/src/scsi.c
new file mode 100644
index 0000000..8c833c0
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/scsi.c
@@ -0,0 +1,50 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/unistd.h>
+#include <linux/spinlock.h>
+#include <linux/kmod.h>
+#include <linux/interrupt.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/mutex.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+
+/**
+ * starget_for_each_device  -  helper to walk all devices of a target
+ * @starget:	target whose devices we want to iterate over.
+ *
+ * This traverses over each devices of @shost.  The devices have
+ * a reference that must be released by scsi_host_put when breaking
+ * out of the loop.
+ */
+void starget_for_each_device(struct scsi_target *starget, void * data,
+		     void (*fn)(struct scsi_device *, void *))
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct scsi_device *sdev;
+
+	printk("%s: entry\n", __FUNCTION__);
+	shost_for_each_device(sdev, shost) {
+		if ((sdev->channel == starget->channel) &&
+		    (sdev->id == starget->id))
+			fn(sdev, data);
+	}
+	printk("%s: exit\n", __FUNCTION__);
+}
+EXPORT_SYMBOL(starget_for_each_device);
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/scsi_lib.c b/kernel_addons/backport/2.6.9_U3/include/src/scsi_lib.c
new file mode 100644
index 0000000..f53f824
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/scsi_lib.c
@@ -0,0 +1,166 @@
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <linux/completion.h>
+#include <linux/kernel.h>
+#include <linux/mempool.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/hardirq.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+
+int scsi_is_target_device(const struct device *dev)
+{
+        char *str = dev->bus_id;
+
+	if (strncmp(str, "target", 6) == 0) {
+		return 1;
+	}
+
+        return 0;
+}
+
+/**
+ * scsi_internal_device_block - internal function to put a device
+ *                              temporarily into the SDEV_BLOCK state
+ * @sdev:       device to block
+ *
+ * Block request made by scsi lld's to temporarily stop all
+ * scsi commands on the specified device.  Called from interrupt
+ * or normal process context.
+ *
+ * Returns zero if successful or error if not
+ *
+ * Notes:
+ *      This routine transitions the device to the SDEV_BLOCK state
+ *      (which must be a legal transition).  When the device is in this
+ *      state, all commands are deferred until the scsi lld reenables
+ *      the device with scsi_device_unblock or device_block_tmo fires.
+ *      This routine assumes the host_lock is held on entry.
+ **/
+int
+scsi_internal_device_block(struct scsi_device *sdev)
+{
+        request_queue_t *q = sdev->request_queue;
+        unsigned long flags;
+        int err = 0;
+
+        err = scsi_device_set_state(sdev, SDEV_BLOCK);
+        if (err)
+		return err;
+                
+        /*
+         * The device has transitioned to SDEV_BLOCK.  Stop the
+         * block layer from calling the midlayer with this device's
+         * request queue.
+         */
+        spin_lock_irqsave(q->queue_lock, flags);
+        blk_stop_queue(q);
+        spin_unlock_irqrestore(q->queue_lock, flags);
+
+        return 0;
+}
+EXPORT_SYMBOL_GPL(scsi_internal_device_block);
+
+/**
+ * scsi_internal_device_unblock - resume a device after a block request
+ * @sdev:       device to resume
+ *
+ * Called by scsi lld's or the midlayer to restart the device queue
+ * for the previously suspended scsi device.  Called from interrupt or
+ * normal process context.
+ *
+ * Returns zero if successful or error if not.
+ *
+ * Notes:
+ *      This routine transitions the device to the SDEV_RUNNING state
+ *      (which must be a legal transition) allowing the midlayer to
+ *      goose the queue for this device.  This routine assumes the
+ *      host_lock is held upon entry.
+ **/
+int
+scsi_internal_device_unblock(struct scsi_device *sdev)
+{
+        request_queue_t *q = sdev->request_queue;
+        int err;
+        unsigned long flags;
+
+
+        /*
+         * Try to transition the scsi device to SDEV_RUNNING
+         * and goose the device queue if successful.
+         */
+        err = scsi_device_set_state(sdev, SDEV_RUNNING);
+        if (err)
+		return err;
+                
+        spin_lock_irqsave(q->queue_lock, flags);
+        blk_start_queue(q);
+        spin_unlock_irqrestore(q->queue_lock, flags);
+
+        return 0;
+}
+EXPORT_SYMBOL_GPL(scsi_internal_device_unblock);
+
+static void
+device_block(struct scsi_device *sdev, void *data)
+{
+        scsi_internal_device_block(sdev);
+}
+
+static int
+target_block(struct device *dev, void *data)
+{
+        if (scsi_is_target_device(dev))
+                starget_for_each_device(to_scsi_target(dev), NULL,
+                                        device_block);
+
+        return 0;
+}
+
+void
+scsi_target_block(struct device *dev)
+{
+        if (scsi_is_target_device(dev))
+                starget_for_each_device(to_scsi_target(dev), NULL,
+                                        device_block);
+        else
+                device_for_each_child(dev, NULL, target_block);
+}
+EXPORT_SYMBOL_GPL(scsi_target_block);
+
+static void
+device_unblock(struct scsi_device *sdev, void *data)
+{
+        scsi_internal_device_unblock(sdev);
+}
+
+static int
+target_unblock(struct device *dev, void *data)
+{
+        if (scsi_is_target_device(dev))
+                starget_for_each_device(to_scsi_target(dev), NULL,
+                                        device_unblock);
+        return 0;
+}
+
+void
+scsi_target_unblock(struct device *dev)
+{
+        if (scsi_is_target_device(dev))
+                starget_for_each_device(to_scsi_target(dev), NULL,
+                                        device_unblock);
+        else
+                device_for_each_child(dev, NULL, target_unblock);
+}
+EXPORT_SYMBOL_GPL(scsi_target_unblock);
+
+MODULE_LICENSE("GPL");
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/scsi_scan.c b/kernel_addons/backport/2.6.9_U3/include/src/scsi_scan.c
new file mode 100644
index 0000000..b7b7674
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/scsi_scan.c
@@ -0,0 +1,48 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/spinlock.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_devinfo.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_eh.h>
+
+/**
+ * int_to_scsilun: reverts an int into a scsi_lun
+ * @int:        integer to be reverted
+ * @scsilun:    struct scsi_lun to be set.
+ *
+ * Description:
+ *     Reverts the functionality of the scsilun_to_int, which packed
+ *     an 8-byte lun value into an int. This routine unpacks the int
+ *     back into the lun value.
+ *     Note: the scsilun_to_int() routine does not truly handle all
+ *     8bytes of the lun value. This functions restores only as much
+ *     as was set by the routine.
+ *
+ * Notes:
+ *     Given an integer : 0x0b030a04,  this function returns a
+ *     scsi_lun of : struct scsi_lun of: 0a 04 0b 03 00 00 00 00
+ *
+ **/
+void int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun)
+{
+        int i;
+
+        memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun));
+
+        for (i = 0; i < sizeof(lun); i += 2) {
+                scsilun->scsi_lun[i] = (lun >> 8) & 0xFF;
+                scsilun->scsi_lun[i+1] = lun & 0xFF;
+                lun = lun >> 16;
+        }
+}
+EXPORT_SYMBOL(int_to_scsilun);
diff --git a/kernel_addons/backport/2.6.9_U3/include/src/transport_class.c b/kernel_addons/backport/2.6.9_U3/include/src/transport_class.c
new file mode 100644
index 0000000..f25e7c6
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U3/include/src/transport_class.c
@@ -0,0 +1,280 @@
+/*
+ * transport_class.c - implementation of generic transport classes
+ *                     using attribute_containers
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ *
+ * The basic idea here is to allow any "device controller" (which
+ * would most often be a Host Bus Adapter to use the services of one
+ * or more tranport classes for performing transport specific
+ * services.  Transport specific services are things that the generic
+ * command layer doesn't want to know about (speed settings, line
+ * condidtioning, etc), but which the user might be interested in.
+ * Thus, the HBA's use the routines exported by the transport classes
+ * to perform these functions.  The transport classes export certain
+ * values to the user via sysfs using attribute containers.
+ *
+ * Note: because not every HBA will care about every transport
+ * attribute, there's a many to one relationship that goes like this:
+ *
+ * transport class<-----attribute container<----class device
+ *
+ * Usually the attribute container is per-HBA, but the design doesn't
+ * mandate that.  Although most of the services will be specific to
+ * the actual external storage connection used by the HBA, the generic
+ * transport class is framed entirely in terms of generic devices to
+ * allow it to be used by any physical HBA in the system.
+ */
+#include <linux/attribute_container.h>
+#include <linux/transport_class.h>
+
+/**
+ * transport_class_register - register an initial transport class
+ *
+ * @tclass:	a pointer to the transport class structure to be initialised
+ *
+ * The transport class contains an embedded class which is used to
+ * identify it.  The caller should initialise this structure with
+ * zeros and then generic class must have been initialised with the
+ * actual transport class unique name.  There's a macro
+ * DECLARE_TRANSPORT_CLASS() to do this (declared classes still must
+ * be registered).
+ *
+ * Returns 0 on success or error on failure.
+ */
+int transport_class_register(struct transport_class *tclass)
+{
+	return class_register(&tclass->class);
+}
+EXPORT_SYMBOL_GPL(transport_class_register);
+
+/**
+ * transport_class_unregister - unregister a previously registered class
+ *
+ * @tclass: The transport class to unregister
+ *
+ * Must be called prior to deallocating the memory for the transport
+ * class.
+ */
+void transport_class_unregister(struct transport_class *tclass)
+{
+	class_unregister(&tclass->class);
+}
+EXPORT_SYMBOL_GPL(transport_class_unregister);
+
+static int anon_transport_dummy_function(struct transport_container *tc,
+					 struct device *dev,
+					 struct class_device *cdev)
+{
+	/* do nothing */
+	return 0;
+}
+
+/**
+ * anon_transport_class_register - register an anonymous class
+ *
+ * @atc: The anon transport class to register
+ *
+ * The anonymous transport class contains both a transport class and a
+ * container.  The idea of an anonymous class is that it never
+ * actually has any device attributes associated with it (and thus
+ * saves on container storage).  So it can only be used for triggering
+ * events.  Use prezero and then use DECLARE_ANON_TRANSPORT_CLASS() to
+ * initialise the anon transport class storage.
+ */
+int anon_transport_class_register(struct anon_transport_class *atc)
+{
+	int error;
+	atc->container.class = &atc->tclass.class;
+	attribute_container_set_no_classdevs(&atc->container);
+	error = attribute_container_register(&atc->container);
+	if (error)
+		return error;
+	atc->tclass.setup = anon_transport_dummy_function;
+	atc->tclass.remove = anon_transport_dummy_function;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(anon_transport_class_register);
+
+/**
+ * anon_transport_class_unregister - unregister an anon class
+ *
+ * @atc: Pointer to the anon transport class to unregister
+ *
+ * Must be called prior to deallocating the memory for the anon
+ * transport class.
+ */
+void anon_transport_class_unregister(struct anon_transport_class *atc)
+{
+	attribute_container_unregister(&atc->container);
+}
+EXPORT_SYMBOL_GPL(anon_transport_class_unregister);
+
+static int transport_setup_classdev(struct attribute_container *cont,
+				    struct device *dev,
+				    struct class_device *classdev)
+{
+	struct transport_class *tclass = class_to_transport_class(cont->class);
+	struct transport_container *tcont = attribute_container_to_transport_container(cont);
+
+	if (tclass->setup)
+		tclass->setup(tcont, dev, classdev);
+
+	return 0;
+}
+
+/**
+ * transport_setup_device - declare a new dev for transport class association
+ *			    but don't make it visible yet.
+ *
+ * @dev: the generic device representing the entity being added
+ *
+ * Usually, dev represents some component in the HBA system (either
+ * the HBA itself or a device remote across the HBA bus).  This
+ * routine is simply a trigger point to see if any set of transport
+ * classes wishes to associate with the added device.  This allocates
+ * storage for the class device and initialises it, but does not yet
+ * add it to the system or add attributes to it (you do this with
+ * transport_add_device).  If you have no need for a separate setup
+ * and add operations, use transport_register_device (see
+ * transport_class.h).
+ */
+
+void transport_setup_device(struct device *dev)
+{
+	attribute_container_add_device(dev, transport_setup_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_setup_device);
+
+static int transport_add_class_device(struct attribute_container *cont,
+				      struct device *dev,
+				      struct class_device *classdev)
+{
+	int error = attribute_container_add_class_device(classdev);
+	struct transport_container *tcont = 
+		attribute_container_to_transport_container(cont);
+
+	if (!error && tcont->statistics)
+		error = sysfs_create_group(&classdev->kobj, tcont->statistics);
+
+	return error;
+}
+
+
+/**
+ * transport_add_device - declare a new dev for transport class association
+ *
+ * @dev: the generic device representing the entity being added
+ *
+ * Usually, dev represents some component in the HBA system (either
+ * the HBA itself or a device remote across the HBA bus).  This
+ * routine is simply a trigger point used to add the device to the
+ * system and register attributes for it.
+ */
+
+void transport_add_device(struct device *dev)
+{
+	attribute_container_device_trigger(dev, transport_add_class_device);
+}
+EXPORT_SYMBOL_GPL(transport_add_device);
+
+static int transport_configure(struct attribute_container *cont,
+			       struct device *dev,
+			       struct class_device *cdev)
+{
+	struct transport_class *tclass = class_to_transport_class(cont->class);
+	struct transport_container *tcont = attribute_container_to_transport_container(cont);
+
+	if (tclass->configure)
+		tclass->configure(tcont, dev, cdev);
+
+	return 0;
+}
+
+/**
+ * transport_configure_device - configure an already set up device
+ *
+ * @dev: generic device representing device to be configured
+ *
+ * The idea of configure is simply to provide a point within the setup
+ * process to allow the transport class to extract information from a
+ * device after it has been setup.  This is used in SCSI because we
+ * have to have a setup device to begin using the HBA, but after we
+ * send the initial inquiry, we use configure to extract the device
+ * parameters.  The device need not have been added to be configured.
+ */
+void transport_configure_device(struct device *dev)
+{
+	attribute_container_device_trigger(dev, transport_configure);
+}
+EXPORT_SYMBOL_GPL(transport_configure_device);
+
+static int transport_remove_classdev(struct attribute_container *cont,
+				     struct device *dev,
+				     struct class_device *classdev)
+{
+	struct transport_container *tcont = 
+		attribute_container_to_transport_container(cont);
+	struct transport_class *tclass = class_to_transport_class(cont->class);
+
+	if (tclass->remove)
+		tclass->remove(tcont, dev, classdev);
+
+	if (tclass->remove != anon_transport_dummy_function) {
+		if (tcont->statistics)
+			sysfs_remove_group(&classdev->kobj, tcont->statistics);
+		attribute_container_class_device_del(classdev);
+	}
+
+	return 0;
+}
+
+
+/**
+ * transport_remove_device - remove the visibility of a device
+ *
+ * @dev: generic device to remove
+ *
+ * This call removes the visibility of the device (to the user from
+ * sysfs), but does not destroy it.  To eliminate a device entirely
+ * you must also call transport_destroy_device.  If you don't need to
+ * do remove and destroy as separate operations, use
+ * transport_unregister_device() (see transport_class.h) which will
+ * perform both calls for you.
+ */
+void transport_remove_device(struct device *dev)
+{
+	attribute_container_device_trigger(dev, transport_remove_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_remove_device);
+
+static void transport_destroy_classdev(struct attribute_container *cont,
+				      struct device *dev,
+				      struct class_device *classdev)
+{
+	struct transport_class *tclass = class_to_transport_class(cont->class);
+
+	if (tclass->remove != anon_transport_dummy_function)
+		class_device_put(classdev);
+}
+
+
+/**
+ * transport_destroy_device - destroy a removed device
+ *
+ * @dev: device to eliminate from the transport class.
+ *
+ * This call triggers the elimination of storage associated with the
+ * transport classdev.  Note: all it really does is relinquish a
+ * reference to the classdev.  The memory will not be freed until the
+ * last reference goes to zero.  Note also that the classdev retains a
+ * reference count on dev, so dev too will remain for as long as the
+ * transport class device remains around.
+ */
+void transport_destroy_device(struct device *dev)
+{
+	attribute_container_remove_device(dev, transport_destroy_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_destroy_device);
diff --git a/kernel_addons/backport/2.6.9_U4/include/linux/attribute_container.h b/kernel_addons/backport/2.6.9_U4/include/linux/attribute_container.h
new file mode 100644
index 0000000..93bfb0b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/linux/attribute_container.h
@@ -0,0 +1,71 @@
+/*
+ * class_container.h - a generic container for all classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ */
+
+#ifndef _ATTRIBUTE_CONTAINER_H_
+#define _ATTRIBUTE_CONTAINER_H_
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/klist.h>
+#include <linux/spinlock.h>
+
+struct attribute_container {
+	struct list_head	node;
+	struct klist		containers;
+	struct class		*class;
+	struct class_device_attribute **attrs;
+	int (*match)(struct attribute_container *, struct device *);
+#define	ATTRIBUTE_CONTAINER_NO_CLASSDEVS	0x01
+	unsigned long		flags;
+};
+
+static inline int
+attribute_container_no_classdevs(struct attribute_container *atc)
+{
+	return atc->flags & ATTRIBUTE_CONTAINER_NO_CLASSDEVS;
+}
+
+static inline void
+attribute_container_set_no_classdevs(struct attribute_container *atc)
+{
+	atc->flags |= ATTRIBUTE_CONTAINER_NO_CLASSDEVS;
+}
+
+int attribute_container_register(struct attribute_container *cont);
+int attribute_container_unregister(struct attribute_container *cont);
+void attribute_container_create_device(struct device *dev,
+				       int (*fn)(struct attribute_container *,
+						 struct device *,
+						 struct class_device *));
+void attribute_container_add_device(struct device *dev,
+				    int (*fn)(struct attribute_container *,
+					      struct device *,
+					      struct class_device *));
+void attribute_container_remove_device(struct device *dev,
+				       void (*fn)(struct attribute_container *,
+						  struct device *,
+						  struct class_device *));
+void attribute_container_device_trigger(struct device *dev, 
+					int (*fn)(struct attribute_container *,
+						  struct device *,
+						  struct class_device *));
+void attribute_container_trigger(struct device *dev, 
+				 int (*fn)(struct attribute_container *,
+					   struct device *));
+int attribute_container_add_attrs(struct class_device *classdev);
+int attribute_container_add_class_device(struct class_device *classdev);
+int attribute_container_add_class_device_adapter(struct attribute_container *cont,
+						 struct device *dev,
+						 struct class_device *classdev);
+void attribute_container_remove_attrs(struct class_device *classdev);
+void attribute_container_class_device_del(struct class_device *classdev);
+struct attribute_container *attribute_container_classdev_to_container(struct class_device *);
+struct class_device *attribute_container_find_class_device(struct attribute_container *, struct device *);
+struct class_device_attribute **attribute_container_classdev_to_attrs(const struct class_device *classdev);
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U4/include/linux/crypto.h b/kernel_addons/backport/2.6.9_U4/include/linux/crypto.h
new file mode 100644
index 0000000..aecccde
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/linux/crypto.h
@@ -0,0 +1,11 @@
+#ifndef LINUX_CRYPTO_BACKPORT_H
+#define LINUX_CRYPTO_BACKPORT_H
+
+#include_next <linux/crypto.h>
+
+#define crypto_hash_init(desc) crypto_digest_init(*desc)
+#define crypto_hash_digest(desc, sg, nbytes, out) crypto_digest_digest(*desc, sg, 1, out)
+#define crypto_hash_update(desc, sg, nbytes) crypto_digest_update(*desc, sg, 1)
+#define crypto_hash_final(desc, out) crypto_digest_final(*desc, out)
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U4/include/linux/kernel.h b/kernel_addons/backport/2.6.9_U4/include/linux/kernel.h
index a37dcd5..02a5907 100644
--- a/kernel_addons/backport/2.6.9_U4/include/linux/kernel.h
+++ b/kernel_addons/backport/2.6.9_U4/include/linux/kernel.h
@@ -4,4 +4,7 @@ #define BACKPORT_KERNEL_H_2_6_19
 #include_next <linux/kernel.h>
 #include <linux/log2.h>
 
+#define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+#define NIPQUAD_FMT "%u.%u.%u.%u"
+
 #endif
diff --git a/kernel_addons/backport/2.6.9_U4/include/linux/kfifo.h b/kernel_addons/backport/2.6.9_U4/include/linux/kfifo.h
index 48eccd8..2b94461 100644
--- a/kernel_addons/backport/2.6.9_U4/include/linux/kfifo.h
+++ b/kernel_addons/backport/2.6.9_U4/include/linux/kfifo.h
@@ -25,6 +25,7 @@ #ifdef __KERNEL__
 
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
+#include <linux/gfp.h>
 
 struct kfifo {
 	unsigned char *buffer;	/* the buffer holding the data */
diff --git a/kernel_addons/backport/2.6.9_U4/include/linux/klist.h b/kernel_addons/backport/2.6.9_U4/include/linux/klist.h
new file mode 100644
index 0000000..7407125
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/linux/klist.h
@@ -0,0 +1,61 @@
+/*
+ *	klist.h - Some generic list helpers, extending struct list_head a bit.
+ *
+ *	Implementations are found in lib/klist.c
+ *
+ *
+ *	Copyright (C) 2005 Patrick Mochel
+ *
+ *	This file is rleased under the GPL v2.
+ */
+
+#ifndef _LINUX_KLIST_H
+#define _LINUX_KLIST_H
+
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/kref.h>
+#include <linux/list.h>
+
+struct klist_node;
+struct klist {
+	spinlock_t		k_lock;
+	struct list_head	k_list;
+	void			(*get)(struct klist_node *);
+	void			(*put)(struct klist_node *);
+};
+
+
+extern void klist_init(struct klist * k, void (*get)(struct klist_node *),
+		       void (*put)(struct klist_node *));
+
+struct klist_node {
+	struct klist		* n_klist;
+	struct list_head	n_node;
+	struct kref		n_ref;
+	struct completion	n_removed;
+};
+
+extern void klist_add_tail(struct klist_node * n, struct klist * k);
+extern void klist_add_head(struct klist_node * n, struct klist * k);
+
+extern void klist_del(struct klist_node * n);
+extern void klist_remove(struct klist_node * n);
+
+extern int klist_node_attached(struct klist_node * n);
+
+
+struct klist_iter {
+	struct klist		* i_klist;
+	struct list_head	* i_head;
+	struct klist_node	* i_cur;
+};
+
+
+extern void klist_iter_init(struct klist * k, struct klist_iter * i);
+extern void klist_iter_init_node(struct klist * k, struct klist_iter * i, 
+				 struct klist_node * n);
+extern void klist_iter_exit(struct klist_iter * i);
+extern struct klist_node * klist_next(struct klist_iter * i);
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U4/include/linux/memory.h b/kernel_addons/backport/2.6.9_U4/include/linux/memory.h
new file mode 100644
index 0000000..654ef55
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/linux/memory.h
@@ -0,0 +1,89 @@
+/*
+ * include/linux/memory.h - generic memory definition
+ *
+ * This is mainly for topological representation. We define the
+ * basic "struct memory_block" here, which can be embedded in per-arch
+ * definitions or NUMA information.
+ *
+ * Basic handling of the devices is done in drivers/base/memory.c
+ * and system devices are handled in drivers/base/sys.c.
+ *
+ * Memory block are exported via sysfs in the class/memory/devices/
+ * directory.
+ *
+ */
+#ifndef _LINUX_MEMORY_H_
+#define _LINUX_MEMORY_H_
+
+#include <linux/sysdev.h>
+#include <linux/node.h>
+#include <linux/compiler.h>
+
+#include <asm/semaphore.h>
+
+struct memory_block {
+	unsigned long phys_index;
+	unsigned long state;
+	/*
+	 * This serializes all state change requests.  It isn't
+	 * held during creation because the control files are
+	 * created long after the critical areas during
+	 * initialization.
+	 */
+	struct semaphore state_sem;
+	int phys_device;		/* to which fru does this belong? */
+	void *hw;			/* optional pointer to fw/hw data */
+	int (*phys_callback)(struct memory_block *);
+	struct sys_device sysdev;
+};
+
+/* These states are exposed to userspace as text strings in sysfs */
+#define	MEM_ONLINE		(1<<0) /* exposed to userspace */
+#define	MEM_GOING_OFFLINE	(1<<1) /* exposed to userspace */
+#define	MEM_OFFLINE		(1<<2) /* exposed to userspace */
+
+/*
+ * All of these states are currently kernel-internal for notifying
+ * kernel components and architectures.
+ *
+ * For MEM_MAPPING_INVALID, all notifier chains with priority >0
+ * are called before pfn_to_page() becomes invalid.  The priority=0
+ * entry is reserved for the function that actually makes
+ * pfn_to_page() stop working.  Any notifiers that want to be called
+ * after that should have priority <0.
+ */
+#define	MEM_MAPPING_INVALID	(1<<3)
+
+struct notifier_block;
+struct mem_section;
+
+#ifndef CONFIG_MEMORY_HOTPLUG_SPARSE
+static inline int memory_dev_init(void)
+{
+	return 0;
+}
+static inline int register_memory_notifier(struct notifier_block *nb)
+{
+	return 0;
+}
+static inline void unregister_memory_notifier(struct notifier_block *nb)
+{
+}
+#else
+extern int register_new_memory(struct mem_section *);
+extern int unregister_memory_section(struct mem_section *);
+extern int memory_dev_init(void);
+extern int remove_memory_block(unsigned long, struct mem_section *, int);
+
+#define CONFIG_MEM_BLOCK_SIZE	(PAGES_PER_SECTION<<PAGE_SHIFT)
+
+
+#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
+
+#define hotplug_memory_notifier(fn, pri) {			\
+	static struct notifier_block fn##_mem_nb =		\
+		{ .notifier_call = fn, .priority = pri };	\
+	register_memory_notifier(&fn##_mem_nb);			\
+}
+
+#endif /* _LINUX_MEMORY_H_ */
diff --git a/kernel_addons/backport/2.6.9_U4/include/linux/netlink.h b/kernel_addons/backport/2.6.9_U4/include/linux/netlink.h
new file mode 100644
index 0000000..6d69105
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/linux/netlink.h
@@ -0,0 +1,14 @@
+#ifndef BACKPORT_LINUX_NETLINK_H
+#define BACKPORT_LINUX_NETLINK_H
+
+#include_next <linux/netlink.h>
+
+#define __nlmsg_put(skb, daemon_pid, seq, type, len, flags) \
+       __nlmsg_put(skb, daemon_pid, 0, 0, len)
+
+#define netlink_kernel_create(uint, groups, input, mod) \
+       netlink_kernel_create(uint, input)
+
+#define NETLINK_ISCSI           8
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U4/include/linux/transport_class.h b/kernel_addons/backport/2.6.9_U4/include/linux/transport_class.h
new file mode 100644
index 0000000..1d6cc22
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/linux/transport_class.h
@@ -0,0 +1,100 @@
+/*
+ * transport_class.h - a generic container for all transport classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ */
+
+#ifndef _TRANSPORT_CLASS_H_
+#define _TRANSPORT_CLASS_H_
+
+#include <linux/device.h>
+#include <linux/attribute_container.h>
+
+struct transport_container;
+
+struct transport_class {
+	struct class class;
+	int (*setup)(struct transport_container *, struct device *,
+		     struct class_device *);
+	int (*configure)(struct transport_container *, struct device *,
+			 struct class_device *);
+	int (*remove)(struct transport_container *, struct device *,
+		      struct class_device *);
+};
+
+#define DECLARE_TRANSPORT_CLASS(cls, nm, su, rm, cfg)			\
+struct transport_class cls = {						\
+	.class = {							\
+		.name = nm,						\
+	},								\
+	.setup = su,							\
+	.remove = rm,							\
+	.configure = cfg,						\
+}
+
+
+struct anon_transport_class {
+	struct transport_class tclass;
+	struct attribute_container container;
+};
+
+#define DECLARE_ANON_TRANSPORT_CLASS(cls, mtch, cfg)		\
+struct anon_transport_class cls = {				\
+	.tclass = {						\
+		.configure = cfg,				\
+	},							\
+	. container = {						\
+		.match = mtch,					\
+	},							\
+}
+
+#define class_to_transport_class(x) \
+	container_of(x, struct transport_class, class)
+
+struct transport_container {
+	struct attribute_container ac;
+	struct attribute_group *statistics;
+};
+
+#define attribute_container_to_transport_container(x) \
+	container_of(x, struct transport_container, ac)
+
+void transport_remove_device(struct device *);
+void transport_add_device(struct device *);
+void transport_setup_device(struct device *);
+void transport_configure_device(struct device *);
+void transport_destroy_device(struct device *);
+
+static inline void
+transport_register_device(struct device *dev)
+{
+	transport_setup_device(dev);
+	transport_add_device(dev);
+}
+
+static inline void
+transport_unregister_device(struct device *dev)
+{
+	transport_remove_device(dev);
+	transport_destroy_device(dev);
+}
+
+static inline int transport_container_register(struct transport_container *tc)
+{
+	return attribute_container_register(&tc->ac);
+}
+
+static inline int transport_container_unregister(struct transport_container *tc)
+{
+	return attribute_container_unregister(&tc->ac);
+}
+
+int transport_class_register(struct transport_class *);
+int anon_transport_class_register(struct anon_transport_class *);
+void transport_class_unregister(struct transport_class *);
+void anon_transport_class_unregister(struct anon_transport_class *);
+
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U4/include/scsi/iscsi_proto.h b/kernel_addons/backport/2.6.9_U4/include/scsi/iscsi_proto.h
new file mode 100644
index 0000000..02f6e4b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/scsi/iscsi_proto.h
@@ -0,0 +1,587 @@
+/*
+ * RFC 3720 (iSCSI) protocol data types
+ *
+ * Copyright (C) 2005 Dmitry Yusupov
+ * Copyright (C) 2005 Alex Aizman
+ * maintained by open-iscsi at googlegroups.com
+ *
+ * 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.
+ *
+ * See the file COPYING included with this distribution for more details.
+ */
+
+#ifndef ISCSI_PROTO_H
+#define ISCSI_PROTO_H
+
+#define ISCSI_DRAFT20_VERSION	0x00
+
+/* default iSCSI listen port for incoming connections */
+#define ISCSI_LISTEN_PORT	3260
+
+/* Padding word length */
+#define PAD_WORD_LEN		4
+
+/*
+ * useful common(control and data pathes) macro
+ */
+#define ntoh24(p) (((p)[0] << 16) | ((p)[1] << 8) | ((p)[2]))
+#define hton24(p, v) { \
+        p[0] = (((v) >> 16) & 0xFF); \
+        p[1] = (((v) >> 8) & 0xFF); \
+        p[2] = ((v) & 0xFF); \
+}
+#define zero_data(p) {p[0]=0;p[1]=0;p[2]=0;}
+
+/*
+ * iSCSI Template Message Header
+ */
+struct iscsi_hdr {
+	uint8_t		opcode;
+	uint8_t		flags;		/* Final bit */
+	uint8_t		rsvd2[2];
+	uint8_t		hlength;	/* AHSs total length */
+	uint8_t		dlength[3];	/* Data length */
+	uint8_t		lun[8];
+	__be32		itt;		/* Initiator Task Tag */
+	__be32		ttt;		/* Target Task Tag */
+	__be32		statsn;
+	__be32		exp_statsn;
+	__be32		max_statsn;
+	uint8_t		other[12];
+};
+
+/************************* RFC 3720 Begin *****************************/
+
+#define ISCSI_RESERVED_TAG		0xffffffff
+
+/* Opcode encoding bits */
+#define ISCSI_OP_RETRY			0x80
+#define ISCSI_OP_IMMEDIATE		0x40
+#define ISCSI_OPCODE_MASK		0x3F
+
+/* Initiator Opcode values */
+#define ISCSI_OP_NOOP_OUT		0x00
+#define ISCSI_OP_SCSI_CMD		0x01
+#define ISCSI_OP_SCSI_TMFUNC		0x02
+#define ISCSI_OP_LOGIN			0x03
+#define ISCSI_OP_TEXT			0x04
+#define ISCSI_OP_SCSI_DATA_OUT		0x05
+#define ISCSI_OP_LOGOUT			0x06
+#define ISCSI_OP_SNACK			0x10
+
+#define ISCSI_OP_VENDOR1_CMD		0x1c
+#define ISCSI_OP_VENDOR2_CMD		0x1d
+#define ISCSI_OP_VENDOR3_CMD		0x1e
+#define ISCSI_OP_VENDOR4_CMD		0x1f
+
+/* Target Opcode values */
+#define ISCSI_OP_NOOP_IN		0x20
+#define ISCSI_OP_SCSI_CMD_RSP		0x21
+#define ISCSI_OP_SCSI_TMFUNC_RSP	0x22
+#define ISCSI_OP_LOGIN_RSP		0x23
+#define ISCSI_OP_TEXT_RSP		0x24
+#define ISCSI_OP_SCSI_DATA_IN		0x25
+#define ISCSI_OP_LOGOUT_RSP		0x26
+#define ISCSI_OP_R2T			0x31
+#define ISCSI_OP_ASYNC_EVENT		0x32
+#define ISCSI_OP_REJECT			0x3f
+
+struct iscsi_ahs_hdr {
+	__be16 ahslength;
+	uint8_t ahstype;
+	uint8_t ahspec[5];
+};
+
+#define ISCSI_AHSTYPE_CDB		1
+#define ISCSI_AHSTYPE_RLENGTH		2
+
+/* iSCSI PDU Header */
+struct iscsi_cmd {
+	uint8_t opcode;
+	uint8_t flags;
+	__be16 rsvd2;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32 itt;	/* Initiator Task Tag */
+	__be32 data_length;
+	__be32 cmdsn;
+	__be32 exp_statsn;
+	uint8_t cdb[16];	/* SCSI Command Block */
+	/* Additional Data (Command Dependent) */
+};
+
+/* Command PDU flags */
+#define ISCSI_FLAG_CMD_FINAL		0x80
+#define ISCSI_FLAG_CMD_READ		0x40
+#define ISCSI_FLAG_CMD_WRITE		0x20
+#define ISCSI_FLAG_CMD_ATTR_MASK	0x07	/* 3 bits */
+
+/* SCSI Command Attribute values */
+#define ISCSI_ATTR_UNTAGGED		0
+#define ISCSI_ATTR_SIMPLE		1
+#define ISCSI_ATTR_ORDERED		2
+#define ISCSI_ATTR_HEAD_OF_QUEUE	3
+#define ISCSI_ATTR_ACA			4
+
+struct iscsi_rlength_ahdr {
+	__be16 ahslength;
+	uint8_t ahstype;
+	uint8_t reserved;
+	__be32 read_length;
+};
+
+/* SCSI Response Header */
+struct iscsi_cmd_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t response;
+	uint8_t cmd_status;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	rsvd1;
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	__be32	exp_datasn;
+	__be32	bi_residual_count;
+	__be32	residual_count;
+	/* Response or Sense Data (optional) */
+};
+
+/* Command Response PDU flags */
+#define ISCSI_FLAG_CMD_BIDI_OVERFLOW	0x10
+#define ISCSI_FLAG_CMD_BIDI_UNDERFLOW	0x08
+#define ISCSI_FLAG_CMD_OVERFLOW		0x04
+#define ISCSI_FLAG_CMD_UNDERFLOW	0x02
+
+/* iSCSI Status values. Valid if Rsp Selector bit is not set */
+#define ISCSI_STATUS_CMD_COMPLETED	0
+#define ISCSI_STATUS_TARGET_FAILURE	1
+#define ISCSI_STATUS_SUBSYS_FAILURE	2
+
+/* Asynchronous Event Header */
+struct iscsi_async {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[2];
+	uint8_t rsvd3;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	uint8_t rsvd4[8];
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	uint8_t async_event;
+	uint8_t async_vcode;
+	__be16	param1;
+	__be16	param2;
+	__be16	param3;
+	uint8_t rsvd5[4];
+};
+
+/* iSCSI Event Codes */
+#define ISCSI_ASYNC_MSG_SCSI_EVENT			0
+#define ISCSI_ASYNC_MSG_REQUEST_LOGOUT			1
+#define ISCSI_ASYNC_MSG_DROPPING_CONNECTION		2
+#define ISCSI_ASYNC_MSG_DROPPING_ALL_CONNECTIONS	3
+#define ISCSI_ASYNC_MSG_PARAM_NEGOTIATION		4
+#define ISCSI_ASYNC_MSG_VENDOR_SPECIFIC			255
+
+/* NOP-Out Message */
+struct iscsi_nopout {
+	uint8_t opcode;
+	uint8_t flags;
+	__be16	rsvd2;
+	uint8_t rsvd3;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	ttt;	/* Target Transfer Tag */
+	__be32	cmdsn;
+	__be32	exp_statsn;
+	uint8_t rsvd4[16];
+};
+
+/* NOP-In Message */
+struct iscsi_nopin {
+	uint8_t opcode;
+	uint8_t flags;
+	__be16	rsvd2;
+	uint8_t rsvd3;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	ttt;	/* Target Transfer Tag */
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	uint8_t rsvd4[12];
+};
+
+/* SCSI Task Management Message Header */
+struct iscsi_tm {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd1[2];
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	rtt;	/* Reference Task Tag */
+	__be32	cmdsn;
+	__be32	exp_statsn;
+	__be32	refcmdsn;
+	__be32	exp_datasn;
+	uint8_t rsvd2[8];
+};
+
+#define ISCSI_FLAG_TM_FUNC_MASK			0x7F
+
+/* Function values */
+#define ISCSI_TM_FUNC_ABORT_TASK		1
+#define ISCSI_TM_FUNC_ABORT_TASK_SET		2
+#define ISCSI_TM_FUNC_CLEAR_ACA			3
+#define ISCSI_TM_FUNC_CLEAR_TASK_SET		4
+#define ISCSI_TM_FUNC_LOGICAL_UNIT_RESET	5
+#define ISCSI_TM_FUNC_TARGET_WARM_RESET		6
+#define ISCSI_TM_FUNC_TARGET_COLD_RESET		7
+#define ISCSI_TM_FUNC_TASK_REASSIGN		8
+
+/* SCSI Task Management Response Header */
+struct iscsi_tm_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t response;	/* see Response values below */
+	uint8_t qualifier;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd2[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	rtt;	/* Reference Task Tag */
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	uint8_t rsvd3[12];
+};
+
+/* Response values */
+#define ISCSI_TMF_RSP_COMPLETE		0x00
+#define ISCSI_TMF_RSP_NO_TASK		0x01
+#define ISCSI_TMF_RSP_NO_LUN		0x02
+#define ISCSI_TMF_RSP_TASK_ALLEGIANT	0x03
+#define ISCSI_TMF_RSP_NO_FAILOVER	0x04
+#define ISCSI_TMF_RSP_NOT_SUPPORTED	0x05
+#define ISCSI_TMF_RSP_AUTH_FAILED	0x06
+#define ISCSI_TMF_RSP_REJECTED		0xff
+
+/* Ready To Transfer Header */
+struct iscsi_r2t_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[2];
+	uint8_t	hlength;
+	uint8_t	dlength[3];
+	uint8_t lun[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	ttt;	/* Target Transfer Tag */
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	__be32	r2tsn;
+	__be32	data_offset;
+	__be32	data_length;
+};
+
+/* SCSI Data Hdr */
+struct iscsi_data {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[2];
+	uint8_t rsvd3;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32	itt;
+	__be32	ttt;
+	__be32	rsvd4;
+	__be32	exp_statsn;
+	__be32	rsvd5;
+	__be32	datasn;
+	__be32	offset;
+	__be32	rsvd6;
+	/* Payload */
+};
+
+/* SCSI Data Response Hdr */
+struct iscsi_data_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2;
+	uint8_t cmd_status;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32	itt;
+	__be32	ttt;
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	__be32	datasn;
+	__be32	offset;
+	__be32	residual_count;
+};
+
+/* Data Response PDU flags */
+#define ISCSI_FLAG_DATA_ACK		0x40
+#define ISCSI_FLAG_DATA_OVERFLOW	0x04
+#define ISCSI_FLAG_DATA_UNDERFLOW	0x02
+#define ISCSI_FLAG_DATA_STATUS		0x01
+
+/* Text Header */
+struct iscsi_text {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[2];
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd4[8];
+	__be32	itt;
+	__be32	ttt;
+	__be32	cmdsn;
+	__be32	exp_statsn;
+	uint8_t rsvd5[16];
+	/* Text - key=value pairs */
+};
+
+#define ISCSI_FLAG_TEXT_CONTINUE	0x40
+
+/* Text Response Header */
+struct iscsi_text_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[2];
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd4[8];
+	__be32	itt;
+	__be32	ttt;
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	uint8_t rsvd5[12];
+	/* Text Response - key:value pairs */
+};
+
+/* Login Header */
+struct iscsi_login {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t max_version;	/* Max. version supported */
+	uint8_t min_version;	/* Min. version supported */
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t isid[6];	/* Initiator Session ID */
+	__be16	tsih;	/* Target Session Handle */
+	__be32	itt;	/* Initiator Task Tag */
+	__be16	cid;
+	__be16	rsvd3;
+	__be32	cmdsn;
+	__be32	exp_statsn;
+	uint8_t rsvd5[16];
+};
+
+/* Login PDU flags */
+#define ISCSI_FLAG_LOGIN_TRANSIT		0x80
+#define ISCSI_FLAG_LOGIN_CONTINUE		0x40
+#define ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK	0x0C	/* 2 bits */
+#define ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK	0x03	/* 2 bits */
+
+#define ISCSI_LOGIN_CURRENT_STAGE(flags) \
+	((flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2)
+#define ISCSI_LOGIN_NEXT_STAGE(flags) \
+	(flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK)
+
+/* Login Response Header */
+struct iscsi_login_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t max_version;	/* Max. version supported */
+	uint8_t active_version;	/* Active version */
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t isid[6];	/* Initiator Session ID */
+	__be16	tsih;	/* Target Session Handle */
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	rsvd3;
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	uint8_t status_class;	/* see Login RSP ststus classes below */
+	uint8_t status_detail;	/* see Login RSP Status details below */
+	uint8_t rsvd4[10];
+};
+
+/* Login stage (phase) codes for CSG, NSG */
+#define ISCSI_INITIAL_LOGIN_STAGE		-1
+#define ISCSI_SECURITY_NEGOTIATION_STAGE	0
+#define ISCSI_OP_PARMS_NEGOTIATION_STAGE	1
+#define ISCSI_FULL_FEATURE_PHASE		3
+
+/* Login Status response classes */
+#define ISCSI_STATUS_CLS_SUCCESS		0x00
+#define ISCSI_STATUS_CLS_REDIRECT		0x01
+#define ISCSI_STATUS_CLS_INITIATOR_ERR		0x02
+#define ISCSI_STATUS_CLS_TARGET_ERR		0x03
+
+/* Login Status response detail codes */
+/* Class-0 (Success) */
+#define ISCSI_LOGIN_STATUS_ACCEPT		0x00
+
+/* Class-1 (Redirection) */
+#define ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP	0x01
+#define ISCSI_LOGIN_STATUS_TGT_MOVED_PERM	0x02
+
+/* Class-2 (Initiator Error) */
+#define ISCSI_LOGIN_STATUS_INIT_ERR		0x00
+#define ISCSI_LOGIN_STATUS_AUTH_FAILED		0x01
+#define ISCSI_LOGIN_STATUS_TGT_FORBIDDEN	0x02
+#define ISCSI_LOGIN_STATUS_TGT_NOT_FOUND	0x03
+#define ISCSI_LOGIN_STATUS_TGT_REMOVED		0x04
+#define ISCSI_LOGIN_STATUS_NO_VERSION		0x05
+#define ISCSI_LOGIN_STATUS_ISID_ERROR		0x06
+#define ISCSI_LOGIN_STATUS_MISSING_FIELDS	0x07
+#define ISCSI_LOGIN_STATUS_CONN_ADD_FAILED	0x08
+#define ISCSI_LOGIN_STATUS_NO_SESSION_TYPE	0x09
+#define ISCSI_LOGIN_STATUS_NO_SESSION		0x0a
+#define ISCSI_LOGIN_STATUS_INVALID_REQUEST	0x0b
+
+/* Class-3 (Target Error) */
+#define ISCSI_LOGIN_STATUS_TARGET_ERROR		0x00
+#define ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE	0x01
+#define ISCSI_LOGIN_STATUS_NO_RESOURCES		0x02
+
+/* Logout Header */
+struct iscsi_logout {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd1[2];
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd2[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be16	cid;
+	uint8_t rsvd3[2];
+	__be32	cmdsn;
+	__be32	exp_statsn;
+	uint8_t rsvd4[16];
+};
+
+/* Logout PDU flags */
+#define ISCSI_FLAG_LOGOUT_REASON_MASK	0x7F
+
+/* logout reason_code values */
+
+#define ISCSI_LOGOUT_REASON_CLOSE_SESSION	0
+#define ISCSI_LOGOUT_REASON_CLOSE_CONNECTION	1
+#define ISCSI_LOGOUT_REASON_RECOVERY		2
+#define ISCSI_LOGOUT_REASON_AEN_REQUEST		3
+
+/* Logout Response Header */
+struct iscsi_logout_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t response;	/* see Logout response values below */
+	uint8_t rsvd2;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd3[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	rsvd4;
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	__be32	rsvd5;
+	__be16	t2wait;
+	__be16	t2retain;
+	__be32	rsvd6;
+};
+
+/* logout response status values */
+
+#define ISCSI_LOGOUT_SUCCESS			0
+#define ISCSI_LOGOUT_CID_NOT_FOUND		1
+#define ISCSI_LOGOUT_RECOVERY_UNSUPPORTED	2
+#define ISCSI_LOGOUT_CLEANUP_FAILED		3
+
+/* SNACK Header */
+struct iscsi_snack {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[14];
+	__be32	itt;
+	__be32	begrun;
+	__be32	runlength;
+	__be32	exp_statsn;
+	__be32	rsvd3;
+	__be32	exp_datasn;
+	uint8_t rsvd6[8];
+};
+
+/* SNACK PDU flags */
+#define ISCSI_FLAG_SNACK_TYPE_MASK	0x0F	/* 4 bits */
+
+/* Reject Message Header */
+struct iscsi_reject {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t reason;
+	uint8_t rsvd2;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd3[8];
+	__be32  ffffffff;
+	uint8_t rsvd4[4];
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	__be32	datasn;
+	uint8_t rsvd5[8];
+	/* Text - Rejected hdr */
+};
+
+/* Reason for Reject */
+#define ISCSI_REASON_CMD_BEFORE_LOGIN	1
+#define ISCSI_REASON_DATA_DIGEST_ERROR	2
+#define ISCSI_REASON_DATA_SNACK_REJECT	3
+#define ISCSI_REASON_PROTOCOL_ERROR	4
+#define ISCSI_REASON_CMD_NOT_SUPPORTED	5
+#define ISCSI_REASON_IMM_CMD_REJECT		6
+#define ISCSI_REASON_TASK_IN_PROGRESS	7
+#define ISCSI_REASON_INVALID_SNACK		8
+#define ISCSI_REASON_BOOKMARK_INVALID	9
+#define ISCSI_REASON_BOOKMARK_NO_RESOURCES	10
+#define ISCSI_REASON_NEGOTIATION_RESET	11
+
+/* Max. number of Key=Value pairs in a text message */
+#define MAX_KEY_VALUE_PAIRS	8192
+
+/* maximum length for text keys/values */
+#define KEY_MAXLEN		64
+#define VALUE_MAXLEN		255
+#define TARGET_NAME_MAXLEN	VALUE_MAXLEN
+
+#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH	8192
+
+/************************* RFC 3720 End *****************************/
+
+#endif /* ISCSI_PROTO_H */
diff --git a/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_device.h b/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_device.h
new file mode 100644
index 0000000..f353e0b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_device.h
@@ -0,0 +1,19 @@
+#ifndef _SCSI_SCSI_DEVICE_H_BACKPORT
+#define _SCSI_SCSI_DEVICE_H_BACKPORT
+
+#include_next <scsi/scsi_device.h>
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+
+struct scsi_lun;
+
+extern void int_to_scsilun(unsigned int, struct scsi_lun *);
+extern void scsi_target_block(struct device *);
+extern void scsi_target_unblock(struct device *);
+extern void starget_for_each_device(struct scsi_target *, void *,
+		     void (*fn)(struct scsi_device *, void *));
+#endif /* _SCSI_SCSI_DEVICE_H_BACKPORT */
diff --git a/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_host.h b/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_host.h
new file mode 100644
index 0000000..b7e019b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_host.h
@@ -0,0 +1,8 @@
+#ifndef _SCSI_SCSI_HOST_H_BACKPORT
+#define _SCSI_SCSI_HOST_H_BACKPORT
+
+#include_next <scsi/scsi_host.h>
+
+#define scsi_queue_work(shost, work) schedule_work(work)
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_transport.h b/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_transport.h
new file mode 100644
index 0000000..99c2b12
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/scsi/scsi_transport.h
@@ -0,0 +1,8 @@
+#ifndef _SCSI_SCSI_TRANSPORT_H_BACKPORT
+#define _SCSI_SCSI_TRANSPORT_H_BACKPORT
+
+#include_next <scsi/scsi_transport.h>
+
+#include <linux/transport_class.h>
+
+#endif /* _SCSI_SCSI_TRANSPORT_H_BACKPORT */
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/attribute_container.c b/kernel_addons/backport/2.6.9_U4/include/src/attribute_container.c
new file mode 100644
index 0000000..44948d1
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/attribute_container.c
@@ -0,0 +1,438 @@
+/*
+ * attribute_container.c - implementation of a simple container for classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ *
+ * The basic idea here is to enable a device to be attached to an
+ * aritrary numer of classes without having to allocate storage for them.
+ * Instead, the contained classes select the devices they need to attach
+ * to via a matching function.
+ */
+
+#include <linux/attribute_container.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/module.h>
+
+#include "base.h"
+
+/* This is a private structure used to tie the classdev and the
+ * container .. it should never be visible outside this file */
+struct internal_container {
+	struct klist_node node;
+	struct attribute_container *cont;
+	struct class_device classdev;
+};
+
+static void internal_container_klist_get(struct klist_node *n)
+{
+	struct internal_container *ic =
+		container_of(n, struct internal_container, node);
+	class_device_get(&ic->classdev);
+}
+
+static void internal_container_klist_put(struct klist_node *n)
+{
+	struct internal_container *ic =
+		container_of(n, struct internal_container, node);
+	class_device_put(&ic->classdev);
+}
+
+
+/**
+ * attribute_container_classdev_to_container - given a classdev, return the container
+ *
+ * @classdev: the class device created by attribute_container_add_device.
+ *
+ * Returns the container associated with this classdev.
+ */
+struct attribute_container *
+attribute_container_classdev_to_container(struct class_device *classdev)
+{
+	struct internal_container *ic =
+		container_of(classdev, struct internal_container, classdev);
+	return ic->cont;
+}
+EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container);
+
+static struct list_head attribute_container_list;
+
+static DECLARE_MUTEX(attribute_container_mutex);
+
+/**
+ * attribute_container_register - register an attribute container
+ *
+ * @cont: The container to register.  This must be allocated by the
+ *        callee and should also be zeroed by it.
+ */
+int
+attribute_container_register(struct attribute_container *cont)
+{
+	INIT_LIST_HEAD(&cont->node);
+	klist_init(&cont->containers,internal_container_klist_get,
+		   internal_container_klist_put);
+		
+	down(&attribute_container_mutex);
+	list_add_tail(&cont->node, &attribute_container_list);
+	up(&attribute_container_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(attribute_container_register);
+
+/**
+ * attribute_container_unregister - remove a container registration
+ *
+ * @cont: previously registered container to remove
+ */
+int
+attribute_container_unregister(struct attribute_container *cont)
+{
+	int retval = -EBUSY;
+	down(&attribute_container_mutex);
+	spin_lock(&cont->containers.k_lock);
+	if (!list_empty(&cont->containers.k_list))
+		goto out;
+	retval = 0;
+	list_del(&cont->node);
+ out:
+	spin_unlock(&cont->containers.k_lock);
+	up(&attribute_container_mutex);
+	return retval;
+		
+}
+EXPORT_SYMBOL_GPL(attribute_container_unregister);
+
+/* private function used as class release */
+static void attribute_container_release(struct class_device *classdev)
+{
+	struct internal_container *ic 
+		= container_of(classdev, struct internal_container, classdev);
+	struct device *dev = classdev->dev;
+
+	kfree(ic);
+	put_device(dev);
+}
+
+/**
+ * attribute_container_add_device - see if any container is interested in dev
+ *
+ * @dev: device to add attributes to
+ * @fn:	 function to trigger addition of class device.
+ *
+ * This function allocates storage for the class device(s) to be
+ * attached to dev (one for each matching attribute_container).  If no
+ * fn is provided, the code will simply register the class device via
+ * class_device_add.  If a function is provided, it is expected to add
+ * the class device at the appropriate time.  One of the things that
+ * might be necessary is to allocate and initialise the classdev and
+ * then add it a later time.  To do this, call this routine for
+ * allocation and initialisation and then use
+ * attribute_container_device_trigger() to call class_device_add() on
+ * it.  Note: after this, the class device contains a reference to dev
+ * which is not relinquished until the release of the classdev.
+ */
+void
+attribute_container_add_device(struct device *dev,
+			       int (*fn)(struct attribute_container *,
+					 struct device *,
+					 struct class_device *))
+{
+	struct attribute_container *cont;
+
+	down(&attribute_container_mutex);
+	list_for_each_entry(cont, &attribute_container_list, node) {
+		struct internal_container *ic;
+
+		if (attribute_container_no_classdevs(cont))
+			continue;
+
+		if (!cont->match(cont, dev))
+			continue;
+
+		ic = kzalloc(sizeof(*ic), GFP_KERNEL);
+		if (!ic) {
+			dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
+			continue;
+		}
+
+		ic->cont = cont;
+		class_device_initialize(&ic->classdev);
+		ic->classdev.dev = get_device(dev);
+		ic->classdev.class = cont->class;
+		cont->class->release = attribute_container_release;
+		strcpy(ic->classdev.class_id, dev->bus_id);
+		if (fn)
+			fn(cont, dev, &ic->classdev);
+		else
+			attribute_container_add_class_device(&ic->classdev);
+		klist_add_tail(&ic->node, &cont->containers);
+	}
+	up(&attribute_container_mutex);
+}
+
+/* FIXME: can't break out of this unless klist_iter_exit is also
+ * called before doing the break
+ */
+#define klist_for_each_entry(pos, head, member, iter) \
+	for (klist_iter_init(head, iter); (pos = ({ \
+		struct klist_node *n = klist_next(iter); \
+		n ? container_of(n, typeof(*pos), member) : \
+			({ klist_iter_exit(iter) ; NULL; }); \
+	}) ) != NULL; )
+			
+
+/**
+ * attribute_container_remove_device - make device eligible for removal.
+ *
+ * @dev:  The generic device
+ * @fn:	  A function to call to remove the device
+ *
+ * This routine triggers device removal.  If fn is NULL, then it is
+ * simply done via class_device_unregister (note that if something
+ * still has a reference to the classdev, then the memory occupied
+ * will not be freed until the classdev is released).  If you want a
+ * two phase release: remove from visibility and then delete the
+ * device, then you should use this routine with a fn that calls
+ * class_device_del() and then use
+ * attribute_container_device_trigger() to do the final put on the
+ * classdev.
+ */
+void
+attribute_container_remove_device(struct device *dev,
+				  void (*fn)(struct attribute_container *,
+					     struct device *,
+					     struct class_device *))
+{
+	struct attribute_container *cont;
+
+	down(&attribute_container_mutex);
+	list_for_each_entry(cont, &attribute_container_list, node) {
+		struct internal_container *ic;
+		struct klist_iter iter;
+
+		if (attribute_container_no_classdevs(cont))
+			continue;
+
+		if (!cont->match(cont, dev))
+			continue;
+
+		klist_for_each_entry(ic, &cont->containers, node, &iter) {
+			if (dev != ic->classdev.dev)
+				continue;
+			klist_del(&ic->node);
+			if (fn)
+				fn(cont, dev, &ic->classdev);
+			else {
+				attribute_container_remove_attrs(&ic->classdev);
+				class_device_unregister(&ic->classdev);
+			}
+		}
+	}
+	up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_device_trigger - execute a trigger for each matching classdev
+ *
+ * @dev:  The generic device to run the trigger for
+ * @fn	  the function to execute for each classdev.
+ *
+ * This funcion is for executing a trigger when you need to know both
+ * the container and the classdev.  If you only care about the
+ * container, then use attribute_container_trigger() instead.
+ */
+void
+attribute_container_device_trigger(struct device *dev, 
+				   int (*fn)(struct attribute_container *,
+					     struct device *,
+					     struct class_device *))
+{
+	struct attribute_container *cont;
+
+	down(&attribute_container_mutex);
+	list_for_each_entry(cont, &attribute_container_list, node) {
+		struct internal_container *ic;
+		struct klist_iter iter;
+
+		if (!cont->match(cont, dev))
+			continue;
+
+		if (attribute_container_no_classdevs(cont)) {
+			fn(cont, dev, NULL);
+			continue;
+		}
+
+		klist_for_each_entry(ic, &cont->containers, node, &iter) {
+			if (dev == ic->classdev.dev)
+				fn(cont, dev, &ic->classdev);
+		}
+	}
+	up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_trigger - trigger a function for each matching container
+ *
+ * @dev:  The generic device to activate the trigger for
+ * @fn:	  the function to trigger
+ *
+ * This routine triggers a function that only needs to know the
+ * matching containers (not the classdev) associated with a device.
+ * It is more lightweight than attribute_container_device_trigger, so
+ * should be used in preference unless the triggering function
+ * actually needs to know the classdev.
+ */
+void
+attribute_container_trigger(struct device *dev,
+			    int (*fn)(struct attribute_container *,
+				      struct device *))
+{
+	struct attribute_container *cont;
+
+	down(&attribute_container_mutex);
+	list_for_each_entry(cont, &attribute_container_list, node) {
+		if (cont->match(cont, dev))
+			fn(cont, dev);
+	}
+	up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_add_attrs - add attributes
+ *
+ * @classdev: The class device
+ *
+ * This simply creates all the class device sysfs files from the
+ * attributes listed in the container
+ */
+int
+attribute_container_add_attrs(struct class_device *classdev)
+{
+	struct attribute_container *cont =
+		attribute_container_classdev_to_container(classdev);
+	struct class_device_attribute **attrs =	cont->attrs;
+	int i, error;
+
+	if (!attrs)
+		return 0;
+
+	for (i = 0; attrs[i]; i++) {
+		error = class_device_create_file(classdev, attrs[i]);
+		if (error)
+			return error;
+	}
+
+	return 0;
+}
+
+/**
+ * attribute_container_add_class_device - same function as class_device_add
+ *
+ * @classdev:	the class device to add
+ *
+ * This performs essentially the same function as class_device_add except for
+ * attribute containers, namely add the classdev to the system and then
+ * create the attribute files
+ */
+int
+attribute_container_add_class_device(struct class_device *classdev)
+{
+	int error = class_device_add(classdev);
+	if (error)
+		return error;
+	return attribute_container_add_attrs(classdev);
+}
+
+/**
+ * attribute_container_add_class_device_adapter - simple adapter for triggers
+ *
+ * This function is identical to attribute_container_add_class_device except
+ * that it is designed to be called from the triggers
+ */
+int
+attribute_container_add_class_device_adapter(struct attribute_container *cont,
+					     struct device *dev,
+					     struct class_device *classdev)
+{
+	return attribute_container_add_class_device(classdev);
+}
+
+/**
+ * attribute_container_remove_attrs - remove any attribute files
+ *
+ * @classdev: The class device to remove the files from
+ *
+ */
+void
+attribute_container_remove_attrs(struct class_device *classdev)
+{
+	struct attribute_container *cont =
+		attribute_container_classdev_to_container(classdev);
+	struct class_device_attribute **attrs =	cont->attrs;
+	int i;
+
+	if (!attrs)
+		return;
+
+	for (i = 0; attrs[i]; i++)
+		class_device_remove_file(classdev, attrs[i]);
+}
+
+/**
+ * attribute_container_class_device_del - equivalent of class_device_del
+ *
+ * @classdev: the class device
+ *
+ * This function simply removes all the attribute files and then calls
+ * class_device_del.
+ */
+void
+attribute_container_class_device_del(struct class_device *classdev)
+{
+	attribute_container_remove_attrs(classdev);
+	class_device_del(classdev);
+}
+
+/**
+ * attribute_container_find_class_device - find the corresponding class_device
+ *
+ * @cont:	the container
+ * @dev:	the generic device
+ *
+ * Looks up the device in the container's list of class devices and returns
+ * the corresponding class_device.
+ */
+struct class_device *
+attribute_container_find_class_device(struct attribute_container *cont,
+				      struct device *dev)
+{
+	struct class_device *cdev = NULL;
+	struct internal_container *ic;
+	struct klist_iter iter;
+
+	klist_for_each_entry(ic, &cont->containers, node, &iter) {
+		if (ic->classdev.dev == dev) {
+			cdev = &ic->classdev;
+			/* FIXME: must exit iterator then break */
+			klist_iter_exit(&iter);
+			break;
+		}
+	}
+
+	return cdev;
+}
+EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
+
+int
+attribute_container_init(void)
+{
+	INIT_LIST_HEAD(&attribute_container_list);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(attribute_container_init);
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/base.h b/kernel_addons/backport/2.6.9_U4/include/src/base.h
new file mode 100644
index 0000000..a5f8936
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/base.h
@@ -0,0 +1 @@
+extern int attribute_container_init(void);
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/init.c b/kernel_addons/backport/2.6.9_U4/include/src/init.c
new file mode 100644
index 0000000..15f0bc6
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/init.c
@@ -0,0 +1,26 @@
+/*
+ *
+ * Copyright (c) 2002-3 Patrick Mochel
+ * Copyright (c) 2002-3 Open Source Development Labs
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/memory.h>
+
+#include "base.h"
+
+/**
+ *	driver_init - initialize driver model.
+ *
+ *	Call the driver model init functions to initialize their
+ *	subsystems. Called early from init/main.c.
+ */
+
+void __init driver_init(void)
+{
+	attribute_container_init();
+}
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/klist.c b/kernel_addons/backport/2.6.9_U4/include/src/klist.c
new file mode 100644
index 0000000..3b29ebc
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/klist.c
@@ -0,0 +1,287 @@
+/*
+ *	klist.c - Routines for manipulating klists.
+ *
+ *
+ *	This klist interface provides a couple of structures that wrap around 
+ *	struct list_head to provide explicit list "head" (struct klist) and 
+ *	list "node" (struct klist_node) objects. For struct klist, a spinlock
+ *	is included that protects access to the actual list itself. struct 
+ *	klist_node provides a pointer to the klist that owns it and a kref
+ *	reference count that indicates the number of current users of that node
+ *	in the list.
+ *
+ *	The entire point is to provide an interface for iterating over a list
+ *	that is safe and allows for modification of the list during the
+ *	iteration (e.g. insertion and removal), including modification of the
+ *	current node on the list.
+ *
+ *	It works using a 3rd object type - struct klist_iter - that is declared
+ *	and initialized before an iteration. klist_next() is used to acquire the
+ *	next element in the list. It returns NULL if there are no more items.
+ *	Internally, that routine takes the klist's lock, decrements the reference
+ *	count of the previous klist_node and increments the count of the next
+ *	klist_node. It then drops the lock and returns.
+ *
+ *	There are primitives for adding and removing nodes to/from a klist. 
+ *	When deleting, klist_del() will simply decrement the reference count. 
+ *	Only when the count goes to 0 is the node removed from the list. 
+ *	klist_remove() will try to delete the node from the list and block
+ *	until it is actually removed. This is useful for objects (like devices)
+ *	that have been removed from the system and must be freed (but must wait
+ *	until all accessors have finished).
+ *
+ *	Copyright (C) 2005 Patrick Mochel
+ *
+ *	This file is released under the GPL v2.
+ */
+
+#include <linux/klist.h>
+#include <linux/module.h>
+
+
+/**
+ *	klist_init - Initialize a klist structure. 
+ *	@k:	The klist we're initializing.
+ *	@get:	The get function for the embedding object (NULL if none)
+ *	@put:	The put function for the embedding object (NULL if none)
+ *
+ * Initialises the klist structure.  If the klist_node structures are
+ * going to be embedded in refcounted objects (necessary for safe
+ * deletion) then the get/put arguments are used to initialise
+ * functions that take and release references on the embedding
+ * objects.
+ */
+
+void klist_init(struct klist * k, void (*get)(struct klist_node *),
+		void (*put)(struct klist_node *))
+{
+	INIT_LIST_HEAD(&k->k_list);
+	spin_lock_init(&k->k_lock);
+	k->get = get;
+	k->put = put;
+}
+
+EXPORT_SYMBOL_GPL(klist_init);
+
+
+static void add_head(struct klist * k, struct klist_node * n)
+{
+	spin_lock(&k->k_lock);
+	list_add(&n->n_node, &k->k_list);
+	spin_unlock(&k->k_lock);
+}
+
+static void add_tail(struct klist * k, struct klist_node * n)
+{
+	spin_lock(&k->k_lock);
+	list_add_tail(&n->n_node, &k->k_list);
+	spin_unlock(&k->k_lock);
+}
+
+
+static void klist_node_init(struct klist * k, struct klist_node * n)
+{
+	INIT_LIST_HEAD(&n->n_node);
+	init_completion(&n->n_removed);
+	kref_init(&n->n_ref);
+	n->n_klist = k;
+	if (k->get)
+		k->get(n);
+}
+
+
+/**
+ *	klist_add_head - Initialize a klist_node and add it to front.
+ *	@n:	node we're adding.
+ *	@k:	klist it's going on.
+ */
+
+void klist_add_head(struct klist_node * n, struct klist * k)
+{
+	klist_node_init(k, n);
+	add_head(k, n);
+}
+
+EXPORT_SYMBOL_GPL(klist_add_head);
+
+
+/**
+ *	klist_add_tail - Initialize a klist_node and add it to back.
+ *	@n:	node we're adding.
+ *	@k:	klist it's going on.
+ */
+
+void klist_add_tail(struct klist_node * n, struct klist * k)
+{
+	klist_node_init(k, n);
+	add_tail(k, n);
+}
+
+EXPORT_SYMBOL_GPL(klist_add_tail);
+
+
+static void klist_release(struct kref * kref)
+{
+	struct klist_node * n = container_of(kref, struct klist_node, n_ref);
+
+	list_del(&n->n_node);
+	complete(&n->n_removed);
+	n->n_klist = NULL;
+}
+
+static int klist_dec_and_del(struct klist_node * n)
+{
+	return kref_put_new(&n->n_ref, klist_release);
+}
+
+
+/**
+ *	klist_del - Decrement the reference count of node and try to remove.
+ *	@n:	node we're deleting.
+ */
+
+void klist_del(struct klist_node * n)
+{
+	struct klist * k = n->n_klist;
+	void (*put)(struct klist_node *) = k->put;
+
+	spin_lock(&k->k_lock);
+	if (!klist_dec_and_del(n))
+		put = NULL;
+	spin_unlock(&k->k_lock);
+	if (put)
+		put(n);
+}
+
+EXPORT_SYMBOL_GPL(klist_del);
+
+
+/**
+ *	klist_remove - Decrement the refcount of node and wait for it to go away.
+ *	@n:	node we're removing.
+ */
+
+void klist_remove(struct klist_node * n)
+{
+	klist_del(n);
+	wait_for_completion(&n->n_removed);
+}
+
+EXPORT_SYMBOL_GPL(klist_remove);
+
+
+/**
+ *	klist_node_attached - Say whether a node is bound to a list or not.
+ *	@n:	Node that we're testing.
+ */
+
+int klist_node_attached(struct klist_node * n)
+{
+	return (n->n_klist != NULL);
+}
+
+EXPORT_SYMBOL_GPL(klist_node_attached);
+
+
+/**
+ *	klist_iter_init_node - Initialize a klist_iter structure.
+ *	@k:	klist we're iterating.
+ *	@i:	klist_iter we're filling.
+ *	@n:	node to start with.
+ *
+ *	Similar to klist_iter_init(), but starts the action off with @n, 
+ *	instead of with the list head.
+ */
+
+void klist_iter_init_node(struct klist * k, struct klist_iter * i, struct klist_node * n)
+{
+	i->i_klist = k;
+	i->i_head = &k->k_list;
+	i->i_cur = n;
+	if (n)
+		kref_get(&n->n_ref);
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_init_node);
+
+
+/**
+ *	klist_iter_init - Iniitalize a klist_iter structure.
+ *	@k:	klist we're iterating.
+ *	@i:	klist_iter structure we're filling.
+ *
+ *	Similar to klist_iter_init_node(), but start with the list head.
+ */
+
+void klist_iter_init(struct klist * k, struct klist_iter * i)
+{
+	klist_iter_init_node(k, i, NULL);
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_init);
+
+
+/**
+ *	klist_iter_exit - Finish a list iteration.
+ *	@i:	Iterator structure.
+ *
+ *	Must be called when done iterating over list, as it decrements the 
+ *	refcount of the current node. Necessary in case iteration exited before
+ *	the end of the list was reached, and always good form.
+ */
+
+void klist_iter_exit(struct klist_iter * i)
+{
+	if (i->i_cur) {
+		klist_del(i->i_cur);
+		i->i_cur = NULL;
+	}
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_exit);
+
+
+static struct klist_node * to_klist_node(struct list_head * n)
+{
+	return container_of(n, struct klist_node, n_node);
+}
+
+
+/**
+ *	klist_next - Ante up next node in list.
+ *	@i:	Iterator structure.
+ *
+ *	First grab list lock. Decrement the reference count of the previous
+ *	node, if there was one. Grab the next node, increment its reference 
+ *	count, drop the lock, and return that next node.
+ */
+
+struct klist_node * klist_next(struct klist_iter * i)
+{
+	struct list_head * next;
+	struct klist_node * lnode = i->i_cur;
+	struct klist_node * knode = NULL;
+	void (*put)(struct klist_node *) = i->i_klist->put;
+
+	spin_lock(&i->i_klist->k_lock);
+	if (lnode) {
+		next = lnode->n_node.next;
+		if (!klist_dec_and_del(lnode))
+			put = NULL;
+	} else
+		next = i->i_head->next;
+
+	if (next != i->i_head) {
+		knode = to_klist_node(next);
+		kref_get(&knode->n_ref);
+	}
+	i->i_cur = knode;
+	spin_unlock(&i->i_klist->k_lock);
+	if (put && lnode)
+		put(lnode);
+	return knode;
+}
+
+EXPORT_SYMBOL_GPL(klist_next);
+
+
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/kref_new.c b/kernel_addons/backport/2.6.9_U4/include/src/kref_new.c
new file mode 100644
index 0000000..d45bb3f
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/kref_new.c
@@ -0,0 +1,29 @@
+#include <linux/kref.h>
+#include <linux/module.h>
+
+/**
+ * kref_put - decrement refcount for object.
+ * @kref: object.
+ * @release: pointer to the function that will clean up the object when the
+ *           last reference to the object is released.
+ *           This pointer is required, and it is not acceptable to pass kfree
+ *           in as this function.
+ *
+ * Decrement the refcount, and if 0, call release().
+ * Return 1 if the object was removed, otherwise return 0.  Beware, if this
+ * function returns 0, you still can not count on the kref from remaining in
+ * memory.  Only use the return value if you want to see if the kref is now
+ * gone, not present.
+ */
+int kref_put_new(struct kref *kref, void (*release)(struct kref *kref))
+{
+        WARN_ON(release == NULL);
+        WARN_ON(release == (void (*)(struct kref *))kfree);
+
+        if (atomic_dec_and_test(&kref->refcount)) {
+                release(kref);
+                return 1;
+        }
+        return 0;
+}
+EXPORT_SYMBOL(kref_put_new);
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/scsi.c b/kernel_addons/backport/2.6.9_U4/include/src/scsi.c
new file mode 100644
index 0000000..8c833c0
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/scsi.c
@@ -0,0 +1,50 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/unistd.h>
+#include <linux/spinlock.h>
+#include <linux/kmod.h>
+#include <linux/interrupt.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/mutex.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+
+/**
+ * starget_for_each_device  -  helper to walk all devices of a target
+ * @starget:	target whose devices we want to iterate over.
+ *
+ * This traverses over each devices of @shost.  The devices have
+ * a reference that must be released by scsi_host_put when breaking
+ * out of the loop.
+ */
+void starget_for_each_device(struct scsi_target *starget, void * data,
+		     void (*fn)(struct scsi_device *, void *))
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct scsi_device *sdev;
+
+	printk("%s: entry\n", __FUNCTION__);
+	shost_for_each_device(sdev, shost) {
+		if ((sdev->channel == starget->channel) &&
+		    (sdev->id == starget->id))
+			fn(sdev, data);
+	}
+	printk("%s: exit\n", __FUNCTION__);
+}
+EXPORT_SYMBOL(starget_for_each_device);
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/scsi_lib.c b/kernel_addons/backport/2.6.9_U4/include/src/scsi_lib.c
new file mode 100644
index 0000000..f53f824
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/scsi_lib.c
@@ -0,0 +1,166 @@
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <linux/completion.h>
+#include <linux/kernel.h>
+#include <linux/mempool.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/hardirq.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+
+int scsi_is_target_device(const struct device *dev)
+{
+        char *str = dev->bus_id;
+
+	if (strncmp(str, "target", 6) == 0) {
+		return 1;
+	}
+
+        return 0;
+}
+
+/**
+ * scsi_internal_device_block - internal function to put a device
+ *                              temporarily into the SDEV_BLOCK state
+ * @sdev:       device to block
+ *
+ * Block request made by scsi lld's to temporarily stop all
+ * scsi commands on the specified device.  Called from interrupt
+ * or normal process context.
+ *
+ * Returns zero if successful or error if not
+ *
+ * Notes:
+ *      This routine transitions the device to the SDEV_BLOCK state
+ *      (which must be a legal transition).  When the device is in this
+ *      state, all commands are deferred until the scsi lld reenables
+ *      the device with scsi_device_unblock or device_block_tmo fires.
+ *      This routine assumes the host_lock is held on entry.
+ **/
+int
+scsi_internal_device_block(struct scsi_device *sdev)
+{
+        request_queue_t *q = sdev->request_queue;
+        unsigned long flags;
+        int err = 0;
+
+        err = scsi_device_set_state(sdev, SDEV_BLOCK);
+        if (err)
+		return err;
+                
+        /*
+         * The device has transitioned to SDEV_BLOCK.  Stop the
+         * block layer from calling the midlayer with this device's
+         * request queue.
+         */
+        spin_lock_irqsave(q->queue_lock, flags);
+        blk_stop_queue(q);
+        spin_unlock_irqrestore(q->queue_lock, flags);
+
+        return 0;
+}
+EXPORT_SYMBOL_GPL(scsi_internal_device_block);
+
+/**
+ * scsi_internal_device_unblock - resume a device after a block request
+ * @sdev:       device to resume
+ *
+ * Called by scsi lld's or the midlayer to restart the device queue
+ * for the previously suspended scsi device.  Called from interrupt or
+ * normal process context.
+ *
+ * Returns zero if successful or error if not.
+ *
+ * Notes:
+ *      This routine transitions the device to the SDEV_RUNNING state
+ *      (which must be a legal transition) allowing the midlayer to
+ *      goose the queue for this device.  This routine assumes the
+ *      host_lock is held upon entry.
+ **/
+int
+scsi_internal_device_unblock(struct scsi_device *sdev)
+{
+        request_queue_t *q = sdev->request_queue;
+        int err;
+        unsigned long flags;
+
+
+        /*
+         * Try to transition the scsi device to SDEV_RUNNING
+         * and goose the device queue if successful.
+         */
+        err = scsi_device_set_state(sdev, SDEV_RUNNING);
+        if (err)
+		return err;
+                
+        spin_lock_irqsave(q->queue_lock, flags);
+        blk_start_queue(q);
+        spin_unlock_irqrestore(q->queue_lock, flags);
+
+        return 0;
+}
+EXPORT_SYMBOL_GPL(scsi_internal_device_unblock);
+
+static void
+device_block(struct scsi_device *sdev, void *data)
+{
+        scsi_internal_device_block(sdev);
+}
+
+static int
+target_block(struct device *dev, void *data)
+{
+        if (scsi_is_target_device(dev))
+                starget_for_each_device(to_scsi_target(dev), NULL,
+                                        device_block);
+
+        return 0;
+}
+
+void
+scsi_target_block(struct device *dev)
+{
+        if (scsi_is_target_device(dev))
+                starget_for_each_device(to_scsi_target(dev), NULL,
+                                        device_block);
+        else
+                device_for_each_child(dev, NULL, target_block);
+}
+EXPORT_SYMBOL_GPL(scsi_target_block);
+
+static void
+device_unblock(struct scsi_device *sdev, void *data)
+{
+        scsi_internal_device_unblock(sdev);
+}
+
+static int
+target_unblock(struct device *dev, void *data)
+{
+        if (scsi_is_target_device(dev))
+                starget_for_each_device(to_scsi_target(dev), NULL,
+                                        device_unblock);
+        return 0;
+}
+
+void
+scsi_target_unblock(struct device *dev)
+{
+        if (scsi_is_target_device(dev))
+                starget_for_each_device(to_scsi_target(dev), NULL,
+                                        device_unblock);
+        else
+                device_for_each_child(dev, NULL, target_unblock);
+}
+EXPORT_SYMBOL_GPL(scsi_target_unblock);
+
+MODULE_LICENSE("GPL");
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/scsi_scan.c b/kernel_addons/backport/2.6.9_U4/include/src/scsi_scan.c
new file mode 100644
index 0000000..b7b7674
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/scsi_scan.c
@@ -0,0 +1,48 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/spinlock.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_devinfo.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_eh.h>
+
+/**
+ * int_to_scsilun: reverts an int into a scsi_lun
+ * @int:        integer to be reverted
+ * @scsilun:    struct scsi_lun to be set.
+ *
+ * Description:
+ *     Reverts the functionality of the scsilun_to_int, which packed
+ *     an 8-byte lun value into an int. This routine unpacks the int
+ *     back into the lun value.
+ *     Note: the scsilun_to_int() routine does not truly handle all
+ *     8bytes of the lun value. This functions restores only as much
+ *     as was set by the routine.
+ *
+ * Notes:
+ *     Given an integer : 0x0b030a04,  this function returns a
+ *     scsi_lun of : struct scsi_lun of: 0a 04 0b 03 00 00 00 00
+ *
+ **/
+void int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun)
+{
+        int i;
+
+        memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun));
+
+        for (i = 0; i < sizeof(lun); i += 2) {
+                scsilun->scsi_lun[i] = (lun >> 8) & 0xFF;
+                scsilun->scsi_lun[i+1] = lun & 0xFF;
+                lun = lun >> 16;
+        }
+}
+EXPORT_SYMBOL(int_to_scsilun);
diff --git a/kernel_addons/backport/2.6.9_U4/include/src/transport_class.c b/kernel_addons/backport/2.6.9_U4/include/src/transport_class.c
new file mode 100644
index 0000000..f25e7c6
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U4/include/src/transport_class.c
@@ -0,0 +1,280 @@
+/*
+ * transport_class.c - implementation of generic transport classes
+ *                     using attribute_containers
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ *
+ * The basic idea here is to allow any "device controller" (which
+ * would most often be a Host Bus Adapter to use the services of one
+ * or more tranport classes for performing transport specific
+ * services.  Transport specific services are things that the generic
+ * command layer doesn't want to know about (speed settings, line
+ * condidtioning, etc), but which the user might be interested in.
+ * Thus, the HBA's use the routines exported by the transport classes
+ * to perform these functions.  The transport classes export certain
+ * values to the user via sysfs using attribute containers.
+ *
+ * Note: because not every HBA will care about every transport
+ * attribute, there's a many to one relationship that goes like this:
+ *
+ * transport class<-----attribute container<----class device
+ *
+ * Usually the attribute container is per-HBA, but the design doesn't
+ * mandate that.  Although most of the services will be specific to
+ * the actual external storage connection used by the HBA, the generic
+ * transport class is framed entirely in terms of generic devices to
+ * allow it to be used by any physical HBA in the system.
+ */
+#include <linux/attribute_container.h>
+#include <linux/transport_class.h>
+
+/**
+ * transport_class_register - register an initial transport class
+ *
+ * @tclass:	a pointer to the transport class structure to be initialised
+ *
+ * The transport class contains an embedded class which is used to
+ * identify it.  The caller should initialise this structure with
+ * zeros and then generic class must have been initialised with the
+ * actual transport class unique name.  There's a macro
+ * DECLARE_TRANSPORT_CLASS() to do this (declared classes still must
+ * be registered).
+ *
+ * Returns 0 on success or error on failure.
+ */
+int transport_class_register(struct transport_class *tclass)
+{
+	return class_register(&tclass->class);
+}
+EXPORT_SYMBOL_GPL(transport_class_register);
+
+/**
+ * transport_class_unregister - unregister a previously registered class
+ *
+ * @tclass: The transport class to unregister
+ *
+ * Must be called prior to deallocating the memory for the transport
+ * class.
+ */
+void transport_class_unregister(struct transport_class *tclass)
+{
+	class_unregister(&tclass->class);
+}
+EXPORT_SYMBOL_GPL(transport_class_unregister);
+
+static int anon_transport_dummy_function(struct transport_container *tc,
+					 struct device *dev,
+					 struct class_device *cdev)
+{
+	/* do nothing */
+	return 0;
+}
+
+/**
+ * anon_transport_class_register - register an anonymous class
+ *
+ * @atc: The anon transport class to register
+ *
+ * The anonymous transport class contains both a transport class and a
+ * container.  The idea of an anonymous class is that it never
+ * actually has any device attributes associated with it (and thus
+ * saves on container storage).  So it can only be used for triggering
+ * events.  Use prezero and then use DECLARE_ANON_TRANSPORT_CLASS() to
+ * initialise the anon transport class storage.
+ */
+int anon_transport_class_register(struct anon_transport_class *atc)
+{
+	int error;
+	atc->container.class = &atc->tclass.class;
+	attribute_container_set_no_classdevs(&atc->container);
+	error = attribute_container_register(&atc->container);
+	if (error)
+		return error;
+	atc->tclass.setup = anon_transport_dummy_function;
+	atc->tclass.remove = anon_transport_dummy_function;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(anon_transport_class_register);
+
+/**
+ * anon_transport_class_unregister - unregister an anon class
+ *
+ * @atc: Pointer to the anon transport class to unregister
+ *
+ * Must be called prior to deallocating the memory for the anon
+ * transport class.
+ */
+void anon_transport_class_unregister(struct anon_transport_class *atc)
+{
+	attribute_container_unregister(&atc->container);
+}
+EXPORT_SYMBOL_GPL(anon_transport_class_unregister);
+
+static int transport_setup_classdev(struct attribute_container *cont,
+				    struct device *dev,
+				    struct class_device *classdev)
+{
+	struct transport_class *tclass = class_to_transport_class(cont->class);
+	struct transport_container *tcont = attribute_container_to_transport_container(cont);
+
+	if (tclass->setup)
+		tclass->setup(tcont, dev, classdev);
+
+	return 0;
+}
+
+/**
+ * transport_setup_device - declare a new dev for transport class association
+ *			    but don't make it visible yet.
+ *
+ * @dev: the generic device representing the entity being added
+ *
+ * Usually, dev represents some component in the HBA system (either
+ * the HBA itself or a device remote across the HBA bus).  This
+ * routine is simply a trigger point to see if any set of transport
+ * classes wishes to associate with the added device.  This allocates
+ * storage for the class device and initialises it, but does not yet
+ * add it to the system or add attributes to it (you do this with
+ * transport_add_device).  If you have no need for a separate setup
+ * and add operations, use transport_register_device (see
+ * transport_class.h).
+ */
+
+void transport_setup_device(struct device *dev)
+{
+	attribute_container_add_device(dev, transport_setup_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_setup_device);
+
+static int transport_add_class_device(struct attribute_container *cont,
+				      struct device *dev,
+				      struct class_device *classdev)
+{
+	int error = attribute_container_add_class_device(classdev);
+	struct transport_container *tcont = 
+		attribute_container_to_transport_container(cont);
+
+	if (!error && tcont->statistics)
+		error = sysfs_create_group(&classdev->kobj, tcont->statistics);
+
+	return error;
+}
+
+
+/**
+ * transport_add_device - declare a new dev for transport class association
+ *
+ * @dev: the generic device representing the entity being added
+ *
+ * Usually, dev represents some component in the HBA system (either
+ * the HBA itself or a device remote across the HBA bus).  This
+ * routine is simply a trigger point used to add the device to the
+ * system and register attributes for it.
+ */
+
+void transport_add_device(struct device *dev)
+{
+	attribute_container_device_trigger(dev, transport_add_class_device);
+}
+EXPORT_SYMBOL_GPL(transport_add_device);
+
+static int transport_configure(struct attribute_container *cont,
+			       struct device *dev,
+			       struct class_device *cdev)
+{
+	struct transport_class *tclass = class_to_transport_class(cont->class);
+	struct transport_container *tcont = attribute_container_to_transport_container(cont);
+
+	if (tclass->configure)
+		tclass->configure(tcont, dev, cdev);
+
+	return 0;
+}
+
+/**
+ * transport_configure_device - configure an already set up device
+ *
+ * @dev: generic device representing device to be configured
+ *
+ * The idea of configure is simply to provide a point within the setup
+ * process to allow the transport class to extract information from a
+ * device after it has been setup.  This is used in SCSI because we
+ * have to have a setup device to begin using the HBA, but after we
+ * send the initial inquiry, we use configure to extract the device
+ * parameters.  The device need not have been added to be configured.
+ */
+void transport_configure_device(struct device *dev)
+{
+	attribute_container_device_trigger(dev, transport_configure);
+}
+EXPORT_SYMBOL_GPL(transport_configure_device);
+
+static int transport_remove_classdev(struct attribute_container *cont,
+				     struct device *dev,
+				     struct class_device *classdev)
+{
+	struct transport_container *tcont = 
+		attribute_container_to_transport_container(cont);
+	struct transport_class *tclass = class_to_transport_class(cont->class);
+
+	if (tclass->remove)
+		tclass->remove(tcont, dev, classdev);
+
+	if (tclass->remove != anon_transport_dummy_function) {
+		if (tcont->statistics)
+			sysfs_remove_group(&classdev->kobj, tcont->statistics);
+		attribute_container_class_device_del(classdev);
+	}
+
+	return 0;
+}
+
+
+/**
+ * transport_remove_device - remove the visibility of a device
+ *
+ * @dev: generic device to remove
+ *
+ * This call removes the visibility of the device (to the user from
+ * sysfs), but does not destroy it.  To eliminate a device entirely
+ * you must also call transport_destroy_device.  If you don't need to
+ * do remove and destroy as separate operations, use
+ * transport_unregister_device() (see transport_class.h) which will
+ * perform both calls for you.
+ */
+void transport_remove_device(struct device *dev)
+{
+	attribute_container_device_trigger(dev, transport_remove_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_remove_device);
+
+static void transport_destroy_classdev(struct attribute_container *cont,
+				      struct device *dev,
+				      struct class_device *classdev)
+{
+	struct transport_class *tclass = class_to_transport_class(cont->class);
+
+	if (tclass->remove != anon_transport_dummy_function)
+		class_device_put(classdev);
+}
+
+
+/**
+ * transport_destroy_device - destroy a removed device
+ *
+ * @dev: device to eliminate from the transport class.
+ *
+ * This call triggers the elimination of storage associated with the
+ * transport classdev.  Note: all it really does is relinquish a
+ * reference to the classdev.  The memory will not be freed until the
+ * last reference goes to zero.  Note also that the classdev retains a
+ * reference count on dev, so dev too will remain for as long as the
+ * transport class device remains around.
+ */
+void transport_destroy_device(struct device *dev)
+{
+	attribute_container_remove_device(dev, transport_destroy_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_destroy_device);
diff --git a/kernel_addons/backport/2.6.9_U5/include/linux/attribute_container.h b/kernel_addons/backport/2.6.9_U5/include/linux/attribute_container.h
new file mode 100644
index 0000000..93bfb0b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/linux/attribute_container.h
@@ -0,0 +1,71 @@
+/*
+ * class_container.h - a generic container for all classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ */
+
+#ifndef _ATTRIBUTE_CONTAINER_H_
+#define _ATTRIBUTE_CONTAINER_H_
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/klist.h>
+#include <linux/spinlock.h>
+
+struct attribute_container {
+	struct list_head	node;
+	struct klist		containers;
+	struct class		*class;
+	struct class_device_attribute **attrs;
+	int (*match)(struct attribute_container *, struct device *);
+#define	ATTRIBUTE_CONTAINER_NO_CLASSDEVS	0x01
+	unsigned long		flags;
+};
+
+static inline int
+attribute_container_no_classdevs(struct attribute_container *atc)
+{
+	return atc->flags & ATTRIBUTE_CONTAINER_NO_CLASSDEVS;
+}
+
+static inline void
+attribute_container_set_no_classdevs(struct attribute_container *atc)
+{
+	atc->flags |= ATTRIBUTE_CONTAINER_NO_CLASSDEVS;
+}
+
+int attribute_container_register(struct attribute_container *cont);
+int attribute_container_unregister(struct attribute_container *cont);
+void attribute_container_create_device(struct device *dev,
+				       int (*fn)(struct attribute_container *,
+						 struct device *,
+						 struct class_device *));
+void attribute_container_add_device(struct device *dev,
+				    int (*fn)(struct attribute_container *,
+					      struct device *,
+					      struct class_device *));
+void attribute_container_remove_device(struct device *dev,
+				       void (*fn)(struct attribute_container *,
+						  struct device *,
+						  struct class_device *));
+void attribute_container_device_trigger(struct device *dev, 
+					int (*fn)(struct attribute_container *,
+						  struct device *,
+						  struct class_device *));
+void attribute_container_trigger(struct device *dev, 
+				 int (*fn)(struct attribute_container *,
+					   struct device *));
+int attribute_container_add_attrs(struct class_device *classdev);
+int attribute_container_add_class_device(struct class_device *classdev);
+int attribute_container_add_class_device_adapter(struct attribute_container *cont,
+						 struct device *dev,
+						 struct class_device *classdev);
+void attribute_container_remove_attrs(struct class_device *classdev);
+void attribute_container_class_device_del(struct class_device *classdev);
+struct attribute_container *attribute_container_classdev_to_container(struct class_device *);
+struct class_device *attribute_container_find_class_device(struct attribute_container *, struct device *);
+struct class_device_attribute **attribute_container_classdev_to_attrs(const struct class_device *classdev);
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U5/include/linux/crypto.h b/kernel_addons/backport/2.6.9_U5/include/linux/crypto.h
new file mode 100644
index 0000000..aecccde
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/linux/crypto.h
@@ -0,0 +1,11 @@
+#ifndef LINUX_CRYPTO_BACKPORT_H
+#define LINUX_CRYPTO_BACKPORT_H
+
+#include_next <linux/crypto.h>
+
+#define crypto_hash_init(desc) crypto_digest_init(*desc)
+#define crypto_hash_digest(desc, sg, nbytes, out) crypto_digest_digest(*desc, sg, 1, out)
+#define crypto_hash_update(desc, sg, nbytes) crypto_digest_update(*desc, sg, 1)
+#define crypto_hash_final(desc, out) crypto_digest_final(*desc, out)
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U5/include/linux/kernel.h b/kernel_addons/backport/2.6.9_U5/include/linux/kernel.h
index a37dcd5..02a5907 100644
--- a/kernel_addons/backport/2.6.9_U5/include/linux/kernel.h
+++ b/kernel_addons/backport/2.6.9_U5/include/linux/kernel.h
@@ -4,4 +4,7 @@ #define BACKPORT_KERNEL_H_2_6_19
 #include_next <linux/kernel.h>
 #include <linux/log2.h>
 
+#define NIP6_FMT "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+#define NIPQUAD_FMT "%u.%u.%u.%u"
+
 #endif
diff --git a/kernel_addons/backport/2.6.9_U5/include/linux/kfifo.h b/kernel_addons/backport/2.6.9_U5/include/linux/kfifo.h
index 48eccd8..2b94461 100644
--- a/kernel_addons/backport/2.6.9_U5/include/linux/kfifo.h
+++ b/kernel_addons/backport/2.6.9_U5/include/linux/kfifo.h
@@ -25,6 +25,7 @@ #ifdef __KERNEL__
 
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
+#include <linux/gfp.h>
 
 struct kfifo {
 	unsigned char *buffer;	/* the buffer holding the data */
diff --git a/kernel_addons/backport/2.6.9_U5/include/linux/klist.h b/kernel_addons/backport/2.6.9_U5/include/linux/klist.h
new file mode 100644
index 0000000..7407125
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/linux/klist.h
@@ -0,0 +1,61 @@
+/*
+ *	klist.h - Some generic list helpers, extending struct list_head a bit.
+ *
+ *	Implementations are found in lib/klist.c
+ *
+ *
+ *	Copyright (C) 2005 Patrick Mochel
+ *
+ *	This file is rleased under the GPL v2.
+ */
+
+#ifndef _LINUX_KLIST_H
+#define _LINUX_KLIST_H
+
+#include <linux/spinlock.h>
+#include <linux/completion.h>
+#include <linux/kref.h>
+#include <linux/list.h>
+
+struct klist_node;
+struct klist {
+	spinlock_t		k_lock;
+	struct list_head	k_list;
+	void			(*get)(struct klist_node *);
+	void			(*put)(struct klist_node *);
+};
+
+
+extern void klist_init(struct klist * k, void (*get)(struct klist_node *),
+		       void (*put)(struct klist_node *));
+
+struct klist_node {
+	struct klist		* n_klist;
+	struct list_head	n_node;
+	struct kref		n_ref;
+	struct completion	n_removed;
+};
+
+extern void klist_add_tail(struct klist_node * n, struct klist * k);
+extern void klist_add_head(struct klist_node * n, struct klist * k);
+
+extern void klist_del(struct klist_node * n);
+extern void klist_remove(struct klist_node * n);
+
+extern int klist_node_attached(struct klist_node * n);
+
+
+struct klist_iter {
+	struct klist		* i_klist;
+	struct list_head	* i_head;
+	struct klist_node	* i_cur;
+};
+
+
+extern void klist_iter_init(struct klist * k, struct klist_iter * i);
+extern void klist_iter_init_node(struct klist * k, struct klist_iter * i, 
+				 struct klist_node * n);
+extern void klist_iter_exit(struct klist_iter * i);
+extern struct klist_node * klist_next(struct klist_iter * i);
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U5/include/linux/memory.h b/kernel_addons/backport/2.6.9_U5/include/linux/memory.h
new file mode 100644
index 0000000..654ef55
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/linux/memory.h
@@ -0,0 +1,89 @@
+/*
+ * include/linux/memory.h - generic memory definition
+ *
+ * This is mainly for topological representation. We define the
+ * basic "struct memory_block" here, which can be embedded in per-arch
+ * definitions or NUMA information.
+ *
+ * Basic handling of the devices is done in drivers/base/memory.c
+ * and system devices are handled in drivers/base/sys.c.
+ *
+ * Memory block are exported via sysfs in the class/memory/devices/
+ * directory.
+ *
+ */
+#ifndef _LINUX_MEMORY_H_
+#define _LINUX_MEMORY_H_
+
+#include <linux/sysdev.h>
+#include <linux/node.h>
+#include <linux/compiler.h>
+
+#include <asm/semaphore.h>
+
+struct memory_block {
+	unsigned long phys_index;
+	unsigned long state;
+	/*
+	 * This serializes all state change requests.  It isn't
+	 * held during creation because the control files are
+	 * created long after the critical areas during
+	 * initialization.
+	 */
+	struct semaphore state_sem;
+	int phys_device;		/* to which fru does this belong? */
+	void *hw;			/* optional pointer to fw/hw data */
+	int (*phys_callback)(struct memory_block *);
+	struct sys_device sysdev;
+};
+
+/* These states are exposed to userspace as text strings in sysfs */
+#define	MEM_ONLINE		(1<<0) /* exposed to userspace */
+#define	MEM_GOING_OFFLINE	(1<<1) /* exposed to userspace */
+#define	MEM_OFFLINE		(1<<2) /* exposed to userspace */
+
+/*
+ * All of these states are currently kernel-internal for notifying
+ * kernel components and architectures.
+ *
+ * For MEM_MAPPING_INVALID, all notifier chains with priority >0
+ * are called before pfn_to_page() becomes invalid.  The priority=0
+ * entry is reserved for the function that actually makes
+ * pfn_to_page() stop working.  Any notifiers that want to be called
+ * after that should have priority <0.
+ */
+#define	MEM_MAPPING_INVALID	(1<<3)
+
+struct notifier_block;
+struct mem_section;
+
+#ifndef CONFIG_MEMORY_HOTPLUG_SPARSE
+static inline int memory_dev_init(void)
+{
+	return 0;
+}
+static inline int register_memory_notifier(struct notifier_block *nb)
+{
+	return 0;
+}
+static inline void unregister_memory_notifier(struct notifier_block *nb)
+{
+}
+#else
+extern int register_new_memory(struct mem_section *);
+extern int unregister_memory_section(struct mem_section *);
+extern int memory_dev_init(void);
+extern int remove_memory_block(unsigned long, struct mem_section *, int);
+
+#define CONFIG_MEM_BLOCK_SIZE	(PAGES_PER_SECTION<<PAGE_SHIFT)
+
+
+#endif /* CONFIG_MEMORY_HOTPLUG_SPARSE */
+
+#define hotplug_memory_notifier(fn, pri) {			\
+	static struct notifier_block fn##_mem_nb =		\
+		{ .notifier_call = fn, .priority = pri };	\
+	register_memory_notifier(&fn##_mem_nb);			\
+}
+
+#endif /* _LINUX_MEMORY_H_ */
diff --git a/kernel_addons/backport/2.6.9_U5/include/linux/netlink.h b/kernel_addons/backport/2.6.9_U5/include/linux/netlink.h
new file mode 100644
index 0000000..6d69105
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/linux/netlink.h
@@ -0,0 +1,14 @@
+#ifndef BACKPORT_LINUX_NETLINK_H
+#define BACKPORT_LINUX_NETLINK_H
+
+#include_next <linux/netlink.h>
+
+#define __nlmsg_put(skb, daemon_pid, seq, type, len, flags) \
+       __nlmsg_put(skb, daemon_pid, 0, 0, len)
+
+#define netlink_kernel_create(uint, groups, input, mod) \
+       netlink_kernel_create(uint, input)
+
+#define NETLINK_ISCSI           8
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U5/include/linux/transport_class.h b/kernel_addons/backport/2.6.9_U5/include/linux/transport_class.h
new file mode 100644
index 0000000..1d6cc22
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/linux/transport_class.h
@@ -0,0 +1,100 @@
+/*
+ * transport_class.h - a generic container for all transport classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ */
+
+#ifndef _TRANSPORT_CLASS_H_
+#define _TRANSPORT_CLASS_H_
+
+#include <linux/device.h>
+#include <linux/attribute_container.h>
+
+struct transport_container;
+
+struct transport_class {
+	struct class class;
+	int (*setup)(struct transport_container *, struct device *,
+		     struct class_device *);
+	int (*configure)(struct transport_container *, struct device *,
+			 struct class_device *);
+	int (*remove)(struct transport_container *, struct device *,
+		      struct class_device *);
+};
+
+#define DECLARE_TRANSPORT_CLASS(cls, nm, su, rm, cfg)			\
+struct transport_class cls = {						\
+	.class = {							\
+		.name = nm,						\
+	},								\
+	.setup = su,							\
+	.remove = rm,							\
+	.configure = cfg,						\
+}
+
+
+struct anon_transport_class {
+	struct transport_class tclass;
+	struct attribute_container container;
+};
+
+#define DECLARE_ANON_TRANSPORT_CLASS(cls, mtch, cfg)		\
+struct anon_transport_class cls = {				\
+	.tclass = {						\
+		.configure = cfg,				\
+	},							\
+	. container = {						\
+		.match = mtch,					\
+	},							\
+}
+
+#define class_to_transport_class(x) \
+	container_of(x, struct transport_class, class)
+
+struct transport_container {
+	struct attribute_container ac;
+	struct attribute_group *statistics;
+};
+
+#define attribute_container_to_transport_container(x) \
+	container_of(x, struct transport_container, ac)
+
+void transport_remove_device(struct device *);
+void transport_add_device(struct device *);
+void transport_setup_device(struct device *);
+void transport_configure_device(struct device *);
+void transport_destroy_device(struct device *);
+
+static inline void
+transport_register_device(struct device *dev)
+{
+	transport_setup_device(dev);
+	transport_add_device(dev);
+}
+
+static inline void
+transport_unregister_device(struct device *dev)
+{
+	transport_remove_device(dev);
+	transport_destroy_device(dev);
+}
+
+static inline int transport_container_register(struct transport_container *tc)
+{
+	return attribute_container_register(&tc->ac);
+}
+
+static inline int transport_container_unregister(struct transport_container *tc)
+{
+	return attribute_container_unregister(&tc->ac);
+}
+
+int transport_class_register(struct transport_class *);
+int anon_transport_class_register(struct anon_transport_class *);
+void transport_class_unregister(struct transport_class *);
+void anon_transport_class_unregister(struct anon_transport_class *);
+
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U5/include/scsi/iscsi_proto.h b/kernel_addons/backport/2.6.9_U5/include/scsi/iscsi_proto.h
new file mode 100644
index 0000000..02f6e4b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/scsi/iscsi_proto.h
@@ -0,0 +1,587 @@
+/*
+ * RFC 3720 (iSCSI) protocol data types
+ *
+ * Copyright (C) 2005 Dmitry Yusupov
+ * Copyright (C) 2005 Alex Aizman
+ * maintained by open-iscsi at googlegroups.com
+ *
+ * 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.
+ *
+ * See the file COPYING included with this distribution for more details.
+ */
+
+#ifndef ISCSI_PROTO_H
+#define ISCSI_PROTO_H
+
+#define ISCSI_DRAFT20_VERSION	0x00
+
+/* default iSCSI listen port for incoming connections */
+#define ISCSI_LISTEN_PORT	3260
+
+/* Padding word length */
+#define PAD_WORD_LEN		4
+
+/*
+ * useful common(control and data pathes) macro
+ */
+#define ntoh24(p) (((p)[0] << 16) | ((p)[1] << 8) | ((p)[2]))
+#define hton24(p, v) { \
+        p[0] = (((v) >> 16) & 0xFF); \
+        p[1] = (((v) >> 8) & 0xFF); \
+        p[2] = ((v) & 0xFF); \
+}
+#define zero_data(p) {p[0]=0;p[1]=0;p[2]=0;}
+
+/*
+ * iSCSI Template Message Header
+ */
+struct iscsi_hdr {
+	uint8_t		opcode;
+	uint8_t		flags;		/* Final bit */
+	uint8_t		rsvd2[2];
+	uint8_t		hlength;	/* AHSs total length */
+	uint8_t		dlength[3];	/* Data length */
+	uint8_t		lun[8];
+	__be32		itt;		/* Initiator Task Tag */
+	__be32		ttt;		/* Target Task Tag */
+	__be32		statsn;
+	__be32		exp_statsn;
+	__be32		max_statsn;
+	uint8_t		other[12];
+};
+
+/************************* RFC 3720 Begin *****************************/
+
+#define ISCSI_RESERVED_TAG		0xffffffff
+
+/* Opcode encoding bits */
+#define ISCSI_OP_RETRY			0x80
+#define ISCSI_OP_IMMEDIATE		0x40
+#define ISCSI_OPCODE_MASK		0x3F
+
+/* Initiator Opcode values */
+#define ISCSI_OP_NOOP_OUT		0x00
+#define ISCSI_OP_SCSI_CMD		0x01
+#define ISCSI_OP_SCSI_TMFUNC		0x02
+#define ISCSI_OP_LOGIN			0x03
+#define ISCSI_OP_TEXT			0x04
+#define ISCSI_OP_SCSI_DATA_OUT		0x05
+#define ISCSI_OP_LOGOUT			0x06
+#define ISCSI_OP_SNACK			0x10
+
+#define ISCSI_OP_VENDOR1_CMD		0x1c
+#define ISCSI_OP_VENDOR2_CMD		0x1d
+#define ISCSI_OP_VENDOR3_CMD		0x1e
+#define ISCSI_OP_VENDOR4_CMD		0x1f
+
+/* Target Opcode values */
+#define ISCSI_OP_NOOP_IN		0x20
+#define ISCSI_OP_SCSI_CMD_RSP		0x21
+#define ISCSI_OP_SCSI_TMFUNC_RSP	0x22
+#define ISCSI_OP_LOGIN_RSP		0x23
+#define ISCSI_OP_TEXT_RSP		0x24
+#define ISCSI_OP_SCSI_DATA_IN		0x25
+#define ISCSI_OP_LOGOUT_RSP		0x26
+#define ISCSI_OP_R2T			0x31
+#define ISCSI_OP_ASYNC_EVENT		0x32
+#define ISCSI_OP_REJECT			0x3f
+
+struct iscsi_ahs_hdr {
+	__be16 ahslength;
+	uint8_t ahstype;
+	uint8_t ahspec[5];
+};
+
+#define ISCSI_AHSTYPE_CDB		1
+#define ISCSI_AHSTYPE_RLENGTH		2
+
+/* iSCSI PDU Header */
+struct iscsi_cmd {
+	uint8_t opcode;
+	uint8_t flags;
+	__be16 rsvd2;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32 itt;	/* Initiator Task Tag */
+	__be32 data_length;
+	__be32 cmdsn;
+	__be32 exp_statsn;
+	uint8_t cdb[16];	/* SCSI Command Block */
+	/* Additional Data (Command Dependent) */
+};
+
+/* Command PDU flags */
+#define ISCSI_FLAG_CMD_FINAL		0x80
+#define ISCSI_FLAG_CMD_READ		0x40
+#define ISCSI_FLAG_CMD_WRITE		0x20
+#define ISCSI_FLAG_CMD_ATTR_MASK	0x07	/* 3 bits */
+
+/* SCSI Command Attribute values */
+#define ISCSI_ATTR_UNTAGGED		0
+#define ISCSI_ATTR_SIMPLE		1
+#define ISCSI_ATTR_ORDERED		2
+#define ISCSI_ATTR_HEAD_OF_QUEUE	3
+#define ISCSI_ATTR_ACA			4
+
+struct iscsi_rlength_ahdr {
+	__be16 ahslength;
+	uint8_t ahstype;
+	uint8_t reserved;
+	__be32 read_length;
+};
+
+/* SCSI Response Header */
+struct iscsi_cmd_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t response;
+	uint8_t cmd_status;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	rsvd1;
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	__be32	exp_datasn;
+	__be32	bi_residual_count;
+	__be32	residual_count;
+	/* Response or Sense Data (optional) */
+};
+
+/* Command Response PDU flags */
+#define ISCSI_FLAG_CMD_BIDI_OVERFLOW	0x10
+#define ISCSI_FLAG_CMD_BIDI_UNDERFLOW	0x08
+#define ISCSI_FLAG_CMD_OVERFLOW		0x04
+#define ISCSI_FLAG_CMD_UNDERFLOW	0x02
+
+/* iSCSI Status values. Valid if Rsp Selector bit is not set */
+#define ISCSI_STATUS_CMD_COMPLETED	0
+#define ISCSI_STATUS_TARGET_FAILURE	1
+#define ISCSI_STATUS_SUBSYS_FAILURE	2
+
+/* Asynchronous Event Header */
+struct iscsi_async {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[2];
+	uint8_t rsvd3;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	uint8_t rsvd4[8];
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	uint8_t async_event;
+	uint8_t async_vcode;
+	__be16	param1;
+	__be16	param2;
+	__be16	param3;
+	uint8_t rsvd5[4];
+};
+
+/* iSCSI Event Codes */
+#define ISCSI_ASYNC_MSG_SCSI_EVENT			0
+#define ISCSI_ASYNC_MSG_REQUEST_LOGOUT			1
+#define ISCSI_ASYNC_MSG_DROPPING_CONNECTION		2
+#define ISCSI_ASYNC_MSG_DROPPING_ALL_CONNECTIONS	3
+#define ISCSI_ASYNC_MSG_PARAM_NEGOTIATION		4
+#define ISCSI_ASYNC_MSG_VENDOR_SPECIFIC			255
+
+/* NOP-Out Message */
+struct iscsi_nopout {
+	uint8_t opcode;
+	uint8_t flags;
+	__be16	rsvd2;
+	uint8_t rsvd3;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	ttt;	/* Target Transfer Tag */
+	__be32	cmdsn;
+	__be32	exp_statsn;
+	uint8_t rsvd4[16];
+};
+
+/* NOP-In Message */
+struct iscsi_nopin {
+	uint8_t opcode;
+	uint8_t flags;
+	__be16	rsvd2;
+	uint8_t rsvd3;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	ttt;	/* Target Transfer Tag */
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	uint8_t rsvd4[12];
+};
+
+/* SCSI Task Management Message Header */
+struct iscsi_tm {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd1[2];
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	rtt;	/* Reference Task Tag */
+	__be32	cmdsn;
+	__be32	exp_statsn;
+	__be32	refcmdsn;
+	__be32	exp_datasn;
+	uint8_t rsvd2[8];
+};
+
+#define ISCSI_FLAG_TM_FUNC_MASK			0x7F
+
+/* Function values */
+#define ISCSI_TM_FUNC_ABORT_TASK		1
+#define ISCSI_TM_FUNC_ABORT_TASK_SET		2
+#define ISCSI_TM_FUNC_CLEAR_ACA			3
+#define ISCSI_TM_FUNC_CLEAR_TASK_SET		4
+#define ISCSI_TM_FUNC_LOGICAL_UNIT_RESET	5
+#define ISCSI_TM_FUNC_TARGET_WARM_RESET		6
+#define ISCSI_TM_FUNC_TARGET_COLD_RESET		7
+#define ISCSI_TM_FUNC_TASK_REASSIGN		8
+
+/* SCSI Task Management Response Header */
+struct iscsi_tm_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t response;	/* see Response values below */
+	uint8_t qualifier;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd2[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	rtt;	/* Reference Task Tag */
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	uint8_t rsvd3[12];
+};
+
+/* Response values */
+#define ISCSI_TMF_RSP_COMPLETE		0x00
+#define ISCSI_TMF_RSP_NO_TASK		0x01
+#define ISCSI_TMF_RSP_NO_LUN		0x02
+#define ISCSI_TMF_RSP_TASK_ALLEGIANT	0x03
+#define ISCSI_TMF_RSP_NO_FAILOVER	0x04
+#define ISCSI_TMF_RSP_NOT_SUPPORTED	0x05
+#define ISCSI_TMF_RSP_AUTH_FAILED	0x06
+#define ISCSI_TMF_RSP_REJECTED		0xff
+
+/* Ready To Transfer Header */
+struct iscsi_r2t_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[2];
+	uint8_t	hlength;
+	uint8_t	dlength[3];
+	uint8_t lun[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	ttt;	/* Target Transfer Tag */
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	__be32	r2tsn;
+	__be32	data_offset;
+	__be32	data_length;
+};
+
+/* SCSI Data Hdr */
+struct iscsi_data {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[2];
+	uint8_t rsvd3;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32	itt;
+	__be32	ttt;
+	__be32	rsvd4;
+	__be32	exp_statsn;
+	__be32	rsvd5;
+	__be32	datasn;
+	__be32	offset;
+	__be32	rsvd6;
+	/* Payload */
+};
+
+/* SCSI Data Response Hdr */
+struct iscsi_data_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2;
+	uint8_t cmd_status;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t lun[8];
+	__be32	itt;
+	__be32	ttt;
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	__be32	datasn;
+	__be32	offset;
+	__be32	residual_count;
+};
+
+/* Data Response PDU flags */
+#define ISCSI_FLAG_DATA_ACK		0x40
+#define ISCSI_FLAG_DATA_OVERFLOW	0x04
+#define ISCSI_FLAG_DATA_UNDERFLOW	0x02
+#define ISCSI_FLAG_DATA_STATUS		0x01
+
+/* Text Header */
+struct iscsi_text {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[2];
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd4[8];
+	__be32	itt;
+	__be32	ttt;
+	__be32	cmdsn;
+	__be32	exp_statsn;
+	uint8_t rsvd5[16];
+	/* Text - key=value pairs */
+};
+
+#define ISCSI_FLAG_TEXT_CONTINUE	0x40
+
+/* Text Response Header */
+struct iscsi_text_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[2];
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd4[8];
+	__be32	itt;
+	__be32	ttt;
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	uint8_t rsvd5[12];
+	/* Text Response - key:value pairs */
+};
+
+/* Login Header */
+struct iscsi_login {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t max_version;	/* Max. version supported */
+	uint8_t min_version;	/* Min. version supported */
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t isid[6];	/* Initiator Session ID */
+	__be16	tsih;	/* Target Session Handle */
+	__be32	itt;	/* Initiator Task Tag */
+	__be16	cid;
+	__be16	rsvd3;
+	__be32	cmdsn;
+	__be32	exp_statsn;
+	uint8_t rsvd5[16];
+};
+
+/* Login PDU flags */
+#define ISCSI_FLAG_LOGIN_TRANSIT		0x80
+#define ISCSI_FLAG_LOGIN_CONTINUE		0x40
+#define ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK	0x0C	/* 2 bits */
+#define ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK	0x03	/* 2 bits */
+
+#define ISCSI_LOGIN_CURRENT_STAGE(flags) \
+	((flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2)
+#define ISCSI_LOGIN_NEXT_STAGE(flags) \
+	(flags & ISCSI_FLAG_LOGIN_NEXT_STAGE_MASK)
+
+/* Login Response Header */
+struct iscsi_login_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t max_version;	/* Max. version supported */
+	uint8_t active_version;	/* Active version */
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t isid[6];	/* Initiator Session ID */
+	__be16	tsih;	/* Target Session Handle */
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	rsvd3;
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	uint8_t status_class;	/* see Login RSP ststus classes below */
+	uint8_t status_detail;	/* see Login RSP Status details below */
+	uint8_t rsvd4[10];
+};
+
+/* Login stage (phase) codes for CSG, NSG */
+#define ISCSI_INITIAL_LOGIN_STAGE		-1
+#define ISCSI_SECURITY_NEGOTIATION_STAGE	0
+#define ISCSI_OP_PARMS_NEGOTIATION_STAGE	1
+#define ISCSI_FULL_FEATURE_PHASE		3
+
+/* Login Status response classes */
+#define ISCSI_STATUS_CLS_SUCCESS		0x00
+#define ISCSI_STATUS_CLS_REDIRECT		0x01
+#define ISCSI_STATUS_CLS_INITIATOR_ERR		0x02
+#define ISCSI_STATUS_CLS_TARGET_ERR		0x03
+
+/* Login Status response detail codes */
+/* Class-0 (Success) */
+#define ISCSI_LOGIN_STATUS_ACCEPT		0x00
+
+/* Class-1 (Redirection) */
+#define ISCSI_LOGIN_STATUS_TGT_MOVED_TEMP	0x01
+#define ISCSI_LOGIN_STATUS_TGT_MOVED_PERM	0x02
+
+/* Class-2 (Initiator Error) */
+#define ISCSI_LOGIN_STATUS_INIT_ERR		0x00
+#define ISCSI_LOGIN_STATUS_AUTH_FAILED		0x01
+#define ISCSI_LOGIN_STATUS_TGT_FORBIDDEN	0x02
+#define ISCSI_LOGIN_STATUS_TGT_NOT_FOUND	0x03
+#define ISCSI_LOGIN_STATUS_TGT_REMOVED		0x04
+#define ISCSI_LOGIN_STATUS_NO_VERSION		0x05
+#define ISCSI_LOGIN_STATUS_ISID_ERROR		0x06
+#define ISCSI_LOGIN_STATUS_MISSING_FIELDS	0x07
+#define ISCSI_LOGIN_STATUS_CONN_ADD_FAILED	0x08
+#define ISCSI_LOGIN_STATUS_NO_SESSION_TYPE	0x09
+#define ISCSI_LOGIN_STATUS_NO_SESSION		0x0a
+#define ISCSI_LOGIN_STATUS_INVALID_REQUEST	0x0b
+
+/* Class-3 (Target Error) */
+#define ISCSI_LOGIN_STATUS_TARGET_ERROR		0x00
+#define ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE	0x01
+#define ISCSI_LOGIN_STATUS_NO_RESOURCES		0x02
+
+/* Logout Header */
+struct iscsi_logout {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd1[2];
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd2[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be16	cid;
+	uint8_t rsvd3[2];
+	__be32	cmdsn;
+	__be32	exp_statsn;
+	uint8_t rsvd4[16];
+};
+
+/* Logout PDU flags */
+#define ISCSI_FLAG_LOGOUT_REASON_MASK	0x7F
+
+/* logout reason_code values */
+
+#define ISCSI_LOGOUT_REASON_CLOSE_SESSION	0
+#define ISCSI_LOGOUT_REASON_CLOSE_CONNECTION	1
+#define ISCSI_LOGOUT_REASON_RECOVERY		2
+#define ISCSI_LOGOUT_REASON_AEN_REQUEST		3
+
+/* Logout Response Header */
+struct iscsi_logout_rsp {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t response;	/* see Logout response values below */
+	uint8_t rsvd2;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd3[8];
+	__be32	itt;	/* Initiator Task Tag */
+	__be32	rsvd4;
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	__be32	rsvd5;
+	__be16	t2wait;
+	__be16	t2retain;
+	__be32	rsvd6;
+};
+
+/* logout response status values */
+
+#define ISCSI_LOGOUT_SUCCESS			0
+#define ISCSI_LOGOUT_CID_NOT_FOUND		1
+#define ISCSI_LOGOUT_RECOVERY_UNSUPPORTED	2
+#define ISCSI_LOGOUT_CLEANUP_FAILED		3
+
+/* SNACK Header */
+struct iscsi_snack {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t rsvd2[14];
+	__be32	itt;
+	__be32	begrun;
+	__be32	runlength;
+	__be32	exp_statsn;
+	__be32	rsvd3;
+	__be32	exp_datasn;
+	uint8_t rsvd6[8];
+};
+
+/* SNACK PDU flags */
+#define ISCSI_FLAG_SNACK_TYPE_MASK	0x0F	/* 4 bits */
+
+/* Reject Message Header */
+struct iscsi_reject {
+	uint8_t opcode;
+	uint8_t flags;
+	uint8_t reason;
+	uint8_t rsvd2;
+	uint8_t hlength;
+	uint8_t dlength[3];
+	uint8_t rsvd3[8];
+	__be32  ffffffff;
+	uint8_t rsvd4[4];
+	__be32	statsn;
+	__be32	exp_cmdsn;
+	__be32	max_cmdsn;
+	__be32	datasn;
+	uint8_t rsvd5[8];
+	/* Text - Rejected hdr */
+};
+
+/* Reason for Reject */
+#define ISCSI_REASON_CMD_BEFORE_LOGIN	1
+#define ISCSI_REASON_DATA_DIGEST_ERROR	2
+#define ISCSI_REASON_DATA_SNACK_REJECT	3
+#define ISCSI_REASON_PROTOCOL_ERROR	4
+#define ISCSI_REASON_CMD_NOT_SUPPORTED	5
+#define ISCSI_REASON_IMM_CMD_REJECT		6
+#define ISCSI_REASON_TASK_IN_PROGRESS	7
+#define ISCSI_REASON_INVALID_SNACK		8
+#define ISCSI_REASON_BOOKMARK_INVALID	9
+#define ISCSI_REASON_BOOKMARK_NO_RESOURCES	10
+#define ISCSI_REASON_NEGOTIATION_RESET	11
+
+/* Max. number of Key=Value pairs in a text message */
+#define MAX_KEY_VALUE_PAIRS	8192
+
+/* maximum length for text keys/values */
+#define KEY_MAXLEN		64
+#define VALUE_MAXLEN		255
+#define TARGET_NAME_MAXLEN	VALUE_MAXLEN
+
+#define DEFAULT_MAX_RECV_DATA_SEGMENT_LENGTH	8192
+
+/************************* RFC 3720 End *****************************/
+
+#endif /* ISCSI_PROTO_H */
diff --git a/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_device.h b/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_device.h
new file mode 100644
index 0000000..f353e0b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_device.h
@@ -0,0 +1,19 @@
+#ifndef _SCSI_SCSI_DEVICE_H_BACKPORT
+#define _SCSI_SCSI_DEVICE_H_BACKPORT
+
+#include_next <scsi/scsi_device.h>
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+
+struct scsi_lun;
+
+extern void int_to_scsilun(unsigned int, struct scsi_lun *);
+extern void scsi_target_block(struct device *);
+extern void scsi_target_unblock(struct device *);
+extern void starget_for_each_device(struct scsi_target *, void *,
+		     void (*fn)(struct scsi_device *, void *));
+#endif /* _SCSI_SCSI_DEVICE_H_BACKPORT */
diff --git a/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_host.h b/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_host.h
new file mode 100644
index 0000000..b7e019b
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_host.h
@@ -0,0 +1,8 @@
+#ifndef _SCSI_SCSI_HOST_H_BACKPORT
+#define _SCSI_SCSI_HOST_H_BACKPORT
+
+#include_next <scsi/scsi_host.h>
+
+#define scsi_queue_work(shost, work) schedule_work(work)
+
+#endif
diff --git a/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_transport.h b/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_transport.h
new file mode 100644
index 0000000..99c2b12
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/scsi/scsi_transport.h
@@ -0,0 +1,8 @@
+#ifndef _SCSI_SCSI_TRANSPORT_H_BACKPORT
+#define _SCSI_SCSI_TRANSPORT_H_BACKPORT
+
+#include_next <scsi/scsi_transport.h>
+
+#include <linux/transport_class.h>
+
+#endif /* _SCSI_SCSI_TRANSPORT_H_BACKPORT */
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/attribute_container.c b/kernel_addons/backport/2.6.9_U5/include/src/attribute_container.c
new file mode 100644
index 0000000..44948d1
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/attribute_container.c
@@ -0,0 +1,438 @@
+/*
+ * attribute_container.c - implementation of a simple container for classes
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ *
+ * The basic idea here is to enable a device to be attached to an
+ * aritrary numer of classes without having to allocate storage for them.
+ * Instead, the contained classes select the devices they need to attach
+ * to via a matching function.
+ */
+
+#include <linux/attribute_container.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/module.h>
+
+#include "base.h"
+
+/* This is a private structure used to tie the classdev and the
+ * container .. it should never be visible outside this file */
+struct internal_container {
+	struct klist_node node;
+	struct attribute_container *cont;
+	struct class_device classdev;
+};
+
+static void internal_container_klist_get(struct klist_node *n)
+{
+	struct internal_container *ic =
+		container_of(n, struct internal_container, node);
+	class_device_get(&ic->classdev);
+}
+
+static void internal_container_klist_put(struct klist_node *n)
+{
+	struct internal_container *ic =
+		container_of(n, struct internal_container, node);
+	class_device_put(&ic->classdev);
+}
+
+
+/**
+ * attribute_container_classdev_to_container - given a classdev, return the container
+ *
+ * @classdev: the class device created by attribute_container_add_device.
+ *
+ * Returns the container associated with this classdev.
+ */
+struct attribute_container *
+attribute_container_classdev_to_container(struct class_device *classdev)
+{
+	struct internal_container *ic =
+		container_of(classdev, struct internal_container, classdev);
+	return ic->cont;
+}
+EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container);
+
+static struct list_head attribute_container_list;
+
+static DECLARE_MUTEX(attribute_container_mutex);
+
+/**
+ * attribute_container_register - register an attribute container
+ *
+ * @cont: The container to register.  This must be allocated by the
+ *        callee and should also be zeroed by it.
+ */
+int
+attribute_container_register(struct attribute_container *cont)
+{
+	INIT_LIST_HEAD(&cont->node);
+	klist_init(&cont->containers,internal_container_klist_get,
+		   internal_container_klist_put);
+		
+	down(&attribute_container_mutex);
+	list_add_tail(&cont->node, &attribute_container_list);
+	up(&attribute_container_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(attribute_container_register);
+
+/**
+ * attribute_container_unregister - remove a container registration
+ *
+ * @cont: previously registered container to remove
+ */
+int
+attribute_container_unregister(struct attribute_container *cont)
+{
+	int retval = -EBUSY;
+	down(&attribute_container_mutex);
+	spin_lock(&cont->containers.k_lock);
+	if (!list_empty(&cont->containers.k_list))
+		goto out;
+	retval = 0;
+	list_del(&cont->node);
+ out:
+	spin_unlock(&cont->containers.k_lock);
+	up(&attribute_container_mutex);
+	return retval;
+		
+}
+EXPORT_SYMBOL_GPL(attribute_container_unregister);
+
+/* private function used as class release */
+static void attribute_container_release(struct class_device *classdev)
+{
+	struct internal_container *ic 
+		= container_of(classdev, struct internal_container, classdev);
+	struct device *dev = classdev->dev;
+
+	kfree(ic);
+	put_device(dev);
+}
+
+/**
+ * attribute_container_add_device - see if any container is interested in dev
+ *
+ * @dev: device to add attributes to
+ * @fn:	 function to trigger addition of class device.
+ *
+ * This function allocates storage for the class device(s) to be
+ * attached to dev (one for each matching attribute_container).  If no
+ * fn is provided, the code will simply register the class device via
+ * class_device_add.  If a function is provided, it is expected to add
+ * the class device at the appropriate time.  One of the things that
+ * might be necessary is to allocate and initialise the classdev and
+ * then add it a later time.  To do this, call this routine for
+ * allocation and initialisation and then use
+ * attribute_container_device_trigger() to call class_device_add() on
+ * it.  Note: after this, the class device contains a reference to dev
+ * which is not relinquished until the release of the classdev.
+ */
+void
+attribute_container_add_device(struct device *dev,
+			       int (*fn)(struct attribute_container *,
+					 struct device *,
+					 struct class_device *))
+{
+	struct attribute_container *cont;
+
+	down(&attribute_container_mutex);
+	list_for_each_entry(cont, &attribute_container_list, node) {
+		struct internal_container *ic;
+
+		if (attribute_container_no_classdevs(cont))
+			continue;
+
+		if (!cont->match(cont, dev))
+			continue;
+
+		ic = kzalloc(sizeof(*ic), GFP_KERNEL);
+		if (!ic) {
+			dev_printk(KERN_ERR, dev, "failed to allocate class container\n");
+			continue;
+		}
+
+		ic->cont = cont;
+		class_device_initialize(&ic->classdev);
+		ic->classdev.dev = get_device(dev);
+		ic->classdev.class = cont->class;
+		cont->class->release = attribute_container_release;
+		strcpy(ic->classdev.class_id, dev->bus_id);
+		if (fn)
+			fn(cont, dev, &ic->classdev);
+		else
+			attribute_container_add_class_device(&ic->classdev);
+		klist_add_tail(&ic->node, &cont->containers);
+	}
+	up(&attribute_container_mutex);
+}
+
+/* FIXME: can't break out of this unless klist_iter_exit is also
+ * called before doing the break
+ */
+#define klist_for_each_entry(pos, head, member, iter) \
+	for (klist_iter_init(head, iter); (pos = ({ \
+		struct klist_node *n = klist_next(iter); \
+		n ? container_of(n, typeof(*pos), member) : \
+			({ klist_iter_exit(iter) ; NULL; }); \
+	}) ) != NULL; )
+			
+
+/**
+ * attribute_container_remove_device - make device eligible for removal.
+ *
+ * @dev:  The generic device
+ * @fn:	  A function to call to remove the device
+ *
+ * This routine triggers device removal.  If fn is NULL, then it is
+ * simply done via class_device_unregister (note that if something
+ * still has a reference to the classdev, then the memory occupied
+ * will not be freed until the classdev is released).  If you want a
+ * two phase release: remove from visibility and then delete the
+ * device, then you should use this routine with a fn that calls
+ * class_device_del() and then use
+ * attribute_container_device_trigger() to do the final put on the
+ * classdev.
+ */
+void
+attribute_container_remove_device(struct device *dev,
+				  void (*fn)(struct attribute_container *,
+					     struct device *,
+					     struct class_device *))
+{
+	struct attribute_container *cont;
+
+	down(&attribute_container_mutex);
+	list_for_each_entry(cont, &attribute_container_list, node) {
+		struct internal_container *ic;
+		struct klist_iter iter;
+
+		if (attribute_container_no_classdevs(cont))
+			continue;
+
+		if (!cont->match(cont, dev))
+			continue;
+
+		klist_for_each_entry(ic, &cont->containers, node, &iter) {
+			if (dev != ic->classdev.dev)
+				continue;
+			klist_del(&ic->node);
+			if (fn)
+				fn(cont, dev, &ic->classdev);
+			else {
+				attribute_container_remove_attrs(&ic->classdev);
+				class_device_unregister(&ic->classdev);
+			}
+		}
+	}
+	up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_device_trigger - execute a trigger for each matching classdev
+ *
+ * @dev:  The generic device to run the trigger for
+ * @fn	  the function to execute for each classdev.
+ *
+ * This funcion is for executing a trigger when you need to know both
+ * the container and the classdev.  If you only care about the
+ * container, then use attribute_container_trigger() instead.
+ */
+void
+attribute_container_device_trigger(struct device *dev, 
+				   int (*fn)(struct attribute_container *,
+					     struct device *,
+					     struct class_device *))
+{
+	struct attribute_container *cont;
+
+	down(&attribute_container_mutex);
+	list_for_each_entry(cont, &attribute_container_list, node) {
+		struct internal_container *ic;
+		struct klist_iter iter;
+
+		if (!cont->match(cont, dev))
+			continue;
+
+		if (attribute_container_no_classdevs(cont)) {
+			fn(cont, dev, NULL);
+			continue;
+		}
+
+		klist_for_each_entry(ic, &cont->containers, node, &iter) {
+			if (dev == ic->classdev.dev)
+				fn(cont, dev, &ic->classdev);
+		}
+	}
+	up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_trigger - trigger a function for each matching container
+ *
+ * @dev:  The generic device to activate the trigger for
+ * @fn:	  the function to trigger
+ *
+ * This routine triggers a function that only needs to know the
+ * matching containers (not the classdev) associated with a device.
+ * It is more lightweight than attribute_container_device_trigger, so
+ * should be used in preference unless the triggering function
+ * actually needs to know the classdev.
+ */
+void
+attribute_container_trigger(struct device *dev,
+			    int (*fn)(struct attribute_container *,
+				      struct device *))
+{
+	struct attribute_container *cont;
+
+	down(&attribute_container_mutex);
+	list_for_each_entry(cont, &attribute_container_list, node) {
+		if (cont->match(cont, dev))
+			fn(cont, dev);
+	}
+	up(&attribute_container_mutex);
+}
+
+/**
+ * attribute_container_add_attrs - add attributes
+ *
+ * @classdev: The class device
+ *
+ * This simply creates all the class device sysfs files from the
+ * attributes listed in the container
+ */
+int
+attribute_container_add_attrs(struct class_device *classdev)
+{
+	struct attribute_container *cont =
+		attribute_container_classdev_to_container(classdev);
+	struct class_device_attribute **attrs =	cont->attrs;
+	int i, error;
+
+	if (!attrs)
+		return 0;
+
+	for (i = 0; attrs[i]; i++) {
+		error = class_device_create_file(classdev, attrs[i]);
+		if (error)
+			return error;
+	}
+
+	return 0;
+}
+
+/**
+ * attribute_container_add_class_device - same function as class_device_add
+ *
+ * @classdev:	the class device to add
+ *
+ * This performs essentially the same function as class_device_add except for
+ * attribute containers, namely add the classdev to the system and then
+ * create the attribute files
+ */
+int
+attribute_container_add_class_device(struct class_device *classdev)
+{
+	int error = class_device_add(classdev);
+	if (error)
+		return error;
+	return attribute_container_add_attrs(classdev);
+}
+
+/**
+ * attribute_container_add_class_device_adapter - simple adapter for triggers
+ *
+ * This function is identical to attribute_container_add_class_device except
+ * that it is designed to be called from the triggers
+ */
+int
+attribute_container_add_class_device_adapter(struct attribute_container *cont,
+					     struct device *dev,
+					     struct class_device *classdev)
+{
+	return attribute_container_add_class_device(classdev);
+}
+
+/**
+ * attribute_container_remove_attrs - remove any attribute files
+ *
+ * @classdev: The class device to remove the files from
+ *
+ */
+void
+attribute_container_remove_attrs(struct class_device *classdev)
+{
+	struct attribute_container *cont =
+		attribute_container_classdev_to_container(classdev);
+	struct class_device_attribute **attrs =	cont->attrs;
+	int i;
+
+	if (!attrs)
+		return;
+
+	for (i = 0; attrs[i]; i++)
+		class_device_remove_file(classdev, attrs[i]);
+}
+
+/**
+ * attribute_container_class_device_del - equivalent of class_device_del
+ *
+ * @classdev: the class device
+ *
+ * This function simply removes all the attribute files and then calls
+ * class_device_del.
+ */
+void
+attribute_container_class_device_del(struct class_device *classdev)
+{
+	attribute_container_remove_attrs(classdev);
+	class_device_del(classdev);
+}
+
+/**
+ * attribute_container_find_class_device - find the corresponding class_device
+ *
+ * @cont:	the container
+ * @dev:	the generic device
+ *
+ * Looks up the device in the container's list of class devices and returns
+ * the corresponding class_device.
+ */
+struct class_device *
+attribute_container_find_class_device(struct attribute_container *cont,
+				      struct device *dev)
+{
+	struct class_device *cdev = NULL;
+	struct internal_container *ic;
+	struct klist_iter iter;
+
+	klist_for_each_entry(ic, &cont->containers, node, &iter) {
+		if (ic->classdev.dev == dev) {
+			cdev = &ic->classdev;
+			/* FIXME: must exit iterator then break */
+			klist_iter_exit(&iter);
+			break;
+		}
+	}
+
+	return cdev;
+}
+EXPORT_SYMBOL_GPL(attribute_container_find_class_device);
+
+int
+attribute_container_init(void)
+{
+	INIT_LIST_HEAD(&attribute_container_list);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(attribute_container_init);
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/base.h b/kernel_addons/backport/2.6.9_U5/include/src/base.h
new file mode 100644
index 0000000..a5f8936
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/base.h
@@ -0,0 +1 @@
+extern int attribute_container_init(void);
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/init.c b/kernel_addons/backport/2.6.9_U5/include/src/init.c
new file mode 100644
index 0000000..15f0bc6
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/init.c
@@ -0,0 +1,26 @@
+/*
+ *
+ * Copyright (c) 2002-3 Patrick Mochel
+ * Copyright (c) 2002-3 Open Source Development Labs
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/memory.h>
+
+#include "base.h"
+
+/**
+ *	driver_init - initialize driver model.
+ *
+ *	Call the driver model init functions to initialize their
+ *	subsystems. Called early from init/main.c.
+ */
+
+void __init driver_init(void)
+{
+	attribute_container_init();
+}
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/klist.c b/kernel_addons/backport/2.6.9_U5/include/src/klist.c
new file mode 100644
index 0000000..3b29ebc
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/klist.c
@@ -0,0 +1,287 @@
+/*
+ *	klist.c - Routines for manipulating klists.
+ *
+ *
+ *	This klist interface provides a couple of structures that wrap around 
+ *	struct list_head to provide explicit list "head" (struct klist) and 
+ *	list "node" (struct klist_node) objects. For struct klist, a spinlock
+ *	is included that protects access to the actual list itself. struct 
+ *	klist_node provides a pointer to the klist that owns it and a kref
+ *	reference count that indicates the number of current users of that node
+ *	in the list.
+ *
+ *	The entire point is to provide an interface for iterating over a list
+ *	that is safe and allows for modification of the list during the
+ *	iteration (e.g. insertion and removal), including modification of the
+ *	current node on the list.
+ *
+ *	It works using a 3rd object type - struct klist_iter - that is declared
+ *	and initialized before an iteration. klist_next() is used to acquire the
+ *	next element in the list. It returns NULL if there are no more items.
+ *	Internally, that routine takes the klist's lock, decrements the reference
+ *	count of the previous klist_node and increments the count of the next
+ *	klist_node. It then drops the lock and returns.
+ *
+ *	There are primitives for adding and removing nodes to/from a klist. 
+ *	When deleting, klist_del() will simply decrement the reference count. 
+ *	Only when the count goes to 0 is the node removed from the list. 
+ *	klist_remove() will try to delete the node from the list and block
+ *	until it is actually removed. This is useful for objects (like devices)
+ *	that have been removed from the system and must be freed (but must wait
+ *	until all accessors have finished).
+ *
+ *	Copyright (C) 2005 Patrick Mochel
+ *
+ *	This file is released under the GPL v2.
+ */
+
+#include <linux/klist.h>
+#include <linux/module.h>
+
+
+/**
+ *	klist_init - Initialize a klist structure. 
+ *	@k:	The klist we're initializing.
+ *	@get:	The get function for the embedding object (NULL if none)
+ *	@put:	The put function for the embedding object (NULL if none)
+ *
+ * Initialises the klist structure.  If the klist_node structures are
+ * going to be embedded in refcounted objects (necessary for safe
+ * deletion) then the get/put arguments are used to initialise
+ * functions that take and release references on the embedding
+ * objects.
+ */
+
+void klist_init(struct klist * k, void (*get)(struct klist_node *),
+		void (*put)(struct klist_node *))
+{
+	INIT_LIST_HEAD(&k->k_list);
+	spin_lock_init(&k->k_lock);
+	k->get = get;
+	k->put = put;
+}
+
+EXPORT_SYMBOL_GPL(klist_init);
+
+
+static void add_head(struct klist * k, struct klist_node * n)
+{
+	spin_lock(&k->k_lock);
+	list_add(&n->n_node, &k->k_list);
+	spin_unlock(&k->k_lock);
+}
+
+static void add_tail(struct klist * k, struct klist_node * n)
+{
+	spin_lock(&k->k_lock);
+	list_add_tail(&n->n_node, &k->k_list);
+	spin_unlock(&k->k_lock);
+}
+
+
+static void klist_node_init(struct klist * k, struct klist_node * n)
+{
+	INIT_LIST_HEAD(&n->n_node);
+	init_completion(&n->n_removed);
+	kref_init(&n->n_ref);
+	n->n_klist = k;
+	if (k->get)
+		k->get(n);
+}
+
+
+/**
+ *	klist_add_head - Initialize a klist_node and add it to front.
+ *	@n:	node we're adding.
+ *	@k:	klist it's going on.
+ */
+
+void klist_add_head(struct klist_node * n, struct klist * k)
+{
+	klist_node_init(k, n);
+	add_head(k, n);
+}
+
+EXPORT_SYMBOL_GPL(klist_add_head);
+
+
+/**
+ *	klist_add_tail - Initialize a klist_node and add it to back.
+ *	@n:	node we're adding.
+ *	@k:	klist it's going on.
+ */
+
+void klist_add_tail(struct klist_node * n, struct klist * k)
+{
+	klist_node_init(k, n);
+	add_tail(k, n);
+}
+
+EXPORT_SYMBOL_GPL(klist_add_tail);
+
+
+static void klist_release(struct kref * kref)
+{
+	struct klist_node * n = container_of(kref, struct klist_node, n_ref);
+
+	list_del(&n->n_node);
+	complete(&n->n_removed);
+	n->n_klist = NULL;
+}
+
+static int klist_dec_and_del(struct klist_node * n)
+{
+	return kref_put_new(&n->n_ref, klist_release);
+}
+
+
+/**
+ *	klist_del - Decrement the reference count of node and try to remove.
+ *	@n:	node we're deleting.
+ */
+
+void klist_del(struct klist_node * n)
+{
+	struct klist * k = n->n_klist;
+	void (*put)(struct klist_node *) = k->put;
+
+	spin_lock(&k->k_lock);
+	if (!klist_dec_and_del(n))
+		put = NULL;
+	spin_unlock(&k->k_lock);
+	if (put)
+		put(n);
+}
+
+EXPORT_SYMBOL_GPL(klist_del);
+
+
+/**
+ *	klist_remove - Decrement the refcount of node and wait for it to go away.
+ *	@n:	node we're removing.
+ */
+
+void klist_remove(struct klist_node * n)
+{
+	klist_del(n);
+	wait_for_completion(&n->n_removed);
+}
+
+EXPORT_SYMBOL_GPL(klist_remove);
+
+
+/**
+ *	klist_node_attached - Say whether a node is bound to a list or not.
+ *	@n:	Node that we're testing.
+ */
+
+int klist_node_attached(struct klist_node * n)
+{
+	return (n->n_klist != NULL);
+}
+
+EXPORT_SYMBOL_GPL(klist_node_attached);
+
+
+/**
+ *	klist_iter_init_node - Initialize a klist_iter structure.
+ *	@k:	klist we're iterating.
+ *	@i:	klist_iter we're filling.
+ *	@n:	node to start with.
+ *
+ *	Similar to klist_iter_init(), but starts the action off with @n, 
+ *	instead of with the list head.
+ */
+
+void klist_iter_init_node(struct klist * k, struct klist_iter * i, struct klist_node * n)
+{
+	i->i_klist = k;
+	i->i_head = &k->k_list;
+	i->i_cur = n;
+	if (n)
+		kref_get(&n->n_ref);
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_init_node);
+
+
+/**
+ *	klist_iter_init - Iniitalize a klist_iter structure.
+ *	@k:	klist we're iterating.
+ *	@i:	klist_iter structure we're filling.
+ *
+ *	Similar to klist_iter_init_node(), but start with the list head.
+ */
+
+void klist_iter_init(struct klist * k, struct klist_iter * i)
+{
+	klist_iter_init_node(k, i, NULL);
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_init);
+
+
+/**
+ *	klist_iter_exit - Finish a list iteration.
+ *	@i:	Iterator structure.
+ *
+ *	Must be called when done iterating over list, as it decrements the 
+ *	refcount of the current node. Necessary in case iteration exited before
+ *	the end of the list was reached, and always good form.
+ */
+
+void klist_iter_exit(struct klist_iter * i)
+{
+	if (i->i_cur) {
+		klist_del(i->i_cur);
+		i->i_cur = NULL;
+	}
+}
+
+EXPORT_SYMBOL_GPL(klist_iter_exit);
+
+
+static struct klist_node * to_klist_node(struct list_head * n)
+{
+	return container_of(n, struct klist_node, n_node);
+}
+
+
+/**
+ *	klist_next - Ante up next node in list.
+ *	@i:	Iterator structure.
+ *
+ *	First grab list lock. Decrement the reference count of the previous
+ *	node, if there was one. Grab the next node, increment its reference 
+ *	count, drop the lock, and return that next node.
+ */
+
+struct klist_node * klist_next(struct klist_iter * i)
+{
+	struct list_head * next;
+	struct klist_node * lnode = i->i_cur;
+	struct klist_node * knode = NULL;
+	void (*put)(struct klist_node *) = i->i_klist->put;
+
+	spin_lock(&i->i_klist->k_lock);
+	if (lnode) {
+		next = lnode->n_node.next;
+		if (!klist_dec_and_del(lnode))
+			put = NULL;
+	} else
+		next = i->i_head->next;
+
+	if (next != i->i_head) {
+		knode = to_klist_node(next);
+		kref_get(&knode->n_ref);
+	}
+	i->i_cur = knode;
+	spin_unlock(&i->i_klist->k_lock);
+	if (put && lnode)
+		put(lnode);
+	return knode;
+}
+
+EXPORT_SYMBOL_GPL(klist_next);
+
+
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/kref_new.c b/kernel_addons/backport/2.6.9_U5/include/src/kref_new.c
new file mode 100644
index 0000000..d45bb3f
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/kref_new.c
@@ -0,0 +1,29 @@
+#include <linux/kref.h>
+#include <linux/module.h>
+
+/**
+ * kref_put - decrement refcount for object.
+ * @kref: object.
+ * @release: pointer to the function that will clean up the object when the
+ *           last reference to the object is released.
+ *           This pointer is required, and it is not acceptable to pass kfree
+ *           in as this function.
+ *
+ * Decrement the refcount, and if 0, call release().
+ * Return 1 if the object was removed, otherwise return 0.  Beware, if this
+ * function returns 0, you still can not count on the kref from remaining in
+ * memory.  Only use the return value if you want to see if the kref is now
+ * gone, not present.
+ */
+int kref_put_new(struct kref *kref, void (*release)(struct kref *kref))
+{
+        WARN_ON(release == NULL);
+        WARN_ON(release == (void (*)(struct kref *))kfree);
+
+        if (atomic_dec_and_test(&kref->refcount)) {
+                release(kref);
+                return 1;
+        }
+        return 0;
+}
+EXPORT_SYMBOL(kref_put_new);
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/scsi.c b/kernel_addons/backport/2.6.9_U5/include/src/scsi.c
new file mode 100644
index 0000000..8c833c0
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/scsi.c
@@ -0,0 +1,50 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/completion.h>
+#include <linux/unistd.h>
+#include <linux/spinlock.h>
+#include <linux/kmod.h>
+#include <linux/interrupt.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/mutex.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+
+/**
+ * starget_for_each_device  -  helper to walk all devices of a target
+ * @starget:	target whose devices we want to iterate over.
+ *
+ * This traverses over each devices of @shost.  The devices have
+ * a reference that must be released by scsi_host_put when breaking
+ * out of the loop.
+ */
+void starget_for_each_device(struct scsi_target *starget, void * data,
+		     void (*fn)(struct scsi_device *, void *))
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct scsi_device *sdev;
+
+	printk("%s: entry\n", __FUNCTION__);
+	shost_for_each_device(sdev, shost) {
+		if ((sdev->channel == starget->channel) &&
+		    (sdev->id == starget->id))
+			fn(sdev, data);
+	}
+	printk("%s: exit\n", __FUNCTION__);
+}
+EXPORT_SYMBOL(starget_for_each_device);
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/scsi_lib.c b/kernel_addons/backport/2.6.9_U5/include/src/scsi_lib.c
new file mode 100644
index 0000000..f53f824
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/scsi_lib.c
@@ -0,0 +1,166 @@
+#include <linux/bio.h>
+#include <linux/blkdev.h>
+#include <linux/completion.h>
+#include <linux/kernel.h>
+#include <linux/mempool.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/hardirq.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_host.h>
+
+int scsi_is_target_device(const struct device *dev)
+{
+        char *str = dev->bus_id;
+
+	if (strncmp(str, "target", 6) == 0) {
+		return 1;
+	}
+
+        return 0;
+}
+
+/**
+ * scsi_internal_device_block - internal function to put a device
+ *                              temporarily into the SDEV_BLOCK state
+ * @sdev:       device to block
+ *
+ * Block request made by scsi lld's to temporarily stop all
+ * scsi commands on the specified device.  Called from interrupt
+ * or normal process context.
+ *
+ * Returns zero if successful or error if not
+ *
+ * Notes:
+ *      This routine transitions the device to the SDEV_BLOCK state
+ *      (which must be a legal transition).  When the device is in this
+ *      state, all commands are deferred until the scsi lld reenables
+ *      the device with scsi_device_unblock or device_block_tmo fires.
+ *      This routine assumes the host_lock is held on entry.
+ **/
+int
+scsi_internal_device_block(struct scsi_device *sdev)
+{
+        request_queue_t *q = sdev->request_queue;
+        unsigned long flags;
+        int err = 0;
+
+        err = scsi_device_set_state(sdev, SDEV_BLOCK);
+        if (err)
+		return err;
+                
+        /*
+         * The device has transitioned to SDEV_BLOCK.  Stop the
+         * block layer from calling the midlayer with this device's
+         * request queue.
+         */
+        spin_lock_irqsave(q->queue_lock, flags);
+        blk_stop_queue(q);
+        spin_unlock_irqrestore(q->queue_lock, flags);
+
+        return 0;
+}
+EXPORT_SYMBOL_GPL(scsi_internal_device_block);
+
+/**
+ * scsi_internal_device_unblock - resume a device after a block request
+ * @sdev:       device to resume
+ *
+ * Called by scsi lld's or the midlayer to restart the device queue
+ * for the previously suspended scsi device.  Called from interrupt or
+ * normal process context.
+ *
+ * Returns zero if successful or error if not.
+ *
+ * Notes:
+ *      This routine transitions the device to the SDEV_RUNNING state
+ *      (which must be a legal transition) allowing the midlayer to
+ *      goose the queue for this device.  This routine assumes the
+ *      host_lock is held upon entry.
+ **/
+int
+scsi_internal_device_unblock(struct scsi_device *sdev)
+{
+        request_queue_t *q = sdev->request_queue;
+        int err;
+        unsigned long flags;
+
+
+        /*
+         * Try to transition the scsi device to SDEV_RUNNING
+         * and goose the device queue if successful.
+         */
+        err = scsi_device_set_state(sdev, SDEV_RUNNING);
+        if (err)
+		return err;
+                
+        spin_lock_irqsave(q->queue_lock, flags);
+        blk_start_queue(q);
+        spin_unlock_irqrestore(q->queue_lock, flags);
+
+        return 0;
+}
+EXPORT_SYMBOL_GPL(scsi_internal_device_unblock);
+
+static void
+device_block(struct scsi_device *sdev, void *data)
+{
+        scsi_internal_device_block(sdev);
+}
+
+static int
+target_block(struct device *dev, void *data)
+{
+        if (scsi_is_target_device(dev))
+                starget_for_each_device(to_scsi_target(dev), NULL,
+                                        device_block);
+
+        return 0;
+}
+
+void
+scsi_target_block(struct device *dev)
+{
+        if (scsi_is_target_device(dev))
+                starget_for_each_device(to_scsi_target(dev), NULL,
+                                        device_block);
+        else
+                device_for_each_child(dev, NULL, target_block);
+}
+EXPORT_SYMBOL_GPL(scsi_target_block);
+
+static void
+device_unblock(struct scsi_device *sdev, void *data)
+{
+        scsi_internal_device_unblock(sdev);
+}
+
+static int
+target_unblock(struct device *dev, void *data)
+{
+        if (scsi_is_target_device(dev))
+                starget_for_each_device(to_scsi_target(dev), NULL,
+                                        device_unblock);
+        return 0;
+}
+
+void
+scsi_target_unblock(struct device *dev)
+{
+        if (scsi_is_target_device(dev))
+                starget_for_each_device(to_scsi_target(dev), NULL,
+                                        device_unblock);
+        else
+                device_for_each_child(dev, NULL, target_unblock);
+}
+EXPORT_SYMBOL_GPL(scsi_target_unblock);
+
+MODULE_LICENSE("GPL");
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/scsi_scan.c b/kernel_addons/backport/2.6.9_U5/include/src/scsi_scan.c
new file mode 100644
index 0000000..b7b7674
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/scsi_scan.c
@@ -0,0 +1,48 @@
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/spinlock.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_devinfo.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_eh.h>
+
+/**
+ * int_to_scsilun: reverts an int into a scsi_lun
+ * @int:        integer to be reverted
+ * @scsilun:    struct scsi_lun to be set.
+ *
+ * Description:
+ *     Reverts the functionality of the scsilun_to_int, which packed
+ *     an 8-byte lun value into an int. This routine unpacks the int
+ *     back into the lun value.
+ *     Note: the scsilun_to_int() routine does not truly handle all
+ *     8bytes of the lun value. This functions restores only as much
+ *     as was set by the routine.
+ *
+ * Notes:
+ *     Given an integer : 0x0b030a04,  this function returns a
+ *     scsi_lun of : struct scsi_lun of: 0a 04 0b 03 00 00 00 00
+ *
+ **/
+void int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun)
+{
+        int i;
+
+        memset(scsilun->scsi_lun, 0, sizeof(scsilun->scsi_lun));
+
+        for (i = 0; i < sizeof(lun); i += 2) {
+                scsilun->scsi_lun[i] = (lun >> 8) & 0xFF;
+                scsilun->scsi_lun[i+1] = lun & 0xFF;
+                lun = lun >> 16;
+        }
+}
+EXPORT_SYMBOL(int_to_scsilun);
diff --git a/kernel_addons/backport/2.6.9_U5/include/src/transport_class.c b/kernel_addons/backport/2.6.9_U5/include/src/transport_class.c
new file mode 100644
index 0000000..f25e7c6
--- /dev/null
+++ b/kernel_addons/backport/2.6.9_U5/include/src/transport_class.c
@@ -0,0 +1,280 @@
+/*
+ * transport_class.c - implementation of generic transport classes
+ *                     using attribute_containers
+ *
+ * Copyright (c) 2005 - James Bottomley <James.Bottomley at steeleye.com>
+ *
+ * This file is licensed under GPLv2
+ *
+ * The basic idea here is to allow any "device controller" (which
+ * would most often be a Host Bus Adapter to use the services of one
+ * or more tranport classes for performing transport specific
+ * services.  Transport specific services are things that the generic
+ * command layer doesn't want to know about (speed settings, line
+ * condidtioning, etc), but which the user might be interested in.
+ * Thus, the HBA's use the routines exported by the transport classes
+ * to perform these functions.  The transport classes export certain
+ * values to the user via sysfs using attribute containers.
+ *
+ * Note: because not every HBA will care about every transport
+ * attribute, there's a many to one relationship that goes like this:
+ *
+ * transport class<-----attribute container<----class device
+ *
+ * Usually the attribute container is per-HBA, but the design doesn't
+ * mandate that.  Although most of the services will be specific to
+ * the actual external storage connection used by the HBA, the generic
+ * transport class is framed entirely in terms of generic devices to
+ * allow it to be used by any physical HBA in the system.
+ */
+#include <linux/attribute_container.h>
+#include <linux/transport_class.h>
+
+/**
+ * transport_class_register - register an initial transport class
+ *
+ * @tclass:	a pointer to the transport class structure to be initialised
+ *
+ * The transport class contains an embedded class which is used to
+ * identify it.  The caller should initialise this structure with
+ * zeros and then generic class must have been initialised with the
+ * actual transport class unique name.  There's a macro
+ * DECLARE_TRANSPORT_CLASS() to do this (declared classes still must
+ * be registered).
+ *
+ * Returns 0 on success or error on failure.
+ */
+int transport_class_register(struct transport_class *tclass)
+{
+	return class_register(&tclass->class);
+}
+EXPORT_SYMBOL_GPL(transport_class_register);
+
+/**
+ * transport_class_unregister - unregister a previously registered class
+ *
+ * @tclass: The transport class to unregister
+ *
+ * Must be called prior to deallocating the memory for the transport
+ * class.
+ */
+void transport_class_unregister(struct transport_class *tclass)
+{
+	class_unregister(&tclass->class);
+}
+EXPORT_SYMBOL_GPL(transport_class_unregister);
+
+static int anon_transport_dummy_function(struct transport_container *tc,
+					 struct device *dev,
+					 struct class_device *cdev)
+{
+	/* do nothing */
+	return 0;
+}
+
+/**
+ * anon_transport_class_register - register an anonymous class
+ *
+ * @atc: The anon transport class to register
+ *
+ * The anonymous transport class contains both a transport class and a
+ * container.  The idea of an anonymous class is that it never
+ * actually has any device attributes associated with it (and thus
+ * saves on container storage).  So it can only be used for triggering
+ * events.  Use prezero and then use DECLARE_ANON_TRANSPORT_CLASS() to
+ * initialise the anon transport class storage.
+ */
+int anon_transport_class_register(struct anon_transport_class *atc)
+{
+	int error;
+	atc->container.class = &atc->tclass.class;
+	attribute_container_set_no_classdevs(&atc->container);
+	error = attribute_container_register(&atc->container);
+	if (error)
+		return error;
+	atc->tclass.setup = anon_transport_dummy_function;
+	atc->tclass.remove = anon_transport_dummy_function;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(anon_transport_class_register);
+
+/**
+ * anon_transport_class_unregister - unregister an anon class
+ *
+ * @atc: Pointer to the anon transport class to unregister
+ *
+ * Must be called prior to deallocating the memory for the anon
+ * transport class.
+ */
+void anon_transport_class_unregister(struct anon_transport_class *atc)
+{
+	attribute_container_unregister(&atc->container);
+}
+EXPORT_SYMBOL_GPL(anon_transport_class_unregister);
+
+static int transport_setup_classdev(struct attribute_container *cont,
+				    struct device *dev,
+				    struct class_device *classdev)
+{
+	struct transport_class *tclass = class_to_transport_class(cont->class);
+	struct transport_container *tcont = attribute_container_to_transport_container(cont);
+
+	if (tclass->setup)
+		tclass->setup(tcont, dev, classdev);
+
+	return 0;
+}
+
+/**
+ * transport_setup_device - declare a new dev for transport class association
+ *			    but don't make it visible yet.
+ *
+ * @dev: the generic device representing the entity being added
+ *
+ * Usually, dev represents some component in the HBA system (either
+ * the HBA itself or a device remote across the HBA bus).  This
+ * routine is simply a trigger point to see if any set of transport
+ * classes wishes to associate with the added device.  This allocates
+ * storage for the class device and initialises it, but does not yet
+ * add it to the system or add attributes to it (you do this with
+ * transport_add_device).  If you have no need for a separate setup
+ * and add operations, use transport_register_device (see
+ * transport_class.h).
+ */
+
+void transport_setup_device(struct device *dev)
+{
+	attribute_container_add_device(dev, transport_setup_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_setup_device);
+
+static int transport_add_class_device(struct attribute_container *cont,
+				      struct device *dev,
+				      struct class_device *classdev)
+{
+	int error = attribute_container_add_class_device(classdev);
+	struct transport_container *tcont = 
+		attribute_container_to_transport_container(cont);
+
+	if (!error && tcont->statistics)
+		error = sysfs_create_group(&classdev->kobj, tcont->statistics);
+
+	return error;
+}
+
+
+/**
+ * transport_add_device - declare a new dev for transport class association
+ *
+ * @dev: the generic device representing the entity being added
+ *
+ * Usually, dev represents some component in the HBA system (either
+ * the HBA itself or a device remote across the HBA bus).  This
+ * routine is simply a trigger point used to add the device to the
+ * system and register attributes for it.
+ */
+
+void transport_add_device(struct device *dev)
+{
+	attribute_container_device_trigger(dev, transport_add_class_device);
+}
+EXPORT_SYMBOL_GPL(transport_add_device);
+
+static int transport_configure(struct attribute_container *cont,
+			       struct device *dev,
+			       struct class_device *cdev)
+{
+	struct transport_class *tclass = class_to_transport_class(cont->class);
+	struct transport_container *tcont = attribute_container_to_transport_container(cont);
+
+	if (tclass->configure)
+		tclass->configure(tcont, dev, cdev);
+
+	return 0;
+}
+
+/**
+ * transport_configure_device - configure an already set up device
+ *
+ * @dev: generic device representing device to be configured
+ *
+ * The idea of configure is simply to provide a point within the setup
+ * process to allow the transport class to extract information from a
+ * device after it has been setup.  This is used in SCSI because we
+ * have to have a setup device to begin using the HBA, but after we
+ * send the initial inquiry, we use configure to extract the device
+ * parameters.  The device need not have been added to be configured.
+ */
+void transport_configure_device(struct device *dev)
+{
+	attribute_container_device_trigger(dev, transport_configure);
+}
+EXPORT_SYMBOL_GPL(transport_configure_device);
+
+static int transport_remove_classdev(struct attribute_container *cont,
+				     struct device *dev,
+				     struct class_device *classdev)
+{
+	struct transport_container *tcont = 
+		attribute_container_to_transport_container(cont);
+	struct transport_class *tclass = class_to_transport_class(cont->class);
+
+	if (tclass->remove)
+		tclass->remove(tcont, dev, classdev);
+
+	if (tclass->remove != anon_transport_dummy_function) {
+		if (tcont->statistics)
+			sysfs_remove_group(&classdev->kobj, tcont->statistics);
+		attribute_container_class_device_del(classdev);
+	}
+
+	return 0;
+}
+
+
+/**
+ * transport_remove_device - remove the visibility of a device
+ *
+ * @dev: generic device to remove
+ *
+ * This call removes the visibility of the device (to the user from
+ * sysfs), but does not destroy it.  To eliminate a device entirely
+ * you must also call transport_destroy_device.  If you don't need to
+ * do remove and destroy as separate operations, use
+ * transport_unregister_device() (see transport_class.h) which will
+ * perform both calls for you.
+ */
+void transport_remove_device(struct device *dev)
+{
+	attribute_container_device_trigger(dev, transport_remove_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_remove_device);
+
+static void transport_destroy_classdev(struct attribute_container *cont,
+				      struct device *dev,
+				      struct class_device *classdev)
+{
+	struct transport_class *tclass = class_to_transport_class(cont->class);
+
+	if (tclass->remove != anon_transport_dummy_function)
+		class_device_put(classdev);
+}
+
+
+/**
+ * transport_destroy_device - destroy a removed device
+ *
+ * @dev: device to eliminate from the transport class.
+ *
+ * This call triggers the elimination of storage associated with the
+ * transport classdev.  Note: all it really does is relinquish a
+ * reference to the classdev.  The memory will not be freed until the
+ * last reference goes to zero.  Note also that the classdev retains a
+ * reference count on dev, so dev too will remain for as long as the
+ * transport class device remains around.
+ */
+void transport_destroy_device(struct device *dev)
+{
+	attribute_container_remove_device(dev, transport_destroy_classdev);
+}
+EXPORT_SYMBOL_GPL(transport_destroy_device);
diff --git a/kernel_patches/backport/2.6.16_sles10/iscsi_scsi_makefile.patch b/kernel_patches/backport/2.6.16_sles10/iscsi_scsi_makefile.patch
new file mode 100644
index 0000000..30b6f0e
--- /dev/null
+++ b/kernel_patches/backport/2.6.16_sles10/iscsi_scsi_makefile.patch
@@ -0,0 +1,9 @@
+diff -ruN ofa_1_2_kernel-20061228-0200/drivers/scsi/Makefile ofa_1_2_kernel-20061228-0200-open-iscsi/drivers/scsi/Makefile
+--- ofa_1_2_kernel-20061228-0200/drivers/scsi/Makefile  1970-01-01 02:00:00.000000000 +0200
++++ ofa_1_2_kernel-20061228-0200-open-iscsi/drivers/scsi/Makefile       2006-12-28 17:01:22.000000000 +0200
+@@ -0,0 +1,5 @@
++obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
++obj-$(CONFIG_ISCSI_TCP)        += libiscsi.o   iscsi_tcp.o
++
++scsi_transport_iscsi-y := scsi_transport_iscsi_f.o
++libiscsi-y             := libiscsi_f.o
diff --git a/kernel_patches/backport/2.6.16_sles10_sp1/iscsi_scsi_makefile.patch b/kernel_patches/backport/2.6.16_sles10_sp1/iscsi_scsi_makefile.patch
new file mode 100644
index 0000000..30b6f0e
--- /dev/null
+++ b/kernel_patches/backport/2.6.16_sles10_sp1/iscsi_scsi_makefile.patch
@@ -0,0 +1,9 @@
+diff -ruN ofa_1_2_kernel-20061228-0200/drivers/scsi/Makefile ofa_1_2_kernel-20061228-0200-open-iscsi/drivers/scsi/Makefile
+--- ofa_1_2_kernel-20061228-0200/drivers/scsi/Makefile  1970-01-01 02:00:00.000000000 +0200
++++ ofa_1_2_kernel-20061228-0200-open-iscsi/drivers/scsi/Makefile       2006-12-28 17:01:22.000000000 +0200
+@@ -0,0 +1,5 @@
++obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
++obj-$(CONFIG_ISCSI_TCP)        += libiscsi.o   iscsi_tcp.o
++
++scsi_transport_iscsi-y := scsi_transport_iscsi_f.o
++libiscsi-y             := libiscsi_f.o
diff --git a/kernel_patches/backport/2.6.18/iscsi_scsi_makefile.patch b/kernel_patches/backport/2.6.18/iscsi_scsi_makefile.patch
new file mode 100644
index 0000000..30b6f0e
--- /dev/null
+++ b/kernel_patches/backport/2.6.18/iscsi_scsi_makefile.patch
@@ -0,0 +1,9 @@
+diff -ruN ofa_1_2_kernel-20061228-0200/drivers/scsi/Makefile ofa_1_2_kernel-20061228-0200-open-iscsi/drivers/scsi/Makefile
+--- ofa_1_2_kernel-20061228-0200/drivers/scsi/Makefile  1970-01-01 02:00:00.000000000 +0200
++++ ofa_1_2_kernel-20061228-0200-open-iscsi/drivers/scsi/Makefile       2006-12-28 17:01:22.000000000 +0200
+@@ -0,0 +1,5 @@
++obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
++obj-$(CONFIG_ISCSI_TCP)        += libiscsi.o   iscsi_tcp.o
++
++scsi_transport_iscsi-y := scsi_transport_iscsi_f.o
++libiscsi-y             := libiscsi_f.o
diff --git a/kernel_patches/backport/2.6.9_U3/add_open_iscsi.patch b/kernel_patches/backport/2.6.9_U3/add_open_iscsi.patch
new file mode 100644
index 0000000..a339163
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U3/add_open_iscsi.patch
@@ -0,0 +1,270 @@
+diff -rup linux-2.6.20/drivers/scsi/iscsi_tcp.c linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.c
+--- linux-2.6.20/drivers/scsi/iscsi_tcp.c	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.c	2007-05-17 16:55:43.000000000 +0300
+@@ -676,7 +676,7 @@ iscsi_tcp_copy(struct iscsi_conn *conn, 
+ }
+ 
+ static inline void
+-partial_sg_digest_update(struct hash_desc *desc, struct scatterlist *sg,
++partial_sg_digest_update(struct crypto_tfm *desc, struct scatterlist *sg,
+ 			 int offset, int length)
+ {
+ 	struct scatterlist temp;
+@@ -684,7 +684,7 @@ partial_sg_digest_update(struct hash_des
+ 	memcpy(&temp, sg, sizeof(struct scatterlist));
+ 	temp.offset = offset;
+ 	temp.length = length;
+-	crypto_hash_update(desc, &temp, length);
++	crypto_hash_update(&desc, &temp, length);
+ }
+ 
+ static void
+@@ -1774,22 +1774,18 @@ iscsi_tcp_conn_create(struct iscsi_cls_s
+ 	/* initial operational parameters */
+ 	tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
+ 
+-	tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+-						  CRYPTO_ALG_ASYNC);
+-	tcp_conn->tx_hash.flags = 0;
+-	if (IS_ERR(tcp_conn->tx_hash.tfm))
++	tcp_conn->tx_hash = crypto_alloc_tfm("crc32c", 0);
++	if (!tcp_conn->tx_hash)
+ 		goto free_tcp_conn;
+ 
+-	tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+-						  CRYPTO_ALG_ASYNC);
+-	tcp_conn->rx_hash.flags = 0;
+-	if (IS_ERR(tcp_conn->rx_hash.tfm))
++	tcp_conn->rx_hash = crypto_alloc_tfm("crc32c", 0);
++	if (!tcp_conn->rx_hash)
+ 		goto free_tx_tfm;
+ 
+ 	return cls_conn;
+ 
+ free_tx_tfm:
+-	crypto_free_hash(tcp_conn->tx_hash.tfm);
++	crypto_free_tfm(tcp_conn->tx_hash);
+ free_tcp_conn:
+ 	kfree(tcp_conn);
+ tcp_conn_alloc_fail:
+@@ -1823,10 +1819,10 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_
+ 	iscsi_tcp_release_conn(conn);
+ 	iscsi_conn_teardown(cls_conn);
+ 
+-	if (tcp_conn->tx_hash.tfm)
+-		crypto_free_hash(tcp_conn->tx_hash.tfm);
+-	if (tcp_conn->rx_hash.tfm)
+-		crypto_free_hash(tcp_conn->rx_hash.tfm);
++	if (tcp_conn->tx_hash)
++		crypto_free_tfm(tcp_conn->tx_hash);
++	if (tcp_conn->rx_hash)
++		crypto_free_tfm(tcp_conn->rx_hash);
+ 
+ 	kfree(tcp_conn);
+ }
+@@ -2017,7 +2013,7 @@ iscsi_tcp_conn_get_param(struct iscsi_cl
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct inet_sock *inet;
++	struct inet_opt *inet;
+ 	struct ipv6_pinfo *np;
+ 	struct sock *sk;
+ 	int len;
+@@ -2135,7 +2131,6 @@ static void iscsi_tcp_session_destroy(st
+ static struct scsi_host_template iscsi_sht = {
+ 	.name			= "iSCSI Initiator over TCP/IP",
+ 	.queuecommand           = iscsi_queuecommand,
+-	.change_queue_depth	= iscsi_change_queue_depth,
+ 	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
+ 	.sg_tablesize		= ISCSI_SG_TABLESIZE,
+ 	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
+diff -rup linux-2.6.20/drivers/scsi/iscsi_tcp.h linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.h
+--- linux-2.6.20/drivers/scsi/iscsi_tcp.h	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.h	2007-05-17 16:38:14.000000000 +0300
+@@ -49,7 +49,6 @@
+ #define ISCSI_SG_TABLESIZE		SG_ALL
+ #define ISCSI_TCP_MAX_CMD_LEN		16
+ 
+-struct crypto_hash;
+ struct socket;
+ 
+ /* Socket connection recieve helper */
+@@ -93,8 +92,8 @@ struct iscsi_tcp_conn {
+ 	void			(*old_write_space)(struct sock *);
+ 
+ 	/* data and header digests */
+-	struct hash_desc	tx_hash;	/* CRC32C (Tx) */
+-	struct hash_desc	rx_hash;	/* CRC32C (Rx) */
++	struct crypto_tfm	*tx_hash;	/* CRC32C (Tx) */
++	struct crypto_tfm	*rx_hash;	/* CRC32C (Rx) */
+ 
+ 	/* MIB custom statistics */
+ 	uint32_t		sendpage_failures_cnt;
+diff -rup linux-2.6.20/drivers/scsi/libiscsi.c linux-2.6.20-rh4-backport/drivers/scsi/libiscsi.c
+--- linux-2.6.20/drivers/scsi/libiscsi.c	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/libiscsi.c	2007-05-17 16:38:14.000000000 +0300
+@@ -1370,7 +1370,6 @@ iscsi_session_setup(struct iscsi_transpo
+ 	shost->max_lun = iscsit->max_lun;
+ 	shost->max_cmd_len = iscsit->max_cmd_len;
+ 	shost->transportt = scsit;
+-	shost->transportt->create_work_queue = 1;
+ 	*hostno = shost->host_no;
+ 
+ 	session = iscsi_hostdata(shost->hostdata);
+diff -rup linux-2.6.20/drivers/scsi/scsi_transport_iscsi.c linux-2.6.20-rh4-backport/drivers/scsi/scsi_transport_iscsi.c
+--- linux-2.6.20/drivers/scsi/scsi_transport_iscsi.c	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/scsi_transport_iscsi.c	2007-05-17 16:38:14.000000000 +0300
+@@ -65,6 +65,8 @@ static DEFINE_SPINLOCK(iscsi_transport_l
+ #define cdev_to_iscsi_internal(_cdev) \
+ 	container_of(_cdev, struct iscsi_internal, cdev)
+ 
++extern int attribute_container_init(void);
++
+ static void iscsi_transport_release(struct class_device *cdev)
+ {
+ 	struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
+@@ -80,6 +82,17 @@ static struct class iscsi_transport_clas
+ 	.release = iscsi_transport_release,
+ };
+ 
++static void iscsi_host_class_release(struct class_device *class_dev)
++{
++	struct Scsi_Host *shost = transport_class_to_shost(class_dev);
++	put_device(&shost->shost_gendev);
++}
++
++struct class iscsi_host_class = {
++	.name = "iscsi_host",
++	.release = iscsi_host_class_release,
++};
++
+ static ssize_t
+ show_transport_handle(struct class_device *cdev, char *buf)
+ {
+@@ -115,10 +128,8 @@ static struct attribute_group iscsi_tran
+ 	.attrs = iscsi_transport_attrs,
+ };
+ 
+-static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+-			    struct class_device *cdev)
++static int iscsi_setup_host(struct Scsi_Host *shost)
+ {
+-	struct Scsi_Host *shost = dev_to_shost(dev);
+ 	struct iscsi_host *ihost = shost->shost_data;
+ 
+ 	memset(ihost, 0, sizeof(*ihost));
+@@ -127,12 +138,6 @@ static int iscsi_setup_host(struct trans
+ 	return 0;
+ }
+ 
+-static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
+-			       "iscsi_host",
+-			       iscsi_setup_host,
+-			       NULL,
+-			       NULL);
+-
+ static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
+ 			       "iscsi_session",
+ 			       NULL,
+@@ -216,24 +221,6 @@ static int iscsi_is_session_dev(const st
+ 	return dev->release == iscsi_session_release;
+ }
+ 
+-static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
+-			   uint id, uint lun)
+-{
+-	struct iscsi_host *ihost = shost->shost_data;
+-	struct iscsi_cls_session *session;
+-
+-	mutex_lock(&ihost->mutex);
+-	list_for_each_entry(session, &ihost->sessions, host_list) {
+-		if ((channel == SCAN_WILD_CARD || channel == 0) &&
+-		    (id == SCAN_WILD_CARD || id == session->target_id))
+-			scsi_scan_target(&session->dev, 0,
+-					 session->target_id, lun, 1);
+-	}
+-	mutex_unlock(&ihost->mutex);
+-
+-	return 0;
+-}
+-
+ static void session_recovery_timedout(struct work_struct *work)
+ {
+ 	struct iscsi_cls_session *session =
+@@ -362,8 +349,6 @@ void iscsi_remove_session(struct iscsi_c
+ 	list_del(&session->host_list);
+ 	mutex_unlock(&ihost->mutex);
+ 
+-	scsi_remove_target(&session->dev);
+-
+ 	transport_unregister_device(&session->dev);
+ 	device_del(&session->dev);
+ }
+@@ -1269,24 +1254,6 @@ static int iscsi_conn_match(struct attri
+ 	return &priv->conn_cont.ac == cont;
+ }
+ 
+-static int iscsi_host_match(struct attribute_container *cont,
+-			    struct device *dev)
+-{
+-	struct Scsi_Host *shost;
+-	struct iscsi_internal *priv;
+-
+-	if (!scsi_is_host_device(dev))
+-		return 0;
+-
+-	shost = dev_to_shost(dev);
+-	if (!shost->transportt  ||
+-	    shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
+-		return 0;
+-
+-        priv = to_iscsi_internal(shost->transportt);
+-        return &priv->t.host_attrs.ac == cont;
+-}
+-
+ struct scsi_transport_template *
+ iscsi_register_transport(struct iscsi_transport *tt)
+ {
+@@ -1306,7 +1273,6 @@ iscsi_register_transport(struct iscsi_tr
+ 	INIT_LIST_HEAD(&priv->list);
+ 	priv->daemon_pid = -1;
+ 	priv->iscsi_transport = tt;
+-	priv->t.user_scan = iscsi_user_scan;
+ 
+ 	priv->cdev.class = &iscsi_transport_class;
+ 	snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name);
+@@ -1319,12 +1285,11 @@ iscsi_register_transport(struct iscsi_tr
+ 		goto unregister_cdev;
+ 
+ 	/* host parameters */
+-	priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
+-	priv->t.host_attrs.ac.class = &iscsi_host_class.class;
+-	priv->t.host_attrs.ac.match = iscsi_host_match;
++
++	priv->t.host_attrs = &priv->host_attrs[0];
++	priv->t.host_class = &iscsi_host_class;
++	priv->t.host_setup = iscsi_setup_host;
+ 	priv->t.host_size = sizeof(struct iscsi_host);
+-	priv->host_attrs[0] = NULL;
+-	transport_container_register(&priv->t.host_attrs);
+ 
+ 	/* connection parameters */
+ 	priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
+@@ -1402,7 +1367,6 @@ int iscsi_unregister_transport(struct is
+ 
+ 	transport_container_unregister(&priv->conn_cont);
+ 	transport_container_unregister(&priv->session_cont);
+-	transport_container_unregister(&priv->t.host_attrs);
+ 
+ 	sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
+ 	class_device_unregister(&priv->cdev);
+@@ -1419,6 +1383,8 @@ static __init int iscsi_transport_init(v
+ 	printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
+ 		ISCSI_TRANSPORT_VERSION);
+ 
++	attribute_container_init();
++
+ 	err = class_register(&iscsi_transport_class);
+ 	if (err)
+ 		return err;
diff --git a/kernel_patches/backport/2.6.9_U3/add_open_iscsi_h.patch b/kernel_patches/backport/2.6.9_U3/add_open_iscsi_h.patch
new file mode 100644
index 0000000..21715fd
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U3/add_open_iscsi_h.patch
@@ -0,0 +1,35 @@
+diff -rup linux-2.6.20/include/scsi/iscsi_if.h linux-2.6.20-rh4-backport/include/scsi/iscsi_if.h
+--- linux-2.6.20/include/scsi/iscsi_if.h	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/iscsi_if.h	2007-05-15 08:49:53.000000000 +0300
+@@ -277,7 +277,6 @@ enum iscsi_param {
+  * These flags describes reason of stop_conn() call
+  */
+ #define STOP_CONN_TERM		0x1
+-#define STOP_CONN_SUSPEND	0x2
+ #define STOP_CONN_RECOVER	0x3
+ 
+ #define ISCSI_STATS_CUSTOM_MAX		32
+diff -rup linux-2.6.20/include/scsi/libiscsi.h linux-2.6.20-rh4-backport/include/scsi/libiscsi.h
+--- linux-2.6.20/include/scsi/libiscsi.h	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/libiscsi.h	2007-05-15 08:54:49.000000000 +0300
+@@ -25,8 +25,6 @@
+ 
+ #include <linux/types.h>
+ #include <linux/mutex.h>
+-#include <linux/timer.h>
+-#include <linux/workqueue.h>
+ #include <scsi/iscsi_proto.h>
+ #include <scsi/iscsi_if.h>
+ 
+diff -rup linux-2.6.20/include/scsi/scsi_transport_iscsi.h linux-2.6.20-rh4-backport/include/scsi/scsi_transport_iscsi.h
+--- linux-2.6.20/include/scsi/scsi_transport_iscsi.h	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/scsi_transport_iscsi.h	2007-05-15 08:54:24.000000000 +0300
+@@ -24,7 +24,7 @@
+ #define SCSI_TRANSPORT_ISCSI_H
+ 
+ #include <linux/device.h>
+-#include <scsi/iscsi_if.h>
++#include "iscsi_if.h"
+ 
+ struct scsi_transport_template;
+ struct iscsi_transport;
diff --git a/kernel_patches/backport/2.6.9_U3/fix_inclusion_order_iscsi_iser.patch b/kernel_patches/backport/2.6.9_U3/fix_inclusion_order_iscsi_iser.patch
new file mode 100644
index 0000000..3c2a969
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U3/fix_inclusion_order_iscsi_iser.patch
@@ -0,0 +1,13 @@
+--- linux-2.6.20-rc7-orig/drivers/infiniband/ulp/iser/iscsi_iser.c	2007-02-08 09:13:43.000000000 +0200
++++ linux-2.6.20-rc7/drivers/infiniband/ulp/iser/iscsi_iser.c	2007-02-08 09:14:31.000000000 +0200
+@@ -70,9 +70,8 @@
+ #include <scsi/scsi_tcq.h>
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi.h>
+-#include <scsi/scsi_transport_iscsi.h>
+-
+ #include "iscsi_iser.h"
++#include <scsi/scsi_transport_iscsi.h>
+ 
+ static unsigned int iscsi_max_lun = 512;
+ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
diff --git a/kernel_patches/backport/2.6.9_U3/iscsi_scsi_addons.patch b/kernel_patches/backport/2.6.9_U3/iscsi_scsi_addons.patch
new file mode 100644
index 0000000..ffa0598
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U3/iscsi_scsi_addons.patch
@@ -0,0 +1,65 @@
+diff --git a/drivers/scsi/init.c b/drivers/scsi/init.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/init.c
+@@ -0,0 +1 @@
++#include "src/init.c"
+diff --git a/drivers/scsi/attribute_container.c b/drivers/scsi/attribute_container.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/attribute_container.c
+@@ -0,0 +1 @@
++#include "src/attribute_container.c"
+diff --git a/drivers/scsi/transport_class.c b/drivers/scsi/transport_class.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/transport_class.c
+@@ -0,0 +1 @@
++#include "src/transport_class.c"
+diff --git a/drivers/scsi/klist.c b/drivers/scsi/klist.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/klist.c
+@@ -0,0 +1 @@
++#include "src/klist.c"
+diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi.c
+@@ -0,0 +1 @@
++#include "src/scsi.c"
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi_lib.c
+@@ -0,0 +1 @@
++#include "src/scsi_lib.c"
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi_scan.c
+@@ -0,0 +1 @@
++#include "src/scsi_scan.c"
+diff --git a/drivers/scsi/kref_new.c b/drivers/scsi/kref_new.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/kref_new.c
+@@ -0,0 +1 @@
++#include "src/kref_new.c"
+diff -rupN ofa_kernel-1.2/drivers/scsi/Makefile ofa_kernel-1.2-iscsi/drivers/scsi/Makefile
+--- ofa_kernel-1.2/drivers/scsi/Makefile	1970-01-01 02:00:00.000000000 +0200
++++ ofa_kernel-1.2-iscsi/drivers/scsi/Makefile	2007-05-16 14:12:22.000000000 +0300
+@@ -0,0 +1,5 @@
++obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
++obj-$(CONFIG_ISCSI_TCP)        += libiscsi.o   iscsi_tcp.o
++
++scsi_transport_iscsi-y	:= scsi_transport_iscsi_f.o scsi.o scsi_lib.o init.o kref_new.o klist.o attribute_container.o transport_class.o
++libiscsi-y		:= libiscsi_f.o scsi_scan.o
diff --git a/kernel_patches/backport/2.6.9_U4/add_open_iscsi.patch b/kernel_patches/backport/2.6.9_U4/add_open_iscsi.patch
new file mode 100644
index 0000000..a339163
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U4/add_open_iscsi.patch
@@ -0,0 +1,270 @@
+diff -rup linux-2.6.20/drivers/scsi/iscsi_tcp.c linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.c
+--- linux-2.6.20/drivers/scsi/iscsi_tcp.c	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.c	2007-05-17 16:55:43.000000000 +0300
+@@ -676,7 +676,7 @@ iscsi_tcp_copy(struct iscsi_conn *conn, 
+ }
+ 
+ static inline void
+-partial_sg_digest_update(struct hash_desc *desc, struct scatterlist *sg,
++partial_sg_digest_update(struct crypto_tfm *desc, struct scatterlist *sg,
+ 			 int offset, int length)
+ {
+ 	struct scatterlist temp;
+@@ -684,7 +684,7 @@ partial_sg_digest_update(struct hash_des
+ 	memcpy(&temp, sg, sizeof(struct scatterlist));
+ 	temp.offset = offset;
+ 	temp.length = length;
+-	crypto_hash_update(desc, &temp, length);
++	crypto_hash_update(&desc, &temp, length);
+ }
+ 
+ static void
+@@ -1774,22 +1774,18 @@ iscsi_tcp_conn_create(struct iscsi_cls_s
+ 	/* initial operational parameters */
+ 	tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
+ 
+-	tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+-						  CRYPTO_ALG_ASYNC);
+-	tcp_conn->tx_hash.flags = 0;
+-	if (IS_ERR(tcp_conn->tx_hash.tfm))
++	tcp_conn->tx_hash = crypto_alloc_tfm("crc32c", 0);
++	if (!tcp_conn->tx_hash)
+ 		goto free_tcp_conn;
+ 
+-	tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+-						  CRYPTO_ALG_ASYNC);
+-	tcp_conn->rx_hash.flags = 0;
+-	if (IS_ERR(tcp_conn->rx_hash.tfm))
++	tcp_conn->rx_hash = crypto_alloc_tfm("crc32c", 0);
++	if (!tcp_conn->rx_hash)
+ 		goto free_tx_tfm;
+ 
+ 	return cls_conn;
+ 
+ free_tx_tfm:
+-	crypto_free_hash(tcp_conn->tx_hash.tfm);
++	crypto_free_tfm(tcp_conn->tx_hash);
+ free_tcp_conn:
+ 	kfree(tcp_conn);
+ tcp_conn_alloc_fail:
+@@ -1823,10 +1819,10 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_
+ 	iscsi_tcp_release_conn(conn);
+ 	iscsi_conn_teardown(cls_conn);
+ 
+-	if (tcp_conn->tx_hash.tfm)
+-		crypto_free_hash(tcp_conn->tx_hash.tfm);
+-	if (tcp_conn->rx_hash.tfm)
+-		crypto_free_hash(tcp_conn->rx_hash.tfm);
++	if (tcp_conn->tx_hash)
++		crypto_free_tfm(tcp_conn->tx_hash);
++	if (tcp_conn->rx_hash)
++		crypto_free_tfm(tcp_conn->rx_hash);
+ 
+ 	kfree(tcp_conn);
+ }
+@@ -2017,7 +2013,7 @@ iscsi_tcp_conn_get_param(struct iscsi_cl
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct inet_sock *inet;
++	struct inet_opt *inet;
+ 	struct ipv6_pinfo *np;
+ 	struct sock *sk;
+ 	int len;
+@@ -2135,7 +2131,6 @@ static void iscsi_tcp_session_destroy(st
+ static struct scsi_host_template iscsi_sht = {
+ 	.name			= "iSCSI Initiator over TCP/IP",
+ 	.queuecommand           = iscsi_queuecommand,
+-	.change_queue_depth	= iscsi_change_queue_depth,
+ 	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
+ 	.sg_tablesize		= ISCSI_SG_TABLESIZE,
+ 	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
+diff -rup linux-2.6.20/drivers/scsi/iscsi_tcp.h linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.h
+--- linux-2.6.20/drivers/scsi/iscsi_tcp.h	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.h	2007-05-17 16:38:14.000000000 +0300
+@@ -49,7 +49,6 @@
+ #define ISCSI_SG_TABLESIZE		SG_ALL
+ #define ISCSI_TCP_MAX_CMD_LEN		16
+ 
+-struct crypto_hash;
+ struct socket;
+ 
+ /* Socket connection recieve helper */
+@@ -93,8 +92,8 @@ struct iscsi_tcp_conn {
+ 	void			(*old_write_space)(struct sock *);
+ 
+ 	/* data and header digests */
+-	struct hash_desc	tx_hash;	/* CRC32C (Tx) */
+-	struct hash_desc	rx_hash;	/* CRC32C (Rx) */
++	struct crypto_tfm	*tx_hash;	/* CRC32C (Tx) */
++	struct crypto_tfm	*rx_hash;	/* CRC32C (Rx) */
+ 
+ 	/* MIB custom statistics */
+ 	uint32_t		sendpage_failures_cnt;
+diff -rup linux-2.6.20/drivers/scsi/libiscsi.c linux-2.6.20-rh4-backport/drivers/scsi/libiscsi.c
+--- linux-2.6.20/drivers/scsi/libiscsi.c	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/libiscsi.c	2007-05-17 16:38:14.000000000 +0300
+@@ -1370,7 +1370,6 @@ iscsi_session_setup(struct iscsi_transpo
+ 	shost->max_lun = iscsit->max_lun;
+ 	shost->max_cmd_len = iscsit->max_cmd_len;
+ 	shost->transportt = scsit;
+-	shost->transportt->create_work_queue = 1;
+ 	*hostno = shost->host_no;
+ 
+ 	session = iscsi_hostdata(shost->hostdata);
+diff -rup linux-2.6.20/drivers/scsi/scsi_transport_iscsi.c linux-2.6.20-rh4-backport/drivers/scsi/scsi_transport_iscsi.c
+--- linux-2.6.20/drivers/scsi/scsi_transport_iscsi.c	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/scsi_transport_iscsi.c	2007-05-17 16:38:14.000000000 +0300
+@@ -65,6 +65,8 @@ static DEFINE_SPINLOCK(iscsi_transport_l
+ #define cdev_to_iscsi_internal(_cdev) \
+ 	container_of(_cdev, struct iscsi_internal, cdev)
+ 
++extern int attribute_container_init(void);
++
+ static void iscsi_transport_release(struct class_device *cdev)
+ {
+ 	struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
+@@ -80,6 +82,17 @@ static struct class iscsi_transport_clas
+ 	.release = iscsi_transport_release,
+ };
+ 
++static void iscsi_host_class_release(struct class_device *class_dev)
++{
++	struct Scsi_Host *shost = transport_class_to_shost(class_dev);
++	put_device(&shost->shost_gendev);
++}
++
++struct class iscsi_host_class = {
++	.name = "iscsi_host",
++	.release = iscsi_host_class_release,
++};
++
+ static ssize_t
+ show_transport_handle(struct class_device *cdev, char *buf)
+ {
+@@ -115,10 +128,8 @@ static struct attribute_group iscsi_tran
+ 	.attrs = iscsi_transport_attrs,
+ };
+ 
+-static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+-			    struct class_device *cdev)
++static int iscsi_setup_host(struct Scsi_Host *shost)
+ {
+-	struct Scsi_Host *shost = dev_to_shost(dev);
+ 	struct iscsi_host *ihost = shost->shost_data;
+ 
+ 	memset(ihost, 0, sizeof(*ihost));
+@@ -127,12 +138,6 @@ static int iscsi_setup_host(struct trans
+ 	return 0;
+ }
+ 
+-static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
+-			       "iscsi_host",
+-			       iscsi_setup_host,
+-			       NULL,
+-			       NULL);
+-
+ static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
+ 			       "iscsi_session",
+ 			       NULL,
+@@ -216,24 +221,6 @@ static int iscsi_is_session_dev(const st
+ 	return dev->release == iscsi_session_release;
+ }
+ 
+-static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
+-			   uint id, uint lun)
+-{
+-	struct iscsi_host *ihost = shost->shost_data;
+-	struct iscsi_cls_session *session;
+-
+-	mutex_lock(&ihost->mutex);
+-	list_for_each_entry(session, &ihost->sessions, host_list) {
+-		if ((channel == SCAN_WILD_CARD || channel == 0) &&
+-		    (id == SCAN_WILD_CARD || id == session->target_id))
+-			scsi_scan_target(&session->dev, 0,
+-					 session->target_id, lun, 1);
+-	}
+-	mutex_unlock(&ihost->mutex);
+-
+-	return 0;
+-}
+-
+ static void session_recovery_timedout(struct work_struct *work)
+ {
+ 	struct iscsi_cls_session *session =
+@@ -362,8 +349,6 @@ void iscsi_remove_session(struct iscsi_c
+ 	list_del(&session->host_list);
+ 	mutex_unlock(&ihost->mutex);
+ 
+-	scsi_remove_target(&session->dev);
+-
+ 	transport_unregister_device(&session->dev);
+ 	device_del(&session->dev);
+ }
+@@ -1269,24 +1254,6 @@ static int iscsi_conn_match(struct attri
+ 	return &priv->conn_cont.ac == cont;
+ }
+ 
+-static int iscsi_host_match(struct attribute_container *cont,
+-			    struct device *dev)
+-{
+-	struct Scsi_Host *shost;
+-	struct iscsi_internal *priv;
+-
+-	if (!scsi_is_host_device(dev))
+-		return 0;
+-
+-	shost = dev_to_shost(dev);
+-	if (!shost->transportt  ||
+-	    shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
+-		return 0;
+-
+-        priv = to_iscsi_internal(shost->transportt);
+-        return &priv->t.host_attrs.ac == cont;
+-}
+-
+ struct scsi_transport_template *
+ iscsi_register_transport(struct iscsi_transport *tt)
+ {
+@@ -1306,7 +1273,6 @@ iscsi_register_transport(struct iscsi_tr
+ 	INIT_LIST_HEAD(&priv->list);
+ 	priv->daemon_pid = -1;
+ 	priv->iscsi_transport = tt;
+-	priv->t.user_scan = iscsi_user_scan;
+ 
+ 	priv->cdev.class = &iscsi_transport_class;
+ 	snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name);
+@@ -1319,12 +1285,11 @@ iscsi_register_transport(struct iscsi_tr
+ 		goto unregister_cdev;
+ 
+ 	/* host parameters */
+-	priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
+-	priv->t.host_attrs.ac.class = &iscsi_host_class.class;
+-	priv->t.host_attrs.ac.match = iscsi_host_match;
++
++	priv->t.host_attrs = &priv->host_attrs[0];
++	priv->t.host_class = &iscsi_host_class;
++	priv->t.host_setup = iscsi_setup_host;
+ 	priv->t.host_size = sizeof(struct iscsi_host);
+-	priv->host_attrs[0] = NULL;
+-	transport_container_register(&priv->t.host_attrs);
+ 
+ 	/* connection parameters */
+ 	priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
+@@ -1402,7 +1367,6 @@ int iscsi_unregister_transport(struct is
+ 
+ 	transport_container_unregister(&priv->conn_cont);
+ 	transport_container_unregister(&priv->session_cont);
+-	transport_container_unregister(&priv->t.host_attrs);
+ 
+ 	sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
+ 	class_device_unregister(&priv->cdev);
+@@ -1419,6 +1383,8 @@ static __init int iscsi_transport_init(v
+ 	printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
+ 		ISCSI_TRANSPORT_VERSION);
+ 
++	attribute_container_init();
++
+ 	err = class_register(&iscsi_transport_class);
+ 	if (err)
+ 		return err;
diff --git a/kernel_patches/backport/2.6.9_U4/add_open_iscsi_h.patch b/kernel_patches/backport/2.6.9_U4/add_open_iscsi_h.patch
new file mode 100644
index 0000000..21715fd
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U4/add_open_iscsi_h.patch
@@ -0,0 +1,35 @@
+diff -rup linux-2.6.20/include/scsi/iscsi_if.h linux-2.6.20-rh4-backport/include/scsi/iscsi_if.h
+--- linux-2.6.20/include/scsi/iscsi_if.h	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/iscsi_if.h	2007-05-15 08:49:53.000000000 +0300
+@@ -277,7 +277,6 @@ enum iscsi_param {
+  * These flags describes reason of stop_conn() call
+  */
+ #define STOP_CONN_TERM		0x1
+-#define STOP_CONN_SUSPEND	0x2
+ #define STOP_CONN_RECOVER	0x3
+ 
+ #define ISCSI_STATS_CUSTOM_MAX		32
+diff -rup linux-2.6.20/include/scsi/libiscsi.h linux-2.6.20-rh4-backport/include/scsi/libiscsi.h
+--- linux-2.6.20/include/scsi/libiscsi.h	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/libiscsi.h	2007-05-15 08:54:49.000000000 +0300
+@@ -25,8 +25,6 @@
+ 
+ #include <linux/types.h>
+ #include <linux/mutex.h>
+-#include <linux/timer.h>
+-#include <linux/workqueue.h>
+ #include <scsi/iscsi_proto.h>
+ #include <scsi/iscsi_if.h>
+ 
+diff -rup linux-2.6.20/include/scsi/scsi_transport_iscsi.h linux-2.6.20-rh4-backport/include/scsi/scsi_transport_iscsi.h
+--- linux-2.6.20/include/scsi/scsi_transport_iscsi.h	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/scsi_transport_iscsi.h	2007-05-15 08:54:24.000000000 +0300
+@@ -24,7 +24,7 @@
+ #define SCSI_TRANSPORT_ISCSI_H
+ 
+ #include <linux/device.h>
+-#include <scsi/iscsi_if.h>
++#include "iscsi_if.h"
+ 
+ struct scsi_transport_template;
+ struct iscsi_transport;
diff --git a/kernel_patches/backport/2.6.9_U4/fix_inclusion_order_iscsi_iser.patch b/kernel_patches/backport/2.6.9_U4/fix_inclusion_order_iscsi_iser.patch
new file mode 100644
index 0000000..3c2a969
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U4/fix_inclusion_order_iscsi_iser.patch
@@ -0,0 +1,13 @@
+--- linux-2.6.20-rc7-orig/drivers/infiniband/ulp/iser/iscsi_iser.c	2007-02-08 09:13:43.000000000 +0200
++++ linux-2.6.20-rc7/drivers/infiniband/ulp/iser/iscsi_iser.c	2007-02-08 09:14:31.000000000 +0200
+@@ -70,9 +70,8 @@
+ #include <scsi/scsi_tcq.h>
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi.h>
+-#include <scsi/scsi_transport_iscsi.h>
+-
+ #include "iscsi_iser.h"
++#include <scsi/scsi_transport_iscsi.h>
+ 
+ static unsigned int iscsi_max_lun = 512;
+ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
diff --git a/kernel_patches/backport/2.6.9_U4/iscsi_scsi_addons.patch b/kernel_patches/backport/2.6.9_U4/iscsi_scsi_addons.patch
new file mode 100644
index 0000000..ffa0598
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U4/iscsi_scsi_addons.patch
@@ -0,0 +1,65 @@
+diff --git a/drivers/scsi/init.c b/drivers/scsi/init.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/init.c
+@@ -0,0 +1 @@
++#include "src/init.c"
+diff --git a/drivers/scsi/attribute_container.c b/drivers/scsi/attribute_container.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/attribute_container.c
+@@ -0,0 +1 @@
++#include "src/attribute_container.c"
+diff --git a/drivers/scsi/transport_class.c b/drivers/scsi/transport_class.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/transport_class.c
+@@ -0,0 +1 @@
++#include "src/transport_class.c"
+diff --git a/drivers/scsi/klist.c b/drivers/scsi/klist.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/klist.c
+@@ -0,0 +1 @@
++#include "src/klist.c"
+diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi.c
+@@ -0,0 +1 @@
++#include "src/scsi.c"
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi_lib.c
+@@ -0,0 +1 @@
++#include "src/scsi_lib.c"
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi_scan.c
+@@ -0,0 +1 @@
++#include "src/scsi_scan.c"
+diff --git a/drivers/scsi/kref_new.c b/drivers/scsi/kref_new.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/kref_new.c
+@@ -0,0 +1 @@
++#include "src/kref_new.c"
+diff -rupN ofa_kernel-1.2/drivers/scsi/Makefile ofa_kernel-1.2-iscsi/drivers/scsi/Makefile
+--- ofa_kernel-1.2/drivers/scsi/Makefile	1970-01-01 02:00:00.000000000 +0200
++++ ofa_kernel-1.2-iscsi/drivers/scsi/Makefile	2007-05-16 14:12:22.000000000 +0300
+@@ -0,0 +1,5 @@
++obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
++obj-$(CONFIG_ISCSI_TCP)        += libiscsi.o   iscsi_tcp.o
++
++scsi_transport_iscsi-y	:= scsi_transport_iscsi_f.o scsi.o scsi_lib.o init.o kref_new.o klist.o attribute_container.o transport_class.o
++libiscsi-y		:= libiscsi_f.o scsi_scan.o
diff --git a/kernel_patches/backport/2.6.9_U5/add_open_iscsi.patch b/kernel_patches/backport/2.6.9_U5/add_open_iscsi.patch
new file mode 100644
index 0000000..a339163
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U5/add_open_iscsi.patch
@@ -0,0 +1,270 @@
+diff -rup linux-2.6.20/drivers/scsi/iscsi_tcp.c linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.c
+--- linux-2.6.20/drivers/scsi/iscsi_tcp.c	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.c	2007-05-17 16:55:43.000000000 +0300
+@@ -676,7 +676,7 @@ iscsi_tcp_copy(struct iscsi_conn *conn, 
+ }
+ 
+ static inline void
+-partial_sg_digest_update(struct hash_desc *desc, struct scatterlist *sg,
++partial_sg_digest_update(struct crypto_tfm *desc, struct scatterlist *sg,
+ 			 int offset, int length)
+ {
+ 	struct scatterlist temp;
+@@ -684,7 +684,7 @@ partial_sg_digest_update(struct hash_des
+ 	memcpy(&temp, sg, sizeof(struct scatterlist));
+ 	temp.offset = offset;
+ 	temp.length = length;
+-	crypto_hash_update(desc, &temp, length);
++	crypto_hash_update(&desc, &temp, length);
+ }
+ 
+ static void
+@@ -1774,22 +1774,18 @@ iscsi_tcp_conn_create(struct iscsi_cls_s
+ 	/* initial operational parameters */
+ 	tcp_conn->hdr_size = sizeof(struct iscsi_hdr);
+ 
+-	tcp_conn->tx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+-						  CRYPTO_ALG_ASYNC);
+-	tcp_conn->tx_hash.flags = 0;
+-	if (IS_ERR(tcp_conn->tx_hash.tfm))
++	tcp_conn->tx_hash = crypto_alloc_tfm("crc32c", 0);
++	if (!tcp_conn->tx_hash)
+ 		goto free_tcp_conn;
+ 
+-	tcp_conn->rx_hash.tfm = crypto_alloc_hash("crc32c", 0,
+-						  CRYPTO_ALG_ASYNC);
+-	tcp_conn->rx_hash.flags = 0;
+-	if (IS_ERR(tcp_conn->rx_hash.tfm))
++	tcp_conn->rx_hash = crypto_alloc_tfm("crc32c", 0);
++	if (!tcp_conn->rx_hash)
+ 		goto free_tx_tfm;
+ 
+ 	return cls_conn;
+ 
+ free_tx_tfm:
+-	crypto_free_hash(tcp_conn->tx_hash.tfm);
++	crypto_free_tfm(tcp_conn->tx_hash);
+ free_tcp_conn:
+ 	kfree(tcp_conn);
+ tcp_conn_alloc_fail:
+@@ -1823,10 +1819,10 @@ iscsi_tcp_conn_destroy(struct iscsi_cls_
+ 	iscsi_tcp_release_conn(conn);
+ 	iscsi_conn_teardown(cls_conn);
+ 
+-	if (tcp_conn->tx_hash.tfm)
+-		crypto_free_hash(tcp_conn->tx_hash.tfm);
+-	if (tcp_conn->rx_hash.tfm)
+-		crypto_free_hash(tcp_conn->rx_hash.tfm);
++	if (tcp_conn->tx_hash)
++		crypto_free_tfm(tcp_conn->tx_hash);
++	if (tcp_conn->rx_hash)
++		crypto_free_tfm(tcp_conn->rx_hash);
+ 
+ 	kfree(tcp_conn);
+ }
+@@ -2017,7 +2013,7 @@ iscsi_tcp_conn_get_param(struct iscsi_cl
+ {
+ 	struct iscsi_conn *conn = cls_conn->dd_data;
+ 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+-	struct inet_sock *inet;
++	struct inet_opt *inet;
+ 	struct ipv6_pinfo *np;
+ 	struct sock *sk;
+ 	int len;
+@@ -2135,7 +2131,6 @@ static void iscsi_tcp_session_destroy(st
+ static struct scsi_host_template iscsi_sht = {
+ 	.name			= "iSCSI Initiator over TCP/IP",
+ 	.queuecommand           = iscsi_queuecommand,
+-	.change_queue_depth	= iscsi_change_queue_depth,
+ 	.can_queue		= ISCSI_XMIT_CMDS_MAX - 1,
+ 	.sg_tablesize		= ISCSI_SG_TABLESIZE,
+ 	.cmd_per_lun		= ISCSI_DEF_CMD_PER_LUN,
+diff -rup linux-2.6.20/drivers/scsi/iscsi_tcp.h linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.h
+--- linux-2.6.20/drivers/scsi/iscsi_tcp.h	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/iscsi_tcp.h	2007-05-17 16:38:14.000000000 +0300
+@@ -49,7 +49,6 @@
+ #define ISCSI_SG_TABLESIZE		SG_ALL
+ #define ISCSI_TCP_MAX_CMD_LEN		16
+ 
+-struct crypto_hash;
+ struct socket;
+ 
+ /* Socket connection recieve helper */
+@@ -93,8 +92,8 @@ struct iscsi_tcp_conn {
+ 	void			(*old_write_space)(struct sock *);
+ 
+ 	/* data and header digests */
+-	struct hash_desc	tx_hash;	/* CRC32C (Tx) */
+-	struct hash_desc	rx_hash;	/* CRC32C (Rx) */
++	struct crypto_tfm	*tx_hash;	/* CRC32C (Tx) */
++	struct crypto_tfm	*rx_hash;	/* CRC32C (Rx) */
+ 
+ 	/* MIB custom statistics */
+ 	uint32_t		sendpage_failures_cnt;
+diff -rup linux-2.6.20/drivers/scsi/libiscsi.c linux-2.6.20-rh4-backport/drivers/scsi/libiscsi.c
+--- linux-2.6.20/drivers/scsi/libiscsi.c	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/libiscsi.c	2007-05-17 16:38:14.000000000 +0300
+@@ -1370,7 +1370,6 @@ iscsi_session_setup(struct iscsi_transpo
+ 	shost->max_lun = iscsit->max_lun;
+ 	shost->max_cmd_len = iscsit->max_cmd_len;
+ 	shost->transportt = scsit;
+-	shost->transportt->create_work_queue = 1;
+ 	*hostno = shost->host_no;
+ 
+ 	session = iscsi_hostdata(shost->hostdata);
+diff -rup linux-2.6.20/drivers/scsi/scsi_transport_iscsi.c linux-2.6.20-rh4-backport/drivers/scsi/scsi_transport_iscsi.c
+--- linux-2.6.20/drivers/scsi/scsi_transport_iscsi.c	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/drivers/scsi/scsi_transport_iscsi.c	2007-05-17 16:38:14.000000000 +0300
+@@ -65,6 +65,8 @@ static DEFINE_SPINLOCK(iscsi_transport_l
+ #define cdev_to_iscsi_internal(_cdev) \
+ 	container_of(_cdev, struct iscsi_internal, cdev)
+ 
++extern int attribute_container_init(void);
++
+ static void iscsi_transport_release(struct class_device *cdev)
+ {
+ 	struct iscsi_internal *priv = cdev_to_iscsi_internal(cdev);
+@@ -80,6 +82,17 @@ static struct class iscsi_transport_clas
+ 	.release = iscsi_transport_release,
+ };
+ 
++static void iscsi_host_class_release(struct class_device *class_dev)
++{
++	struct Scsi_Host *shost = transport_class_to_shost(class_dev);
++	put_device(&shost->shost_gendev);
++}
++
++struct class iscsi_host_class = {
++	.name = "iscsi_host",
++	.release = iscsi_host_class_release,
++};
++
+ static ssize_t
+ show_transport_handle(struct class_device *cdev, char *buf)
+ {
+@@ -115,10 +128,8 @@ static struct attribute_group iscsi_tran
+ 	.attrs = iscsi_transport_attrs,
+ };
+ 
+-static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
+-			    struct class_device *cdev)
++static int iscsi_setup_host(struct Scsi_Host *shost)
+ {
+-	struct Scsi_Host *shost = dev_to_shost(dev);
+ 	struct iscsi_host *ihost = shost->shost_data;
+ 
+ 	memset(ihost, 0, sizeof(*ihost));
+@@ -127,12 +138,6 @@ static int iscsi_setup_host(struct trans
+ 	return 0;
+ }
+ 
+-static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
+-			       "iscsi_host",
+-			       iscsi_setup_host,
+-			       NULL,
+-			       NULL);
+-
+ static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
+ 			       "iscsi_session",
+ 			       NULL,
+@@ -216,24 +221,6 @@ static int iscsi_is_session_dev(const st
+ 	return dev->release == iscsi_session_release;
+ }
+ 
+-static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
+-			   uint id, uint lun)
+-{
+-	struct iscsi_host *ihost = shost->shost_data;
+-	struct iscsi_cls_session *session;
+-
+-	mutex_lock(&ihost->mutex);
+-	list_for_each_entry(session, &ihost->sessions, host_list) {
+-		if ((channel == SCAN_WILD_CARD || channel == 0) &&
+-		    (id == SCAN_WILD_CARD || id == session->target_id))
+-			scsi_scan_target(&session->dev, 0,
+-					 session->target_id, lun, 1);
+-	}
+-	mutex_unlock(&ihost->mutex);
+-
+-	return 0;
+-}
+-
+ static void session_recovery_timedout(struct work_struct *work)
+ {
+ 	struct iscsi_cls_session *session =
+@@ -362,8 +349,6 @@ void iscsi_remove_session(struct iscsi_c
+ 	list_del(&session->host_list);
+ 	mutex_unlock(&ihost->mutex);
+ 
+-	scsi_remove_target(&session->dev);
+-
+ 	transport_unregister_device(&session->dev);
+ 	device_del(&session->dev);
+ }
+@@ -1269,24 +1254,6 @@ static int iscsi_conn_match(struct attri
+ 	return &priv->conn_cont.ac == cont;
+ }
+ 
+-static int iscsi_host_match(struct attribute_container *cont,
+-			    struct device *dev)
+-{
+-	struct Scsi_Host *shost;
+-	struct iscsi_internal *priv;
+-
+-	if (!scsi_is_host_device(dev))
+-		return 0;
+-
+-	shost = dev_to_shost(dev);
+-	if (!shost->transportt  ||
+-	    shost->transportt->host_attrs.ac.class != &iscsi_host_class.class)
+-		return 0;
+-
+-        priv = to_iscsi_internal(shost->transportt);
+-        return &priv->t.host_attrs.ac == cont;
+-}
+-
+ struct scsi_transport_template *
+ iscsi_register_transport(struct iscsi_transport *tt)
+ {
+@@ -1306,7 +1273,6 @@ iscsi_register_transport(struct iscsi_tr
+ 	INIT_LIST_HEAD(&priv->list);
+ 	priv->daemon_pid = -1;
+ 	priv->iscsi_transport = tt;
+-	priv->t.user_scan = iscsi_user_scan;
+ 
+ 	priv->cdev.class = &iscsi_transport_class;
+ 	snprintf(priv->cdev.class_id, BUS_ID_SIZE, "%s", tt->name);
+@@ -1319,12 +1285,11 @@ iscsi_register_transport(struct iscsi_tr
+ 		goto unregister_cdev;
+ 
+ 	/* host parameters */
+-	priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];
+-	priv->t.host_attrs.ac.class = &iscsi_host_class.class;
+-	priv->t.host_attrs.ac.match = iscsi_host_match;
++
++	priv->t.host_attrs = &priv->host_attrs[0];
++	priv->t.host_class = &iscsi_host_class;
++	priv->t.host_setup = iscsi_setup_host;
+ 	priv->t.host_size = sizeof(struct iscsi_host);
+-	priv->host_attrs[0] = NULL;
+-	transport_container_register(&priv->t.host_attrs);
+ 
+ 	/* connection parameters */
+ 	priv->conn_cont.ac.attrs = &priv->conn_attrs[0];
+@@ -1402,7 +1367,6 @@ int iscsi_unregister_transport(struct is
+ 
+ 	transport_container_unregister(&priv->conn_cont);
+ 	transport_container_unregister(&priv->session_cont);
+-	transport_container_unregister(&priv->t.host_attrs);
+ 
+ 	sysfs_remove_group(&priv->cdev.kobj, &iscsi_transport_group);
+ 	class_device_unregister(&priv->cdev);
+@@ -1419,6 +1383,8 @@ static __init int iscsi_transport_init(v
+ 	printk(KERN_INFO "Loading iSCSI transport class v%s.\n",
+ 		ISCSI_TRANSPORT_VERSION);
+ 
++	attribute_container_init();
++
+ 	err = class_register(&iscsi_transport_class);
+ 	if (err)
+ 		return err;
diff --git a/kernel_patches/backport/2.6.9_U5/add_open_iscsi_h.patch b/kernel_patches/backport/2.6.9_U5/add_open_iscsi_h.patch
new file mode 100644
index 0000000..21715fd
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U5/add_open_iscsi_h.patch
@@ -0,0 +1,35 @@
+diff -rup linux-2.6.20/include/scsi/iscsi_if.h linux-2.6.20-rh4-backport/include/scsi/iscsi_if.h
+--- linux-2.6.20/include/scsi/iscsi_if.h	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/iscsi_if.h	2007-05-15 08:49:53.000000000 +0300
+@@ -277,7 +277,6 @@ enum iscsi_param {
+  * These flags describes reason of stop_conn() call
+  */
+ #define STOP_CONN_TERM		0x1
+-#define STOP_CONN_SUSPEND	0x2
+ #define STOP_CONN_RECOVER	0x3
+ 
+ #define ISCSI_STATS_CUSTOM_MAX		32
+diff -rup linux-2.6.20/include/scsi/libiscsi.h linux-2.6.20-rh4-backport/include/scsi/libiscsi.h
+--- linux-2.6.20/include/scsi/libiscsi.h	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/libiscsi.h	2007-05-15 08:54:49.000000000 +0300
+@@ -25,8 +25,6 @@
+ 
+ #include <linux/types.h>
+ #include <linux/mutex.h>
+-#include <linux/timer.h>
+-#include <linux/workqueue.h>
+ #include <scsi/iscsi_proto.h>
+ #include <scsi/iscsi_if.h>
+ 
+diff -rup linux-2.6.20/include/scsi/scsi_transport_iscsi.h linux-2.6.20-rh4-backport/include/scsi/scsi_transport_iscsi.h
+--- linux-2.6.20/include/scsi/scsi_transport_iscsi.h	2007-02-04 20:44:54.000000000 +0200
++++ linux-2.6.20-rh4-backport/include/scsi/scsi_transport_iscsi.h	2007-05-15 08:54:24.000000000 +0300
+@@ -24,7 +24,7 @@
+ #define SCSI_TRANSPORT_ISCSI_H
+ 
+ #include <linux/device.h>
+-#include <scsi/iscsi_if.h>
++#include "iscsi_if.h"
+ 
+ struct scsi_transport_template;
+ struct iscsi_transport;
diff --git a/kernel_patches/backport/2.6.9_U5/fix_inclusion_order_iscsi_iser.patch b/kernel_patches/backport/2.6.9_U5/fix_inclusion_order_iscsi_iser.patch
new file mode 100644
index 0000000..3c2a969
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U5/fix_inclusion_order_iscsi_iser.patch
@@ -0,0 +1,13 @@
+--- linux-2.6.20-rc7-orig/drivers/infiniband/ulp/iser/iscsi_iser.c	2007-02-08 09:13:43.000000000 +0200
++++ linux-2.6.20-rc7/drivers/infiniband/ulp/iser/iscsi_iser.c	2007-02-08 09:14:31.000000000 +0200
+@@ -70,9 +70,8 @@
+ #include <scsi/scsi_tcq.h>
+ #include <scsi/scsi_host.h>
+ #include <scsi/scsi.h>
+-#include <scsi/scsi_transport_iscsi.h>
+-
+ #include "iscsi_iser.h"
++#include <scsi/scsi_transport_iscsi.h>
+ 
+ static unsigned int iscsi_max_lun = 512;
+ module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
diff --git a/kernel_patches/backport/2.6.9_U5/iscsi_scsi_addons.patch b/kernel_patches/backport/2.6.9_U5/iscsi_scsi_addons.patch
new file mode 100644
index 0000000..ffa0598
--- /dev/null
+++ b/kernel_patches/backport/2.6.9_U5/iscsi_scsi_addons.patch
@@ -0,0 +1,65 @@
+diff --git a/drivers/scsi/init.c b/drivers/scsi/init.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/init.c
+@@ -0,0 +1 @@
++#include "src/init.c"
+diff --git a/drivers/scsi/attribute_container.c b/drivers/scsi/attribute_container.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/attribute_container.c
+@@ -0,0 +1 @@
++#include "src/attribute_container.c"
+diff --git a/drivers/scsi/transport_class.c b/drivers/scsi/transport_class.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/transport_class.c
+@@ -0,0 +1 @@
++#include "src/transport_class.c"
+diff --git a/drivers/scsi/klist.c b/drivers/scsi/klist.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/klist.c
+@@ -0,0 +1 @@
++#include "src/klist.c"
+diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi.c
+@@ -0,0 +1 @@
++#include "src/scsi.c"
+diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi_lib.c
+@@ -0,0 +1 @@
++#include "src/scsi_lib.c"
+diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/scsi_scan.c
+@@ -0,0 +1 @@
++#include "src/scsi_scan.c"
+diff --git a/drivers/scsi/kref_new.c b/drivers/scsi/kref_new.c
+new file mode 100644
+index 0000000..58cf933
+--- /dev/null
++++ b/drivers/scsi/kref_new.c
+@@ -0,0 +1 @@
++#include "src/kref_new.c"
+diff -rupN ofa_kernel-1.2/drivers/scsi/Makefile ofa_kernel-1.2-iscsi/drivers/scsi/Makefile
+--- ofa_kernel-1.2/drivers/scsi/Makefile	1970-01-01 02:00:00.000000000 +0200
++++ ofa_kernel-1.2-iscsi/drivers/scsi/Makefile	2007-05-16 14:12:22.000000000 +0300
+@@ -0,0 +1,5 @@
++obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
++obj-$(CONFIG_ISCSI_TCP)        += libiscsi.o   iscsi_tcp.o
++
++scsi_transport_iscsi-y	:= scsi_transport_iscsi_f.o scsi.o scsi_lib.o init.o kref_new.o klist.o attribute_container.o transport_class.o
++libiscsi-y		:= libiscsi_f.o scsi_scan.o
diff --git a/kernel_patches/fixes/iscsi_scsi_makefile.patch b/kernel_patches/fixes/iscsi_scsi_makefile.patch
deleted file mode 100644
index 9c4fd01..0000000
--- a/kernel_patches/fixes/iscsi_scsi_makefile.patch
+++ /dev/null
@@ -1,10 +0,0 @@
-Add a Makefile based on the kernel's drivers/scsi/Makefile in order to build open-iscsi.
-
-Signed-off-by: Erez Zilber <erezz at voltaire.com>
-
-diff -ruN ofa_1_2_kernel-20061228-0200/drivers/scsi/Makefile ofa_1_2_kernel-20061228-0200-open-iscsi/drivers/scsi/Makefile
---- ofa_1_2_kernel-20061228-0200/drivers/scsi/Makefile  1970-01-01 02:00:00.000000000 +0200
-+++ ofa_1_2_kernel-20061228-0200-open-iscsi/drivers/scsi/Makefile       2006-12-28 17:01:22.000000000 +0200
-@@ -0,0 +1,2 @@
-+obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o
-+obj-$(CONFIG_ISCSI_TCP)        += libiscsi.o   iscsi_tcp.o
diff --git a/ofed_scripts/makefile b/ofed_scripts/makefile
index 34a8996..62abe2c 100644
--- a/ofed_scripts/makefile
+++ b/ofed_scripts/makefile
@@ -60,6 +60,12 @@ kernel:
 	@echo "Kernel version: $(KVERSION)"
 	@echo "Modules directory: $(DESTDIR)/$(MODULES_DIR)"
 	@echo "Kernel sources: $(KSRC)"
+	if [ -e $(CWD)/drivers/scsi/libiscsi.c ]; then \
+		mv $(CWD)/drivers/scsi/libiscsi.c $(CWD)/drivers/scsi/libiscsi_f.c; \
+	fi
+	if [ -e $(CWD)/drivers/scsi/scsi_transport_iscsi.c ]; then \
+		mv $(CWD)/drivers/scsi/scsi_transport_iscsi.c $(CWD)/drivers/scsi/scsi_transport_iscsi_f.c; \
+	fi
 	env EXTRA_CFLAGS="$(OPENIB_KERNEL_EXTRA_CFLAGS) $(KERNEL_MEMTRACK_CFLAGS) -I$(CWD)/include -I$(CWD)/drivers/infiniband/include \
 		-I$(CWD)/drivers/infiniband/ulp/ipoib \
 		-I$(CWD)/drivers/infiniband/debug \





More information about the general mailing list