aboutsummaryrefslogtreecommitdiffstats
path: root/include/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'include/scsi')
-rw-r--r--include/scsi/scsi.h412
-rw-r--r--include/scsi/scsi_cmnd.h165
-rw-r--r--include/scsi/scsi_dbg.h21
-rw-r--r--include/scsi/scsi_device.h282
-rw-r--r--include/scsi/scsi_devinfo.h31
-rw-r--r--include/scsi/scsi_driver.h31
-rw-r--r--include/scsi/scsi_eh.h63
-rw-r--r--include/scsi/scsi_host.h642
-rw-r--r--include/scsi/scsi_ioctl.h50
-rw-r--r--include/scsi/scsi_request.h73
-rw-r--r--include/scsi/scsi_tcq.h134
-rw-r--r--include/scsi/scsi_transport.h48
-rw-r--r--include/scsi/scsi_transport_fc.h442
-rw-r--r--include/scsi/scsi_transport_iscsi.h178
-rw-r--r--include/scsi/scsi_transport_spi.h135
-rw-r--r--include/scsi/scsicam.h19
-rw-r--r--include/scsi/sg.h326
17 files changed, 3052 insertions, 0 deletions
diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h
new file mode 100644
index 000000000000..1d54c063ae52
--- /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 000000000000..9d9871c28abd
--- /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 000000000000..12e90934a7a8
--- /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 000000000000..07d974051b0c
--- /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 000000000000..174101b2069b
--- /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 000000000000..850dfa877fda
--- /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 000000000000..80557f879e3e
--- /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 000000000000..27f2c4e8943a
--- /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 000000000000..d4be4d92d586
--- /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 000000000000..98719407d554
--- /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 000000000000..e47e36a4ef49
--- /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 000000000000..2dcee7a84752
--- /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 000000000000..70ad16315a16
--- /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 000000000000..1b26a6c0aa2a
--- /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 000000000000..6dcf497bf46d
--- /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 000000000000..24ede474752e
--- /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 000000000000..0a487fe26d4f
--- /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