Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
new file mode 100644
index 0000000..1d54c06
--- /dev/null
+++ b/include/scsi/scsi.h
@@ -0,0 +1,412 @@
+/*
+ * This header file contains public constants and structures used by
+ * the scsi code for linux.
+ *
+ * For documentation on the OPCODES, MESSAGES, and SENSE values,
+ * please consult the SCSI standard.
+ */
+#ifndef _SCSI_SCSI_H
+#define _SCSI_SCSI_H
+
+#include <linux/types.h>
+
+/*
+ *	The maximum sg list length SCSI can cope with
+ *	(currently must be a power of 2 between 32 and 256)
+ */
+#define SCSI_MAX_PHYS_SEGMENTS	MAX_PHYS_SEGMENTS
+
+
+/*
+ *	SCSI command lengths
+ */
+
+extern const unsigned char scsi_command_size[8];
+#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
+
+/*
+ *	SCSI device types
+ */
+
+#define MAX_SCSI_DEVICE_CODE 14
+extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
+
+/*
+ *      SCSI opcodes
+ */
+
+#define TEST_UNIT_READY       0x00
+#define REZERO_UNIT           0x01
+#define REQUEST_SENSE         0x03
+#define FORMAT_UNIT           0x04
+#define READ_BLOCK_LIMITS     0x05
+#define REASSIGN_BLOCKS       0x07
+#define READ_6                0x08
+#define WRITE_6               0x0a
+#define SEEK_6                0x0b
+#define READ_REVERSE          0x0f
+#define WRITE_FILEMARKS       0x10
+#define SPACE                 0x11
+#define INQUIRY               0x12
+#define RECOVER_BUFFERED_DATA 0x14
+#define MODE_SELECT           0x15
+#define RESERVE               0x16
+#define RELEASE               0x17
+#define COPY                  0x18
+#define ERASE                 0x19
+#define MODE_SENSE            0x1a
+#define START_STOP            0x1b
+#define RECEIVE_DIAGNOSTIC    0x1c
+#define SEND_DIAGNOSTIC       0x1d
+#define ALLOW_MEDIUM_REMOVAL  0x1e
+
+#define SET_WINDOW            0x24
+#define READ_CAPACITY         0x25
+#define READ_10               0x28
+#define WRITE_10              0x2a
+#define SEEK_10               0x2b
+#define WRITE_VERIFY          0x2e
+#define VERIFY                0x2f
+#define SEARCH_HIGH           0x30
+#define SEARCH_EQUAL          0x31
+#define SEARCH_LOW            0x32
+#define SET_LIMITS            0x33
+#define PRE_FETCH             0x34
+#define READ_POSITION         0x34
+#define SYNCHRONIZE_CACHE     0x35
+#define LOCK_UNLOCK_CACHE     0x36
+#define READ_DEFECT_DATA      0x37
+#define MEDIUM_SCAN           0x38
+#define COMPARE               0x39
+#define COPY_VERIFY           0x3a
+#define WRITE_BUFFER          0x3b
+#define READ_BUFFER           0x3c
+#define UPDATE_BLOCK          0x3d
+#define READ_LONG             0x3e
+#define WRITE_LONG            0x3f
+#define CHANGE_DEFINITION     0x40
+#define WRITE_SAME            0x41
+#define READ_TOC              0x43
+#define LOG_SELECT            0x4c
+#define LOG_SENSE             0x4d
+#define MODE_SELECT_10        0x55
+#define RESERVE_10            0x56
+#define RELEASE_10            0x57
+#define MODE_SENSE_10         0x5a
+#define PERSISTENT_RESERVE_IN 0x5e
+#define PERSISTENT_RESERVE_OUT 0x5f
+#define REPORT_LUNS           0xa0
+#define MOVE_MEDIUM           0xa5
+#define READ_12               0xa8
+#define WRITE_12              0xaa
+#define WRITE_VERIFY_12       0xae
+#define SEARCH_HIGH_12        0xb0
+#define SEARCH_EQUAL_12       0xb1
+#define SEARCH_LOW_12         0xb2
+#define READ_ELEMENT_STATUS   0xb8
+#define SEND_VOLUME_TAG       0xb6
+#define WRITE_LONG_2          0xea
+#define READ_16               0x88
+#define WRITE_16              0x8a
+#define VERIFY_16	      0x8f
+#define SERVICE_ACTION_IN     0x9e
+/* values for service action in */
+#define	SAI_READ_CAPACITY_16  0x10
+
+
+/*
+ *  SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
+ *  T10/1561-D Revision 4 Draft dated 7th November 2002.
+ */
+#define SAM_STAT_GOOD            0x00
+#define SAM_STAT_CHECK_CONDITION 0x02
+#define SAM_STAT_CONDITION_MET   0x04
+#define SAM_STAT_BUSY            0x08
+#define SAM_STAT_INTERMEDIATE    0x10
+#define SAM_STAT_INTERMEDIATE_CONDITION_MET 0x14
+#define SAM_STAT_RESERVATION_CONFLICT 0x18
+#define SAM_STAT_COMMAND_TERMINATED 0x22	/* obsolete in SAM-3 */
+#define SAM_STAT_TASK_SET_FULL   0x28
+#define SAM_STAT_ACA_ACTIVE      0x30
+#define SAM_STAT_TASK_ABORTED    0x40
+
+/** scsi_status_is_good - check the status return.
+ *
+ * @status: the status passed up from the driver (including host and
+ *          driver components)
+ *
+ * This returns true for known good conditions that may be treated as
+ * command completed normally
+ */
+static inline int scsi_status_is_good(int status)
+{
+	/*
+	 * FIXME: bit0 is listed as reserved in SCSI-2, but is
+	 * significant in SCSI-3.  For now, we follow the SCSI-2
+	 * behaviour and ignore reserved bits.
+	 */
+	status &= 0xfe;
+	return ((status == SAM_STAT_GOOD) ||
+		(status == SAM_STAT_INTERMEDIATE) ||
+		(status == SAM_STAT_INTERMEDIATE_CONDITION_MET) ||
+		/* FIXME: this is obsolete in SAM-3 */
+		(status == SAM_STAT_COMMAND_TERMINATED));
+}
+
+/*
+ *  Status codes. These are deprecated as they are shifted 1 bit right
+ *  from those found in the SCSI standards. This causes confusion for
+ *  applications that are ported to several OSes. Prefer SAM Status codes
+ *  above.
+ */
+
+#define GOOD                 0x00
+#define CHECK_CONDITION      0x01
+#define CONDITION_GOOD       0x02
+#define BUSY                 0x04
+#define INTERMEDIATE_GOOD    0x08
+#define INTERMEDIATE_C_GOOD  0x0a
+#define RESERVATION_CONFLICT 0x0c
+#define COMMAND_TERMINATED   0x11
+#define QUEUE_FULL           0x14
+#define ACA_ACTIVE           0x18
+#define TASK_ABORTED         0x20
+
+#define STATUS_MASK          0xfe
+
+/*
+ *  SENSE KEYS
+ */
+
+#define NO_SENSE            0x00
+#define RECOVERED_ERROR     0x01
+#define NOT_READY           0x02
+#define MEDIUM_ERROR        0x03
+#define HARDWARE_ERROR      0x04
+#define ILLEGAL_REQUEST     0x05
+#define UNIT_ATTENTION      0x06
+#define DATA_PROTECT        0x07
+#define BLANK_CHECK         0x08
+#define COPY_ABORTED        0x0a
+#define ABORTED_COMMAND     0x0b
+#define VOLUME_OVERFLOW     0x0d
+#define MISCOMPARE          0x0e
+
+
+/*
+ *  DEVICE TYPES
+ */
+
+#define TYPE_DISK           0x00
+#define TYPE_TAPE           0x01
+#define TYPE_PRINTER        0x02
+#define TYPE_PROCESSOR      0x03    /* HP scanners use this */
+#define TYPE_WORM           0x04    /* Treated as ROM by our system */
+#define TYPE_ROM            0x05
+#define TYPE_SCANNER        0x06
+#define TYPE_MOD            0x07    /* Magneto-optical disk - 
+				     * - treated as TYPE_DISK */
+#define TYPE_MEDIUM_CHANGER 0x08
+#define TYPE_COMM           0x09    /* Communications device */
+#define TYPE_ENCLOSURE      0x0d    /* Enclosure Services Device */
+#define TYPE_RAID           0x0c
+#define TYPE_NO_LUN         0x7f
+
+/*
+ * standard mode-select header prepended to all mode-select commands
+ */
+
+struct ccs_modesel_head {
+	__u8 _r1;			/* reserved */
+	__u8 medium;		/* device-specific medium type */
+	__u8 _r2;			/* reserved */
+	__u8 block_desc_length;	/* block descriptor length */
+	__u8 density;		/* device-specific density code */
+	__u8 number_blocks_hi;	/* number of blocks in this block desc */
+	__u8 number_blocks_med;
+	__u8 number_blocks_lo;
+	__u8 _r3;
+	__u8 block_length_hi;	/* block length for blocks in this desc */
+	__u8 block_length_med;
+	__u8 block_length_lo;
+};
+
+/*
+ * ScsiLun: 8 byte LUN.
+ */
+struct scsi_lun {
+	__u8 scsi_lun[8];
+};
+
+/*
+ *  MESSAGE CODES
+ */
+
+#define COMMAND_COMPLETE    0x00
+#define EXTENDED_MESSAGE    0x01
+#define     EXTENDED_MODIFY_DATA_POINTER    0x00
+#define     EXTENDED_SDTR                   0x01
+#define     EXTENDED_EXTENDED_IDENTIFY      0x02    /* SCSI-I only */
+#define     EXTENDED_WDTR                   0x03
+#define     EXTENDED_PPR                    0x04
+#define     EXTENDED_MODIFY_BIDI_DATA_PTR   0x05
+#define SAVE_POINTERS       0x02
+#define RESTORE_POINTERS    0x03
+#define DISCONNECT          0x04
+#define INITIATOR_ERROR     0x05
+#define ABORT_TASK_SET      0x06
+#define MESSAGE_REJECT      0x07
+#define NOP                 0x08
+#define MSG_PARITY_ERROR    0x09
+#define LINKED_CMD_COMPLETE 0x0a
+#define LINKED_FLG_CMD_COMPLETE 0x0b
+#define TARGET_RESET        0x0c
+#define ABORT_TASK          0x0d
+#define CLEAR_TASK_SET      0x0e
+#define INITIATE_RECOVERY   0x0f            /* SCSI-II only */
+#define RELEASE_RECOVERY    0x10            /* SCSI-II only */
+#define CLEAR_ACA           0x16
+#define LOGICAL_UNIT_RESET  0x17
+#define SIMPLE_QUEUE_TAG    0x20
+#define HEAD_OF_QUEUE_TAG   0x21
+#define ORDERED_QUEUE_TAG   0x22
+#define IGNORE_WIDE_RESIDUE 0x23
+#define ACA                 0x24
+#define QAS_REQUEST         0x55
+
+/* Old SCSI2 names, don't use in new code */
+#define BUS_DEVICE_RESET    TARGET_RESET
+#define ABORT               ABORT_TASK_SET
+
+/*
+ * Host byte codes
+ */
+
+#define DID_OK          0x00	/* NO error                                */
+#define DID_NO_CONNECT  0x01	/* Couldn't connect before timeout period  */
+#define DID_BUS_BUSY    0x02	/* BUS stayed busy through time out period */
+#define DID_TIME_OUT    0x03	/* TIMED OUT for other reason              */
+#define DID_BAD_TARGET  0x04	/* BAD target.                             */
+#define DID_ABORT       0x05	/* Told to abort for some other reason     */
+#define DID_PARITY      0x06	/* Parity error                            */
+#define DID_ERROR       0x07	/* Internal error                          */
+#define DID_RESET       0x08	/* Reset by somebody.                      */
+#define DID_BAD_INTR    0x09	/* Got an interrupt we weren't expecting.  */
+#define DID_PASSTHROUGH 0x0a	/* Force command past mid-layer            */
+#define DID_SOFT_ERROR  0x0b	/* The low level driver just wish a retry  */
+#define DID_IMM_RETRY   0x0c	/* Retry without decrementing retry count  */
+#define DRIVER_OK       0x00	/* Driver status                           */
+
+/*
+ *  These indicate the error that occurred, and what is available.
+ */
+
+#define DRIVER_BUSY         0x01
+#define DRIVER_SOFT         0x02
+#define DRIVER_MEDIA        0x03
+#define DRIVER_ERROR        0x04
+
+#define DRIVER_INVALID      0x05
+#define DRIVER_TIMEOUT      0x06
+#define DRIVER_HARD         0x07
+#define DRIVER_SENSE	    0x08
+
+#define SUGGEST_RETRY       0x10
+#define SUGGEST_ABORT       0x20
+#define SUGGEST_REMAP       0x30
+#define SUGGEST_DIE         0x40
+#define SUGGEST_SENSE       0x80
+#define SUGGEST_IS_OK       0xff
+
+#define DRIVER_MASK         0x0f
+#define SUGGEST_MASK        0xf0
+
+/*
+ * Internal return values.
+ */
+
+#define NEEDS_RETRY     0x2001
+#define SUCCESS         0x2002
+#define FAILED          0x2003
+#define QUEUED          0x2004
+#define SOFT_ERROR      0x2005
+#define ADD_TO_MLQUEUE  0x2006
+#define TIMEOUT_ERROR   0x2007
+
+/*
+ * Midlevel queue return values.
+ */
+#define SCSI_MLQUEUE_HOST_BUSY   0x1055
+#define SCSI_MLQUEUE_DEVICE_BUSY 0x1056
+#define SCSI_MLQUEUE_EH_RETRY    0x1057
+
+/*
+ *  Use these to separate status msg and our bytes
+ *
+ *  These are set by:
+ *
+ *      status byte = set from target device
+ *      msg_byte    = return status from host adapter itself.
+ *      host_byte   = set by low-level driver to indicate status.
+ *      driver_byte = set by mid-level.
+ */
+#define status_byte(result) (((result) >> 1) & 0x7f)
+#define msg_byte(result)    (((result) >> 8) & 0xff)
+#define host_byte(result)   (((result) >> 16) & 0xff)
+#define driver_byte(result) (((result) >> 24) & 0xff)
+#define suggestion(result)  (driver_byte(result) & SUGGEST_MASK)
+
+#define sense_class(sense)  (((sense) >> 4) & 0x7)
+#define sense_error(sense)  ((sense) & 0xf)
+#define sense_valid(sense)  ((sense) & 0x80);
+
+
+#define IDENTIFY_BASE       0x80
+#define IDENTIFY(can_disconnect, lun)   (IDENTIFY_BASE |\
+		     ((can_disconnect) ?  0x40 : 0) |\
+		     ((lun) & 0x07))
+
+/*
+ *  struct scsi_device::scsi_level values. For SCSI devices other than those
+ *  prior to SCSI-2 (i.e. over 12 years old) this value is (resp[2] + 1)
+ *  where "resp" is a byte array of the response to an INQUIRY. The scsi_level
+ *  variable is visible to the user via sysfs.
+ */
+
+#define SCSI_UNKNOWN    0
+#define SCSI_1          1
+#define SCSI_1_CCS      2
+#define SCSI_2          3
+#define SCSI_3          4        /* SPC */
+#define SCSI_SPC_2      5
+#define SCSI_SPC_3      6
+
+/*
+ * INQ PERIPHERAL QUALIFIERS
+ */
+#define SCSI_INQ_PQ_CON         0x00
+#define SCSI_INQ_PQ_NOT_CON     0x01
+#define SCSI_INQ_PQ_NOT_CAP     0x03
+
+
+/*
+ * Here are some scsi specific ioctl commands which are sometimes useful.
+ *
+ * Note that include/linux/cdrom.h also defines IOCTL 0x5300 - 0x5395
+ */
+
+/* Used to obtain PUN and LUN info.  Conflicts with CDROMAUDIOBUFSIZ */
+#define SCSI_IOCTL_GET_IDLUN		0x5382
+
+/* 0x5383 and 0x5384 were used for SCSI_IOCTL_TAGGED_{ENABLE,DISABLE} */
+
+/* Used to obtain the host number of a device. */
+#define SCSI_IOCTL_PROBE_HOST		0x5385
+
+/* Used to obtain the bus number for a device */
+#define SCSI_IOCTL_GET_BUS_NUMBER	0x5386
+
+/* Used to obtain the PCI location of a device */
+#define SCSI_IOCTL_GET_PCI		0x5387
+
+#endif /* _SCSI_SCSI_H */
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
new file mode 100644
index 0000000..9d9871c
--- /dev/null
+++ b/include/scsi/scsi_cmnd.h
@@ -0,0 +1,165 @@
+#ifndef _SCSI_SCSI_CMND_H
+#define _SCSI_SCSI_CMND_H
+
+#include <linux/dma-mapping.h>
+#include <linux/list.h>
+#include <linux/types.h>
+
+struct request;
+struct scatterlist;
+struct scsi_device;
+struct scsi_request;
+
+
+/* embedded in scsi_cmnd */
+struct scsi_pointer {
+	char *ptr;		/* data pointer */
+	int this_residual;	/* left in this buffer */
+	struct scatterlist *buffer;	/* which buffer */
+	int buffers_residual;	/* how many buffers left */
+
+        dma_addr_t dma_handle;
+
+	volatile int Status;
+	volatile int Message;
+	volatile int have_data_in;
+	volatile int sent_command;
+	volatile int phase;
+};
+
+struct scsi_cmnd {
+	int     sc_magic;
+
+	struct scsi_device *device;
+	unsigned short state;
+	unsigned short owner;
+	struct scsi_request *sc_request;
+
+	struct list_head list;  /* scsi_cmnd participates in queue lists */
+
+	struct list_head eh_entry; /* entry for the host eh_cmd_q */
+	int eh_state;		/* Used for state tracking in error handlr */
+	int eh_eflags;		/* Used by error handlr */
+	void (*done) (struct scsi_cmnd *);	/* Mid-level done function */
+
+	/*
+	 * A SCSI Command is assigned a nonzero serial_number when internal_cmnd
+	 * passes it to the driver's queue command function.  The serial_number
+	 * is cleared when scsi_done is entered indicating that the command has
+	 * been completed.  If a timeout occurs, the serial number at the moment
+	 * of timeout is copied into serial_number_at_timeout.  By subsequently
+	 * comparing the serial_number and serial_number_at_timeout fields
+	 * during abort or reset processing, we can detect whether the command
+	 * has already completed.  This also detects cases where the command has
+	 * completed and the SCSI Command structure has already being reused
+	 * for another command, so that we can avoid incorrectly aborting or
+	 * resetting the new command.
+	 * The serial number is only unique per host.
+	 */
+	unsigned long serial_number;
+	unsigned long serial_number_at_timeout;
+
+	int retries;
+	int allowed;
+	int timeout_per_command;
+	int timeout_total;
+	int timeout;
+
+	/*
+	 * We handle the timeout differently if it happens when a reset, 
+	 * abort, etc are in process. 
+	 */
+	unsigned volatile char internal_timeout;
+
+	unsigned char cmd_len;
+	unsigned char old_cmd_len;
+	enum dma_data_direction sc_data_direction;
+	enum dma_data_direction sc_old_data_direction;
+
+	/* These elements define the operation we are about to perform */
+#define MAX_COMMAND_SIZE	16
+	unsigned char cmnd[MAX_COMMAND_SIZE];
+	unsigned request_bufflen;	/* Actual request size */
+
+	struct timer_list eh_timeout;	/* Used to time out the command. */
+	void *request_buffer;		/* Actual requested buffer */
+
+	/* These elements define the operation we ultimately want to perform */
+	unsigned char data_cmnd[MAX_COMMAND_SIZE];
+	unsigned short old_use_sg;	/* We save  use_sg here when requesting
+					 * sense info */
+	unsigned short use_sg;	/* Number of pieces of scatter-gather */
+	unsigned short sglist_len;	/* size of malloc'd scatter-gather list */
+	unsigned short abort_reason;	/* If the mid-level code requests an
+					 * abort, this is the reason. */
+	unsigned bufflen;	/* Size of data buffer */
+	void *buffer;		/* Data buffer */
+
+	unsigned underflow;	/* Return error if less than
+				   this amount is transferred */
+	unsigned old_underflow;	/* save underflow here when reusing the
+				 * command for error handling */
+
+	unsigned transfersize;	/* How much we are guaranteed to
+				   transfer with each SCSI transfer
+				   (ie, between disconnect / 
+				   reconnects.   Probably == sector
+				   size */
+
+	int resid;		/* Number of bytes requested to be
+				   transferred less actual number
+				   transferred (0 if not supported) */
+
+	struct request *request;	/* The command we are
+				   	   working on */
+
+#define SCSI_SENSE_BUFFERSIZE 	96
+	unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];		/* obtained by REQUEST SENSE
+						 * when CHECK CONDITION is
+						 * received on original command 
+						 * (auto-sense) */
+
+	/* Low-level done function - can be used by low-level driver to point
+	 *        to completion function.  Not used by mid/upper level code. */
+	void (*scsi_done) (struct scsi_cmnd *);
+
+	/*
+	 * The following fields can be written to by the host specific code. 
+	 * Everything else should be left alone. 
+	 */
+	struct scsi_pointer SCp;	/* Scratchpad used by some host adapters */
+
+	unsigned char *host_scribble;	/* The host adapter is allowed to
+					   * call scsi_malloc and get some memory
+					   * and hang it here.     The host adapter
+					   * is also expected to call scsi_free
+					   * to release this memory.  (The memory
+					   * obtained by scsi_malloc is guaranteed
+					   * to be at an address < 16Mb). */
+
+	int result;		/* Status code from lower level driver */
+
+	unsigned char tag;	/* SCSI-II queued command tag */
+	unsigned long pid;	/* Process ID, starts at 0. Unique per host. */
+};
+
+/*
+ * These are the values that scsi_cmd->state can take.
+ */
+#define SCSI_STATE_TIMEOUT         0x1000
+#define SCSI_STATE_FINISHED        0x1001
+#define SCSI_STATE_FAILED          0x1002
+#define SCSI_STATE_QUEUED          0x1003
+#define SCSI_STATE_UNUSED          0x1006
+#define SCSI_STATE_DISCONNECTING   0x1008
+#define SCSI_STATE_INITIALIZING    0x1009
+#define SCSI_STATE_BHQUEUE         0x100a
+#define SCSI_STATE_MLQUEUE         0x100b
+
+
+extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, int);
+extern void scsi_put_command(struct scsi_cmnd *);
+extern void scsi_io_completion(struct scsi_cmnd *, unsigned int, unsigned int);
+extern void scsi_finish_command(struct scsi_cmnd *cmd);
+
+#endif /* _SCSI_SCSI_CMND_H */
diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h
new file mode 100644
index 0000000..12e9093
--- /dev/null
+++ b/include/scsi/scsi_dbg.h
@@ -0,0 +1,21 @@
+#ifndef _SCSI_SCSI_DBG_H
+#define _SCSI_SCSI_DBG_H
+
+struct scsi_cmnd;
+struct scsi_request;
+
+extern void scsi_print_command(struct scsi_cmnd *);
+extern void __scsi_print_command(unsigned char *);
+extern void scsi_print_sense(const char *, struct scsi_cmnd *);
+extern void scsi_print_req_sense(const char *, struct scsi_request *);
+extern void __scsi_print_sense(const char *name,
+			       const unsigned char *sense_buffer,
+			       int sense_len);
+extern void scsi_print_driverbyte(int);
+extern void scsi_print_hostbyte(int);
+extern void scsi_print_status(unsigned char);
+extern int scsi_print_msg(const unsigned char *);
+extern const char *scsi_sense_key_string(unsigned char);
+extern const char *scsi_extd_sense_format(unsigned char, unsigned char);
+
+#endif /* _SCSI_SCSI_DBG_H */
diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
new file mode 100644
index 0000000..07d97405
--- /dev/null
+++ b/include/scsi/scsi_device.h
@@ -0,0 +1,282 @@
+#ifndef _SCSI_SCSI_DEVICE_H
+#define _SCSI_SCSI_DEVICE_H
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <asm/atomic.h>
+
+struct request_queue;
+struct scsi_cmnd;
+struct scsi_mode_data;
+
+
+/*
+ * sdev state: If you alter this, you also need to alter scsi_sysfs.c
+ * (for the ascii descriptions) and the state model enforcer:
+ * scsi_lib:scsi_device_set_state().
+ */
+enum scsi_device_state {
+	SDEV_CREATED = 1,	/* device created but not added to sysfs
+				 * Only internal commands allowed (for inq) */
+	SDEV_RUNNING,		/* device properly configured
+				 * All commands allowed */
+	SDEV_CANCEL,		/* beginning to delete device
+				 * Only error handler commands allowed */
+	SDEV_DEL,		/* device deleted 
+				 * no commands allowed */
+	SDEV_QUIESCE,		/* Device quiescent.  No block commands
+				 * will be accepted, only specials (which
+				 * originate in the mid-layer) */
+	SDEV_OFFLINE,		/* Device offlined (by error handling or
+				 * user request */
+	SDEV_BLOCK,		/* Device blocked by scsi lld.  No scsi 
+				 * commands from user or midlayer should be issued
+				 * to the scsi lld. */
+};
+
+struct scsi_device {
+	struct Scsi_Host *host;
+	struct request_queue *request_queue;
+
+	/* the next two are protected by the host->host_lock */
+	struct list_head    siblings;   /* list of all devices on this host */
+	struct list_head    same_target_siblings; /* just the devices sharing same target id */
+
+	volatile unsigned short device_busy;	/* commands actually active on low-level */
+	spinlock_t sdev_lock;           /* also the request queue_lock */
+	spinlock_t list_lock;
+	struct list_head cmd_list;	/* queue of in use SCSI Command structures */
+	struct list_head starved_entry;
+	struct scsi_cmnd *current_cmnd;	/* currently active command */
+	unsigned short queue_depth;	/* How deep of a queue we want */
+	unsigned short last_queue_full_depth; /* These two are used by */
+	unsigned short last_queue_full_count; /* scsi_track_queue_full() */
+	unsigned long last_queue_full_time;/* don't let QUEUE_FULLs on the same
+					   jiffie count on our counter, they
+					   could all be from the same event. */
+
+	unsigned int id, lun, channel;
+
+	unsigned int manufacturer;	/* Manufacturer of device, for using 
+					 * vendor-specific cmd's */
+	unsigned sector_size;	/* size in bytes */
+
+	void *hostdata;		/* available to low-level driver */
+	char devfs_name[256];	/* devfs junk */
+	char type;
+	char scsi_level;
+	char inq_periph_qual;	/* PQ from INQUIRY data */	
+	unsigned char inquiry_len;	/* valid bytes in 'inquiry' */
+	unsigned char * inquiry;	/* INQUIRY response data */
+	char * vendor;		/* [back_compat] point into 'inquiry' ... */
+	char * model;		/* ... after scan; point to static string */
+	char * rev;		/* ... "nullnullnullnull" before scan */
+	unsigned char current_tag;	/* current tag */
+	struct scsi_target      *sdev_target;   /* used only for single_lun */
+
+	unsigned int	sdev_bflags; /* black/white flags as also found in
+				 * scsi_devinfo.[hc]. For now used only to
+				 * pass settings from slave_alloc to scsi
+				 * core. */
+	unsigned writeable:1;
+	unsigned removable:1;
+	unsigned changed:1;	/* Data invalid due to media change */
+	unsigned busy:1;	/* Used to prevent races */
+	unsigned lockable:1;	/* Able to prevent media removal */
+	unsigned locked:1;      /* Media removal disabled */
+	unsigned borken:1;	/* Tell the Seagate driver to be 
+				 * painfully slow on this device */
+	unsigned disconnect:1;	/* can disconnect */
+	unsigned soft_reset:1;	/* Uses soft reset option */
+	unsigned sdtr:1;	/* Device supports SDTR messages */
+	unsigned wdtr:1;	/* Device supports WDTR messages */
+	unsigned ppr:1;		/* Device supports PPR messages */
+	unsigned tagged_supported:1;	/* Supports SCSI-II tagged queuing */
+	unsigned simple_tags:1;	/* simple queue tag messages are enabled */
+	unsigned ordered_tags:1;/* ordered queue tag messages are enabled */
+	unsigned single_lun:1;	/* Indicates we should only allow I/O to
+				 * one of the luns for the device at a 
+				 * time. */
+	unsigned was_reset:1;	/* There was a bus reset on the bus for 
+				 * this device */
+	unsigned expecting_cc_ua:1; /* Expecting a CHECK_CONDITION/UNIT_ATTN
+				     * because we did a bus reset. */
+	unsigned use_10_for_rw:1; /* first try 10-byte read / write */
+	unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
+	unsigned skip_ms_page_8:1;	/* do not use MODE SENSE page 0x08 */
+	unsigned skip_ms_page_3f:1;	/* do not use MODE SENSE page 0x3f */
+	unsigned use_192_bytes_for_3f:1; /* ask for 192 bytes from page 0x3f */
+	unsigned no_start_on_add:1;	/* do not issue start on add */
+	unsigned allow_restart:1; /* issue START_UNIT in error handler */
+	unsigned no_uld_attach:1; /* disable connecting to upper level drivers */
+	unsigned select_no_atn:1;
+	unsigned fix_capacity:1;	/* READ_CAPACITY is too high by 1 */
+	unsigned retry_hwerror:1;	/* Retry HARDWARE_ERROR */
+
+	unsigned int device_blocked;	/* Device returned QUEUE_FULL. */
+
+	unsigned int max_device_blocked; /* what device_blocked counts down from  */
+#define SCSI_DEFAULT_DEVICE_BLOCKED	3
+
+	atomic_t iorequest_cnt;
+	atomic_t iodone_cnt;
+	atomic_t ioerr_cnt;
+
+	int timeout;
+
+	struct device		sdev_gendev;
+	struct class_device	sdev_classdev;
+
+	enum scsi_device_state sdev_state;
+	unsigned long		sdev_data[0];
+} __attribute__((aligned(sizeof(unsigned long))));
+#define	to_scsi_device(d)	\
+	container_of(d, struct scsi_device, sdev_gendev)
+#define	class_to_sdev(d)	\
+	container_of(d, struct scsi_device, sdev_classdev)
+#define transport_class_to_sdev(class_dev) \
+	to_scsi_device(class_dev->dev)
+
+/*
+ * scsi_target: representation of a scsi target, for now, this is only
+ * used for single_lun devices. If no one has active IO to the target,
+ * starget_sdev_user is NULL, else it points to the active sdev.
+ */
+struct scsi_target {
+	struct scsi_device	*starget_sdev_user;
+	struct list_head	siblings;
+	struct list_head	devices;
+	struct device		dev;
+	unsigned int		reap_ref; /* protected by the host lock */
+	unsigned int		channel;
+	unsigned int		id; /* target id ... replace
+				     * scsi_device.id eventually */
+	unsigned long		create:1; /* signal that it needs to be added */
+	unsigned long		starget_data[0];
+} __attribute__((aligned(sizeof(unsigned long))));
+
+#define to_scsi_target(d)	container_of(d, struct scsi_target, dev)
+static inline struct scsi_target *scsi_target(struct scsi_device *sdev)
+{
+	return to_scsi_target(sdev->sdev_gendev.parent);
+}
+#define transport_class_to_starget(class_dev) \
+	to_scsi_target(class_dev->dev)
+
+extern struct scsi_device *__scsi_add_device(struct Scsi_Host *,
+		uint, uint, uint, void *hostdata);
+#define scsi_add_device(host, channel, target, lun) \
+	__scsi_add_device(host, channel, target, lun, NULL)
+extern void scsi_remove_device(struct scsi_device *);
+extern int scsi_device_cancel(struct scsi_device *, int);
+
+extern int scsi_device_get(struct scsi_device *);
+extern void scsi_device_put(struct scsi_device *);
+extern struct scsi_device *scsi_device_lookup(struct Scsi_Host *,
+					      uint, uint, uint);
+extern struct scsi_device *__scsi_device_lookup(struct Scsi_Host *,
+						uint, uint, uint);
+extern struct scsi_device *scsi_device_lookup_by_target(struct scsi_target *,
+							uint);
+extern struct scsi_device *__scsi_device_lookup_by_target(struct scsi_target *,
+							  uint);
+extern void starget_for_each_device(struct scsi_target *, void *,
+		     void (*fn)(struct scsi_device *, void *));
+
+/* only exposed to implement shost_for_each_device */
+extern struct scsi_device *__scsi_iterate_devices(struct Scsi_Host *,
+						  struct scsi_device *);
+
+/**
+ * shost_for_each_device  -  iterate over all devices of a host
+ * @sdev:	iterator
+ * @host:	host whiches 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.
+ */
+#define shost_for_each_device(sdev, shost) \
+	for ((sdev) = __scsi_iterate_devices((shost), NULL); \
+	     (sdev); \
+	     (sdev) = __scsi_iterate_devices((shost), (sdev)))
+
+/**
+ * __shost_for_each_device  -  iterate over all devices of a host (UNLOCKED)
+ * @sdev:	iterator
+ * @host:	host whiches devices we want to iterate over
+ *
+ * This traverses over each devices of @shost.  It does _not_ take a
+ * reference on the scsi_device, thus it the whole loop must be protected
+ * by shost->host_lock.
+ *
+ * Note:  The only reason why drivers would want to use this is because
+ * they're need to access the device list in irq context.  Otherwise you
+ * really want to use shost_for_each_device instead.
+ */
+#define __shost_for_each_device(sdev, shost) \
+	list_for_each_entry((sdev), &((shost)->__devices), siblings)
+
+extern void scsi_adjust_queue_depth(struct scsi_device *, int, int);
+extern int scsi_track_queue_full(struct scsi_device *, int);
+
+extern int scsi_set_medium_removal(struct scsi_device *, char);
+
+extern int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage,
+			   unsigned char *buffer, int len, int timeout,
+			   int retries, struct scsi_mode_data *data);
+extern int scsi_test_unit_ready(struct scsi_device *sdev, int timeout,
+				int retries);
+extern int scsi_device_set_state(struct scsi_device *sdev,
+				 enum scsi_device_state state);
+extern int scsi_device_quiesce(struct scsi_device *sdev);
+extern void scsi_device_resume(struct scsi_device *sdev);
+extern void scsi_target_quiesce(struct scsi_target *);
+extern void scsi_target_resume(struct scsi_target *);
+extern void scsi_scan_target(struct device *parent, unsigned int channel,
+			     unsigned int id, unsigned int lun, int rescan);
+extern void scsi_target_reap(struct scsi_target *);
+extern void scsi_target_block(struct device *);
+extern void scsi_target_unblock(struct device *);
+extern void scsi_remove_target(struct device *);
+extern const char *scsi_device_state_name(enum scsi_device_state);
+extern int scsi_is_sdev_device(const struct device *);
+extern int scsi_is_target_device(const struct device *);
+static inline int scsi_device_online(struct scsi_device *sdev)
+{
+	return sdev->sdev_state != SDEV_OFFLINE;
+}
+
+/* accessor functions for the SCSI parameters */
+static inline int scsi_device_sync(struct scsi_device *sdev)
+{
+	return sdev->sdtr;
+}
+static inline int scsi_device_wide(struct scsi_device *sdev)
+{
+	return sdev->wdtr;
+}
+static inline int scsi_device_dt(struct scsi_device *sdev)
+{
+	return sdev->ppr;
+}
+static inline int scsi_device_dt_only(struct scsi_device *sdev)
+{
+	if (sdev->inquiry_len < 57)
+		return 0;
+	return (sdev->inquiry[56] & 0x0c) == 0x04;
+}
+static inline int scsi_device_ius(struct scsi_device *sdev)
+{
+	if (sdev->inquiry_len < 57)
+		return 0;
+	return sdev->inquiry[56] & 0x01;
+}
+static inline int scsi_device_qas(struct scsi_device *sdev)
+{
+	if (sdev->inquiry_len < 57)
+		return 0;
+	return sdev->inquiry[56] & 0x02;
+}
+#endif /* _SCSI_SCSI_DEVICE_H */
diff --git a/include/scsi/scsi_devinfo.h b/include/scsi/scsi_devinfo.h
new file mode 100644
index 0000000..174101b
--- /dev/null
+++ b/include/scsi/scsi_devinfo.h
@@ -0,0 +1,31 @@
+#ifndef _SCSI_SCSI_DEVINFO_H
+#define _SCSI_SCSI_DEVINFO_H
+/*
+ * Flags for SCSI devices that need special treatment
+ */
+#define BLIST_NOLUN     	0x001	/* Only scan LUN 0 */
+#define BLIST_FORCELUN  	0x002	/* Known to have LUNs, force scanning,
+					   deprecated: Use max_luns=N */
+#define BLIST_BORKEN    	0x004	/* Flag for broken handshaking */
+#define BLIST_KEY       	0x008	/* unlock by special command */
+#define BLIST_SINGLELUN 	0x010	/* Do not use LUNs in parallel */
+#define BLIST_NOTQ		0x020	/* Buggy Tagged Command Queuing */
+#define BLIST_SPARSELUN 	0x040	/* Non consecutive LUN numbering */
+#define BLIST_MAX5LUN		0x080	/* Avoid LUNS >= 5 */
+#define BLIST_ISROM     	0x100	/* Treat as (removable) CD-ROM */
+#define BLIST_LARGELUN		0x200	/* LUNs past 7 on a SCSI-2 device */
+#define BLIST_INQUIRY_36	0x400	/* override additional length field */
+#define BLIST_INQUIRY_58	0x800	/* ... for broken inquiry responses */
+#define BLIST_NOSTARTONADD	0x1000	/* do not do automatic start on add */
+#define BLIST_MS_SKIP_PAGE_08	0x2000	/* do not send ms page 0x08 */
+#define BLIST_MS_SKIP_PAGE_3F	0x4000	/* do not send ms page 0x3f */
+#define BLIST_USE_10_BYTE_MS	0x8000	/* use 10 byte ms before 6 byte ms */
+#define BLIST_MS_192_BYTES_FOR_3F	0x10000	/*  192 byte ms page 0x3f request */
+#define BLIST_REPORTLUN2	0x20000	/* try REPORT_LUNS even for SCSI-2 devs
+ 					   (if HBA supports more than 8 LUNs) */
+#define BLIST_NOREPORTLUN	0x40000	/* don't try REPORT_LUNS scan (SCSI-3 devs) */
+#define BLIST_NOT_LOCKABLE	0x80000	/* don't use PREVENT-ALLOW commands */
+#define BLIST_NO_ULD_ATTACH	0x100000 /* device is actually for RAID config */
+#define BLIST_SELECT_NO_ATN	0x200000 /* select without ATN */
+#define BLIST_RETRY_HWERROR	0x400000 /* retry HARDWARE_ERROR */
+#endif
diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h
new file mode 100644
index 0000000..850dfa8
--- /dev/null
+++ b/include/scsi/scsi_driver.h
@@ -0,0 +1,31 @@
+#ifndef _SCSI_SCSI_DRIVER_H
+#define _SCSI_SCSI_DRIVER_H
+
+#include <linux/device.h>
+
+struct module;
+struct scsi_cmnd;
+
+
+struct scsi_driver {
+	struct module		*owner;
+	struct device_driver	gendrv;
+
+	int (*init_command)(struct scsi_cmnd *);
+	void (*rescan)(struct device *);
+	int (*issue_flush)(struct device *, sector_t *);
+	int (*prepare_flush)(struct request_queue *, struct request *);
+	void (*end_flush)(struct request_queue *, struct request *);
+};
+#define to_scsi_driver(drv) \
+	container_of((drv), struct scsi_driver, gendrv)
+
+extern int scsi_register_driver(struct device_driver *);
+#define scsi_unregister_driver(drv) \
+	driver_unregister(drv);
+
+extern int scsi_register_interface(struct class_interface *);
+#define scsi_unregister_interface(intf) \
+	class_interface_unregister(intf)
+
+#endif /* _SCSI_SCSI_DRIVER_H */
diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h
new file mode 100644
index 0000000..80557f8
--- /dev/null
+++ b/include/scsi/scsi_eh.h
@@ -0,0 +1,63 @@
+#ifndef _SCSI_SCSI_EH_H
+#define _SCSI_SCSI_EH_H
+
+struct scsi_cmnd;
+struct scsi_device;
+struct scsi_request;
+struct Scsi_Host;
+
+/*
+ * This is a slightly modified SCSI sense "descriptor" format header.
+ * The addition is to allow the 0x70 and 0x71 response codes. The idea
+ * is to place the salient data from either "fixed" or "descriptor" sense
+ * format into one structure to ease application processing.
+ *
+ * The original sense buffer should be kept around for those cases
+ * in which more information is required (e.g. the LBA of a MEDIUM ERROR).
+ */
+struct scsi_sense_hdr {		/* See SPC-3 section 4.5 */
+	u8 response_code;	/* permit: 0x0, 0x70, 0x71, 0x72, 0x73 */
+	u8 sense_key;
+	u8 asc;
+	u8 ascq;
+	u8 byte4;
+	u8 byte5;
+	u8 byte6;
+	u8 additional_length;	/* always 0 for fixed sense format */
+};
+
+
+extern void scsi_add_timer(struct scsi_cmnd *, int,
+		void (*)(struct scsi_cmnd *));
+extern int scsi_delete_timer(struct scsi_cmnd *);
+extern void scsi_report_bus_reset(struct Scsi_Host *, int);
+extern void scsi_report_device_reset(struct Scsi_Host *, int, int);
+extern int scsi_block_when_processing_errors(struct scsi_device *);
+extern int scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
+		struct scsi_sense_hdr *sshdr);
+extern int scsi_request_normalize_sense(struct scsi_request *sreq,
+		struct scsi_sense_hdr *sshdr);
+extern int scsi_command_normalize_sense(struct scsi_cmnd *cmd,
+		struct scsi_sense_hdr *sshdr);
+
+static inline int scsi_sense_is_deferred(struct scsi_sense_hdr *sshdr)
+{
+	return ((sshdr->response_code >= 0x70) && (sshdr->response_code & 1));
+}
+
+extern const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,
+				       int desc_type);
+
+extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
+				   u64 * info_out);
+ 
+/*
+ * Reset request from external source
+ */
+#define SCSI_TRY_RESET_DEVICE	1
+#define SCSI_TRY_RESET_BUS	2
+#define SCSI_TRY_RESET_HOST	3
+
+extern int scsi_reset_provider(struct scsi_device *, int);
+
+#endif /* _SCSI_SCSI_EH_H */
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
new file mode 100644
index 0000000..27f2c4e
--- /dev/null
+++ b/include/scsi/scsi_host.h
@@ -0,0 +1,642 @@
+#ifndef _SCSI_SCSI_HOST_H
+#define _SCSI_SCSI_HOST_H
+
+#include <linux/device.h>
+#include <linux/list.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+struct block_device;
+struct module;
+struct scsi_cmnd;
+struct scsi_device;
+struct Scsi_Host;
+struct scsi_host_cmd_pool;
+struct scsi_transport_template;
+
+
+/*
+ * The various choices mean:
+ * NONE: Self evident.	Host adapter is not capable of scatter-gather.
+ * ALL:	 Means that the host adapter module can do scatter-gather,
+ *	 and that there is no limit to the size of the table to which
+ *	 we scatter/gather data.
+ * Anything else:  Indicates the maximum number of chains that can be
+ *	 used in one scatter-gather request.
+ */
+#define SG_NONE 0
+#define SG_ALL 0xff
+
+
+#define DISABLE_CLUSTERING 0
+#define ENABLE_CLUSTERING 1
+
+enum scsi_eh_timer_return {
+	EH_NOT_HANDLED,
+	EH_HANDLED,
+	EH_RESET_TIMER,
+};
+
+
+struct scsi_host_template {
+	struct module *module;
+	const char *name;
+
+	/*
+	 * Used to initialize old-style drivers.  For new-style drivers
+	 * just perform all work in your module initialization function.
+	 *
+	 * Status:  OBSOLETE
+	 */
+	int (* detect)(struct scsi_host_template *);
+
+	/*
+	 * Used as unload callback for hosts with old-style drivers.
+	 *
+	 * Status: OBSOLETE
+	 */
+	int (* release)(struct Scsi_Host *);
+
+	/*
+	 * The info function will return whatever useful information the
+	 * developer sees fit.  If not provided, then the name field will
+	 * be used instead.
+	 *
+	 * Status: OPTIONAL
+	 */
+	const char *(* info)(struct Scsi_Host *);
+
+	/*
+	 * Ioctl interface
+	 *
+	 * Status: OPTIONAL
+	 */
+	int (* ioctl)(struct scsi_device *dev, int cmd, void __user *arg);
+
+
+#ifdef CONFIG_COMPAT
+	/* 
+	 * Compat handler. Handle 32bit ABI.
+	 * When unknown ioctl is passed return -ENOIOCTLCMD.
+	 *
+	 * Status: OPTIONAL
+	 */
+	int (* compat_ioctl)(struct scsi_device *dev, int cmd, void __user *arg);
+#endif
+
+	/*
+	 * The queuecommand function is used to queue up a scsi
+	 * command block to the LLDD.  When the driver finished
+	 * processing the command the done callback is invoked.
+	 *
+	 * If queuecommand returns 0, then the HBA has accepted the
+	 * command.  The done() function must be called on the command
+	 * when the driver has finished with it. (you may call done on the
+	 * command before queuecommand returns, but in this case you
+	 * *must* return 0 from queuecommand).
+	 *
+	 * Queuecommand may also reject the command, in which case it may
+	 * not touch the command and must not call done() for it.
+	 *
+	 * There are two possible rejection returns:
+	 *
+	 *   SCSI_MLQUEUE_DEVICE_BUSY: Block this device temporarily, but
+	 *   allow commands to other devices serviced by this host.
+	 *
+	 *   SCSI_MLQUEUE_HOST_BUSY: Block all devices served by this
+	 *   host temporarily.
+	 *
+         * For compatibility, any other non-zero return is treated the
+         * same as SCSI_MLQUEUE_HOST_BUSY.
+	 *
+	 * NOTE: "temporarily" means either until the next command for#
+	 * this device/host completes, or a period of time determined by
+	 * I/O pressure in the system if there are no other outstanding
+	 * commands.
+	 *
+	 * STATUS: REQUIRED
+	 */
+	int (* queuecommand)(struct scsi_cmnd *,
+			     void (*done)(struct scsi_cmnd *));
+
+	/*
+	 * This is an error handling strategy routine.  You don't need to
+	 * define one of these if you don't want to - there is a default
+	 * routine that is present that should work in most cases.  For those
+	 * driver authors that have the inclination and ability to write their
+	 * own strategy routine, this is where it is specified.  Note - the
+	 * strategy routine is *ALWAYS* run in the context of the kernel eh
+	 * thread.  Thus you are guaranteed to *NOT* be in an interrupt
+	 * handler when you execute this, and you are also guaranteed to
+	 * *NOT* have any other commands being queued while you are in the
+	 * strategy routine. When you return from this function, operations
+	 * return to normal.
+	 *
+	 * See scsi_error.c scsi_unjam_host for additional comments about
+	 * what this function should and should not be attempting to do.
+	 *
+	 * Status: REQUIRED	(at least one of them)
+	 */
+	int (* eh_strategy_handler)(struct Scsi_Host *);
+	int (* eh_abort_handler)(struct scsi_cmnd *);
+	int (* eh_device_reset_handler)(struct scsi_cmnd *);
+	int (* eh_bus_reset_handler)(struct scsi_cmnd *);
+	int (* eh_host_reset_handler)(struct scsi_cmnd *);
+
+	/*
+	 * This is an optional routine to notify the host that the scsi
+	 * timer just fired.  The returns tell the timer routine what to
+	 * do about this:
+	 *
+	 * EH_HANDLED:		I fixed the error, please complete the command
+	 * EH_RESET_TIMER:	I need more time, reset the timer and
+	 *			begin counting again
+	 * EH_NOT_HANDLED	Begin normal error recovery
+	 *
+	 * Status: OPTIONAL
+	 */
+	enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *);
+
+	/*
+	 * Before the mid layer attempts to scan for a new device where none
+	 * currently exists, it will call this entry in your driver.  Should
+	 * your driver need to allocate any structs or perform any other init
+	 * items in order to send commands to a currently unused target/lun
+	 * combo, then this is where you can perform those allocations.  This
+	 * is specifically so that drivers won't have to perform any kind of
+	 * "is this a new device" checks in their queuecommand routine,
+	 * thereby making the hot path a bit quicker.
+	 *
+	 * Return values: 0 on success, non-0 on failure
+	 *
+	 * Deallocation:  If we didn't find any devices at this ID, you will
+	 * get an immediate call to slave_destroy().  If we find something
+	 * here then you will get a call to slave_configure(), then the
+	 * device will be used for however long it is kept around, then when
+	 * the device is removed from the system (or * possibly at reboot
+	 * time), you will then get a call to slave_destroy().  This is
+	 * assuming you implement slave_configure and slave_destroy.
+	 * However, if you allocate memory and hang it off the device struct,
+	 * then you must implement the slave_destroy() routine at a minimum
+	 * in order to avoid leaking memory
+	 * each time a device is tore down.
+	 *
+	 * Status: OPTIONAL
+	 */
+	int (* slave_alloc)(struct scsi_device *);
+
+	/*
+	 * Once the device has responded to an INQUIRY and we know the
+	 * device is online, we call into the low level driver with the
+	 * struct scsi_device *.  If the low level device driver implements
+	 * this function, it *must* perform the task of setting the queue
+	 * depth on the device.  All other tasks are optional and depend
+	 * on what the driver supports and various implementation details.
+	 * 
+	 * Things currently recommended to be handled at this time include:
+	 *
+	 * 1.  Setting the device queue depth.  Proper setting of this is
+	 *     described in the comments for scsi_adjust_queue_depth.
+	 * 2.  Determining if the device supports the various synchronous
+	 *     negotiation protocols.  The device struct will already have
+	 *     responded to INQUIRY and the results of the standard items
+	 *     will have been shoved into the various device flag bits, eg.
+	 *     device->sdtr will be true if the device supports SDTR messages.
+	 * 3.  Allocating command structs that the device will need.
+	 * 4.  Setting the default timeout on this device (if needed).
+	 * 5.  Anything else the low level driver might want to do on a device
+	 *     specific setup basis...
+	 * 6.  Return 0 on success, non-0 on error.  The device will be marked
+	 *     as offline on error so that no access will occur.  If you return
+	 *     non-0, your slave_destroy routine will never get called for this
+	 *     device, so don't leave any loose memory hanging around, clean
+	 *     up after yourself before returning non-0
+	 *
+	 * Status: OPTIONAL
+	 */
+	int (* slave_configure)(struct scsi_device *);
+
+	/*
+	 * Immediately prior to deallocating the device and after all activity
+	 * has ceased the mid layer calls this point so that the low level
+	 * driver may completely detach itself from the scsi device and vice
+	 * versa.  The low level driver is responsible for freeing any memory
+	 * it allocated in the slave_alloc or slave_configure calls. 
+	 *
+	 * Status: OPTIONAL
+	 */
+	void (* slave_destroy)(struct scsi_device *);
+
+	/*
+	 * fill in this function to allow the queue depth of this host
+	 * to be changeable (on a per device basis).  returns either
+	 * the current queue depth setting (may be different from what
+	 * was passed in) or an error.  An error should only be
+	 * returned if the requested depth is legal but the driver was
+	 * unable to set it.  If the requested depth is illegal, the
+	 * driver should set and return the closest legal queue depth.
+	 *
+	 */
+	int (* change_queue_depth)(struct scsi_device *, int);
+
+	/*
+	 * fill in this function to allow the changing of tag types
+	 * (this also allows the enabling/disabling of tag command
+	 * queueing).  An error should only be returned if something
+	 * went wrong in the driver while trying to set the tag type.
+	 * If the driver doesn't support the requested tag type, then
+	 * it should set the closest type it does support without
+	 * returning an error.  Returns the actual tag type set.
+	 */
+	int (* change_queue_type)(struct scsi_device *, int);
+
+	/*
+	 * This function determines the bios parameters for a given
+	 * harddisk.  These tend to be numbers that are made up by
+	 * the host adapter.  Parameters:
+	 * size, device, list (heads, sectors, cylinders)
+	 *
+	 * Status: OPTIONAL */
+	int (* bios_param)(struct scsi_device *, struct block_device *,
+			sector_t, int []);
+
+	/*
+	 * Can be used to export driver statistics and other infos to the
+	 * world outside the kernel ie. userspace and it also provides an
+	 * interface to feed the driver with information.
+	 *
+	 * Status: OBSOLETE
+	 */
+	int (*proc_info)(struct Scsi_Host *, char *, char **, off_t, int, int);
+
+	/*
+	 * Name of proc directory
+	 */
+	char *proc_name;
+
+	/*
+	 * Used to store the procfs directory if a driver implements the
+	 * proc_info method.
+	 */
+	struct proc_dir_entry *proc_dir;
+
+	/*
+	 * This determines if we will use a non-interrupt driven
+	 * or an interrupt driven scheme,  It is set to the maximum number
+	 * of simultaneous commands a given host adapter will accept.
+	 */
+	int can_queue;
+
+	/*
+	 * In many instances, especially where disconnect / reconnect are
+	 * supported, our host also has an ID on the SCSI bus.  If this is
+	 * the case, then it must be reserved.  Please set this_id to -1 if
+	 * your setup is in single initiator mode, and the host lacks an
+	 * ID.
+	 */
+	int this_id;
+
+	/*
+	 * This determines the degree to which the host adapter is capable
+	 * of scatter-gather.
+	 */
+	unsigned short sg_tablesize;
+
+	/*
+	 * If the host adapter has limitations beside segment count
+	 */
+	unsigned short max_sectors;
+
+	/*
+	 * dma scatter gather segment boundary limit. a segment crossing this
+	 * boundary will be split in two.
+	 */
+	unsigned long dma_boundary;
+
+	/*
+	 * This specifies "machine infinity" for host templates which don't
+	 * limit the transfer size.  Note this limit represents an absolute
+	 * maximum, and may be over the transfer limits allowed for
+	 * individual devices (e.g. 256 for SCSI-1)
+	 */
+#define SCSI_DEFAULT_MAX_SECTORS	1024
+
+	/*
+	 * True if this host adapter can make good use of linked commands.
+	 * This will allow more than one command to be queued to a given
+	 * unit on a given host.  Set this to the maximum number of command
+	 * blocks to be provided for each device.  Set this to 1 for one
+	 * command block per lun, 2 for two, etc.  Do not set this to 0.
+	 * You should make sure that the host adapter will do the right thing
+	 * before you try setting this above 1.
+	 */
+	short cmd_per_lun;
+
+	/*
+	 * present contains counter indicating how many boards of this
+	 * type were found when we did the scan.
+	 */
+	unsigned char present;
+
+	/*
+	 * true if this host adapter uses unchecked DMA onto an ISA bus.
+	 */
+	unsigned unchecked_isa_dma:1;
+
+	/*
+	 * true if this host adapter can make good use of clustering.
+	 * I originally thought that if the tablesize was large that it
+	 * was a waste of CPU cycles to prepare a cluster list, but
+	 * it works out that the Buslogic is faster if you use a smaller
+	 * number of segments (i.e. use clustering).  I guess it is
+	 * inefficient.
+	 */
+	unsigned use_clustering:1;
+
+	/*
+	 * True for emulated SCSI host adapters (e.g. ATAPI)
+	 */
+	unsigned emulated:1;
+
+	/*
+	 * True if the low-level driver performs its own reset-settle delays.
+	 */
+	unsigned skip_settle_delay:1;
+
+	/*
+	 * ordered write support
+	 */
+	unsigned ordered_flush:1;
+	unsigned ordered_tag:1;
+
+	/*
+	 * Countdown for host blocking with no commands outstanding
+	 */
+	unsigned int max_host_blocked;
+
+	/*
+	 * Default value for the blocking.  If the queue is empty,
+	 * host_blocked counts down in the request_fn until it restarts
+	 * host operations as zero is reached.  
+	 *
+	 * FIXME: This should probably be a value in the template
+	 */
+#define SCSI_DEFAULT_HOST_BLOCKED	7
+
+	/*
+	 * Pointer to the sysfs class properties for this host, NULL terminated.
+	 */
+	struct class_device_attribute **shost_attrs;
+
+	/*
+	 * Pointer to the SCSI device properties for this host, NULL terminated.
+	 */
+	struct device_attribute **sdev_attrs;
+
+	/*
+	 * List of hosts per template.
+	 *
+	 * This is only for use by scsi_module.c for legacy templates.
+	 * For these access to it is synchronized implicitly by
+	 * module_init/module_exit.
+	 */
+	struct list_head legacy_hosts;
+};
+
+/*
+ * shost states
+ */
+enum {
+	SHOST_ADD,
+	SHOST_DEL,
+	SHOST_CANCEL,
+	SHOST_RECOVERY,
+};
+
+struct Scsi_Host {
+	/*
+	 * __devices is protected by the host_lock, but you should
+	 * usually use scsi_device_lookup / shost_for_each_device
+	 * to access it and don't care about locking yourself.
+	 * In the rare case of beeing in irq context you can use
+	 * their __ prefixed variants with the lock held. NEVER
+	 * access this list directly from a driver.
+	 */
+	struct list_head	__devices;
+	struct list_head	__targets;
+	
+	struct scsi_host_cmd_pool *cmd_pool;
+	spinlock_t		free_list_lock;
+	struct list_head	free_list; /* backup store of cmd structs */
+	struct list_head	starved_list;
+
+	spinlock_t		default_lock;
+	spinlock_t		*host_lock;
+
+	struct semaphore	scan_mutex;/* serialize scanning activity */
+
+	struct list_head	eh_cmd_q;
+	struct task_struct    * ehandler;  /* Error recovery thread. */
+	struct semaphore      * eh_wait;   /* The error recovery thread waits
+					      on this. */
+	struct completion     * eh_notify; /* wait for eh to begin or end */
+	struct semaphore      * eh_action; /* Wait for specific actions on the
+                                          host. */
+	unsigned int            eh_active:1; /* Indicates the eh thread is awake and active if
+                                          this is true. */
+	unsigned int            eh_kill:1; /* set when killing the eh thread */
+	wait_queue_head_t       host_wait;
+	struct scsi_host_template *hostt;
+	struct scsi_transport_template *transportt;
+	volatile unsigned short host_busy;   /* commands actually active on low-level */
+	volatile unsigned short host_failed; /* commands that failed. */
+    
+	unsigned short host_no;  /* Used for IOCTL_GET_IDLUN, /proc/scsi et al. */
+	int resetting; /* if set, it means that last_reset is a valid value */
+	unsigned long last_reset;
+
+	/*
+	 * These three parameters can be used to allow for wide scsi,
+	 * and for host adapters that support multiple busses
+	 * The first two should be set to 1 more than the actual max id
+	 * or lun (i.e. 8 for normal systems).
+	 */
+	unsigned int max_id;
+	unsigned int max_lun;
+	unsigned int max_channel;
+
+	/*
+	 * This is a unique identifier that must be assigned so that we
+	 * have some way of identifying each detected host adapter properly
+	 * and uniquely.  For hosts that do not support more than one card
+	 * in the system at one time, this does not need to be set.  It is
+	 * initialized to 0 in scsi_register.
+	 */
+	unsigned int unique_id;
+
+	/*
+	 * The maximum length of SCSI commands that this host can accept.
+	 * Probably 12 for most host adapters, but could be 16 for others.
+	 * For drivers that don't set this field, a value of 12 is
+	 * assumed.  I am leaving this as a number rather than a bit
+	 * because you never know what subsequent SCSI standards might do
+	 * (i.e. could there be a 20 byte or a 24-byte command a few years
+	 * down the road?).  
+	 */
+	unsigned char max_cmd_len;
+
+	int this_id;
+	int can_queue;
+	short cmd_per_lun;
+	short unsigned int sg_tablesize;
+	short unsigned int max_sectors;
+	unsigned long dma_boundary;
+	/* 
+	 * Used to assign serial numbers to the cmds.
+	 * Protected by the host lock.
+	 */
+	unsigned long cmd_serial_number, cmd_pid; 
+	
+	unsigned unchecked_isa_dma:1;
+	unsigned use_clustering:1;
+	unsigned use_blk_tcq:1;
+
+	/*
+	 * Host has requested that no further requests come through for the
+	 * time being.
+	 */
+	unsigned host_self_blocked:1;
+    
+	/*
+	 * Host uses correct SCSI ordering not PC ordering. The bit is
+	 * set for the minority of drivers whose authors actually read
+	 * the spec ;)
+	 */
+	unsigned reverse_ordering:1;
+
+	/*
+	 * ordered write support
+	 */
+	unsigned ordered_flush:1;
+	unsigned ordered_tag:1;
+
+	/*
+	 * Optional work queue to be utilized by the transport
+	 */
+	char work_q_name[KOBJ_NAME_LEN];
+	struct workqueue_struct *work_q;
+
+	/*
+	 * Host has rejected a command because it was busy.
+	 */
+	unsigned int host_blocked;
+
+	/*
+	 * Value host_blocked counts down from
+	 */
+	unsigned int max_host_blocked;
+
+	/* legacy crap */
+	unsigned long base;
+	unsigned long io_port;
+	unsigned char n_io_port;
+	unsigned char dma_channel;
+	unsigned int  irq;
+	
+
+	unsigned long shost_state;
+
+	/* ldm bits */
+	struct device		shost_gendev;
+	struct class_device	shost_classdev;
+
+	/*
+	 * List of hosts per template.
+	 *
+	 * This is only for use by scsi_module.c for legacy templates.
+	 * For these access to it is synchronized implicitly by
+	 * module_init/module_exit.
+	 */
+	struct list_head sht_legacy_list;
+
+	/*
+	 * Points to the transport data (if any) which is allocated
+	 * separately
+	 */
+	void *shost_data;
+
+	/*
+	 * We should ensure that this is aligned, both for better performance
+	 * and also because some compilers (m68k) don't automatically force
+	 * alignment to a long boundary.
+	 */
+	unsigned long hostdata[0]  /* Used for storage of host specific stuff */
+		__attribute__ ((aligned (sizeof(unsigned long))));
+};
+
+#define		class_to_shost(d)	\
+	container_of(d, struct Scsi_Host, shost_classdev)
+
+int scsi_is_host_device(const struct device *);
+
+static inline struct Scsi_Host *dev_to_shost(struct device *dev)
+{
+	while (!scsi_is_host_device(dev)) {
+		if (!dev->parent)
+			return NULL;
+		dev = dev->parent;
+	}
+	return container_of(dev, struct Scsi_Host, shost_gendev);
+}
+
+extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *);
+extern void scsi_flush_work(struct Scsi_Host *);
+
+extern struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *, int);
+extern int __must_check scsi_add_host(struct Scsi_Host *, struct device *);
+extern void scsi_scan_host(struct Scsi_Host *);
+extern void scsi_scan_single_target(struct Scsi_Host *, unsigned int,
+	unsigned int);
+extern void scsi_rescan_device(struct device *);
+extern void scsi_remove_host(struct Scsi_Host *);
+extern struct Scsi_Host *scsi_host_get(struct Scsi_Host *);
+extern void scsi_host_put(struct Scsi_Host *t);
+extern struct Scsi_Host *scsi_host_lookup(unsigned short);
+
+extern u64 scsi_calculate_bounce_limit(struct Scsi_Host *);
+
+static inline void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock)
+{
+	shost->host_lock = lock;
+}
+
+static inline void scsi_set_device(struct Scsi_Host *shost,
+                                   struct device *dev)
+{
+        shost->shost_gendev.parent = dev;
+}
+
+static inline struct device *scsi_get_device(struct Scsi_Host *shost)
+{
+        return shost->shost_gendev.parent;
+}
+
+extern void scsi_unblock_requests(struct Scsi_Host *);
+extern void scsi_block_requests(struct Scsi_Host *);
+
+struct class_container;
+/*
+ * These two functions are used to allocate and free a pseudo device
+ * which will connect to the host adapter itself rather than any
+ * physical device.  You must deallocate when you are done with the
+ * thing.  This physical pseudo-device isn't real and won't be available
+ * from any high-level drivers.
+ */
+extern void scsi_free_host_dev(struct scsi_device *);
+extern struct scsi_device *scsi_get_host_dev(struct Scsi_Host *);
+
+/* legacy interfaces */
+extern struct Scsi_Host *scsi_register(struct scsi_host_template *, int);
+extern void scsi_unregister(struct Scsi_Host *);
+
+#endif /* _SCSI_SCSI_HOST_H */
diff --git a/include/scsi/scsi_ioctl.h b/include/scsi/scsi_ioctl.h
new file mode 100644
index 0000000..d4be4d9
--- /dev/null
+++ b/include/scsi/scsi_ioctl.h
@@ -0,0 +1,50 @@
+#ifndef _SCSI_IOCTL_H
+#define _SCSI_IOCTL_H 
+
+#define SCSI_IOCTL_SEND_COMMAND 1
+#define SCSI_IOCTL_TEST_UNIT_READY 2
+#define SCSI_IOCTL_BENCHMARK_COMMAND 3
+#define SCSI_IOCTL_SYNC 4			/* Request synchronous parameters */
+#define SCSI_IOCTL_START_UNIT 5
+#define SCSI_IOCTL_STOP_UNIT 6
+/* The door lock/unlock constants are compatible with Sun constants for
+   the cdrom */
+#define SCSI_IOCTL_DOORLOCK 0x5380		/* lock the eject mechanism */
+#define SCSI_IOCTL_DOORUNLOCK 0x5381		/* unlock the mechanism	  */
+
+#define	SCSI_REMOVAL_PREVENT	1
+#define	SCSI_REMOVAL_ALLOW	0
+
+#ifdef __KERNEL__
+
+struct scsi_device;
+
+/*
+ * Structures used for scsi_ioctl et al.
+ */
+
+typedef struct scsi_ioctl_command {
+	unsigned int inlen;
+	unsigned int outlen;
+	unsigned char data[0];
+} Scsi_Ioctl_Command;
+
+typedef struct scsi_idlun {
+	__u32 dev_id;
+	__u32 host_unique_id;
+} Scsi_Idlun;
+
+/* Fibre Channel WWN, port_id struct */
+typedef struct scsi_fctargaddress {
+	__u32 host_port_id;
+	unsigned char host_wwn[8]; // include NULL term.
+} Scsi_FCTargAddress;
+
+extern int scsi_ioctl(struct scsi_device *, int, void __user *);
+extern int scsi_ioctl_send_command(struct scsi_device *,
+				   struct scsi_ioctl_command __user *);
+extern int scsi_nonblockable_ioctl(struct scsi_device *sdev, int cmd,
+				   void __user *arg, struct file *filp);
+
+#endif /* __KERNEL__ */
+#endif /* _SCSI_IOCTL_H */
diff --git a/include/scsi/scsi_request.h b/include/scsi/scsi_request.h
new file mode 100644
index 0000000..9871940
--- /dev/null
+++ b/include/scsi/scsi_request.h
@@ -0,0 +1,73 @@
+#ifndef _SCSI_SCSI_REQUEST_H
+#define _SCSI_SCSI_REQUEST_H
+
+#include <scsi/scsi_cmnd.h>
+
+struct request;
+struct scsi_cmnd;
+struct scsi_device;
+struct Scsi_Host;
+
+
+/*
+ * This is essentially a slimmed down version of Scsi_Cmnd.  The point of
+ * having this is that requests that are injected into the queue as result
+ * of things like ioctls and character devices shouldn't be using a
+ * Scsi_Cmnd until such a time that the command is actually at the head
+ * of the queue and being sent to the driver.
+ */
+struct scsi_request {
+	int     sr_magic;
+	int     sr_result;	/* Status code from lower level driver */
+	unsigned char sr_sense_buffer[SCSI_SENSE_BUFFERSIZE];		/* obtained by REQUEST SENSE
+						 * when CHECK CONDITION is
+						 * received on original command 
+						 * (auto-sense) */
+
+	struct Scsi_Host *sr_host;
+	struct scsi_device *sr_device;
+	struct scsi_cmnd *sr_command;
+	struct request *sr_request;	/* A copy of the command we are
+				   working on */
+	unsigned sr_bufflen;	/* Size of data buffer */
+	void *sr_buffer;		/* Data buffer */
+	int sr_allowed;
+	enum dma_data_direction sr_data_direction;
+	unsigned char sr_cmd_len;
+	unsigned char sr_cmnd[MAX_COMMAND_SIZE];
+	void (*sr_done) (struct scsi_cmnd *);	/* Mid-level done function */
+	int sr_timeout_per_command;
+	unsigned short sr_use_sg;	/* Number of pieces of scatter-gather */
+	unsigned short sr_sglist_len;	/* size of malloc'd scatter-gather list */
+	unsigned sr_underflow;	/* Return error if less than
+				   this amount is transferred */
+ 	void *upper_private_data;	/* reserved for owner (usually upper
+ 					   level driver) of this request */
+};
+
+extern struct scsi_request *scsi_allocate_request(struct scsi_device *, int);
+extern void scsi_release_request(struct scsi_request *);
+extern void scsi_wait_req(struct scsi_request *, const void *cmnd,
+			  void *buffer, unsigned bufflen,
+			  int timeout, int retries);
+extern void scsi_do_req(struct scsi_request *, const void *cmnd,
+			void *buffer, unsigned bufflen,
+			void (*done) (struct scsi_cmnd *),
+			int timeout, int retries);
+
+struct scsi_mode_data {
+	__u32	length;
+	__u16	block_descriptor_length;
+	__u8	medium_type;
+	__u8	device_specific;
+	__u8	header_length;
+	__u8	longlba:1;
+};
+
+extern int __scsi_mode_sense(struct scsi_request *SRpnt, int dbd,
+			     int modepage, unsigned char *buffer, int len,
+			     int timeout, int retries,
+			     struct scsi_mode_data *data);
+
+
+#endif /* _SCSI_SCSI_REQUEST_H */
diff --git a/include/scsi/scsi_tcq.h b/include/scsi/scsi_tcq.h
new file mode 100644
index 0000000..e47e36a
--- /dev/null
+++ b/include/scsi/scsi_tcq.h
@@ -0,0 +1,134 @@
+#ifndef _SCSI_SCSI_TCQ_H
+#define _SCSI_SCSI_TCQ_H
+
+#include <linux/blkdev.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+
+
+#define MSG_SIMPLE_TAG	0x20
+#define MSG_HEAD_TAG	0x21
+#define MSG_ORDERED_TAG	0x22
+
+#define SCSI_NO_TAG	(-1)    /* identify no tag in use */
+
+
+
+/**
+ * scsi_get_tag_type - get the type of tag the device supports
+ * @sdev:	the scsi device
+ *
+ * Notes:
+ *	If the drive only supports simple tags, returns MSG_SIMPLE_TAG
+ *	if it supports all tag types, returns MSG_ORDERED_TAG.
+ */
+static inline int scsi_get_tag_type(struct scsi_device *sdev)
+{
+	if (!sdev->tagged_supported)
+		return 0;
+	if (sdev->ordered_tags)
+		return MSG_ORDERED_TAG;
+	if (sdev->simple_tags)
+		return MSG_SIMPLE_TAG;
+	return 0;
+}
+
+static inline void scsi_set_tag_type(struct scsi_device *sdev, int tag)
+{
+	switch (tag) {
+	case MSG_ORDERED_TAG:
+		sdev->ordered_tags = 1;
+		/* fall through */
+	case MSG_SIMPLE_TAG:
+		sdev->simple_tags = 1;
+		break;
+	case 0:
+		/* fall through */
+	default:
+		sdev->ordered_tags = 0;
+		sdev->simple_tags = 0;
+		break;
+	}
+}
+/**
+ * scsi_activate_tcq - turn on tag command queueing
+ * @SDpnt:	device to turn on TCQ for
+ * @depth:	queue depth
+ *
+ * Notes:
+ *	Eventually, I hope depth would be the maximum depth
+ *	the device could cope with and the real queue depth
+ *	would be adjustable from 0 to depth.
+ **/
+static inline void scsi_activate_tcq(struct scsi_device *sdev, int depth)
+{
+	if (!sdev->tagged_supported)
+		return;
+
+	if (!blk_queue_tagged(sdev->request_queue))
+		blk_queue_init_tags(sdev->request_queue, depth, NULL);
+
+	scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
+}
+
+/**
+ * scsi_deactivate_tcq - turn off tag command queueing
+ * @SDpnt:	device to turn off TCQ for
+ **/
+static inline void scsi_deactivate_tcq(struct scsi_device *sdev, int depth)
+{
+	if (blk_queue_tagged(sdev->request_queue))
+		blk_queue_free_tags(sdev->request_queue);
+	scsi_adjust_queue_depth(sdev, 0, depth);
+}
+
+/**
+ * scsi_populate_tag_msg - place a tag message in a buffer
+ * @SCpnt:	pointer to the Scsi_Cmnd for the tag
+ * @msg:	pointer to the area to place the tag
+ *
+ * Notes:
+ *	designed to create the correct type of tag message for the 
+ *	particular request.  Returns the size of the tag message.
+ *	May return 0 if TCQ is disabled for this device.
+ **/
+static inline int scsi_populate_tag_msg(struct scsi_cmnd *cmd, char *msg)
+{
+        struct request *req = cmd->request;
+	struct scsi_device *sdev = cmd->device;
+
+        if (blk_rq_tagged(req)) {
+		if (sdev->ordered_tags && req->flags & REQ_HARDBARRIER)
+        	        *msg++ = MSG_ORDERED_TAG;
+        	else
+        	        *msg++ = MSG_SIMPLE_TAG;
+        	*msg++ = req->tag;
+        	return 2;
+	}
+
+	return 0;
+}
+
+/**
+ * scsi_find_tag - find a tagged command by device
+ * @SDpnt:	pointer to the ScSI device
+ * @tag:	the tag number
+ *
+ * Notes:
+ *	Only works with tags allocated by the generic blk layer.
+ **/
+static inline struct scsi_cmnd *scsi_find_tag(struct scsi_device *sdev, int tag)
+{
+
+        struct request *req;
+
+        if (tag != SCSI_NO_TAG) {
+        	req = blk_queue_find_tag(sdev->request_queue, tag);
+	        return req ? (struct scsi_cmnd *)req->special : NULL;
+	}
+
+	/* single command, look in space */
+	return sdev->current_cmnd;
+}
+
+#endif /* _SCSI_SCSI_TCQ_H */
diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h
new file mode 100644
index 0000000..2dcee7a
--- /dev/null
+++ b/include/scsi/scsi_transport.h
@@ -0,0 +1,48 @@
+/* 
+ *  Transport specific attributes.
+ *
+ *  Copyright (c) 2003 Silicon Graphics, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef SCSI_TRANSPORT_H
+#define SCSI_TRANSPORT_H
+
+#include <linux/transport_class.h>
+
+struct scsi_transport_template {
+	/* the attribute containers */
+	struct transport_container host_attrs;
+	struct transport_container target_attrs;
+	struct transport_container device_attrs;
+
+	/* The size of the specific transport attribute structure (a
+	 * space of this size will be left at the end of the
+	 * scsi_* structure */
+	int	device_size;
+	int	target_size;
+	int	host_size;
+
+	/*
+	 * True if the transport wants to use a host-based work-queue
+	 */
+	unsigned int create_work_queue : 1;
+};
+
+#define transport_class_to_shost(tc) \
+	dev_to_shost((tc)->dev)
+
+
+#endif /* SCSI_TRANSPORT_H */
diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h
new file mode 100644
index 0000000..70ad163
--- /dev/null
+++ b/include/scsi/scsi_transport_fc.h
@@ -0,0 +1,442 @@
+/* 
+ *  FiberChannel transport specific attributes exported to sysfs.
+ *
+ *  Copyright (c) 2003 Silicon Graphics, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  ========
+ *
+ *  Copyright (C) 2004-2005   James Smart, Emulex Corporation
+ *    Rewrite for host, target, device, and remote port attributes,
+ *    statistics, and service functions...
+ *
+ */
+#ifndef SCSI_TRANSPORT_FC_H
+#define SCSI_TRANSPORT_FC_H
+
+#include <linux/config.h>
+
+struct scsi_transport_template;
+
+
+/*
+ * FC Port definitions - Following FC HBAAPI guidelines
+ *
+ * Note: Not all binary values for the different fields match HBAAPI.
+ *  Instead, we use densely packed ordinal values or enums.
+ *  We get away with this as we never present the actual binary values
+ *  externally. For sysfs, we always present the string that describes
+ *  the value. Thus, an admin doesn't need a magic HBAAPI decoder ring
+ *  to understand the values. The HBAAPI user-space library is free to
+ *  convert the strings into the HBAAPI-specified binary values.
+ *
+ * Note: Not all HBAAPI-defined values are contained in the definitions
+ *  below. Those not appropriate to an fc_host (e.g. FCP initiator) have
+ *  been removed.
+ */
+
+/*
+ * fc_port_type: If you alter this, you also need to alter scsi_transport_fc.c
+ * (for the ascii descriptions).
+ */
+enum fc_port_type {
+	FC_PORTTYPE_UNKNOWN,
+	FC_PORTTYPE_OTHER,
+	FC_PORTTYPE_NOTPRESENT,
+	FC_PORTTYPE_NPORT,		/* Attached to FPort */
+	FC_PORTTYPE_NLPORT,		/* (Public) Loop w/ FLPort */
+	FC_PORTTYPE_LPORT,		/* (Private) Loop w/o FLPort */
+	FC_PORTTYPE_PTP,		/* Point to Point w/ another NPort */
+};
+
+/*
+ * fc_port_state: If you alter this, you also need to alter scsi_transport_fc.c
+ * (for the ascii descriptions).
+ */
+enum fc_port_state {
+	FC_PORTSTATE_UNKNOWN,
+	FC_PORTSTATE_NOTPRESENT,
+	FC_PORTSTATE_ONLINE,
+	FC_PORTSTATE_OFFLINE,		/* User has taken Port Offline */
+	FC_PORTSTATE_BLOCKED,
+	FC_PORTSTATE_BYPASSED,
+	FC_PORTSTATE_DIAGNOSTICS,
+	FC_PORTSTATE_LINKDOWN,
+	FC_PORTSTATE_ERROR,
+	FC_PORTSTATE_LOOPBACK,
+};
+
+
+/* 
+ * FC Classes of Service
+ * Note: values are not enumerated, as they can be "or'd" together
+ * for reporting (e.g. report supported_classes). If you alter this list,
+ * you also need to alter scsi_transport_fc.c (for the ascii descriptions).
+ */
+#define FC_COS_UNSPECIFIED		0
+#define FC_COS_CLASS1			2
+#define FC_COS_CLASS2			4
+#define FC_COS_CLASS3			8
+#define FC_COS_CLASS4			0x10
+#define FC_COS_CLASS6			0x40
+
+/* 
+ * FC Port Speeds
+ * Note: values are not enumerated, as they can be "or'd" together
+ * for reporting (e.g. report supported_speeds). If you alter this list,
+ * you also need to alter scsi_transport_fc.c (for the ascii descriptions).
+ */
+#define FC_PORTSPEED_UNKNOWN		0 /* Unknown - transceiver
+					     incapable of reporting */
+#define FC_PORTSPEED_1GBIT		1
+#define FC_PORTSPEED_2GBIT		2
+#define FC_PORTSPEED_10GBIT		4
+#define FC_PORTSPEED_4GBIT		8
+#define FC_PORTSPEED_NOT_NEGOTIATED	(1 << 15) /* Speed not established */
+
+/*
+ * fc_tgtid_binding_type: If you alter this, you also need to alter
+ * scsi_transport_fc.c (for the ascii descriptions).
+ */
+enum fc_tgtid_binding_type  {
+	FC_TGTID_BIND_NONE,
+	FC_TGTID_BIND_BY_WWPN,
+	FC_TGTID_BIND_BY_WWNN,
+	FC_TGTID_BIND_BY_ID,
+};
+
+/*
+ * FC Remote Port Roles
+ * Note: values are not enumerated, as they can be "or'd" together
+ * for reporting (e.g. report roles). If you alter this list,
+ * you also need to alter scsi_transport_fc.c (for the ascii descriptions).
+ */
+#define FC_RPORT_ROLE_UNKNOWN			0x00
+#define FC_RPORT_ROLE_FCP_TARGET		0x01
+#define FC_RPORT_ROLE_FCP_INITIATOR		0x02
+#define FC_RPORT_ROLE_IP_PORT			0x04
+
+
+/*
+ * fc_rport_identifiers: This set of data contains all elements
+ * to uniquely identify a remote FC port. The driver uses this data
+ * to report the existence of a remote FC port in the topology. Internally,
+ * the transport uses this data for attributes and to manage consistent
+ * target id bindings.
+ */
+struct fc_rport_identifiers {
+	u64 node_name;
+	u64 port_name;
+	u32 port_id;
+	u32 roles;
+};
+
+/* Macro for use in defining Remote Port attributes */
+#define FC_RPORT_ATTR(_name,_mode,_show,_store)				\
+struct class_device_attribute class_device_attr_rport_##_name = 	\
+	__ATTR(_name,_mode,_show,_store)
+
+
+/*
+ * FC Remote Port Attributes
+ *
+ * This structure exists for each remote FC port that a LLDD notifies
+ * the subsystem of.  A remote FC port may or may not be a SCSI Target,
+ * also be a SCSI initiator, IP endpoint, etc. As such, the remote
+ * port is considered a separate entity, independent of "role" (such
+ * as scsi target).
+ *
+ * --
+ *
+ * Attributes are based on HBAAPI V2.0 definitions. Only those
+ * attributes that are determinable by the local port (aka Host)
+ * are contained.
+ *
+ * Fixed attributes are not expected to change. The driver is
+ * expected to set these values after successfully calling
+ * fc_remote_port_add(). The transport fully manages all get functions
+ * w/o driver interaction.
+ *
+ * Dynamic attributes are expected to change. The driver participates
+ * in all get/set operations via functions provided by the driver.
+ *
+ * Private attributes are transport-managed values. They are fully
+ * managed by the transport w/o driver interaction.
+ */
+
+struct fc_rport {	/* aka fc_starget_attrs */
+	/* Fixed Attributes */
+	u32 maxframe_size;
+	u32 supported_classes;
+
+	/* Dynamic Attributes */
+	u32 dev_loss_tmo;	/* Remote Port loss timeout in seconds. */
+
+	/* Private (Transport-managed) Attributes */
+	u64 node_name;
+	u64 port_name;
+	u32 port_id;
+	u32 roles;
+	enum fc_port_state port_state;	/* Will only be ONLINE or UNKNOWN */
+	u32 scsi_target_id;
+
+	/* exported data */
+	void *dd_data;			/* Used for driver-specific storage */
+
+	/* internal data */
+	unsigned int channel;
+	u32 number;
+	struct list_head peers;
+	struct device dev;
+ 	struct work_struct dev_loss_work;
+ 	struct work_struct scan_work;
+} __attribute__((aligned(sizeof(unsigned long))));
+
+#define	dev_to_rport(d)				\
+	container_of(d, struct fc_rport, dev)
+#define transport_class_to_rport(classdev)	\
+	dev_to_rport(classdev->dev)
+#define rport_to_shost(r)			\
+	dev_to_shost(r->dev.parent)
+
+/*
+ * FC SCSI Target Attributes
+ *
+ * The SCSI Target is considered an extention of a remote port (as
+ * a remote port can be more than a SCSI Target). Within the scsi
+ * subsystem, we leave the Target as a separate entity. Doing so
+ * provides backward compatibility with prior FC transport api's,
+ * and lets remote ports be handled entirely within the FC transport
+ * and independently from the scsi subsystem. The drawback is that
+ * some data will be duplicated.
+ */
+
+struct fc_starget_attrs {	/* aka fc_target_attrs */
+	/* Dynamic Attributes */
+	u64 node_name;
+	u64 port_name;
+	u32 port_id;
+};
+
+#define fc_starget_node_name(x) \
+	(((struct fc_starget_attrs *)&(x)->starget_data)->node_name)
+#define fc_starget_port_name(x)	\
+	(((struct fc_starget_attrs *)&(x)->starget_data)->port_name)
+#define fc_starget_port_id(x) \
+	(((struct fc_starget_attrs *)&(x)->starget_data)->port_id)
+
+#define starget_to_rport(s)			\
+	scsi_is_fc_rport(s->dev.parent) ? dev_to_rport(s->dev.parent) : NULL
+
+
+/*
+ * FC Local Port (Host) Statistics
+ */
+
+/* FC Statistics - Following FC HBAAPI v2.0 guidelines */
+struct fc_host_statistics {
+	/* port statistics */
+	u64 seconds_since_last_reset;
+	u64 tx_frames;
+	u64 tx_words;
+	u64 rx_frames;
+	u64 rx_words;
+	u64 lip_count;
+	u64 nos_count;
+	u64 error_frames;
+	u64 dumped_frames;
+	u64 link_failure_count;
+	u64 loss_of_sync_count;
+	u64 loss_of_signal_count;
+	u64 prim_seq_protocol_err_count;
+	u64 invalid_tx_word_count;
+	u64 invalid_crc_count;
+	
+	/* fc4 statistics  (only FCP supported currently) */
+	u64 fcp_input_requests;
+	u64 fcp_output_requests;
+	u64 fcp_control_requests;
+	u64 fcp_input_megabytes;
+	u64 fcp_output_megabytes;
+};
+
+
+/*
+ * FC Local Port (Host) Attributes
+ *
+ * Attributes are based on HBAAPI V2.0 definitions.
+ * Note: OSDeviceName is determined by user-space library
+ *
+ * Fixed attributes are not expected to change. The driver is
+ * expected to set these values after successfully calling scsi_add_host().
+ * The transport fully manages all get functions w/o driver interaction.
+ *
+ * Dynamic attributes are expected to change. The driver participates
+ * in all get/set operations via functions provided by the driver.
+ *
+ * Private attributes are transport-managed values. They are fully
+ * managed by the transport w/o driver interaction.
+ */
+
+#define FC_FC4_LIST_SIZE		32
+#define FC_SYMBOLIC_NAME_SIZE		256
+#define FC_VERSION_STRING_SIZE		64
+#define FC_SERIAL_NUMBER_SIZE		80
+
+struct fc_host_attrs {
+	/* Fixed Attributes */
+	u64 node_name;
+	u64 port_name;
+	u32 supported_classes;
+	u8  supported_fc4s[FC_FC4_LIST_SIZE];
+	char symbolic_name[FC_SYMBOLIC_NAME_SIZE];
+	u32 supported_speeds;
+	u32 maxframe_size;
+	char serial_number[FC_SERIAL_NUMBER_SIZE];
+
+	/* Dynamic Attributes */
+	u32 port_id;
+	enum fc_port_type port_type;
+	enum fc_port_state port_state;
+	u8  active_fc4s[FC_FC4_LIST_SIZE];
+	u32 speed;
+	u64 fabric_name;
+
+	/* Private (Transport-managed) Attributes */
+	enum fc_tgtid_binding_type  tgtid_bind_type;
+
+	/* internal data */
+	struct list_head rports;
+	struct list_head rport_bindings;
+	u32 next_rport_number;
+	u32 next_target_id;
+};
+
+#define fc_host_node_name(x) \
+	(((struct fc_host_attrs *)(x)->shost_data)->node_name)
+#define fc_host_port_name(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->port_name)
+#define fc_host_supported_classes(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->supported_classes)
+#define fc_host_supported_fc4s(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->supported_fc4s)
+#define fc_host_symbolic_name(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->symbolic_name)
+#define fc_host_supported_speeds(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->supported_speeds)
+#define fc_host_maxframe_size(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->maxframe_size)
+#define fc_host_serial_number(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->serial_number)
+#define fc_host_port_id(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->port_id)
+#define fc_host_port_type(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->port_type)
+#define fc_host_port_state(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->port_state)
+#define fc_host_active_fc4s(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->active_fc4s)
+#define fc_host_speed(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->speed)
+#define fc_host_fabric_name(x)	\
+	(((struct fc_host_attrs *)(x)->shost_data)->fabric_name)
+#define fc_host_tgtid_bind_type(x) \
+	(((struct fc_host_attrs *)(x)->shost_data)->tgtid_bind_type)
+#define fc_host_rports(x) \
+	(((struct fc_host_attrs *)(x)->shost_data)->rports)
+#define fc_host_rport_bindings(x) \
+	(((struct fc_host_attrs *)(x)->shost_data)->rport_bindings)
+#define fc_host_next_rport_number(x) \
+	(((struct fc_host_attrs *)(x)->shost_data)->next_rport_number)
+#define fc_host_next_target_id(x) \
+	(((struct fc_host_attrs *)(x)->shost_data)->next_target_id)
+
+
+/* The functions by which the transport class and the driver communicate */
+struct fc_function_template {
+	void    (*get_rport_dev_loss_tmo)(struct fc_rport *);
+	void	(*set_rport_dev_loss_tmo)(struct fc_rport *, u32);
+
+	void	(*get_starget_node_name)(struct scsi_target *);
+	void	(*get_starget_port_name)(struct scsi_target *);
+	void 	(*get_starget_port_id)(struct scsi_target *);
+
+	void 	(*get_host_port_id)(struct Scsi_Host *);
+	void	(*get_host_port_type)(struct Scsi_Host *);
+	void	(*get_host_port_state)(struct Scsi_Host *);
+	void	(*get_host_active_fc4s)(struct Scsi_Host *);
+	void	(*get_host_speed)(struct Scsi_Host *);
+	void	(*get_host_fabric_name)(struct Scsi_Host *);
+
+	struct fc_host_statistics * (*get_fc_host_stats)(struct Scsi_Host *);
+	void	(*reset_fc_host_stats)(struct Scsi_Host *);
+
+	/* allocation lengths for host-specific data */
+	u32	 			dd_fcrport_size;
+
+	/* 
+	 * The driver sets these to tell the transport class it
+	 * wants the attributes displayed in sysfs.  If the show_ flag
+	 * is not set, the attribute will be private to the transport
+	 * class 
+	 */
+
+	/* remote port fixed attributes */
+	unsigned long	show_rport_maxframe_size:1;
+	unsigned long	show_rport_supported_classes:1;
+	unsigned long   show_rport_dev_loss_tmo:1;
+
+	/*
+	 * target dynamic attributes
+	 * These should all be "1" if the driver uses the remote port
+	 * add/delete functions (so attributes reflect rport values).
+	 */
+	unsigned long	show_starget_node_name:1;
+	unsigned long	show_starget_port_name:1;
+	unsigned long	show_starget_port_id:1;
+
+	/* host fixed attributes */
+	unsigned long	show_host_node_name:1;
+	unsigned long	show_host_port_name:1;
+	unsigned long	show_host_supported_classes:1;
+	unsigned long	show_host_supported_fc4s:1;
+	unsigned long	show_host_symbolic_name:1;
+	unsigned long	show_host_supported_speeds:1;
+	unsigned long	show_host_maxframe_size:1;
+	unsigned long	show_host_serial_number:1;
+	/* host dynamic attributes */
+	unsigned long	show_host_port_id:1;
+	unsigned long	show_host_port_type:1;
+	unsigned long	show_host_port_state:1;
+	unsigned long	show_host_active_fc4s:1;
+	unsigned long	show_host_speed:1;
+	unsigned long	show_host_fabric_name:1;
+};
+
+
+struct scsi_transport_template *fc_attach_transport(
+			struct fc_function_template *);
+void fc_release_transport(struct scsi_transport_template *);
+void fc_remove_host(struct Scsi_Host *);
+struct fc_rport *fc_remote_port_add(struct Scsi_Host *shost,
+			int channel, struct fc_rport_identifiers  *ids);
+void fc_remote_port_delete(struct fc_rport  *rport);
+void fc_remote_port_rolechg(struct fc_rport  *rport, u32 roles);
+int fc_remote_port_block(struct fc_rport *rport);
+void fc_remote_port_unblock(struct fc_rport *rport);
+int scsi_is_fc_rport(const struct device *);
+
+#endif /* SCSI_TRANSPORT_FC_H */
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
new file mode 100644
index 0000000..1b26a6c
--- /dev/null
+++ b/include/scsi/scsi_transport_iscsi.h
@@ -0,0 +1,178 @@
+/* 
+ * iSCSI transport class definitions
+ *
+ * Copyright (C) IBM Corporation, 2004
+ * Copyright (C) Mike Christie, 2004
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+#ifndef SCSI_TRANSPORT_ISCSI_H
+#define SCSI_TRANSPORT_ISCSI_H
+
+#include <linux/config.h>
+#include <linux/in6.h>
+#include <linux/in.h>
+
+struct scsi_transport_template;
+
+struct iscsi_class_session {
+	uint8_t isid[6];
+	uint16_t tsih;
+	int header_digest;		/* 1 CRC32, 0 None */
+	int data_digest;		/* 1 CRC32, 0 None */
+	uint16_t tpgt;
+	union {
+		struct in6_addr sin6_addr;
+		struct in_addr sin_addr;
+	} u;
+	sa_family_t addr_type;		/* must be AF_INET or AF_INET6 */
+	uint16_t port;			/* must be in network byte order */
+	int initial_r2t;		/* 1 Yes, 0 No */
+	int immediate_data;		/* 1 Yes, 0 No */
+	uint32_t max_recv_data_segment_len;
+	uint32_t max_burst_len;
+	uint32_t first_burst_len;
+	uint16_t def_time2wait;
+	uint16_t def_time2retain;
+	uint16_t max_outstanding_r2t;
+	int data_pdu_in_order;		/* 1 Yes, 0 No */
+	int data_sequence_in_order;	/* 1 Yes, 0 No */
+	int erl;
+};
+
+/*
+ * accessor macros
+ */
+#define iscsi_isid(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->isid)
+#define iscsi_tsih(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->tsih)
+#define iscsi_header_digest(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->header_digest)
+#define iscsi_data_digest(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->data_digest)
+#define iscsi_port(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->port)
+#define iscsi_addr_type(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->addr_type)
+#define iscsi_sin_addr(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->u.sin_addr)
+#define iscsi_sin6_addr(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->u.sin6_addr)
+#define iscsi_tpgt(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->tpgt)
+#define iscsi_initial_r2t(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->initial_r2t)
+#define iscsi_immediate_data(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->immediate_data)
+#define iscsi_max_recv_data_segment_len(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->max_recv_data_segment_len)
+#define iscsi_max_burst_len(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->max_burst_len)
+#define iscsi_first_burst_len(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->first_burst_len)
+#define iscsi_def_time2wait(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->def_time2wait)
+#define iscsi_def_time2retain(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->def_time2retain)
+#define iscsi_max_outstanding_r2t(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->max_outstanding_r2t)
+#define iscsi_data_pdu_in_order(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->data_pdu_in_order)
+#define iscsi_data_sequence_in_order(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->data_sequence_in_order)
+#define iscsi_erl(x) \
+	(((struct iscsi_class_session *)&(x)->starget_data)->erl)
+
+/*
+ * The functions by which the transport class and the driver communicate
+ */
+struct iscsi_function_template {
+	/*
+	 * target attrs
+	 */
+	void (*get_isid)(struct scsi_target *);
+	void (*get_tsih)(struct scsi_target *);
+	void (*get_header_digest)(struct scsi_target *);
+	void (*get_data_digest)(struct scsi_target *);
+	void (*get_port)(struct scsi_target *);
+	void (*get_tpgt)(struct scsi_target *);
+	/*
+	 * In get_ip_address the lld must set the address and
+	 * the address type
+	 */
+	void (*get_ip_address)(struct scsi_target *);
+	/*
+	 * The lld should snprintf the name or alias to the buffer
+	 */
+	ssize_t (*get_target_name)(struct scsi_target *, char *, ssize_t);
+	ssize_t (*get_target_alias)(struct scsi_target *, char *, ssize_t);
+	void (*get_initial_r2t)(struct scsi_target *);
+	void (*get_immediate_data)(struct scsi_target *);
+	void (*get_max_recv_data_segment_len)(struct scsi_target *);
+	void (*get_max_burst_len)(struct scsi_target *);
+	void (*get_first_burst_len)(struct scsi_target *);
+	void (*get_def_time2wait)(struct scsi_target *);
+	void (*get_def_time2retain)(struct scsi_target *);
+	void (*get_max_outstanding_r2t)(struct scsi_target *);
+	void (*get_data_pdu_in_order)(struct scsi_target *);
+	void (*get_data_sequence_in_order)(struct scsi_target *);
+	void (*get_erl)(struct scsi_target *);
+
+	/*
+	 * host atts
+	 */
+
+	/*
+	 * The lld should snprintf the name or alias to the buffer
+	 */
+	ssize_t (*get_initiator_alias)(struct Scsi_Host *, char *, ssize_t);
+	ssize_t (*get_initiator_name)(struct Scsi_Host *, char *, ssize_t);
+	/*
+	 * The driver sets these to tell the transport class it
+	 * wants the attributes displayed in sysfs.  If the show_ flag
+	 * is not set, the attribute will be private to the transport
+	 * class. We could probably just test if a get_ fn was set
+	 * since we only use the values for sysfs but this is how
+	 * fc does it too.
+	 */
+	unsigned long show_isid:1;
+	unsigned long show_tsih:1;
+	unsigned long show_header_digest:1;
+	unsigned long show_data_digest:1;
+	unsigned long show_port:1;
+	unsigned long show_tpgt:1;
+	unsigned long show_ip_address:1;
+	unsigned long show_target_name:1;
+	unsigned long show_target_alias:1;
+	unsigned long show_initial_r2t:1;
+	unsigned long show_immediate_data:1;
+	unsigned long show_max_recv_data_segment_len:1;
+	unsigned long show_max_burst_len:1;
+	unsigned long show_first_burst_len:1;
+	unsigned long show_def_time2wait:1;
+	unsigned long show_def_time2retain:1;
+	unsigned long show_max_outstanding_r2t:1;
+	unsigned long show_data_pdu_in_order:1;
+	unsigned long show_data_sequence_in_order:1;
+	unsigned long show_erl:1;
+	unsigned long show_initiator_name:1;
+	unsigned long show_initiator_alias:1;
+};
+
+struct scsi_transport_template *iscsi_attach_transport(struct iscsi_function_template *);
+void iscsi_release_transport(struct scsi_transport_template *);
+
+#endif
diff --git a/include/scsi/scsi_transport_spi.h b/include/scsi/scsi_transport_spi.h
new file mode 100644
index 0000000..6dcf497
--- /dev/null
+++ b/include/scsi/scsi_transport_spi.h
@@ -0,0 +1,135 @@
+/* 
+ *  Parallel SCSI (SPI) transport specific attributes exported to sysfs.
+ *
+ *  Copyright (c) 2003 Silicon Graphics, Inc.  All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef SCSI_TRANSPORT_SPI_H
+#define SCSI_TRANSPORT_SPI_H
+
+#include <linux/config.h>
+#include <linux/transport_class.h>
+
+struct scsi_transport_template;
+
+struct spi_transport_attrs {
+	int period;		/* value in the PPR/SDTR command */
+	int offset;
+	unsigned int width:1;	/* 0 - narrow, 1 - wide */
+	unsigned int iu:1;	/* Information Units enabled */
+	unsigned int dt:1;	/* DT clocking enabled */
+	unsigned int qas:1;	/* Quick Arbitration and Selection enabled */
+	unsigned int wr_flow:1;	/* Write Flow control enabled */
+	unsigned int rd_strm:1;	/* Read streaming enabled */
+	unsigned int rti:1;	/* Retain Training Information */
+	unsigned int pcomp_en:1;/* Precompensation enabled */
+	unsigned int initial_dv:1; /* DV done to this target yet  */
+	unsigned long flags;	/* flags field for drivers to use */
+	/* Device Properties fields */
+	unsigned int support_sync:1; /* synchronous support */
+	unsigned int support_wide:1; /* wide support */
+	unsigned int support_dt:1; /* allows DT phases */
+	unsigned int support_dt_only; /* disallows ST phases */
+	unsigned int support_ius; /* support Information Units */
+	unsigned int support_qas; /* supports quick arbitration and selection */
+	/* Private Fields */
+	unsigned int dv_pending:1; /* Internal flag */
+	struct semaphore dv_sem; /* semaphore to serialise dv */
+};
+
+enum spi_signal_type {
+	SPI_SIGNAL_UNKNOWN = 1,
+	SPI_SIGNAL_SE,
+	SPI_SIGNAL_LVD,
+	SPI_SIGNAL_HVD,
+};
+
+struct spi_host_attrs {
+	enum spi_signal_type signalling;
+};
+
+/* accessor functions */
+#define spi_period(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->period)
+#define spi_offset(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->offset)
+#define spi_width(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->width)
+#define spi_iu(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->iu)
+#define spi_dt(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->dt)
+#define spi_qas(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->qas)
+#define spi_wr_flow(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->wr_flow)
+#define spi_rd_strm(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->rd_strm)
+#define spi_rti(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->rti)
+#define spi_pcomp_en(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->pcomp_en)
+#define spi_initial_dv(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->initial_dv)
+
+#define spi_support_sync(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->support_sync)
+#define spi_support_wide(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->support_wide)
+#define spi_support_dt(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->support_dt)
+#define spi_support_dt_only(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->support_dt_only)
+#define spi_support_ius(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->support_ius)
+#define spi_support_qas(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->support_qas)
+
+#define spi_flags(x)	(((struct spi_transport_attrs *)&(x)->starget_data)->flags)
+#define spi_signalling(h)	(((struct spi_host_attrs *)(h)->shost_data)->signalling)
+
+
+
+/* The functions by which the transport class and the driver communicate */
+struct spi_function_template {
+	void	(*get_period)(struct scsi_target *);
+	void	(*set_period)(struct scsi_target *, int);
+	void	(*get_offset)(struct scsi_target *);
+	void	(*set_offset)(struct scsi_target *, int);
+	void	(*get_width)(struct scsi_target *);
+	void	(*set_width)(struct scsi_target *, int);
+	void	(*get_iu)(struct scsi_target *);
+	void	(*set_iu)(struct scsi_target *, int);
+	void	(*get_dt)(struct scsi_target *);
+	void	(*set_dt)(struct scsi_target *, int);
+	void	(*get_qas)(struct scsi_target *);
+	void	(*set_qas)(struct scsi_target *, int);
+	void	(*get_wr_flow)(struct scsi_target *);
+	void	(*set_wr_flow)(struct scsi_target *, int);
+	void	(*get_rd_strm)(struct scsi_target *);
+	void	(*set_rd_strm)(struct scsi_target *, int);
+	void	(*get_rti)(struct scsi_target *);
+	void	(*set_rti)(struct scsi_target *, int);
+	void	(*get_pcomp_en)(struct scsi_target *);
+	void	(*set_pcomp_en)(struct scsi_target *, int);
+	void	(*get_signalling)(struct Scsi_Host *);
+	void	(*set_signalling)(struct Scsi_Host *, enum spi_signal_type);
+	/* The driver sets these to tell the transport class it
+	 * wants the attributes displayed in sysfs.  If the show_ flag
+	 * is not set, the attribute will be private to the transport
+	 * class */
+	unsigned long	show_period:1;
+	unsigned long	show_offset:1;
+	unsigned long	show_width:1;
+	unsigned long	show_iu:1;
+	unsigned long	show_dt:1;
+	unsigned long	show_qas:1;
+	unsigned long	show_wr_flow:1;
+	unsigned long	show_rd_strm:1;
+	unsigned long	show_rti:1;
+	unsigned long	show_pcomp_en:1;
+};
+
+struct scsi_transport_template *spi_attach_transport(struct spi_function_template *);
+void spi_release_transport(struct scsi_transport_template *);
+void spi_schedule_dv_device(struct scsi_device *);
+void spi_dv_device(struct scsi_device *);
+void spi_display_xfer_agreement(struct scsi_target *);
+
+#endif /* SCSI_TRANSPORT_SPI_H */
diff --git a/include/scsi/scsicam.h b/include/scsi/scsicam.h
new file mode 100644
index 0000000..24ede47
--- /dev/null
+++ b/include/scsi/scsicam.h
@@ -0,0 +1,19 @@
+/*
+ * scsicam.h - SCSI CAM support functions, use for HDIO_GETGEO, etc.
+ *
+ * Copyright 1993, 1994 Drew Eckhardt
+ *      Visionary Computing 
+ *      (Unix and Linux consulting and custom programming)
+ *      drew@Colorado.EDU
+ *	+1 (303) 786-7975
+ *
+ * For more information, please consult the SCSI-CAM draft.
+ */
+
+#ifndef SCSICAM_H
+#define SCSICAM_H
+extern int scsicam_bios_param (struct block_device *bdev, sector_t capacity, int *ip);
+extern int scsi_partsize(unsigned char *buf, unsigned long capacity,
+           unsigned int  *cyls, unsigned int *hds, unsigned int *secs);
+extern unsigned char *scsi_bios_ptable(struct block_device *bdev);
+#endif /* def SCSICAM_H */
diff --git a/include/scsi/sg.h b/include/scsi/sg.h
new file mode 100644
index 0000000..0a487fe
--- /dev/null
+++ b/include/scsi/sg.h
@@ -0,0 +1,326 @@
+#ifndef _SCSI_GENERIC_H
+#define _SCSI_GENERIC_H
+
+#include <linux/compiler.h>
+
+/*
+   History:
+    Started: Aug 9 by Lawrence Foard (entropy@world.std.com), to allow user
+     process control of SCSI devices.
+    Development Sponsored by Killy Corp. NY NY
+Original driver (sg.h):
+*       Copyright (C) 1992 Lawrence Foard
+Version 2 and 3 extensions to driver:
+*       Copyright (C) 1998 - 2003 Douglas Gilbert
+
+    Version: 3.5.29 (20030529)
+    This version is for 2.5 series kernels.
+
+    Changes since 3.5.28 (20030308)
+	- fix bug introduced in version 3.1.24 (last segment of sgat list)
+    Changes since 3.5.27 (20020812)
+    	- remove procfs entries: hosts, host_hdr + host_strs (now in sysfs)
+	- add sysfs sg driver params: def_reserved_size, allow_dio, version
+	- new boot option: "sg_allow_dio" and module parameter: "allow_dio"
+        - multiple internal changes due to scsi subsystem rework	
+    Changes since 3.5.26 (20020708)
+	- re-add direct IO using Kai Makisara's work
+	- re-tab to 8, start using C99-isms
+	- simplify memory management
+    Changes since 3.5.25 (20020504)
+	- driverfs additions
+	- copy_to/from_user() fixes [William Stinson]
+	- disable kiobufs support
+
+    For a full changelog see http://www.torque.net/sg
+
+Map of SG verions to the Linux kernels in which they appear:
+       ----------        ----------------------------------
+       original          all kernels < 2.2.6
+       2.1.40            2.2.20
+       3.0.x             optional version 3 sg driver for 2.2 series
+       3.1.17++          2.4.0++
+       3.5.23++          2.5.0++
+
+Major new features in SG 3.x driver (cf SG 2.x drivers)
+	- SG_IO ioctl() combines function if write() and read()
+	- new interface (sg_io_hdr_t) but still supports old interface
+	- scatter/gather in user space, direct IO, and mmap supported
+
+ The normal action of this driver is to use the adapter (HBA) driver to DMA
+ data into kernel buffers and then use the CPU to copy the data into the 
+ user space (vice versa for writes). That is called "indirect" IO due to 
+ the double handling of data. There are two methods offered to remove the
+ redundant copy: 1) direct IO which uses the kernel kiobuf mechanism and 
+ 2) using the mmap() system call to map the reserve buffer (this driver has 
+ one reserve buffer per fd) into the user space. Both have their advantages.
+ In terms of absolute speed mmap() is faster. If speed is not a concern, 
+ indirect IO should be fine. Read the documentation for more information.
+
+ ** N.B. To use direct IO 'echo 1 > /proc/scsi/sg/allow_dio' may be
+         needed. That pseudo file's content is defaulted to 0. **
+ 
+ Historical note: this SCSI pass-through driver has been known as "sg" for 
+ a decade. In broader kernel discussions "sg" is used to refer to scatter
+ gather techniques. The context should clarify which "sg" is referred to.
+
+ Documentation
+ =============
+ A web site for the SG device driver can be found at:
+	http://www.torque.net/sg  [alternatively check the MAINTAINERS file]
+ The documentation for the sg version 3 driver can be found at:
+ 	http://www.torque.net/sg/p/sg_v3_ho.html
+ This is a rendering from DocBook source [change the extension to "sgml"
+ or "xml"]. There are renderings in "ps", "pdf", "rtf" and "txt" (soon).
+
+ The older, version 2 documents discuss the original sg interface in detail:
+	http://www.torque.net/sg/p/scsi-generic.txt
+	http://www.torque.net/sg/p/scsi-generic_long.txt
+ A version of this document (potentially out of date) may also be found in
+ the kernel source tree, probably at:
+        Documentation/scsi/scsi-generic.txt .
+
+ Utility and test programs are available at the sg web site. They are 
+ bundled as sg_utils (for the lk 2.2 series) and sg3_utils (for the
+ lk 2.4 series).
+
+ There is a HOWTO on the Linux SCSI subsystem in the lk 2.4 series at:
+ 	http://www.linuxdoc.org/HOWTO/SCSI-2.4-HOWTO
+*/
+
+
+/* New interface introduced in the 3.x SG drivers follows */
+
+typedef struct sg_iovec /* same structure as used by readv() Linux system */
+{                       /* call. It defines one scatter-gather element. */
+    void __user *iov_base;      /* Starting address  */
+    size_t iov_len;             /* Length in bytes  */
+} sg_iovec_t;
+
+
+typedef struct sg_io_hdr
+{
+    int interface_id;           /* [i] 'S' for SCSI generic (required) */
+    int dxfer_direction;        /* [i] data transfer direction  */
+    unsigned char cmd_len;      /* [i] SCSI command length ( <= 16 bytes) */
+    unsigned char mx_sb_len;    /* [i] max length to write to sbp */
+    unsigned short iovec_count; /* [i] 0 implies no scatter gather */
+    unsigned int dxfer_len;     /* [i] byte count of data transfer */
+    void __user *dxferp;	/* [i], [*io] points to data transfer memory
+					      or scatter gather list */
+    unsigned char __user *cmdp; /* [i], [*i] points to command to perform */
+    void __user *sbp;		/* [i], [*o] points to sense_buffer memory */
+    unsigned int timeout;       /* [i] MAX_UINT->no timeout (unit: millisec) */
+    unsigned int flags;         /* [i] 0 -> default, see SG_FLAG... */
+    int pack_id;                /* [i->o] unused internally (normally) */
+    void __user * usr_ptr;      /* [i->o] unused internally */
+    unsigned char status;       /* [o] scsi status */
+    unsigned char masked_status;/* [o] shifted, masked scsi status */
+    unsigned char msg_status;   /* [o] messaging level data (optional) */
+    unsigned char sb_len_wr;    /* [o] byte count actually written to sbp */
+    unsigned short host_status; /* [o] errors from host adapter */
+    unsigned short driver_status;/* [o] errors from software driver */
+    int resid;                  /* [o] dxfer_len - actual_transferred */
+    unsigned int duration;      /* [o] time taken by cmd (unit: millisec) */
+    unsigned int info;          /* [o] auxiliary information */
+} sg_io_hdr_t;  /* 64 bytes long (on i386) */
+
+#define SG_INTERFACE_ID_ORIG 'S'
+
+/* Use negative values to flag difference from original sg_header structure */
+#define SG_DXFER_NONE (-1)      /* e.g. a SCSI Test Unit Ready command */
+#define SG_DXFER_TO_DEV (-2)    /* e.g. a SCSI WRITE command */
+#define SG_DXFER_FROM_DEV (-3)  /* e.g. a SCSI READ command */
+#define SG_DXFER_TO_FROM_DEV (-4) /* treated like SG_DXFER_FROM_DEV with the
+				   additional property than during indirect
+				   IO the user buffer is copied into the
+				   kernel buffers before the transfer */
+#define SG_DXFER_UNKNOWN (-5)   /* Unknown data direction */
+
+/* following flag values can be "or"-ed together */
+#define SG_FLAG_DIRECT_IO 1     /* default is indirect IO */
+#define SG_FLAG_UNUSED_LUN_INHIBIT 2   /* default is overwrite lun in SCSI */
+				/* command block (when <= SCSI_2) */
+#define SG_FLAG_MMAP_IO 4       /* request memory mapped IO */
+#define SG_FLAG_NO_DXFER 0x10000 /* no transfer of kernel buffers to/from */
+				/* user space (debug indirect IO) */
+
+/* following 'info' values are "or"-ed together */
+#define SG_INFO_OK_MASK 0x1
+#define SG_INFO_OK 0x0          /* no sense, host nor driver "noise" */
+#define SG_INFO_CHECK 0x1       /* something abnormal happened */
+
+#define SG_INFO_DIRECT_IO_MASK 0x6
+#define SG_INFO_INDIRECT_IO 0x0 /* data xfer via kernel buffers (or no xfer) */
+#define SG_INFO_DIRECT_IO 0x2   /* direct IO requested and performed */
+#define SG_INFO_MIXED_IO 0x4    /* part direct, part indirect IO */
+
+
+typedef struct sg_scsi_id { /* used by SG_GET_SCSI_ID ioctl() */
+    int host_no;        /* as in "scsi<n>" where 'n' is one of 0, 1, 2 etc */
+    int channel;
+    int scsi_id;        /* scsi id of target device */
+    int lun;
+    int scsi_type;      /* TYPE_... defined in scsi/scsi.h */
+    short h_cmd_per_lun;/* host (adapter) maximum commands per lun */
+    short d_queue_depth;/* device (or adapter) maximum queue length */
+    int unused[2];      /* probably find a good use, set 0 for now */
+} sg_scsi_id_t; /* 32 bytes long on i386 */
+
+typedef struct sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */
+    char req_state;     /* 0 -> not used, 1 -> written, 2 -> ready to read */
+    char orphan;        /* 0 -> normal request, 1 -> from interruped SG_IO */
+    char sg_io_owned;   /* 0 -> complete with read(), 1 -> owned by SG_IO */
+    char problem;       /* 0 -> no problem detected, 1 -> error to report */
+    int pack_id;        /* pack_id associated with request */
+    void __user *usr_ptr;     /* user provided pointer (in new interface) */
+    unsigned int duration; /* millisecs elapsed since written (req_state==1)
+			      or request duration (req_state==2) */
+    int unused;
+} sg_req_info_t; /* 20 bytes long on i386 */
+
+
+/* IOCTLs: Those ioctls that are relevant to the SG 3.x drivers follow.
+ [Those that only apply to the SG 2.x drivers are at the end of the file.]
+ (_GET_s yield result via 'int *' 3rd argument unless otherwise indicated) */
+
+#define SG_EMULATED_HOST 0x2203 /* true for emulated host adapter (ATAPI) */
+
+/* Used to configure SCSI command transformation layer for ATAPI devices */
+/* Only supported by the ide-scsi driver */
+#define SG_SET_TRANSFORM 0x2204 /* N.B. 3rd arg is not pointer but value: */
+		      /* 3rd arg = 0 to disable transform, 1 to enable it */
+#define SG_GET_TRANSFORM 0x2205
+
+#define SG_SET_RESERVED_SIZE 0x2275  /* request a new reserved buffer size */
+#define SG_GET_RESERVED_SIZE 0x2272  /* actual size of reserved buffer */
+
+/* The following ioctl has a 'sg_scsi_id_t *' object as its 3rd argument. */
+#define SG_GET_SCSI_ID 0x2276   /* Yields fd's bus, chan, dev, lun + type */
+/* SCSI id information can also be obtained from SCSI_IOCTL_GET_IDLUN */
+
+/* Override host setting and always DMA using low memory ( <16MB on i386) */
+#define SG_SET_FORCE_LOW_DMA 0x2279  /* 0-> use adapter setting, 1-> force */
+#define SG_GET_LOW_DMA 0x227a   /* 0-> use all ram for dma; 1-> low dma ram */
+
+/* When SG_SET_FORCE_PACK_ID set to 1, pack_id is input to read() which
+   tries to fetch a packet with a matching pack_id, waits, or returns EAGAIN.
+   If pack_id is -1 then read oldest waiting. When ...FORCE_PACK_ID set to 0
+   then pack_id ignored by read() and oldest readable fetched. */
+#define SG_SET_FORCE_PACK_ID 0x227b
+#define SG_GET_PACK_ID 0x227c /* Yields oldest readable pack_id (or -1) */
+
+#define SG_GET_NUM_WAITING 0x227d /* Number of commands awaiting read() */
+
+/* Yields max scatter gather tablesize allowed by current host adapter */
+#define SG_GET_SG_TABLESIZE 0x227F  /* 0 implies can't do scatter gather */
+
+#define SG_GET_VERSION_NUM 0x2282 /* Example: version 2.1.34 yields 20134 */
+
+/* Returns -EBUSY if occupied. 3rd argument pointer to int (see next) */
+#define SG_SCSI_RESET 0x2284
+/* Associated values that can be given to SG_SCSI_RESET follow */
+#define		SG_SCSI_RESET_NOTHING	0
+#define		SG_SCSI_RESET_DEVICE	1
+#define		SG_SCSI_RESET_BUS	2
+#define		SG_SCSI_RESET_HOST	3
+
+/* synchronous SCSI command ioctl, (only in version 3 interface) */
+#define SG_IO 0x2285   /* similar effect as write() followed by read() */
+
+#define SG_GET_REQUEST_TABLE 0x2286   /* yields table of active requests */
+
+/* How to treat EINTR during SG_IO ioctl(), only in SG 3.x series */
+#define SG_SET_KEEP_ORPHAN 0x2287 /* 1 -> hold for read(), 0 -> drop (def) */
+#define SG_GET_KEEP_ORPHAN 0x2288
+
+/* yields scsi midlevel's access_count for this SCSI device */
+#define SG_GET_ACCESS_COUNT 0x2289  
+
+
+#define SG_SCATTER_SZ (8 * 4096)  /* PAGE_SIZE not available to user */
+/* Largest size (in bytes) a single scatter-gather list element can have.
+   The value must be a power of 2 and <= (PAGE_SIZE * 32) [131072 bytes on
+   i386]. The minimum value is PAGE_SIZE. If scatter-gather not supported
+   by adapter then this value is the largest data block that can be
+   read/written by a single scsi command. The user can find the value of
+   PAGE_SIZE by calling getpagesize() defined in unistd.h . */
+
+#define SG_DEFAULT_RETRIES 0
+
+/* Defaults, commented if they differ from original sg driver */
+#define SG_DEF_FORCE_LOW_DMA 0  /* was 1 -> memory below 16MB on i386 */
+#define SG_DEF_FORCE_PACK_ID 0
+#define SG_DEF_KEEP_ORPHAN 0
+#define SG_DEF_RESERVED_SIZE SG_SCATTER_SZ /* load time option */
+
+/* maximum outstanding requests, write() yields EDOM if exceeded */
+#define SG_MAX_QUEUE 16
+
+#define SG_BIG_BUFF SG_DEF_RESERVED_SIZE    /* for backward compatibility */
+
+/* Alternate style type names, "..._t" variants preferred */
+typedef struct sg_io_hdr Sg_io_hdr;
+typedef struct sg_io_vec Sg_io_vec;
+typedef struct sg_scsi_id Sg_scsi_id;
+typedef struct sg_req_info Sg_req_info;
+
+
+/* vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv */
+/*   The older SG interface based on the 'sg_header' structure follows.   */
+/* ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ */
+
+#define SG_MAX_SENSE 16   /* this only applies to the sg_header interface */
+
+struct sg_header
+{
+    int pack_len;    /* [o] reply_len (ie useless), ignored as input */
+    int reply_len;   /* [i] max length of expected reply (inc. sg_header) */
+    int pack_id;     /* [io] id number of packet (use ints >= 0) */
+    int result;      /* [o] 0==ok, else (+ve) Unix errno (best ignored) */
+    unsigned int twelve_byte:1;
+	/* [i] Force 12 byte command length for group 6 & 7 commands  */
+    unsigned int target_status:5;   /* [o] scsi status from target */
+    unsigned int host_status:8;     /* [o] host status (see "DID" codes) */
+    unsigned int driver_status:8;   /* [o] driver status+suggestion */
+    unsigned int other_flags:10;    /* unused */
+    unsigned char sense_buffer[SG_MAX_SENSE]; /* [o] Output in 3 cases:
+	   when target_status is CHECK_CONDITION or
+	   when target_status is COMMAND_TERMINATED or
+	   when (driver_status & DRIVER_SENSE) is true. */
+};      /* This structure is 36 bytes long on i386 */
+
+
+/* IOCTLs: The following are not required (or ignored) when the sg_io_hdr_t
+	   interface is used. They are kept for backward compatibility with
+	   the original and version 2 drivers. */
+
+#define SG_SET_TIMEOUT 0x2201  /* unit: jiffies (10ms on i386) */
+#define SG_GET_TIMEOUT 0x2202  /* yield timeout as _return_ value */
+
+/* Get/set command queuing state per fd (default is SG_DEF_COMMAND_Q.
+   Each time a sg_io_hdr_t object is seen on this file descriptor, this
+   command queuing flag is set on (overriding the previous setting). */
+#define SG_GET_COMMAND_Q 0x2270   /* Yields 0 (queuing off) or 1 (on) */
+#define SG_SET_COMMAND_Q 0x2271   /* Change queuing state with 0 or 1 */
+
+/* Turn on/off error sense trace (1 and 0 respectively, default is off).
+   Try using: "# cat /proc/scsi/sg/debug" instead in the v3 driver */
+#define SG_SET_DEBUG 0x227e    /* 0 -> turn off debug */
+
+#define SG_NEXT_CMD_LEN 0x2283  /* override SCSI command length with given
+		   number on the next write() on this file descriptor */
+
+
+/* Defaults, commented if they differ from original sg driver */
+#ifdef __KERNEL__
+#define SG_DEFAULT_TIMEOUT_USER	(60*USER_HZ) /* HZ == 'jiffies in 1 second' */
+#else
+#define SG_DEFAULT_TIMEOUT	(60*HZ)	     /* HZ == 'jiffies in 1 second' */
+#endif
+
+#define SG_DEF_COMMAND_Q 0     /* command queuing is always on when
+				  the new interface is used */
+#define SG_DEF_UNDERRUN_FLAG 0
+
+#endif