Commit 130fbeeb authored by James Bottomley's avatar James Bottomley

Merge ssh://linux-scsi@linux-scsi.bkbits.net/scsi-for-linus-2.5

into mulgrave.(none):/home/jejb/BK/scsi-for-linus-2.5
parents d572f1a5 8403fb48
......@@ -7,11 +7,18 @@ Tested in single and dual HBA configuration, 32 and 64bit busses,
SEST size 512 Exchanges (simultaneous I/Os) limited by module kmalloc()
max of 128k bytes contiguous.
Ver 2.5.3 Aug 01, 2002
* fix the passthru ioctl to handle the Scsi_Cmnd->request being a pointer
Ver 2.5.1 Jul 30, 2002
* fix ioctl to pay attention to the specified LUN.
Ver 2.5.0 Nov 29, 2001
* eliminated io_request_lock. This change makes the driver specific
to the 2.5.x kernels.
* silenced excessively noisy printks.
Ver 2.1.2 July 23, 2002
* initialize DumCmnd->lun in cpqfcTS_ioctl (used in fcFindLoggedInPorts as LUN index)
Ver 2.1.1 Oct 18, 2001
* reinitialize Cmnd->SCp.sent_command (used to identify commands as
passthrus) on calling scsi_done, since the scsi mid layer does not
......
This diff is collapsed.
......@@ -33,7 +33,7 @@
// don't forget to also change MODULE_DESCRIPTION in cpqfcTSinit.c
#define VER_MAJOR 2
#define VER_MINOR 5
#define VER_SUBMINOR 0
#define VER_SUBMINOR 3
// Macros for kernel (esp. SMP) tracing using a PCI analyzer
// (e.g. x86).
......@@ -907,9 +907,17 @@ typedef struct
} FC_SCSI_QUE, *PFC_SCSI_QUE;
typedef struct {
/* This is tacked on to a Scsi_Request in upper_private_data
for pasthrough ioctls, as a place to hold data that can't
be stashed anywhere else in the Scsi_Request. We differentiate
this from _real_ upper_private_data by checking if the virt addr
is within our special pool. */
ushort bus;
ushort pdrive;
} cpqfc_passthru_private_t;
#define CPQFC_MAX_PASSTHRU_CMDS 100
#define DYNAMIC_ALLOCATIONS 4 // Tachyon aligned allocations: ERQ,IMQ,SFQ,SEST
......@@ -949,6 +957,8 @@ typedef struct
PFC_LINK_QUE fcLQ; // the WorkerThread operates on this
spinlock_t hba_spinlock; // held/released by WorkerThread
cpqfc_passthru_private_t *private_data_pool;
unsigned long *private_data_bits;
} CPQFCHBA;
......@@ -1405,6 +1415,7 @@ struct ext_sg_entry_t {
__u32 lba; /* lower bus address bits 0-31 */
};
// J. McCarty's LINK.H
//
// LS_RJT Reason Codes
......
......@@ -2887,15 +2887,22 @@ static void ScsiReportLunsDone(Scsi_Cmnd *Cmnd)
Done:
}
extern int is_private_data_of_cpqfc(CPQFCHBA *hba, void * pointer);
extern void cpqfc_free_private_data(CPQFCHBA *hba, cpqfc_passthru_private_t *data);
static void
call_scsi_done(Scsi_Cmnd *Cmnd)
{
// We have to reinitialize sent_command here, so the scsi-mid
// layer won't re-use the scsi command leaving it set incorrectly.
// (incorrectly for our purposes...it's normally unused.)
if (Cmnd->SCp.sent_command != 0) { // was it a passthru?
Cmnd->SCp.sent_command = 0;
CPQFCHBA *hba;
hba = (CPQFCHBA *) Cmnd->host->hostdata;
// Was this command a cpqfc passthru ioctl ?
if (Cmnd->sc_request != NULL && Cmnd->host != NULL &&
Cmnd->host->hostdata != NULL &&
is_private_data_of_cpqfc((CPQFCHBA *) Cmnd->host->hostdata,
Cmnd->sc_request->upper_private_data)) {
cpqfc_free_private_data(hba,
Cmnd->sc_request->upper_private_data);
Cmnd->sc_request->upper_private_data = NULL;
Cmnd->result &= 0xff00ffff;
Cmnd->result |= (DID_PASSTHROUGH << 16); // prevents retry
}
......@@ -3293,6 +3300,7 @@ static int GetLoopID( ULONG al_pa )
}
#endif
extern cpqfc_passthru_private_t *cpqfc_private(Scsi_Request *sr);
// Search the singly (forward) linked list "fcPorts" looking for
// either the SCSI target (if != -1), port_id (if not NULL),
......@@ -3366,8 +3374,18 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort(
{
// For "passthru" modes, the IOCTL caller is responsible
// for setting the FCP-LUN addressing
if( !Cmnd->SCp.sent_command ) // NOT passthru?
{
if (Cmnd->sc_request != NULL && Cmnd->host != NULL &&
Cmnd->host->hostdata != NULL &&
is_private_data_of_cpqfc((CPQFCHBA *) Cmnd->host->hostdata,
Cmnd->sc_request->upper_private_data)) {
/* This is a passthru... */
cpqfc_passthru_private_t *pd;
pd = Cmnd->sc_request->upper_private_data;
Cmnd->SCp.phase = pd->bus;
// Cmnd->SCp.have_data_in = pd->pdrive;
Cmnd->SCp.have_data_in = Cmnd->lun;
} else {
/* This is not a passthru... */
// set the FCP-LUN addressing type
Cmnd->SCp.phase = pLoggedInPort->ScsiNexus.VolumeSetAddressing;
......@@ -3380,6 +3398,8 @@ PFC_LOGGEDIN_PORT fcFindLoggedInPort(
// Report Luns command
if( pLoggedInPort->ScsiNexus.LunMasking == 1)
{
if (Cmnd->lun > sizeof(pLoggedInPort->ScsiNexus.lun))
return NULL;
// we KNOW all the valid LUNs... 0xFF is invalid!
Cmnd->SCp.have_data_in = pLoggedInPort->ScsiNexus.lun[Cmnd->lun];
if (pLoggedInPort->ScsiNexus.lun[Cmnd->lun] == 0xFF)
......@@ -3504,7 +3524,6 @@ static void UnblockScsiDevice( struct Scsi_Host *HostAdapter,
{
printk("LinkDnCmnd scsi_done ptr null, port_id %Xh\n",
pLoggedInPort->port_id);
Cmnd->SCp.sent_command = 0;
}
else
call_scsi_done(Cmnd);
......@@ -5232,7 +5251,6 @@ static ULONG build_SEST_sgList(
sgl = (struct scatterlist*)Cmnd->request_buffer;
sg_count = pci_map_sg(pcidev, sgl, Cmnd->use_sg,
scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
// printk("sgl = %p, sg_count = %d\n", (void *) sgl, sg_count);
if( sg_count <= 3 ) {
// we need to be careful here that no individual mapping
......@@ -5261,7 +5279,6 @@ static ULONG build_SEST_sgList(
// printk("totalsgs = %d, sgcount=%d\n",totalsgs,sg_count);
}
// printk("totalsgs = %d, sgcount=%d\n", totalsgs, sg_count);
if( totalsgs <= 3 ) // can (must) use "local" SEST list
{
while( bytes_to_go)
......@@ -6164,13 +6181,11 @@ void cpqfcTSCompleteExchange(
}
else
{
Exchanges->fcExchange[ x_ID ].Cmnd->SCp.sent_command = 0;
// printk(" not calling scsi_done on x_ID %Xh, Cmnd %p\n",
// x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
}
}
else{
Exchanges->fcExchange[ x_ID ].Cmnd->SCp.sent_command = 0;
printk(" x_ID %Xh, type %Xh, Cdb0 %Xh\n", x_ID,
Exchanges->fcExchange[ x_ID ].type,
Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0]);
......@@ -6463,10 +6478,10 @@ static int build_FCP_payload( Scsi_Cmnd *Cmnd,
for( i=0; (i < Cmnd->cmd_len) && i < MAX_COMMAND_SIZE; i++)
*payload++ = Cmnd->cmnd[i];
if( Cmnd->cmd_len == 16 )
{
memcpy( payload, &Cmnd->SCp.buffers_residual, 4);
}
// if( Cmnd->cmd_len == 16 )
// {
// memcpy( payload, &Cmnd->SCp.buffers_residual, 4);
// }
payload+= (16 - i);
// FCP_DL is largest number of expected data bytes
......
This diff is collapsed.
#ifndef _SCSI_DEBUG_H
#include <linux/types.h>
#include <linux/kdev_t.h>
static int scsi_debug_detect(Scsi_Host_Template *);
static int scsi_debug_release(struct Scsi_Host *);
/* static int scsi_debug_command(Scsi_Cmnd *); */
static int scsi_debug_queuecommand(Scsi_Cmnd *, void (*done) (Scsi_Cmnd *));
static int scsi_debug_abort(Scsi_Cmnd *);
static int scsi_debug_ioctl(Scsi_Device *, int, void *);
static int scsi_debug_biosparam(Disk *, struct block_device *, int[]);
static int scsi_debug_abort(Scsi_Cmnd *);
static int scsi_debug_bus_reset(Scsi_Cmnd *);
static int scsi_debug_device_reset(Scsi_Cmnd *);
static int scsi_debug_host_reset(Scsi_Cmnd *);
......@@ -20,29 +23,29 @@ static const char * scsi_debug_info(struct Scsi_Host *);
/*
* This driver is written for the lk 2.5 series
*/
#define SCSI_DEBUG_CANQUEUE 255
#define SCSI_DEBUG_CANQUEUE 255 /* needs to be >= 1 */
#define SCSI_DEBUG_MAX_CMD_LEN 16
#define SCSI_DEBUG_TEMPLATE \
{proc_info: scsi_debug_proc_info, \
name: "SCSI DEBUG", \
info: scsi_debug_info, \
detect: scsi_debug_detect, \
release: scsi_debug_release, \
ioctl: scsi_debug_ioctl, \
queuecommand: scsi_debug_queuecommand, \
eh_abort_handler: scsi_debug_abort, \
eh_bus_reset_handler: scsi_debug_bus_reset, \
eh_device_reset_handler: scsi_debug_device_reset, \
eh_host_reset_handler: scsi_debug_host_reset, \
bios_param: scsi_debug_biosparam, \
can_queue: SCSI_DEBUG_CANQUEUE, \
this_id: 7, \
sg_tablesize: 64, \
cmd_per_lun: 3, \
unchecked_isa_dma: 0, \
use_clustering: ENABLE_CLUSTERING, \
}
static Scsi_Host_Template driver_template = {
.proc_info = scsi_debug_proc_info,
.name = "SCSI DEBUG",
.info = scsi_debug_info,
.detect = scsi_debug_detect,
.release = scsi_debug_release,
.ioctl = scsi_debug_ioctl,
.queuecommand = scsi_debug_queuecommand,
.eh_abort_handler = scsi_debug_abort,
.eh_bus_reset_handler = scsi_debug_bus_reset,
.eh_device_reset_handler = scsi_debug_device_reset,
.eh_host_reset_handler = scsi_debug_host_reset,
.bios_param = scsi_debug_biosparam,
.can_queue = SCSI_DEBUG_CANQUEUE,
.this_id = 7,
.sg_tablesize = 64,
.cmd_per_lun = 3,
.unchecked_isa_dma = 0,
.use_clustering = ENABLE_CLUSTERING,
}; /* the name 'driver_template' is used by scsi_module.c */
#endif
......@@ -34,12 +34,15 @@ scsi_module.c is normally included at the end of a lower
level driver. For it to work a declaration like this is needed before
it is included:
static Scsi_Host_Template driver_template = DRIVER_TEMPLATE;
/* DRIVER_TEMPLATE should contain pointers to supported interface
functions. Scsi_Host_Template is defined in hosts.h */
#include "scsi_module.c"
In this case "DRIVER_TEMPLATE" is defined to be a structure initializer
that is placed in the driver header file by convention. It contains
pointers to supported interface functions and other values.
Scsi_Host_Template is defined in hosts.h .
The scsi_module.c assumes the name "driver_template" is appropriately
defined. It contains 2 functions:
defined. scsi_module.c contains 2 functions:
1) init_this_scsi_driver() called during builtin and module driver
initialization: invokes mid level's scsi_register_host()
2) exit_this_scsi_driver() called during closedown: invokes
......@@ -68,7 +71,7 @@ The interface functions are listed below in alphabetical order.
/**
* bios_param - fetch head, sector, cylinder info for a disk
* @sdkp: pointer to disk structure (defined in sd.h)
* @dev: corresponds to dev_t of device file name (e.g. /dev/sdb)
* @bdev: pointer to block device context (defined in fs.h)
* @params: three element array to place output:
* params[0] number of heads
* params[1] number of sectors
......@@ -267,6 +270,8 @@ The interface functions are listed below in alphabetical order.
* unsupported ioctl() 'cmd' numbers should return -ENOTTY.
* However the mid level returns -EINVAL for unrecognized 'cmd'
* numbers when this function is not supplied by the driver.
* Unfortunately some applications expect -EINVAL and react badly
* when -ENOTTY is returned; stick with -EINVAL.
**/
int ioctl(Scsi_Device *sdp, int cmd, void *arg);
......@@ -304,7 +309,10 @@ int proc_info(char * buffer, char ** start, off_t offset,
* @scp: pointer to scsi command object
* @done: function pointer to be invoked on completion
*
* Returns 1 if the adapter is busy, else returns 0.
* Returns 1 if the adapter (host) is busy, else returns 0. One
* reason for an adapter to be busy is that the number
* of outstanding queued commands is already equal to
* Scsi_Host::can_queue .
*
* Required: if Scsi_Host::can_queue is ever non-zero
* then this function is required.
......@@ -324,6 +332,9 @@ int proc_info(char * buffer, char ** start, off_t offset,
* return value should be generated by this function. However, in
* this case, it should be placed in scp->result before this function
* returns.
* If a status of CHECK CONDITION is placed in "result" when the
* 'done' callback is invoked, then the lower level driver should
* perform autosense and fill in the Scsi_Cmnd::sense_buffer array.
**/
int queuecommand(Scsi_Cmnd * scp, void (*done)(Scsi_Cmnd *));
......@@ -505,6 +516,28 @@ lock of equal granularity (i.e. per host). Using finer grain locks
(e.g. per scsi device) may be possible by juggling locks in
queuecommand().
Autosense
=========
Autosense (or auto-sense) is defined in the SAM-2 document as "the
automatic return of sense data to the application client coincident
with the completion of a SCSI command" when a status of CHECK CONDITION
occurs. Lower level drivers should perform autosense. This should be
done when the lower level driver detects a CHECK CONDITION status by either:
a) instructing the SCSI protocol (e.g. SCSI Parallel Interface (SPI))
to perform an extra data in phase on such responses
b) or, the lower level driver issuing a REQUEST SENSE command itself
Either way, the mid level decides whether the lower level driver has
performed autosense by checking Scsi_Cmnd::sense_buffer[0] . If this
byte has an upper nibble of 7 then autosense is assumed to have taken
place. If it has another value (and this byte is initialized to 0 before
each command) then the mid level will issue a REQUEST SENSE command.
In the presence of queued commands the "nexus" that maintains sense
buffer data from the command that failed until a following REQUEST SENSE
may get out of synchronization. This is why it is best for the lower
level driver to perform autosense.
Changes since lk 2.4 series
===========================
......@@ -514,6 +547,7 @@ per scsi host.
The older error handling mechanism has been removed. This means the
lower level interface functions abort() and reset() have been removed.
The Scsi_Host_Template::use_new_eh_code flag has been removed.
In the 2.4 series the scsi subsystem configuration descriptions were
aggregated with the configuration descriptions from all other Linux
......@@ -532,4 +566,4 @@ The following people have contributed to this document:
Douglas Gilbert
dgilbert@interlog.com
27th April 2002
13th August 2002
This diff is collapsed.
This diff is collapsed.
......@@ -11,9 +11,13 @@ Original driver (sg.h):
Version 2 and 3 extensions to driver:
* Copyright (C) 1998 - 2002 Douglas Gilbert
Version: 3.5.26 (20020708)
Version: 3.5.27 (20020812)
This version is for 2.5 series kernels.
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]
......
......@@ -129,6 +129,7 @@ EXPORT_SYMBOL(highmem_start_page);
EXPORT_SYMBOL(kmap_prot);
EXPORT_SYMBOL(kmap_pte);
#endif
EXPORT_SYMBOL(get_user_pages);
/* filesystem internal functions */
EXPORT_SYMBOL(def_blk_fops);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment