patch-2.1.75 linux/drivers/scsi/scsi.h
Next file: linux/drivers/scsi/scsi_debug.c
Previous file: linux/drivers/scsi/scsi.c
Back to the patch index
Back to the overall index
- Lines: 718
- Date:
Sun Dec 21 17:59:19 1997
- Orig file:
v2.1.74/linux/drivers/scsi/scsi.h
- Orig date:
Wed Nov 12 13:34:26 1997
diff -u --recursive --new-file v2.1.74/linux/drivers/scsi/scsi.h linux/drivers/scsi/scsi.h
@@ -24,6 +24,7 @@
#include <linux/random.h>
#include <asm/hardirq.h>
+#include <asm/scatterlist.h>
#include <asm/io.h>
/*
@@ -39,9 +40,57 @@
#define MAX_SCSI_DEVICE_CODE 10
extern const char *const scsi_device_types[MAX_SCSI_DEVICE_CODE];
-extern void scsi_make_blocked_list(void);
-extern volatile int in_scan_scsis;
-extern const unsigned char scsi_command_size[8];
+/*
+ * 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) & 0x1f)
+#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 NEEDS_RETRY 0x2001
+#define SUCCESS 0x2002
+#define FAILED 0x2003
+#define QUEUED 0x2004
+#define SOFT_ERROR 0x2005
+#define ADD_TO_MLQUEUE 0x2006
+
+/*
+ * 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
+
+/*
+ * These are the values that the owner field can take.
+ * They are used as an indication of who the command belongs to.
+ */
+#define SCSI_OWNER_HIGHLEVEL 0x100
+#define SCSI_OWNER_MIDLEVEL 0x101
+#define SCSI_OWNER_LOWLEVEL 0x102
+#define SCSI_OWNER_ERROR_HANDLER 0x103
+#define SCSI_OWNER_BH_HANDLER 0x104
+#define SCSI_OWNER_NOBODY 0x105
+
#define COMMAND_SIZE(opcode) scsi_command_size[((opcode) >> 5) & 7]
#define IDENTIFY_BASE 0x80
@@ -50,6 +99,126 @@
((lun) & 0x07))
+/*
+ * This defines the scsi logging feature. It is a means by which the
+ * user can select how much information they get about various goings on,
+ * and it can be really useful for fault tracing. The logging word is divided
+ * into 8 nibbles, each of which describes a loglevel. The division of things
+ * is somewhat arbitrary, and the division of the word could be changed if it
+ * were really needed for any reason. The numbers below are the only place where these
+ * are specified. For a first go-around, 3 bits is more than enough, since this
+ * gives 8 levels of logging (really 7, since 0 is always off). Cutting to 2 bits
+ * might be wise at some point.
+ */
+
+#define SCSI_LOG_ERROR_SHIFT 0
+#define SCSI_LOG_TIMEOUT_SHIFT 3
+#define SCSI_LOG_SCAN_SHIFT 6
+#define SCSI_LOG_MLQUEUE_SHIFT 9
+#define SCSI_LOG_MLCOMPLETE_SHIFT 12
+#define SCSI_LOG_LLQUEUE_SHIFT 15
+#define SCSI_LOG_LLCOMPLETE_SHIFT 18
+#define SCSI_LOG_HLQUEUE_SHIFT 21
+#define SCSI_LOG_HLCOMPLETE_SHIFT 24
+#define SCSI_LOG_IOCTL_SHIFT 27
+
+#define SCSI_LOG_ERROR_BITS 3
+#define SCSI_LOG_TIMEOUT_BITS 3
+#define SCSI_LOG_SCAN_BITS 3
+#define SCSI_LOG_MLQUEUE_BITS 3
+#define SCSI_LOG_MLCOMPLETE_BITS 3
+#define SCSI_LOG_LLQUEUE_BITS 3
+#define SCSI_LOG_LLCOMPLETE_BITS 3
+#define SCSI_LOG_HLQUEUE_BITS 3
+#define SCSI_LOG_HLCOMPLETE_BITS 3
+#define SCSI_LOG_IOCTL_BITS 3
+
+#if CONFIG_SCSI_LOGGING
+
+#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) \
+{ \
+ unsigned int mask; \
+ \
+ mask = (1 << (BITS)) - 1; \
+ if( ((scsi_logging_level >> (SHIFT)) & mask) > (LEVEL) ) \
+ { \
+ (CMD); \
+ } \
+}
+
+#define SCSI_SET_LOGGING(SHIFT, BITS, LEVEL) \
+{ \
+ unsigned int mask; \
+ \
+ mask = ((1 << (BITS)) - 1) << SHIFT; \
+ scsi_logging_level = ((scsi_logging_level & ~mask) \
+ | ((LEVEL << SHIFT) & mask)); \
+}
+
+
+
+#else
+
+/*
+ * With no logging enabled, stub these out so they don't do anything.
+ */
+#define SCSI_SET_LOGGING(SHIFT, BITS, LEVEL)
+
+#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD)
+#endif
+
+/*
+ * These are the macros that are actually used throughout the code to
+ * log events. If logging isn't enabled, they are no-ops and will be
+ * completely absent from the user's code.
+ *
+ * The 'set' versions of the macros are really intended to only be called
+ * from the /proc filesystem, and in production kernels this will be about
+ * all that is ever used. It could be useful in a debugging environment to
+ * bump the logging level when certain strange events are detected, however.
+ */
+#define SCSI_LOG_ERROR_RECOVERY(LEVEL,CMD) \
+ SCSI_CHECK_LOGGING(SCSI_LOG_ERROR_SHIFT, SCSI_LOG_ERROR_BITS, LEVEL,CMD);
+#define SCSI_LOG_TIMEOUT(LEVEL,CMD) \
+ SCSI_CHECK_LOGGING(SCSI_LOG_TIMEOUT_SHIFT, SCSI_LOG_TIMEOUT_BITS, LEVEL,CMD);
+#define SCSI_LOG_SCAN_BUS(LEVEL,CMD) \
+ SCSI_CHECK_LOGGING(SCSI_LOG_SCAN_SHIFT, SCSI_LOG_SCAN_BITS, LEVEL,CMD);
+#define SCSI_LOG_MLQUEUE(LEVEL,CMD) \
+ SCSI_CHECK_LOGGING(SCSI_LOG_MLQUEUE_SHIFT, SCSI_LOG_MLQUEUE_BITS, LEVEL,CMD);
+#define SCSI_LOG_MLCOMPLETE(LEVEL,CMD) \
+ SCSI_CHECK_LOGGING(SCSI_LOG_MLCOMPLETE_SHIFT, SCSI_LOG_MLCOMPLETE_BITS, LEVEL,CMD);
+#define SCSI_LOG_LLQUEUE(LEVEL,CMD) \
+ SCSI_CHECK_LOGGING(SCSI_LOG_LLQUEUE_SHIFT, SCSI_LOG_LLQUEUE_BITS, LEVEL,CMD);
+#define SCSI_LOG_LLCOMPLETE(LEVEL,CMD) \
+ SCSI_CHECK_LOGGING(SCSI_LOG_LLCOMPLETE_SHIFT, SCSI_LOG_LLCOMPLETE_BITS, LEVEL,CMD);
+#define SCSI_LOG_HLQUEUE(LEVEL,CMD) \
+ SCSI_CHECK_LOGGING(SCSI_LOG_HLQUEUE_SHIFT, SCSI_LOG_HLQUEUE_BITS, LEVEL,CMD);
+#define SCSI_LOG_HLCOMPLETE(LEVEL,CMD) \
+ SCSI_CHECK_LOGGING(SCSI_LOG_HLCOMPLETE_SHIFT, SCSI_LOG_HLCOMPLETE_BITS, LEVEL,CMD);
+#define SCSI_LOG_IOCTL(LEVEL,CMD) \
+ SCSI_CHECK_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL,CMD);
+
+
+#define SCSI_SET_ERROR_RECOVERY_LOGGING(LEVEL) \
+ SCSI_SET_LOGGING(SCSI_LOG_ERROR_SHIFT, SCSI_LOG_ERROR_BITS, LEVEL);
+#define SCSI_SET_TIMEOUT_LOGGING(LEVEL) \
+ SCSI_SET_LOGGING(SCSI_LOG_TIMEOUT_SHIFT, SCSI_LOG_TIMEOUT_BITS, LEVEL);
+#define SCSI_SET_SCAN_BUS_LOGGING(LEVEL) \
+ SCSI_SET_LOGGING(SCSI_LOG_SCAN_SHIFT, SCSI_LOG_SCAN_BITS, LEVEL);
+#define SCSI_SET_MLQUEUE_LOGGING(LEVEL) \
+ SCSI_SET_LOGGING(SCSI_LOG_MLQUEUE_SHIFT, SCSI_LOG_MLQUEUE_BITS, LEVEL);
+#define SCSI_SET_MLCOMPLETE_LOGGING(LEVEL) \
+ SCSI_SET_LOGGING(SCSI_LOG_MLCOMPLETE_SHIFT, SCSI_LOG_MLCOMPLETE_BITS, LEVEL);
+#define SCSI_SET_LLQUEUE_LOGGING(LEVEL) \
+ SCSI_SET_LOGGING(SCSI_LOG_LLQUEUE_SHIFT, SCSI_LOG_LLQUEUE_BITS, LEVEL);
+#define SCSI_SET_LLCOMPLETE_LOGGING(LEVEL) \
+ SCSI_SET_LOGGING(SCSI_LOG_LLCOMPLETE_SHIFT, SCSI_LOG_LLCOMPLETE_BITS, LEVEL);
+#define SCSI_SET_HLQUEUE_LOGGING(LEVEL) \
+ SCSI_SET_LOGGING(SCSI_LOG_HLQUEUE_SHIFT, SCSI_LOG_HLQUEUE_BITS, LEVEL);
+#define SCSI_SET_HLCOMPLETE_LOGGING(LEVEL) \
+ SCSI_SET_LOGGING(SCSI_LOG_HLCOMPLETE_SHIFT, SCSI_LOG_HLCOMPLETE_BITS, LEVEL);
+#define SCSI_SET_IOCTL_LOGGING(LEVEL) \
+ SCSI_SET_LOGGING(SCSI_LOG_IOCTL_SHIFT, SCSI_LOG_IOCTL_BITS, LEVEL);
/*
* the return of the status word will be in the following format :
@@ -81,6 +250,7 @@
#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 DRIVER_OK 0x00 /* Driver status */
/*
@@ -139,14 +309,107 @@
#define IS_ABORTING 0x10
#define ASKED_FOR_SENSE 0x20
+
+#define CONTIGUOUS_BUFFERS(X,Y) ((X->b_data+X->b_size) == Y->b_data)
+
+/*
+ * This is the crap from the old error handling code. We have it in a special
+ * place so that we can more easily delete it later on.
+ */
+#include "scsi_obsolete.h"
+
+/*
+ * Add some typedefs so that we can prototyope a bunch of the functions.
+ */
+typedef struct scsi_device Scsi_Device;
+typedef struct scsi_cmnd Scsi_Cmnd;
+
+/*
+ * Here is where we prototype most of the mid-layer.
+ */
+
+/*
+ * Initializes all SCSI devices. This scans all scsi busses.
+ */
+
+extern int scsi_dev_init (void);
+
+
+
+void * scsi_malloc(unsigned int);
+int scsi_free(void *, unsigned int);
+extern unsigned int scsi_logging_level; /* What do we log? */
+extern unsigned int scsi_dma_free_sectors; /* How much room do we have left */
+extern unsigned int scsi_need_isa_buffer; /* True if some devices need indirection
+ * buffers */
+extern void scsi_make_blocked_list(void);
+extern volatile int in_scan_scsis;
+extern const unsigned char scsi_command_size[8];
+
+/*
+ * These are the error handling functions defined in scsi_error.c
+ */
+extern void scsi_add_timer(Scsi_Cmnd * SCset, int timeout,
+ void (*complete)(Scsi_Cmnd *));
+extern void scsi_done (Scsi_Cmnd *SCpnt);
+extern int scsi_delete_timer(Scsi_Cmnd * SCset);
+extern void scsi_error_handler(void * host);
+extern int scsi_retry_command(Scsi_Cmnd *);
+extern void scsi_finish_command(Scsi_Cmnd *);
+extern int scsi_sense_valid(Scsi_Cmnd *);
+extern int scsi_decide_disposition (Scsi_Cmnd * SCpnt);
+extern int scsi_block_when_processing_errors(Scsi_Device *);
+extern void scsi_sleep(int);
+
+/*
+ * scsi_abort aborts the current command that is executing on host host.
+ * The error code, if non zero is returned in the host byte, otherwise
+ * DID_ABORT is returned in the hostbyte.
+ */
+
+extern void scsi_do_cmd (Scsi_Cmnd *, const void *cmnd ,
+ void *buffer, unsigned bufflen,
+ void (*done)(struct scsi_cmnd *),
+ int timeout, int retries);
+
+
+extern Scsi_Cmnd * scsi_allocate_device(struct request **, Scsi_Device *, int);
+
+extern Scsi_Cmnd * scsi_request_queueable(struct request *, Scsi_Device *);
+
+extern void scsi_release_command(Scsi_Cmnd *);
+
+extern int max_scsi_hosts;
+
+extern void proc_print_scsidevice(Scsi_Device *, char *, int *, int);
+
+extern void print_command(unsigned char *);
+extern void print_sense(const char *, Scsi_Cmnd *);
+extern void print_driverbyte(int scsiresult);
+extern void print_hostbyte(int scsiresult);
+
/*
* The scsi_device struct contains what we know about each given scsi
* device.
*/
-typedef struct scsi_device {
+struct scsi_device {
+/* private: */
+ /*
+ * This information is private to the scsi mid-layer. Wrapping it in a
+ * struct private is a way of marking it in a sort of C++ type of way.
+ */
struct scsi_device * next; /* Used for linked list */
+ struct scsi_device * prev; /* Used for linked list */
+ struct wait_queue * device_wait;/* Used to wait if
+ device is busy */
+ struct Scsi_Host * host;
+ volatile unsigned short device_busy; /* commands actually active on low-level */
+ void (* scsi_request_fn)(void); /* Used to jumpstart things after an
+ * ioctl */
+ Scsi_Cmnd * device_queue; /* queue of SCSI Command structures */
+/* public: */
unsigned char id, lun, channel;
unsigned int manufacturer; /* Manufacturer of device, for using
@@ -154,11 +417,7 @@
int attached; /* # of high level drivers attached to
* this */
int access_count; /* Count of open channels/mounts */
- struct wait_queue * device_wait;/* Used to wait if device is busy */
- struct Scsi_Host * host;
- void (*scsi_request_fn)(void); /* Used to jumpstart things after an
- * ioctl */
- struct scsi_cmnd *device_queue; /* queue of SCSI Command structures */
+
void *hostdata; /* available to low-level driver */
char type;
char scsi_level;
@@ -168,6 +427,7 @@
unsigned char sync_max_offset; /* Not greater than this offset */
unsigned char queue_depth; /* How deep a queue to use */
+ unsigned online:1;
unsigned writeable:1;
unsigned removable:1;
unsigned random:1;
@@ -190,35 +450,8 @@
* this device */
unsigned expecting_cc_ua:1; /* Expecting a CHECK_CONDITION/UNIT_ATTN
* because we did a bus reset. */
-} Scsi_Device;
-
-/*
- * Use these to separate status msg and our bytes
- */
-
-#define status_byte(result) (((result) >> 1) & 0x1f)
-#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);
-
-/*
- * These are the SCSI devices available on the system.
- */
-
-extern Scsi_Device * scsi_devices;
-
-/*
- * Initializes all SCSI devices. This scans all scsi busses.
- */
-
-extern int scsi_dev_init (void);
-
-#include <asm/scatterlist.h>
+ unsigned device_blocked:1; /* Device returned QUEUE_FULL. */
+};
#ifdef __mc68000__
#include <asm/pgtable.h>
@@ -230,109 +463,6 @@
/*
- * These are the return codes for the abort and reset functions. The mid-level
- * code uses these to decide what to do next. Each of the low level abort
- * and reset functions must correctly indicate what it has done.
- * The descriptions are written from the point of view of the mid-level code,
- * so that the return code is telling the mid-level drivers exactly what
- * the low level driver has already done, and what remains to be done.
- */
-
-/* We did not do anything.
- * Wait some more for this command to complete, and if this does not work,
- * try something more serious. */
-#define SCSI_ABORT_SNOOZE 0
-
-/* This means that we were able to abort the command. We have already
- * called the mid-level done function, and do not expect an interrupt that
- * will lead to another call to the mid-level done function for this command */
-#define SCSI_ABORT_SUCCESS 1
-
-/* We called for an abort of this command, and we should get an interrupt
- * when this succeeds. Thus we should not restore the timer for this
- * command in the mid-level abort function. */
-#define SCSI_ABORT_PENDING 2
-
-/* Unable to abort - command is currently on the bus. Grin and bear it. */
-#define SCSI_ABORT_BUSY 3
-
-/* The command is not active in the low level code. Command probably
- * finished. */
-#define SCSI_ABORT_NOT_RUNNING 4
-
-/* Something went wrong. The low level driver will indicate the correct
- * error condition when it calls scsi_done, so the mid-level abort function
- * can simply wait until this comes through */
-#define SCSI_ABORT_ERROR 5
-
-/* We do not know how to reset the bus, or we do not want to. Bummer.
- * Anyway, just wait a little more for the command in question, and hope that
- * it eventually finishes. If it never finishes, the SCSI device could
- * hang, so use this with caution. */
-#define SCSI_RESET_SNOOZE 0
-
-/* We do not know how to reset the bus, or we do not want to. Bummer.
- * We have given up on this ever completing. The mid-level code will
- * request sense information to decide how to proceed from here. */
-#define SCSI_RESET_PUNT 1
-
-/* This means that we were able to reset the bus. We have restarted all of
- * the commands that should be restarted, and we should be able to continue
- * on normally from here. We do not expect any interrupts that will return
- * DID_RESET to any of the other commands in the host_queue, and the mid-level
- * code does not need to do anything special to keep the commands alive.
- * If a hard reset was performed then all outstanding commands on the
- * bus have been restarted. */
-#define SCSI_RESET_SUCCESS 2
-
-/* We called for a reset of this bus, and we should get an interrupt
- * when this succeeds. Each command should get its own status
- * passed up to scsi_done, but this has not happened yet.
- * If a hard reset was performed, then we expect an interrupt
- * for *each* of the outstanding commands that will have the
- * effect of restarting the commands.
- */
-#define SCSI_RESET_PENDING 3
-
-/* We did a reset, but do not expect an interrupt to signal DID_RESET.
- * This tells the upper level code to request the sense info, and this
- * should keep the command alive. */
-#define SCSI_RESET_WAKEUP 4
-
-/* The command is not active in the low level code. Command probably
- finished. */
-#define SCSI_RESET_NOT_RUNNING 5
-
-/* Something went wrong, and we do not know how to fix it. */
-#define SCSI_RESET_ERROR 6
-
-#define SCSI_RESET_SYNCHRONOUS 0x01
-#define SCSI_RESET_ASYNCHRONOUS 0x02
-#define SCSI_RESET_SUGGEST_BUS_RESET 0x04
-#define SCSI_RESET_SUGGEST_HOST_RESET 0x08
-/*
- * This is a bitmask that is ored with one of the above codes.
- * It tells the mid-level code that we did a hard reset.
- */
-#define SCSI_RESET_BUS_RESET 0x100
-/*
- * This is a bitmask that is ored with one of the above codes.
- * It tells the mid-level code that we did a host adapter reset.
- */
-#define SCSI_RESET_HOST_RESET 0x200
-/*
- * Used to mask off bits and to obtain the basic action that was
- * performed.
- */
-#define SCSI_RESET_ACTION 0xff
-
-void * scsi_malloc(unsigned int);
-int scsi_free(void *, unsigned int);
-extern unsigned int dma_free_sectors; /* How much room do we have left */
-extern unsigned int need_isa_buffer; /* True if some devices need indirection
- * buffers */
-
-/*
* The Scsi_Cmnd structure is used by scsi.c internally, and for communication
* with low level drivers that support multiple outstanding commands.
*/
@@ -349,43 +479,22 @@
volatile int phase;
} Scsi_Pointer;
-typedef struct scsi_cmnd {
+
+struct scsi_cmnd {
+/* private: */
+ /*
+ * This information is private to the scsi mid-layer. Wrapping it in a
+ * struct private is a way of marking it in a sort of C++ type of way.
+ */
struct Scsi_Host * host;
- Scsi_Device * device;
- unsigned char target, lun, channel;
- unsigned char cmd_len;
- unsigned char old_cmd_len;
- struct scsi_cmnd *next, *prev, *device_next, *reset_chain;
-
- /* These elements define the operation we are about to perform */
- unsigned char cmnd[12];
- unsigned request_bufflen; /* Actual request size */
-
- void * request_buffer; /* Actual requested buffer */
-
- /* These elements define the operation we ultimately want to perform */
- unsigned char data_cmnd[12];
- 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
- * transfered */
-
- unsigned transfersize; /* How much we are guaranteed to transfer with
- * each SCSI transfer (ie, between disconnect /
- * reconnects. Probably == sector size */
+ unsigned short state;
+ unsigned short owner;
+ Scsi_Device * device;
+ struct scsi_cmnd * next;
+ struct scsi_cmnd * reset_chain;
-
- struct request request; /* A copy of the command we are working on */
-
- unsigned char sense_buffer[16]; /* Sense for this command, if needed */
-
+ int eh_state; /* Used for state tracking in 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
@@ -398,41 +507,96 @@
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.
- */
-
- unsigned long serial_number;
- unsigned long serial_number_at_timeout;
-
- int retries;
- int allowed;
- int timeout_per_command, timeout_total, timeout;
-
+ */
+
+ 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.
+ * We handle the timeout differently if it happens when a reset,
+ * abort, etc are in process.
*/
unsigned volatile char internal_timeout;
+ struct scsi_cmnd * bh_next; /* To enumerate the commands waiting
+ to be processed. */
+
+/* public: */
+
+ unsigned char target;
+ unsigned char lun;
+ unsigned char channel;
+ unsigned char cmd_len;
+ unsigned char old_cmd_len;
+
+ /* These elements define the operation we are about to perform */
+ unsigned char cmnd[12];
+ 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[12];
+ 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 transfered */
+
+ unsigned transfersize; /* How much we are guaranteed to
+ transfer with each SCSI transfer
+ (ie, between disconnect /
+ reconnects. Probably == sector
+ size */
- unsigned flags;
+ struct request request; /* A copy of the command we are
+ working on */
+
+ unsigned char sense_buffer[16]; /* Sense for this command,
+ needed */
+
+ unsigned flags;
+
+ /*
+ * These two flags are used to track commands that are in the
+ * mid-level queue. The idea is that a command can be there for
+ * one of two reasons - either the host is busy or the device is
+ * busy. Thus when a command on the host finishes, we only try
+ * and requeue commands that we might expect to be queueable.
+ */
+ unsigned host_wait:1;
+ unsigned device_wait:1;
+
/* These variables are for the cdrom only. Once we have variable size
* buffers in the buffer cache, they will go away. */
- int this_count;
+ int this_count;
/* End of special cdrom variables */
/* 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 *);
- void (*done)(struct scsi_cmnd *); /* Mid-level done function */
+ void (*scsi_done)(struct scsi_cmnd *);
/*
* The following fields can be written to by the host specific code.
* Everything else should be left alone.
*/
- Scsi_Pointer SCp; /* Scratchpad used by some host adapters */
+ Scsi_Pointer SCp; /* Scratchpad used by some host adapters */
- unsigned char * host_scribble; /* The host adapter is allowed to
+ 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
@@ -440,42 +604,22 @@
* obtained by scsi_malloc is guaranteed
* to be at an address < 16Mb). */
- int result; /* Status code from lower level driver */
+ int result; /* Status code from lower level driver */
- unsigned char tag; /* SCSI-II queued command tag */
- unsigned long pid; /* Process ID, starts at 0 */
-} Scsi_Cmnd;
+ unsigned char tag; /* SCSI-II queued command tag */
+ unsigned long pid; /* Process ID, starts at 0 */
+};
+
/*
- * scsi_abort aborts the current command that is executing on host host.
- * The error code, if non zero is returned in the host byte, otherwise
- * DID_ABORT is returned in the hostbyte.
+ * Definitions and prototypes used for scsi mid-level queue.
*/
+#define SCSI_MLQUEUE_HOST_BUSY 0x1055
+#define SCSI_MLQUEUE_DEVICE_BUSY 0x1056
-extern int scsi_abort (Scsi_Cmnd *, int code);
-
-extern void scsi_do_cmd (Scsi_Cmnd *, const void *cmnd ,
- void *buffer, unsigned bufflen,
- void (*done)(struct scsi_cmnd *),
- int timeout, int retries);
-
-
-extern Scsi_Cmnd * allocate_device(struct request **, Scsi_Device *, int);
-
-extern Scsi_Cmnd * request_queueable(struct request *, Scsi_Device *);
-extern int scsi_reset (Scsi_Cmnd *, unsigned int);
-
-extern int max_scsi_hosts;
-
-extern void proc_print_scsidevice(Scsi_Device *, char *, int *, int);
-
-extern void print_command(unsigned char *);
-extern void print_sense(const char *, Scsi_Cmnd *);
-extern void print_driverbyte(int scsiresult);
-extern void print_hostbyte(int scsiresult);
+extern scsi_mlqueue_insert(Scsi_Cmnd * cmd, int reason);
+extern scsi_mlqueue_finish(struct Scsi_Host * host, Scsi_Device * device);
-extern void scsi_mark_host_reset(struct Scsi_Host *Host);
-extern void scsi_mark_bus_reset(struct Scsi_Host *Host, int channel);
#if defined(MAJOR_NR) && (MAJOR_NR != SCSI_TAPE_MAJOR)
#include "hosts.h"
@@ -527,9 +671,9 @@
wake_up(&next->host_wait);
}
- req->rq_status = RQ_INACTIVE;
wake_up(&wait_for_request);
wake_up(&SCpnt->device->device_wait);
+ scsi_release_command(SCpnt);
return NULL;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov