bk://linux-scsi.bkbits.net/scsi-misc-2.6
jejb@mulgrave.(none)|ChangeSet|20041024214801|61319 jejb

# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/10/24 22:09:45-07:00 akpm@bix.(none) 
#   Merge bk://linux-scsi.bkbits.net/scsi-misc-2.6
#   into bix.(none):/usr/src/bk-scsi
# 
# drivers/scsi/megaraid/megaraid_mbox.c
#   2004/10/24 22:09:40-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/24 16:48:01-05:00 jejb@mulgrave.(none) 
#   scsi_debug v 1.75
#   
#   From: 	Douglas Gilbert <dougg@torque.net>
#   
#       - fix highmem data transfers
#            - fix kunmap_atomic() argument
#            - disable clustering
#       - allow every_nth < 0 for error continuously once
#         count is reached
#       - minor sense buffer handling cleanup
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi_debug.c
#   2004/10/24 16:47:49-05:00 jejb@mulgrave.(none) +265 -214
#   scsi_debug v 1.75
# 
# ChangeSet
#   2004/10/24 12:58:33-04:00 stern@rowland.harvard.edu 
#   [PATCH] SCSI core: Fix refcounting error
#   
#   This bug was present as of 2.6.9-bk7, apparently introduced along with the
#   addition of SCSI targets into sysfs.  The code takes a reference to the
#   host for each initialized sdev but only drops a reference when each
#   target is released.  As you might expect, this causes a refcount leak
#   whenever a target has more than 0 LUNs.
#   
#   The patch changes things so that the reference is acquired when the target
#   is initialized, not when the sdev is initialized.
#   
#   Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi_sysfs.c
#   2004/10/24 07:09:42-04:00 stern@rowland.harvard.edu +1 -1
#   SCSI core: Fix refcounting error
# 
# drivers/scsi/scsi_scan.c
#   2004/10/24 07:09:48-04:00 stern@rowland.harvard.edu +1 -2
#   SCSI core: Fix refcounting error
# 
# ChangeSet
#   2004/10/24 12:09:06-04:00 jejb@mulgrave.(none) 
#   sym2 2.1.18m
#   
#   From: 	Matthew Wilcox <matthew@wil.cx>
#   
#   sym2 2.1.18m:
#    - Improve documentation
#    - Remove host-level command queueing (Christoph Hellwig)
#    - Add support for IU and QAS
#    - sparse annotation (Randolph Chung)
#    - Remove SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT ifdefs
#    - Switch to the new module_param interface
#      - Rename tags to cmd_per_lun for consistency
#      - Fix debug param
#      - Split extended tags functionality into the new tag_ctrl parameter
#      - rewrite how safe param works
#      - reverse_probe param has had no effect for a while, remove it.
#      - Add descriptions for all the parameters
#    - Add MODULE_AUTHOR and MODULE_DESCRIPTION
#    - Restructure sym_config_pqs() a little
#    - Move hostid setup to a more sensible place
#    - Do away with SYM_GLUE_C
#    - Use a completion instead of a semaphore (Thomas Gleixner)
#    - Use IDENTIFY() instead of M_IDENTIFY
#    - Define messages in terms of those defined in <scsi/scsi.h>
#    - Define PCI IDs in terms of those in <linux/pci_ids.h>
#    - Define sym2's status codes in terms of the SAM ones defined in <scsi/scsi.h>
#   
#   Added brown bag fix
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/sym53c8xx_2/sym_misc.c
#   2004/10/24 12:08:18-04:00 jejb@mulgrave.(none) +3 -1
#   sym2 2.1.18m
# 
# drivers/scsi/sym53c8xx_2/sym_hipd.c
#   2004/10/24 12:08:18-04:00 jejb@mulgrave.(none) +46 -54
#   sym2 2.1.18m
# 
# drivers/scsi/sym53c8xx_2/sym_glue.h
#   2004/10/24 12:08:18-04:00 jejb@mulgrave.(none) +0 -3
#   sym2 2.1.18m
# 
# drivers/scsi/sym53c8xx_2/sym_glue.c
#   2004/10/24 12:08:18-04:00 jejb@mulgrave.(none) +156 -240
#   sym2 2.1.18m
# 
# drivers/scsi/sym53c8xx_2/sym_defs.h
#   2004/10/24 12:08:18-04:00 jejb@mulgrave.(none) +47 -53
#   sym2 2.1.18m
# 
# drivers/scsi/sym53c8xx_2/sym53c8xx.h
#   2004/10/24 12:08:18-04:00 jejb@mulgrave.(none) +2 -45
#   sym2 2.1.18m
# 
# Documentation/scsi/sym53c8xx_2.txt
#   2004/10/24 12:08:18-04:00 jejb@mulgrave.(none) +135 -225
#   sym2 2.1.18m
# 
# ChangeSet
#   2004/10/24 11:55:44-04:00 adam@yggdrasil.com 
#   [PATCH] dmx3191d.c lacked MODULE_DEVICE_TABLE()
#   
#   The MODULE_DEVICE_TABLE() declaration, which is used by boot and hot
#   plug facilities to load the module when the hardware is present was
#   missed in the PCI API conversion.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/dmx3191d.c
#   2004/10/21 18:21:02-04:00 adam@yggdrasil.com +1 -0
#   dmx3191d.c lacked MODULE_DEVICE_TABLE()
# 
# ChangeSet
#   2004/10/24 11:43:08-04:00 akpm@osdl.org 
#   [PATCH] aic7xxx remove warnings
#   
#   From: Jan Dittmer <jdittmer@ppp0.net>
#   
#   This patch converts the aic7xxx driver to use module_param instead of
#   MODULE_PARM and therefore gets rid of two warning in the non-modular build
#   case.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/aic7xxx/aic7xxx_osm.c
#   2004/10/11 12:06:57-04:00 akpm@osdl.org +1 -3
#   aic7xxx remove warnings
# 
# ChangeSet
#   2004/10/24 11:38:59-04:00 akpm@osdl.org 
#   [PATCH] Add megaraid PCI IDs
#   
#   From: "Sergey S. Kostyliov" <rathamahata@ehouse.ru>
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/megaraid/megaraid_mbox.c
#   2004/10/08 11:12:09-04:00 akpm@osdl.org +6 -0
#   Add megaraid PCI IDs
# 
# ChangeSet
#   2004/10/24 11:35:46-04:00 rddunlap@osdl.org 
#   [PATCH] qla1280: driver_setup not __initdata
#   
#   'driver_setup' cannot be __initdata if slave_configure() can be called
#   after driver-init:
#   Error: ./drivers/scsi/qla1280.o .text refers to 0000000000000fbf R_X86_64_PC32     .init.data+0x000000000000007b
#   Error: ./drivers/scsi/qla1280.o .text refers to 0000000000000fc9 R_X86_64_PC32     .init.data+0x000000000000007e
#   Error: ./drivers/scsi/qla1280.o .text refers to 0000000000000fea R_X86_64_PC32     .init.data+0x000000000000007b
#   Error: ./drivers/scsi/qla1280.o .text refers to 0000000000000ff4 R_X86_64_PC32     .init.data+0x0000000000000080
#   Error: ./drivers/scsi/qla1280.o .text refers to 0000000000001039 R_X86_64_PC32     .init.data+0x000000000000007b
#   Error: ./drivers/scsi/qla1280.o .text refers to 0000000000001043 R_X86_64_PC32     .init.data+0x0000000000000082
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qla1280.c
#   2004/10/20 00:01:59-04:00 rddunlap@osdl.org +1 -1
#   qla1280: driver_setup not __initdata
# 
# ChangeSet
#   2004/10/24 11:29:52-04:00 andrew.vasquez@qlogic.com 
#   [PATCH] SCSI: fix `risc_code_addr01' multiple definition
#   
#   Make all of the qlogic firmware pointers static
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qlogicfc_asm.c
#   2004/10/07 14:10:08-04:00 andrew.vasquez@qlogic.com +5 -5
#   SCSI: fix `risc_code_addr01' multiple definition
# 
# ChangeSet
#   2004/10/21 00:22:42-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-scsi
# 
# drivers/scsi/megaraid/megaraid_mbox.h
#   2004/10/21 00:22:38-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/megaraid/megaraid_mbox.c
#   2004/10/21 00:22:38-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/19 22:12:26-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-scsi
# 
# drivers/scsi/megaraid/megaraid_mbox.c
#   2004/10/19 22:12:23-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/15 22:40:42-07:00 akpm@bix.(none) 
#   Merge bk://linux-scsi.bkbits.net/scsi-misc-2.6
#   into bix.(none):/usr/src/bk-scsi
# 
# drivers/scsi/megaraid/megaraid_mbox.h
#   2004/10/15 22:40:38-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# drivers/scsi/megaraid/megaraid_mbox.c
#   2004/10/15 22:40:38-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# Documentation/scsi/ChangeLog.megaraid
#   2004/10/15 22:40:38-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/10/13 13:38:51-07:00 akpm@bix.(none) 
#   foo
# 
# Documentation/scsi/ChangeLog.megaraid
#   2004/10/13 13:38:44-07:00 akpm@bix.(none) +0 -8
#   foo
# 
# drivers/scsi/megaraid/megaraid_mbox.h
#   2004/10/13 13:32:32-07:00 akpm@bix.(none) +0 -2
#   Auto merged
# 
# drivers/scsi/megaraid/megaraid_mbox.c
#   2004/10/13 13:32:32-07:00 akpm@bix.(none) +0 -3
#   Auto merged
# 
diff -Nru a/Documentation/scsi/sym53c8xx_2.txt b/Documentation/scsi/sym53c8xx_2.txt
--- a/Documentation/scsi/sym53c8xx_2.txt	2004-11-09 00:24:04 -08:00
+++ b/Documentation/scsi/sym53c8xx_2.txt	2004-11-09 00:24:04 -08:00
@@ -4,7 +4,9 @@
 21 Rue Carnot
 95170 DEUIL LA BARRE - FRANCE
 
-Decembre 28 2000
+Updated by Matthew Wilcox <matthew@wil.cx>
+
+2004-10-09
 ===============================================================================
 
 1.  Introduction
@@ -29,26 +31,20 @@
 10. Boot setup commands
       10.1 Syntax
       10.2 Available arguments
-             10.2.1  Master parity checking
-             10.2.2  Scsi parity checking
-             10.2.3  Default number of tagged commands
-             10.2.4  Default synchronous period factor
-             10.2.5  Verbosity level
-             10.2.6  Debug mode
-             10.2.7  Burst max
-             10.2.8  LED support
-             10.2.9  Max wide
-             10.2.10 Differential mode
-             10.2.11 IRQ mode
-             10.2.12 Reverse probe
-             10.2.13 Fix up PCI configuration space
-             10.2.14 Serial NVRAM
-             10.2.15 Check SCSI BUS 
-             10.2.16 Exclude a host from being attached
-             10.2.17 Suggest a default SCSI id for hosts
-      10.3 PCI configuration fix-up boot option
-      10.4 Serial NVRAM support boot option
-      10.5 SCSI BUS checking boot option
+             10.2.1  Default number of tagged commands
+             10.2.2  Burst max
+             10.2.3  LED support
+             10.2.4  Differential mode
+             10.2.5  IRQ mode
+             10.2.6  Check SCSI BUS 
+             10.2.7  Suggest a default SCSI id for hosts
+             10.2.8  Verbosity level
+             10.2.9  Debug mode
+             10.2.10 Settle delay
+             10.2.11 Serial NVRAM
+             10.2.12 Exclude a host from being attached
+      10.3 Converting from old options
+      10.4 SCSI BUS checking boot option
 11. SCSI problem troubleshooting
       15.1 Problem tracking
       15.2 Understanding hardware error reports
@@ -94,6 +90,9 @@
       Write a glue code for Linux.
           Gerard Roudier
 
+2004: Remove FreeBSD compatibility code.  Remove support for versions of
+      Linux before 2.6.  Start using Linux facilities.
+
 This README file addresses the Linux version of the driver. Under FreeBSD, 
 the driver documentation is the sym.8 man page.
 
@@ -279,11 +278,10 @@
 6. Parity checking
 
 The driver supports SCSI parity checking and PCI bus master parity
-checking. These features must be enabled in order to ensure safe data
-transfers. However, some flawed devices or mother boards will have
-problems with parity. You can disable either PCI parity or SCSI parity 
-checking by entering appropriate options from the boot command line.
-(See 10: Boot setup commands).
+checking.  These features must be enabled in order to ensure safe
+data transfers.  Some flawed devices or mother boards may have problems
+with parity.  The options to defeat parity checking have been removed
+from the driver.
 
 7. Profiling information
 
@@ -428,77 +426,90 @@
 
 10.1 Syntax
 
-Setup commands can be passed to the driver either at boot time or as a 
-string variable using 'insmod'.
-
-A boot setup command for this driver begins with the driver name "sym53c8xx=".
-The kernel syntax parser then expects an optionnal list of integers separated 
-with comma followed by an optional list of  comma-separated strings.
+Setup commands can be passed to the driver either at boot time or as
+parameters to modprobe, as described in Documentation/kernel-parameters.txt
 
 Example of boot setup command under lilo prompt:
 
-lilo: linux root=/dev/sda2 sym53c8xx=tags:4,sync:10,debug:0x200
+lilo: linux root=/dev/sda2 sym53c8xx.cmd_per_lun=4 sym53c8xx.sync=10 sym53c8xx.debug=0x200
 
 - enable tagged commands, up to 4 tagged commands queued.
 - set synchronous negotiation speed to 10 Mega-transfers / second.
 - set DEBUG_NEGO flag.
 
-Since comma seems not to be allowed when defining a string variable using  
-'insmod', the driver also accepts <space> as option separator. 
-The following command will install driver module with the same options as 
-above.
+The following command will install the driver module with the same
+options as above.
 
-    insmod sym53c8xx.o sym53c8xx="tags:4 sync:10 debug:0x200"
-
-The integer list of arguments is discarded by the driver. 
-
-Each string argument must be specified as "keyword:value". Only lower-case 
-characters and digits are allowed.
+    modprobe sym53c8xx cmd_per_lun=4 sync=10 debug=0x200"
 
 10.2 Available arguments
 
-10.2.1  Master parity checking
-        mpar:y     enabled
-        mpar:n     disabled
-
-10.2.2  Scsi parity checking
-        spar:y     enabled
-        spar:n     disabled
-
-10.2.3  Default number of tagged commands
-        tags:0     (or tags:1 ) tagged command queuing disabled
-        tags:#tags (#tags  > 1) tagged command queuing enabled
+10.2.1  Default number of tagged commands
+        cmd_per_lun=0 (or cmd_per_lun=1) tagged command queuing disabled
+        cmd_per_lun=#tags (#tags > 1) tagged command queuing enabled
   #tags will be truncated to the max queued commands configuration parameter.
-  This option also allows to specify a command queue depth for each device 
-  that support tagged command queueing.
+
+10.2.2  Detailed control of tagged commands
+  This option allows you to specify a command queue depth for each device 
+  that supports tagged command queueing.
   Example:
-      sym53c8xx=tags:10/t2t3q16-t5q24/t1u2q32
-               will set devices queue depth as follow:
+      tag_ctrl=10/t2t3q16-t5q24/t1u2q32
+  will set devices queue depth as follow:
       - controller #0 target #2 and target #3                  -> 16 commands,
       - controller #0 target #5                                -> 24 commands,
       - controller #1 target #1 logical unit #2                -> 32 commands,
       - all other logical units (all targets, all controllers) -> 10 commands.
 
-10.2.4  Default synchronous period factor
-        sync:255     disabled (asynchronous transfer mode)
-        sync:#factor
-  #factor =  9     Ultra-3 SCSI 80 Mega-transfers / second (Wide only)
-  #factor = 10     Ultra-2 SCSI 40 Mega-transfers / second
-  #factor = 11     Ultra-2 SCSI 33 Mega-transfers / second
-  #factor < 25     Ultra   SCSI 20 Mega-transfers / second
-  #factor < 50     Fast    SCSI-2
-
-  In all cases, the driver will use the minimum transfer period supported by 
-  controllers according to SYM53C8XX chip type.
-
-10.2.5  Verbosity level
-        verb:0     minimal
-        verb:1     normal
-        verb:2     too much
-
-10.2.6 Debug mode
-        debug:0	 clear debug flags
-        debug:#x   set debug flags
+10.2.3 Burst max
+        burst=0    burst disabled
+        burst=255  get burst length from initial IO register settings.
+        burst=#x   burst enabled (1<<#x burst transfers max)
+  #x is an integer value which is log base 2 of the burst transfers max.
+  By default the driver uses the maximum value supported by the chip.
+
+10.2.4 LED support
+        led=1      enable  LED support
+        led=0      disable LED support
+  Do not enable LED support if your scsi board does not use SDMS BIOS.
+  (See 'Configuration parameters')
+
+10.2.4 Differential mode
+        diff=0	never set up diff mode
+        diff=1	set up diff mode if BIOS set it
+        diff=2	always set up diff mode
+        diff=3	set diff mode if GPIO3 is not set
+
+10.2.5 IRQ mode
+        irqm=0     always open drain
+        irqm=1     same as initial settings (assumed BIOS settings)
+        irqm=2     always totem pole
+
+10.2.6 Check SCSI BUS 
+        buschk=<option bits>
+
+    Available option bits:
+        0x0:   No check.
+        0x1:   Check and do not attach the controller on error.  
+        0x2:   Check and just warn on error.
+
+10.2.7 Suggest a default SCSI id for hosts
+        hostid=255	no id suggested.
+        hostid=#x   (0 < x < 7) x suggested for hosts SCSI id.
+
+    If a host SCSI id is available from the NVRAM, the driver will ignore 
+    any value suggested as boot option. Otherwise, if a suggested value 
+    different from 255 has been supplied, it will use it. Otherwise, it will 
+    try to deduce the value previously set in the hardware and use value 
+    7 if the hardware value is zero.
+
+10.2.8  Verbosity level
+        verb=0     minimal
+        verb=1     normal
+        verb=2     too much
+
+10.2.9 Debug mode
+        debug=0	 clear debug flags
+        debug=#x   set debug flags
   #x is an integer value combining the following power-of-2 values:
   DEBUG_ALLOC       0x1
   DEBUG_PHASE       0x2
@@ -517,55 +528,17 @@
   You can play safely with DEBUG_NEGO. However, some of these flags may 
   generate bunches of syslog messages. 
 
-10.2.7 Burst max
-        burst:0    burst disabled
-        burst:255  get burst length from initial IO register settings.
-        burst:#x   burst enabled (1<<#x burst transfers max)
-  #x is an integer value which is log base 2 of the burst transfers max.
-  By default the driver uses the maximum value supported by the chip.
-
-10.2.8 LED support
-        led:1      enable  LED support
-        led:0      disable LED support
-  Donnot enable LED support if your scsi board does not use SDMS BIOS.
-  (See 'Configuration parameters')
-
-10.2.9 Max wide
-        wide:1      wide scsi enabled
-        wide:0      wide scsi disabled
-  Some scsi boards use a 875 (ultra wide) and only supply narrow connectors.
-  If you have connected a wide device with a 50 pins to 68 pins cable 
-  converter, any accepted wide negotiation will break further data transfers.
-  In such a case, using "wide:0" in the bootup command will be helpfull. 
-
-10.2.10 Differential mode
-        diff:0	never set up diff mode
-        diff:1	set up diff mode if BIOS set it
-        diff:2	always set up diff mode
-        diff:3	set diff mode if GPIO3 is not set
-
-10.2.11 IRQ mode
-        irqm:0     always open drain
-        irqm:1     same as initial settings (assumed BIOS settings)
-        irqm:2     always totem pole
-
-10.2.12 Reverse probe
-        revprob:n   probe chip ids from the PCI configuration in this order:
-                    810, 815, 825, 860, 875, 885, 875A, 895, 896, 895A,
-                    1510D, 1010-33, 1010-66.
-        revprob:y   probe chip ids in the reverse order.
-
-10.2.13 Fix up PCI configuration space
-        pcifix:<option bits>
+10.2.10 Settle delay
+        settle=n	delay for n seconds
 
-    Available option bits:
-        0x0:   No attempt to fix PCI configuration space registers values.
-        0x1:   Set PCI cache-line size register if not set.
-        0x2:   Set write and invalidate bit in PCI command register.
-
-10.2.14 Serial NVRAM
-        nvram:n     do not look for serial NVRAM
-        nvram:y     test controllers for onboard serial NVRAM
+  After a bus reset, the driver will delay for n seconds before talking
+  to any device on the bus.  The default is 3 seconds and safe mode will
+  default it to 10.
+
+10.2.11 Serial NVRAM
+	NB: option not currently implemented.
+        nvram=n     do not look for serial NVRAM
+        nvram=y     test controllers for onboard serial NVRAM
         (alternate binary form)
         nvram=<bits options>
         0x01   look for NVRAM  (equivalent to nvram=y)
@@ -574,105 +547,28 @@
         0x08   ignore NVRAM "Scan at boot time" parameter for all devices
         0x80   also attach controllers set to OFF in the NVRAM (sym53c8xx only)
 
-10.2.15 Check SCSI BUS 
-        buschk:<option bits>
-
-    Available option bits:
-        0x0:   No check.
-        0x1:   Check and do not attach the controller on error.  
-        0x2:   Check and just warn on error.
-
-10.2.16 Exclude a host from being attached
-        excl=<io_address>
+10.2.12 Exclude a host from being attached
+        excl=<io_address>,...
 
     Prevent host at a given io address from being attached.
-    For example 'sym53c8xx=excl:0xb400,excl:0xc000' indicate to the 
+    For example 'excl=0xb400,0xc000' indicate to the 
     driver not to attach hosts at address 0xb400 and 0xc000.
 
-10.2.17 Suggest a default SCSI id for hosts
-        hostid:255	no id suggested.
-        hostid:#x   (0 < x < 7) x suggested for hosts SCSI id.
-
-    If a host SCSI id is available from the NVRAM, the driver will ignore 
-    any value suggested as boot option. Otherwise, if a suggested value 
-    different from 255 has been supplied, it will use it. Otherwise, it will 
-    try to deduce the value previously set in the hardware and use value 
-    7 if the hardware value is zero.
-
-10.3 PCI configuration fix-up boot option
-
-pcifix:<option bits>
+10.3 Converting from old style options
 
-Available option bits:
-    0x1:     Set PCI cache-line size register if not set.
-    0x2:     Set write and invalidate bit in PCI command register.
+Previously, the sym2 driver accepted arguments of the form
+	sym53c8xx=tags:4,sync:10,debug:0x200
 
-Use 'pcifix:3' in order to allow the driver to fix both PCI features.
+As a result of the new module parameters, this is no longer available.
+Most of the options have remained the same, but tags has split into
+cmd_per_lun and tag_ctrl for its two different purposes.  The sample above
+would be specified as:
+	modprobe sym53c8xx cmd_per_lun=4 sync=10 debug=0x200
 
-Recent SYMBIOS 53C8XX scsi processors are able to use PCI read multiple 
-and PCI write and invalidate commands. These features require the 
-cache line size register to be properly set in the PCI configuration 
-space of the chips. On the other hand, chips will use PCI write and 
-invalidate commands only if the corresponding bit is set to 1 in the 
-PCI command register.
+or on the kernel boot line as:
+	sym53c8xx.cmd_per_lun=4 sym53c8xx.sync=10 sym53c8xx.debug=0x200
 
-Not all PCI bioses set the PCI cache line register and the PCI write and 
-invalidate bit in the PCI configuration space of 53C8XX chips.
-Optimized PCI accesses may be broken for some PCI/memory controllers or 
-make problems with some PCI boards.
-
-10.4 Serial NVRAM support boot option
-
-nvram:n     do not look for serial NVRAM
-nvram:y     test controllers for onboard serial NVRAM
-
-This option can also been entered as an hexadecimal value that allows 
-to control what information the driver will get from the NVRAM and what 
-information it will ignore.
-For details see '17. Serial NVRAM support'.
-
-When this option is enabled, the driver tries to detect all boards using 
-a Serial NVRAM. This memory is used to hold user set up parameters.
-
-The parameters the driver is able to get from the NVRAM depend on the 
-data format used, as follow:
-
-                                 Tekram format      Symbios format
-General and host parameters
-    Boot order                         N                   Y
-    Host SCSI ID                       Y                   Y
-    SCSI parity checking               Y                   Y
-    Verbose boot messages              N                   Y
-SCSI devices parameters
-    Synchronous transfer speed         Y                   Y
-    Wide 16 / Narrow                   Y                   Y
-    Tagged Command Queuing enabled     Y                   Y
-    Disconnections enabled             Y                   Y
-    Scan at boot time                  N                   Y
-
-In order to speed up the system boot, for each device configured without 
-the "scan at boot time" option, the driver forces an error on the 
-first TEST UNIT READY command received for this device.
-
-Some SDMS BIOS revisions seem to be unable to boot cleanly with very fast 
-hard disks. In such a situation you cannot configure the NVRAM with 
-optimized parameters value.
-
-The 'nvram' boot option can be entered in hexadecimal form in order 
-to ignore some options configured in the NVRAM, as follow:
-
-nvram=<bits options>
-      0x01   look for NVRAM  (equivalent to nvram=y)
-      0x02   ignore NVRAM "Synchronous negotiation" parameters for all devices
-      0x04   ignore NVRAM "Wide negotiation"  parameter for all devices
-      0x08   ignore NVRAM "Scan at boot time" parameter for all devices
-      0x80   also attach controllers set to OFF in the NVRAM (sym53c8xx only)
-
-Option 0x80 is disabled by default.
-Result is that, by default (option not set), the sym53c8xx driver will not 
-attach controllers set to OFF in the NVRAM.
-
-10.5 SCSI BUS checking boot option.
+10.4 SCSI BUS checking boot option.
 
 When this option is set to a non-zero value, the driver checks SCSI lines 
 logic state, 100 micro-seconds after having asserted the SCSI RESET line.
@@ -805,14 +701,8 @@
 host adaptor and it's attached drives.
 
 The Symbios NVRAM also holds data on the boot order of host adaptors in a
-system with more than one host adaptor. This enables the order of scanning
-the cards for drives to be changed from the default used during host adaptor
-detection.
-
-This can be done to a limited extent at the moment using "reverse probe" but
-this only changes the order of detection of different types of cards. The
-NVRAM boot order settings can do this as well as change the order the same
-types of cards are scanned in, something "reverse probe" cannot do.
+system with more than one host adaptor.  This information is no longer used
+as it's fundamentally incompatible with the hotplug PCI model.
 
 Tekram boards using Symbios chips, DC390W/F/U, which have NVRAM are detected
 and this is used to distinguish between Symbios compatible and Tekram host 
@@ -823,6 +713,26 @@
 "diff" support. ("led pin" support for Symbios compatible cards can remain
 enabled when using Tekram cards. It does nothing useful for Tekram host
 adaptors but does not cause problems either.)
+
+The parameters the driver is able to get from the NVRAM depend on the 
+data format used, as follow:
+
+                                 Tekram format      Symbios format
+General and host parameters
+    Boot order                         N                   Y
+    Host SCSI ID                       Y                   Y
+    SCSI parity checking               Y                   Y
+    Verbose boot messages              N                   Y
+SCSI devices parameters
+    Synchronous transfer speed         Y                   Y
+    Wide 16 / Narrow                   Y                   Y
+    Tagged Command Queuing enabled     Y                   Y
+    Disconnections enabled             Y                   Y
+    Scan at boot time                  N                   Y
+
+In order to speed up the system boot, for each device configured without 
+the "scan at boot time" option, the driver forces an error on the 
+first TEST UNIT READY command received for this device.
 
 
 17.2 Symbios NVRAM layout
diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c	2004-11-09 00:24:04 -08:00
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c	2004-11-09 00:24:04 -08:00
@@ -438,7 +438,7 @@
 MODULE_DESCRIPTION("Adaptec Aic77XX/78XX SCSI Host Bus Adapter driver");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(AIC7XXX_DRIVER_VERSION);
-MODULE_PARM(aic7xxx, "s");
+module_param(aic7xxx, charp, 0444);
 MODULE_PARM_DESC(aic7xxx,
 "period delimited, options string.\n"
 "	verbose			Enable verbose/diagnostic logging\n"
@@ -845,7 +845,6 @@
 		return (0);
 	}
 	ahc_linux_size_nseg();
-#ifdef MODULE
 	/*
 	 * If we've been passed any parameters, process them now.
 	 */
@@ -857,7 +856,6 @@
 "aic7xxx: to see the proper way to specify options to the aic7xxx module\n"
 "aic7xxx: Specifically, don't use any commas when passing arguments to\n"
 "aic7xxx: insmod or else it might trash certain memory areas.\n");
-#endif
 
 	template->proc_name = "aic7xxx";
 
diff -Nru a/drivers/scsi/dmx3191d.c b/drivers/scsi/dmx3191d.c
--- a/drivers/scsi/dmx3191d.c	2004-11-09 00:24:04 -08:00
+++ b/drivers/scsi/dmx3191d.c	2004-11-09 00:24:04 -08:00
@@ -146,6 +146,7 @@
 		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4},
 	{ }
 };
+MODULE_DEVICE_TABLE(pci, dmx3191d_pci_tbl);
 
 static struct pci_driver dmx3191d_pci_driver = {
 	.name		= DMX3191D_DRIVER_NAME,
diff -Nru a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c
--- a/drivers/scsi/megaraid/megaraid_mbox.c	2004-11-09 00:24:04 -08:00
+++ b/drivers/scsi/megaraid/megaraid_mbox.c	2004-11-09 00:24:04 -08:00
@@ -295,6 +295,12 @@
 		PCI_SUBSYS_ID_PERC3_SC,
 	},
 	{
+		PCI_VENDOR_ID_AMI,
+		PCI_DEVICE_ID_AMI_MEGARAID3,
+		PCI_VENDOR_ID_AMI,
+		PCI_SUBSYS_ID_PERC3_SC,
+	},
+	{
 		PCI_VENDOR_ID_LSI_LOGIC,
 		PCI_DEVICE_ID_MEGARAID_SCSI_320_0,
 		PCI_VENDOR_ID_LSI_LOGIC,
diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
--- a/drivers/scsi/qla1280.c	2004-11-09 00:24:05 -08:00
+++ b/drivers/scsi/qla1280.c	2004-11-09 00:24:05 -08:00
@@ -549,7 +549,7 @@
 static int qla1280_set_target_parameters(struct scsi_qla_host *, int, int);
 
 
-static struct qla_driver_setup driver_setup __initdata;
+static struct qla_driver_setup driver_setup;
 
 /*
  * convert scsi data direction to request_t control flags
diff -Nru a/drivers/scsi/qlogicfc_asm.c b/drivers/scsi/qlogicfc_asm.c
--- a/drivers/scsi/qlogicfc_asm.c	2004-11-09 00:24:04 -08:00
+++ b/drivers/scsi/qlogicfc_asm.c	2004-11-09 00:24:04 -08:00
@@ -19,10 +19,10 @@
  *	Firmware Version 1.19.16 (10:36 Nov 02, 2000)
  */
 
-unsigned short risc_code_addr01 = 0x1000 ;
+static unsigned short risc_code_addr01 = 0x1000 ;
 
-unsigned short risc_code_length2100 = 0x9260;
-unsigned short risc_code2100[] = {
+static unsigned short risc_code_length2100 = 0x9260;
+static unsigned short risc_code2100[] = {
 	0x0078, 0x102d, 0x0000, 0x9260, 0x0000, 0x0001, 0x0013, 0x0010,
 	0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939,
 	0x3920, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241,
@@ -4729,8 +4729,8 @@
  *	Firmware Version 2.01.27 (11:07 Dec 18, 2000)
  */
 
-unsigned short risc_code_length2200 = 0x9cbf;
-unsigned short risc_code2200[] = { 
+static unsigned short risc_code_length2200 = 0x9cbf;
+static unsigned short risc_code2200[] = { 
 	0x0470, 0x0000, 0x0000, 0x9cbf, 0x0000, 0x0002, 0x0001, 0x001b,
 	0x0017, 0x2043, 0x4f50, 0x5952, 0x4947, 0x4854, 0x2031, 0x3939,
 	0x3920, 0x514c, 0x4f47, 0x4943, 0x2043, 0x4f52, 0x504f, 0x5241,
diff -Nru a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
--- a/drivers/scsi/scsi_debug.c	2004-11-09 00:24:04 -08:00
+++ b/drivers/scsi/scsi_debug.c	2004-11-09 00:24:05 -08:00
@@ -55,8 +55,8 @@
 #include "scsi_logging.h"
 #include "scsi_debug.h"
 
-#define SCSI_DEBUG_VERSION "1.74"
-static const char * scsi_debug_version_date = "20040829";
+#define SCSI_DEBUG_VERSION "1.75"
+static const char * scsi_debug_version_date = "20041023";
 
 /* Additional Sense Code (ASC) used */
 #define NO_ADDED_SENSE 0x0
@@ -82,7 +82,7 @@
 #define DEF_EVERY_NTH   0
 #define DEF_NUM_PARTS   0
 #define DEF_OPTS   0
-#define DEF_SCSI_LEVEL   4    /* SPC-2 */
+#define DEF_SCSI_LEVEL   5    /* INQUIRY, byte2 [5->SPC-3] */
 #define DEF_PTYPE   0
 #define DEF_D_SENSE   0
 
@@ -95,6 +95,13 @@
  *   - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
  *   - a RECOVERED_ERROR is simulated on successful read and write
  *     commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
+ *
+ * When "every_nth" < 0 then after "- every_nth" commands:
+ *   - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
+ *   - a RECOVERED_ERROR is simulated on successful read and write
+ *     commands if SCSI_DEBUG_OPT_RECOVERED_ERR is set.
+ * This will continue until some other action occurs (e.g. the user
+ * writing a new value (other than -1 or 1) to every_nth via sysfs).
  */
 
 /* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
@@ -195,14 +202,12 @@
 	.cmd_per_lun =		3,
 	.max_sectors =		4096,
 	.unchecked_isa_dma = 	0,
-	.use_clustering = 	ENABLE_CLUSTERING,
+	.use_clustering = 	DISABLE_CLUSTERING,
 	.module =		THIS_MODULE,
 };
 
 static unsigned char * fake_storep;	/* ramdisk storage */
 
-static unsigned char spare_buff[SDEBUG_SENSE_LEN];
-
 static int num_aborts = 0;
 static int num_dev_resets = 0;
 static int num_bus_resets = 0;
@@ -228,21 +233,28 @@
 		(DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
 
 /* function declarations */
-static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
-			int bufflen, struct sdebug_dev_info * devip);
-static int resp_mode_sense(unsigned char * cmd, int target,
-			   unsigned char * buff, int bufflen,
+static int resp_inquiry(struct scsi_cmnd * SCpnt, int target,
+			struct sdebug_dev_info * devip);
+static int resp_requests(struct scsi_cmnd * SCpnt,
+			 struct sdebug_dev_info * devip);
+static int resp_readcap(struct scsi_cmnd * SCpnt,
+			struct sdebug_dev_info * devip);
+static int resp_mode_sense(struct scsi_cmnd * SCpnt, int target,
 			   struct sdebug_dev_info * devip);
 static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block,
 		     int num, struct sdebug_dev_info * devip);
 static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block,
 		      int num, struct sdebug_dev_info * devip);
-static int resp_report_luns(unsigned char * cmd, unsigned char * buff,
-			    int bufflen, struct sdebug_dev_info * devip);
+static int resp_report_luns(struct scsi_cmnd * SCpnt,
+			    struct sdebug_dev_info * devip);
+static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
+                                int arr_len);
+static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
+                               int max_arr_len);
 static void timer_intr_handler(unsigned long);
 static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev);
 static void mk_sense_buffer(struct sdebug_dev_info * devip, int key,
-			    int asc, int asq, int inbandLen);
+			    int asc, int asq);
 static int check_reset(struct scsi_cmnd * SCpnt,
 		       struct sdebug_dev_info * devip);
 static int schedule_resp(struct scsi_cmnd * cmnd,
@@ -264,49 +276,20 @@
 static struct device pseudo_primary;
 static struct bus_type pseudo_lld_bus;
 
-static unsigned char * scatg2virt(const struct scatterlist * sclp)
-{
-	if (NULL == sclp)
-		return NULL;
-	else if (sclp->page)
-		return (unsigned char *)page_address(sclp->page) +
-		       sclp->offset;
-	else
-		return NULL;
-}
 
 static
 int scsi_debug_queuecommand(struct scsi_cmnd * SCpnt, done_funct_t done)
 {
 	unsigned char *cmd = (unsigned char *) SCpnt->cmnd;
 	int block, upper_blk, num, k;
-	unsigned char *buff;
 	int errsts = 0;
 	int target = SCpnt->device->id;
-	int bufflen = SCpnt->request_bufflen;
-	unsigned long capac;
 	struct sdebug_dev_info * devip = NULL;
-	unsigned char * sbuff;
 	int inj_recovered = 0;
 
 	if (done == NULL)
 		return 0;	/* assume mid level reprocessing command */
 
-	if (SCpnt->use_sg) { /* just use first element */
-		struct scatterlist *sgpnt = (struct scatterlist *)
-						SCpnt->request_buffer;
-
-		buff = scatg2virt(&sgpnt[0]);
-		bufflen = sgpnt[0].length;
-		/* READ and WRITE process scatterlist themselves */
-	}
-	else
-		buff = (unsigned char *) SCpnt->request_buffer;
-	if (NULL == buff) {
-		buff = spare_buff;	/* assume cmd moves no data */
-		bufflen = SDEBUG_SENSE_LEN;
-	}
-
 	if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) {
 		printk(KERN_INFO "scsi_debug: cmd ");
 		for (k = 0, num = SCpnt->cmd_len; k < num; ++k)
@@ -328,9 +311,11 @@
 		return schedule_resp(SCpnt, NULL, done,
 				     DID_NO_CONNECT << 16, 0);
 
-        if ((scsi_debug_every_nth > 0) &&
-            (++scsi_debug_cmnd_count >= scsi_debug_every_nth)) {
-                scsi_debug_cmnd_count =0;
+        if ((scsi_debug_every_nth != 0) &&
+            (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) {
+                scsi_debug_cmnd_count = 0;
+		if (scsi_debug_every_nth < -1)
+			scsi_debug_every_nth = -1;
 		if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
 			return 0; /* ignore command causing timeout */
 		else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
@@ -339,23 +324,14 @@
 
 	switch (*cmd) {
 	case INQUIRY:     /* mandatory, ignore unit attention */
-		errsts = resp_inquiry(cmd, target, buff, bufflen, devip);
+		errsts = resp_inquiry(SCpnt, target, devip);
 		break;
 	case REQUEST_SENSE:	/* mandatory, ignore unit attention */
-		if (devip) {
-			sbuff = devip->sense_buff;
-			memcpy(buff, sbuff, (bufflen < SDEBUG_SENSE_LEN) ?
-					     bufflen : SDEBUG_SENSE_LEN);
-			mk_sense_buffer(devip, 0, NO_ADDED_SENSE, 0, 7);
-		} else {
-			memset(buff, 0, bufflen);
-			buff[0] = 0x70;
-		}
+		errsts = resp_requests(SCpnt, devip);
 		break;
 	case REZERO_UNIT:	/* actually this is REWIND for SSC */
 	case START_STOP:
 		errsts = check_reset(SCpnt, devip);
-		memset(buff, 0, bufflen);
 		break;
 	case ALLOW_MEDIUM_REMOVAL:
 		if ((errsts = check_reset(SCpnt, devip)))
@@ -366,40 +342,24 @@
 		break;
 	case SEND_DIAGNOSTIC:     /* mandatory */
 		errsts = check_reset(SCpnt, devip);
-		memset(buff, 0, bufflen);
 		break;
 	case TEST_UNIT_READY:     /* mandatory */
 		errsts = check_reset(SCpnt, devip);
-		memset(buff, 0, bufflen);
 		break;
         case RESERVE:
 		errsts = check_reset(SCpnt, devip);
-		memset(buff, 0, bufflen);
                 break;
         case RESERVE_10:
 		errsts = check_reset(SCpnt, devip);
-		memset(buff, 0, bufflen);
                 break;
         case RELEASE:
 		errsts = check_reset(SCpnt, devip);
-		memset(buff, 0, bufflen);
                 break;
         case RELEASE_10:
 		errsts = check_reset(SCpnt, devip);
-		memset(buff, 0, bufflen);
                 break;
 	case READ_CAPACITY:
-		errsts = check_reset(SCpnt, devip);
-		memset(buff, 0, bufflen);
-		if (bufflen > 7) {
-			capac = (unsigned long)sdebug_capacity - 1;
-			buff[0] = (capac >> 24);
-			buff[1] = (capac >> 16) & 0xff;
-			buff[2] = (capac >> 8) & 0xff;
-			buff[3] = capac & 0xff;
-			buff[6] = (SECT_SIZE_PER(target) >> 8) & 0xff;
-			buff[7] = SECT_SIZE_PER(target) & 0xff;
-		}
+		errsts = resp_readcap(SCpnt, devip);
 		break;
 	case READ_16:
 	case READ_12:
@@ -432,12 +392,15 @@
 		errsts = resp_read(SCpnt, upper_blk, block, num, devip);
 		if (inj_recovered && (0 == errsts)) {
 			mk_sense_buffer(devip, RECOVERED_ERROR,
-					THRESHHOLD_EXCEEDED, 0, 18);
+					THRESHHOLD_EXCEEDED, 0);
 			errsts = check_condition_result;
 		}
 		break;
 	case REPORT_LUNS:	/* mandatory, ignore unit attention */
-		errsts = resp_report_luns(cmd, buff, bufflen, devip);
+		errsts = resp_report_luns(SCpnt, devip);
+		break;
+	case VERIFY:		/* 10 byte SBC-2 command */
+		errsts = check_reset(SCpnt, devip);
 		break;
 	case WRITE_16:
 	case WRITE_12:
@@ -470,19 +433,16 @@
 		errsts = resp_write(SCpnt, upper_blk, block, num, devip);
 		if (inj_recovered && (0 == errsts)) {
 			mk_sense_buffer(devip, RECOVERED_ERROR,
-					THRESHHOLD_EXCEEDED, 0, 18);
+					THRESHHOLD_EXCEEDED, 0);
 			errsts = check_condition_result;
 		}
 		break;
 	case MODE_SENSE:
 	case MODE_SENSE_10:
-		if ((errsts = check_reset(SCpnt, devip)))
-			break;
-		errsts = resp_mode_sense(cmd, target, buff, bufflen, devip);
+		errsts = resp_mode_sense(SCpnt, target, devip);
 		break;
 	case SYNCHRONIZE_CACHE:
 		errsts = check_reset(SCpnt, devip);
-		memset(buff, 0, bufflen);
 		break;
 	default:
 		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
@@ -490,7 +450,7 @@
 			       "supported\n", *cmd);
 		if ((errsts = check_reset(SCpnt, devip)))
 			break;	/* Unit attention takes precedence */
-		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0, 18);
+		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0);
 		errsts = check_condition_result;
 		break;
 	}
@@ -513,18 +473,105 @@
 			printk(KERN_INFO "scsi_debug: Reporting Unit "
 			       "attention: power on reset\n");
 		devip->reset = 0;
-		mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0, 18);
+		mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0);
 		return check_condition_result;
 	}
 	return 0;
 }
 
-#define SDEBUG_LONG_INQ_SZ 96
-#define SDEBUG_MAX_INQ_ARR_SZ 128
+/* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */
+static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
+				int arr_len)
+{
+	int k, req_len, act_len, len, active;
+	void * kaddr;
+	void * kaddr_off;
+	struct scatterlist * sgpnt;
+
+	if (0 == scp->request_bufflen)
+		return 0;
+	if (NULL == scp->request_buffer)
+		return (DID_ERROR << 16);
+	if (! ((scp->sc_data_direction == DMA_BIDIRECTIONAL) ||
+	      (scp->sc_data_direction == DMA_FROM_DEVICE)))
+		return (DID_ERROR << 16);
+	if (0 == scp->use_sg) {
+		req_len = scp->request_bufflen;
+		act_len = (req_len < arr_len) ? req_len : arr_len;
+		memcpy(scp->request_buffer, arr, act_len);
+		scp->resid = req_len - act_len;
+		return 0;
+	}
+	sgpnt = (struct scatterlist *)scp->request_buffer;
+	active = 1;
+	for (k = 0, req_len = 0, act_len = 0; k < scp->use_sg; ++k, ++sgpnt) {
+		if (active) {
+			kaddr = (unsigned char *)
+				kmap_atomic(sgpnt->page, KM_USER0);
+			if (NULL == kaddr)
+				return (DID_ERROR << 16);
+			kaddr_off = (unsigned char *)kaddr + sgpnt->offset;
+			len = sgpnt->length;
+			if ((req_len + len) > arr_len) {
+				active = 0;
+				len = arr_len - req_len;
+			}
+			memcpy(kaddr_off, arr + req_len, len);
+			kunmap_atomic(kaddr, KM_USER0);
+			act_len += len;
+		}
+		req_len += sgpnt->length;
+	}
+	scp->resid = req_len - act_len;
+	return 0;
+}
 
-static const char * vendor_id = "Linux   ";
-static const char * product_id = "scsi_debug      ";
-static const char * product_rev = "0004";
+/* Returns number of bytes fetched into 'arr' or -1 if error. */
+static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,
+			       int max_arr_len)
+{
+	int k, req_len, len, fin;
+	void * kaddr;
+	void * kaddr_off;
+	struct scatterlist * sgpnt;
+
+	if (0 == scp->request_bufflen)
+		return 0;
+	if (NULL == scp->request_buffer)
+		return -1;
+	if (! ((scp->sc_data_direction == DMA_BIDIRECTIONAL) ||
+	      (scp->sc_data_direction == DMA_TO_DEVICE)))
+		return -1;
+	if (0 == scp->use_sg) {
+		req_len = scp->request_bufflen;
+		len = (req_len < max_arr_len) ? req_len : max_arr_len;
+		memcpy(arr, scp->request_buffer, len);
+		return len;
+	}
+	sgpnt = (struct scatterlist *)scp->request_buffer;
+	for (k = 0, req_len = 0, fin = 0; k < scp->use_sg; ++k, ++sgpnt) {
+		kaddr = (unsigned char *)kmap_atomic(sgpnt->page, KM_USER0);
+		if (NULL == kaddr)
+			return -1;
+		kaddr_off = (unsigned char *)kaddr + sgpnt->offset;
+		len = sgpnt->length;
+		if ((req_len + len) > max_arr_len) {
+			len = max_arr_len - req_len;
+			fin = 1;
+		}
+		memcpy(arr + req_len, kaddr_off, len);
+		kunmap_atomic(kaddr, KM_USER0);
+		if (fin)
+			return req_len + len;
+		req_len += sgpnt->length;
+	}
+	return req_len;
+}
+
+
+static const char * inq_vendor_id = "Linux   ";
+static const char * inq_product_id = "scsi_debug      ";
+static const char * inq_product_rev = "0004";
 
 static int inquiry_evpd_83(unsigned char * arr, int dev_id_num,
 			   const char * dev_id_str, int dev_id_str_len)
@@ -536,8 +583,8 @@
 	arr[0] = 0x2;	/* ASCII */
 	arr[1] = 0x1;
 	arr[2] = 0x0;
-	memcpy(&arr[4], vendor_id, 8);
-	memcpy(&arr[12], product_id, 16);
+	memcpy(&arr[4], inq_vendor_id, 8);
+	memcpy(&arr[12], inq_product_id, 16);
 	memcpy(&arr[28], dev_id_str, dev_id_str_len);
 	num = 8 + 16 + dev_id_str_len;
 	arr[3] = num;
@@ -558,24 +605,25 @@
 	return num + 12;
 }
 
-static int resp_inquiry(unsigned char * cmd, int target, unsigned char * buff,
-			int bufflen, struct sdebug_dev_info * devip)
+
+#define SDEBUG_LONG_INQ_SZ 96
+#define SDEBUG_MAX_INQ_ARR_SZ 128
+
+static int resp_inquiry(struct scsi_cmnd * scp, int target,
+			struct sdebug_dev_info * devip)
 {
 	unsigned char pq_pdt;
 	unsigned char arr[SDEBUG_MAX_INQ_ARR_SZ];
-	int min_len = bufflen > SDEBUG_MAX_INQ_ARR_SZ ?
-			SDEBUG_MAX_INQ_ARR_SZ : bufflen;
+	unsigned char *cmd = (unsigned char *)scp->cmnd;
+	int alloc_len;
 
-	if (bufflen < cmd[4])
-		printk(KERN_INFO "scsi_debug: inquiry: bufflen=%d "
-		       "< alloc_length=%d\n", bufflen, (int)cmd[4]);
-	memset(buff, 0, bufflen);
+	alloc_len = (cmd[3] << 8) + cmd[4];
 	memset(arr, 0, SDEBUG_MAX_INQ_ARR_SZ);
 	pq_pdt = (scsi_debug_ptype & 0x1f);
 	arr[0] = pq_pdt;
 	if (0x2 & cmd[1]) {  /* CMDDT bit set */
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
-			       	0, 18);
+			       	0);
 		return check_condition_result;
 	} else if (0x1 & cmd[1]) {  /* EVPD bit set */
 		int dev_id_num, len;
@@ -600,11 +648,11 @@
 		} else {
 			/* Illegal request, invalid field in cdb */
 			mk_sense_buffer(devip, ILLEGAL_REQUEST,
-					INVALID_FIELD_IN_CDB, 0, 18);
+					INVALID_FIELD_IN_CDB, 0);
 			return check_condition_result;
 		}
-		memcpy(buff, arr, min_len);
-		return 0;
+		return fill_from_dev_buffer(scp, arr,
+			    min(alloc_len, SDEBUG_MAX_INQ_ARR_SZ));
 	}
 	/* drops through here for a standard inquiry */
 	arr[1] = DEV_REMOVEABLE(target) ? 0x80 : 0;	/* Removable disk */
@@ -612,20 +660,67 @@
 	arr[3] = 2;    /* response_data_format==2 */
 	arr[4] = SDEBUG_LONG_INQ_SZ - 5;
 	arr[6] = 0x1; /* claim: ADDR16 */
+	/* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */
 	arr[7] = 0x3a; /* claim: WBUS16, SYNC, LINKED + CMDQUE */
-	memcpy(&arr[8], vendor_id, 8);
-	memcpy(&arr[16], product_id, 16);
-	memcpy(&arr[32], product_rev, 4);
+	memcpy(&arr[8], inq_vendor_id, 8);
+	memcpy(&arr[16], inq_product_id, 16);
+	memcpy(&arr[32], inq_product_rev, 4);
 	/* version descriptors (2 bytes each) follow */
 	arr[58] = 0x0; arr[59] = 0x40; /* SAM-2 */
-	arr[60] = 0x2; arr[61] = 0x60; /* SPC-2 */
+	arr[60] = 0x3; arr[61] = 0x0;  /* SPC-3 */
 	if (scsi_debug_ptype == 0) {
-	    arr[62] = 0x1; arr[63] = 0x80; /* SBC */
+		arr[62] = 0x1; arr[63] = 0x80; /* SBC */
 	} else if (scsi_debug_ptype == 1) {
-	    arr[62] = 0x2; arr[63] = 0x00; /* SSC */
+		arr[62] = 0x2; arr[63] = 0x00; /* SSC */
 	}
-	memcpy(buff, arr, min_len);
-	return 0;
+	return fill_from_dev_buffer(scp, arr,
+			    min(alloc_len, SDEBUG_LONG_INQ_SZ));
+}
+
+static int resp_requests(struct scsi_cmnd * scp,
+			 struct sdebug_dev_info * devip)
+{
+	unsigned char * sbuff;
+	unsigned char *cmd = (unsigned char *)scp->cmnd;
+	unsigned char arr[SDEBUG_SENSE_LEN];
+	int len = 18;
+
+	memset(arr, 0, SDEBUG_SENSE_LEN);
+	if (devip->reset == 1)
+		mk_sense_buffer(devip, 0, NO_ADDED_SENSE, 0);
+	sbuff = devip->sense_buff;
+	if ((cmd[1] & 1) && (! scsi_debug_dsense)) {
+		/* DESC bit set and sense_buff in fixed format */
+		arr[0] = 0x72;
+		arr[1] = sbuff[2];     /* sense key */
+		arr[2] = sbuff[12];    /* asc */
+		arr[3] = sbuff[13];    /* ascq */
+		len = 8;
+	} else
+		memcpy(arr, sbuff, SDEBUG_SENSE_LEN);
+	mk_sense_buffer(devip, 0, NO_ADDED_SENSE, 0);
+	return fill_from_dev_buffer(scp, arr, len);
+}
+
+#define SDEBUG_READCAP_ARR_SZ 8
+static int resp_readcap(struct scsi_cmnd * scp,
+			struct sdebug_dev_info * devip)
+{
+	unsigned char arr[SDEBUG_READCAP_ARR_SZ];
+	unsigned long capac;
+	int errsts;
+
+	if ((errsts = check_reset(scp, devip)))
+		return errsts;
+	memset(arr, 0, SDEBUG_READCAP_ARR_SZ);
+	capac = (unsigned long)sdebug_capacity - 1;
+	arr[0] = (capac >> 24);
+	arr[1] = (capac >> 16) & 0xff;
+	arr[2] = (capac >> 8) & 0xff;
+	arr[3] = capac & 0xff;
+	arr[6] = (SECT_SIZE_PER(target) >> 8) & 0xff;
+	arr[7] = SECT_SIZE_PER(target) & 0xff;
+	return fill_from_dev_buffer(scp, arr, SDEBUG_READCAP_ARR_SZ);
 }
 
 /* <<Following mode page info copied from ST318451LW>> */
@@ -706,34 +801,29 @@
 
 #define SDEBUG_MAX_MSENSE_SZ 256
 
-static int resp_mode_sense(unsigned char * cmd, int target,
-			   unsigned char * buff, int bufflen,
+static int resp_mode_sense(struct scsi_cmnd * scp, int target,
 			   struct sdebug_dev_info * devip)
 {
 	unsigned char dbd;
 	int pcontrol, pcode, subpcode;
 	unsigned char dev_spec;
-	int alloc_len, msense_6, offset, len;
+	int alloc_len, msense_6, offset, len, errsts;
 	unsigned char * ap;
 	unsigned char arr[SDEBUG_MAX_MSENSE_SZ];
-	int min_len = bufflen > SDEBUG_MAX_MSENSE_SZ ?
-			SDEBUG_MAX_MSENSE_SZ : bufflen;
+	unsigned char *cmd = (unsigned char *)scp->cmnd;
 
-	SCSI_LOG_LLQUEUE(3, printk("Mode sense ...(%p %d)\n", buff, bufflen));
+	if ((errsts = check_reset(scp, devip)))
+		return errsts;
 	dbd = cmd[1] & 0x8;
 	pcontrol = (cmd[2] & 0xc0) >> 6;
 	pcode = cmd[2] & 0x3f;
 	subpcode = cmd[3];
 	msense_6 = (MODE_SENSE == cmd[0]);
 	alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]);
-	if (bufflen < alloc_len)
-		printk(KERN_INFO "scsi_debug: mode_sense: bufflen=%d "
-		       "< alloc_length=%d\n", bufflen, alloc_len);
-	memset(buff, 0, bufflen);
 	memset(arr, 0, SDEBUG_MAX_MSENSE_SZ);
 	if (0x3 == pcontrol) {  /* Saving values not supported */
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP,
-			       	0, 18);
+			       	0);
 		return check_condition_result;
 	}
 	dev_spec = DEV_READONLY(target) ? 0x80 : 0x0;
@@ -748,7 +838,7 @@
 
 	if (0 != subpcode) { /* TODO: Control Extension page */
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
-			       	0, 18);
+			       	0);
 		return check_condition_result;
 	}
 	switch (pcode) {
@@ -787,146 +877,104 @@
 		break;
 	default:
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
-			       	0, 18);
+			       	0);
 		return check_condition_result;
 	}
 	if (msense_6)
 		arr[0] = offset - 1;
 	else {
-		offset -= 2;
-		arr[0] = (offset >> 8) & 0xff;
-		arr[1] = offset & 0xff;
+		arr[0] = ((offset - 2) >> 8) & 0xff;
+		arr[1] = (offset - 2) & 0xff;
 	}
-	memcpy(buff, arr, min_len);
-	return 0;
+	return fill_from_dev_buffer(scp, arr, min(alloc_len, offset));
 }
 
 static int resp_read(struct scsi_cmnd * SCpnt, int upper_blk, int block,
 		     int num, struct sdebug_dev_info * devip)
 {
-        unsigned char *buff = (unsigned char *) SCpnt->request_buffer;
-        int nbytes, sgcount;
-        struct scatterlist *sgpnt = NULL;
-        int bufflen = SCpnt->request_bufflen;
 	unsigned long iflags;
+	int ret;
 
 	if (upper_blk || (block + num > sdebug_capacity)) {
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
-				0, 18);
+				0);
 		return check_condition_result;
 	}
 	if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
 	    (block <= OPT_MEDIUM_ERR_ADDR) &&
 	    ((block + num) > OPT_MEDIUM_ERR_ADDR)) {
 		mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR,
-				0, 18);
+				0);
 		/* claim unrecoverable read error */
 		return check_condition_result;
 	}
 	read_lock_irqsave(&atomic_rw, iflags);
-        sgcount = 0;
-	nbytes = bufflen;
-	/* printk(KERN_INFO "scsi_debug_read: block=%d, tot_bufflen=%d\n",
-	       block, bufflen); */
-	if (SCpnt->use_sg) {
-		sgcount = 0;
-		sgpnt = (struct scatterlist *) buff;
-		buff = scatg2virt(&sgpnt[sgcount]);
-		bufflen = sgpnt[sgcount].length;
-	}
-	do {
-		memcpy(buff, fake_storep + (block * SECT_SIZE), bufflen);
-		nbytes -= bufflen;
-		if (SCpnt->use_sg) {
-			block += bufflen >> POW2_SECT_SIZE;
-			sgcount++;
-			if (nbytes) {
-				buff = scatg2virt(&sgpnt[sgcount]);
-				bufflen = sgpnt[sgcount].length;
-			}
-		} else if (nbytes > 0)
-			printk(KERN_WARNING "scsi_debug:resp_read: unexpected "
-			       "nbytes=%d\n", nbytes);
-	} while (nbytes);
+	ret = fill_from_dev_buffer(SCpnt, fake_storep + (block * SECT_SIZE),
+			   	   num * SECT_SIZE);
 	read_unlock_irqrestore(&atomic_rw, iflags);
-	return 0;
+	return ret;
 }
 
 static int resp_write(struct scsi_cmnd * SCpnt, int upper_blk, int block,
 		      int num, struct sdebug_dev_info * devip)
 {
-        unsigned char *buff = (unsigned char *) SCpnt->request_buffer;
-        int nbytes, sgcount;
-        struct scatterlist *sgpnt = NULL;
-        int bufflen = SCpnt->request_bufflen;
 	unsigned long iflags;
+	int res;
 
 	if (upper_blk || (block + num > sdebug_capacity)) {
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE,
-			       	0, 18);
+			       	0);
 		return check_condition_result;
 	}
 
 	write_lock_irqsave(&atomic_rw, iflags);
-        sgcount = 0;
-	nbytes = bufflen;
-	if (SCpnt->use_sg) {
-		sgcount = 0;
-		sgpnt = (struct scatterlist *) buff;
-		buff = scatg2virt(&sgpnt[sgcount]);
-		bufflen = sgpnt[sgcount].length;
-	}
-	do {
-		memcpy(fake_storep + (block * SECT_SIZE), buff, bufflen);
-
-		nbytes -= bufflen;
-		if (SCpnt->use_sg) {
-			block += bufflen >> POW2_SECT_SIZE;
-			sgcount++;
-			if (nbytes) {
-				buff = scatg2virt(&sgpnt[sgcount]);
-				bufflen = sgpnt[sgcount].length;
-			}
-		} else if (nbytes > 0)
-			printk(KERN_WARNING "scsi_debug:resp_write: "
-			       "unexpected nbytes=%d\n", nbytes);
-	} while (nbytes);
+	res = fetch_to_dev_buffer(SCpnt, fake_storep + (block * SECT_SIZE),
+			   	  num * SECT_SIZE);
 	write_unlock_irqrestore(&atomic_rw, iflags);
+	if (-1 == res)
+		return (DID_ERROR << 16);
+	else if ((res < (num * SECT_SIZE)) &&
+		 (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts))
+		printk(KERN_INFO "scsi_debug: write: cdb indicated=%d, "
+		       " IO sent=%d bytes\n", num * SECT_SIZE, res);
 	return 0;
 }
 
-static int resp_report_luns(unsigned char * cmd, unsigned char * buff,
-			    int bufflen, struct sdebug_dev_info * devip)
+#define SDEBUG_RLUN_ARR_SZ 128
+
+static int resp_report_luns(struct scsi_cmnd * scp,
+			    struct sdebug_dev_info * devip)
 {
 	unsigned int alloc_len;
 	int lun_cnt, i, upper;
+	unsigned char *cmd = (unsigned char *)scp->cmnd;
 	int select_report = (int)cmd[2];
 	struct scsi_lun *one_lun;
+	unsigned char arr[SDEBUG_RLUN_ARR_SZ];
 
 	alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24);
 	if ((alloc_len < 16) || (select_report > 2)) {
 		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
-			       	0, 18);
+			       	0);
 		return check_condition_result;
 	}
-	if (bufflen > 8) { /* can produce response with up to 16k luns
-			      (lun 0 to lun 16383) */
-		memset(buff, 0, bufflen);
-		lun_cnt = scsi_debug_max_luns;
-		buff[2] = ((sizeof(struct scsi_lun) * lun_cnt) >> 8) & 0xff;
-		buff[3] = (sizeof(struct scsi_lun) * lun_cnt) & 0xff;
-		lun_cnt = min((int)((bufflen - 8) / sizeof(struct scsi_lun)),
-			      lun_cnt);
-		one_lun = (struct scsi_lun *) &buff[8];
-		for (i = 0; i < lun_cnt; i++) {
-			upper = (i >> 8) & 0x3f;
-			if (upper)
-				one_lun[i].scsi_lun[0] =
-				    (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
-			one_lun[i].scsi_lun[1] = i & 0xff;
-		}
+	/* can produce response with up to 16k luns (lun 0 to lun 16383) */
+	memset(arr, 0, SDEBUG_RLUN_ARR_SZ);
+	lun_cnt = scsi_debug_max_luns;
+	arr[2] = ((sizeof(struct scsi_lun) * lun_cnt) >> 8) & 0xff;
+	arr[3] = (sizeof(struct scsi_lun) * lun_cnt) & 0xff;
+	lun_cnt = min((int)((SDEBUG_RLUN_ARR_SZ - 8) /
+			    sizeof(struct scsi_lun)), lun_cnt);
+	one_lun = (struct scsi_lun *) &arr[8];
+	for (i = 0; i < lun_cnt; i++) {
+		upper = (i >> 8) & 0x3f;
+		if (upper)
+			one_lun[i].scsi_lun[0] =
+			    (upper | (SAM2_LUN_ADDRESS_METHOD << 6));
+		one_lun[i].scsi_lun[1] = i & 0xff;
 	}
-	return 0;
+	return fill_from_dev_buffer(scp, arr,
+				    min((int)alloc_len, SDEBUG_RLUN_ARR_SZ));
 }
 
 /* When timer goes off this function is called. */
@@ -1041,14 +1089,19 @@
 		open_devip->reset = 1;
 		open_devip->used = 1;
 		memset(open_devip->sense_buff, 0, SDEBUG_SENSE_LEN);
-		open_devip->sense_buff[0] = 0x70;
+		if (scsi_debug_dsense)
+			open_devip->sense_buff[0] = 0x72;
+		else {
+			open_devip->sense_buff[0] = 0x70;
+			open_devip->sense_buff[7] = 0xa;
+		}
 		return open_devip;
         }
         return NULL;
 }
 
 static void mk_sense_buffer(struct sdebug_dev_info * devip, int key,
-			    int asc, int asq, int inbandLen)
+			    int asc, int asq)
 {
 	unsigned char * sbuff;
 
@@ -1060,11 +1113,9 @@
 		sbuff[2] = asc;
 		sbuff[3] = asq;
 	} else {
-		if (inbandLen > SDEBUG_SENSE_LEN)
-			inbandLen = SDEBUG_SENSE_LEN;
 		sbuff[0] = 0x70;  /* fixed, current */
 		sbuff[2] = key;
-		sbuff[7] = (inbandLen > 7) ? (inbandLen - 8) : 0;
+		sbuff[7] = 0xa;	  /* implies 18 byte sense buffer */
 		sbuff[12] = asc;
 		sbuff[13] = asq;
 	}
@@ -1355,7 +1406,7 @@
 MODULE_PARM_DESC(num_tgts, "number of SCSI targets per host to simulate");
 MODULE_PARM_DESC(opts, "1->noise, 2->medium_error, 4->...");
 MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
-MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=4[SPC-2])");
+MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])");
 
 
 static char sdebug_info[256];
@@ -1391,7 +1442,7 @@
 		if (1 != sscanf(arr, "%d", &pos))
 			return -EINVAL;
 		scsi_debug_opts = pos;
-		if (scsi_debug_every_nth > 0)
+		if (scsi_debug_every_nth != 0)
                         scsi_debug_cmnd_count = 0;
 		return length;
 	}
@@ -1547,7 +1598,7 @@
 {
         int nth;
 
-	if ((count > 0) && (1 == sscanf(buf, "%d", &nth)) && (nth >= 0)) {
+	if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) {
 		scsi_debug_every_nth = nth;
 		scsi_debug_cmnd_count = 0;
 		return count;
diff -Nru a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
--- a/drivers/scsi/scsi_scan.c	2004-11-09 00:24:05 -08:00
+++ b/drivers/scsi/scsi_scan.c	2004-11-09 00:24:05 -08:00
@@ -271,8 +271,7 @@
 			goto out_cleanup_slave;
 	}
 
-	if (get_device(&sdev->host->shost_gendev) == NULL ||
-	    scsi_sysfs_device_initialize(sdev) != 0)
+	if (scsi_sysfs_device_initialize(sdev) != 0)
 		goto out_cleanup_slave;
 
 
diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
--- a/drivers/scsi/scsi_sysfs.c	2004-11-09 00:24:04 -08:00
+++ b/drivers/scsi/scsi_sysfs.c	2004-11-09 00:24:04 -08:00
@@ -775,7 +775,7 @@
 		memset(starget, 0, size);
 		dev = &starget->dev;
 		device_initialize(dev);
-		dev->parent = &shost->shost_gendev;
+		dev->parent = get_device(&shost->shost_gendev);
 		dev->release = scsi_target_dev_release;
 		sprintf(dev->bus_id, "target%d:%d:%d",
 			shost->host_no, sdev->channel, sdev->id);
diff -Nru a/drivers/scsi/sym53c8xx_2/sym53c8xx.h b/drivers/scsi/sym53c8xx_2/sym53c8xx.h
--- a/drivers/scsi/sym53c8xx_2/sym53c8xx.h	2004-11-09 00:24:05 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym53c8xx.h	2004-11-09 00:24:05 -08:00
@@ -68,7 +68,6 @@
  */
 #if 1
 #define	SYM_LINUX_PROC_INFO_SUPPORT
-#define SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT
 #define SYM_LINUX_USER_COMMAND_SUPPORT
 #define SYM_LINUX_USER_INFO_SUPPORT
 #define SYM_LINUX_DEBUG_CONTROL_SUPPORT
@@ -129,9 +128,7 @@
 	u_char	scsi_bus_check;
 	u_char	host_id;
 
-	u_char	reverse_probe;
 	u_char	verbose;
-	u_short	debug;
 	u_char	settle_delay;
 	u_char	use_nvram;
 	u_long	excludes[8];
@@ -145,6 +142,7 @@
 #define SYM_SETUP_IRQ_MODE		sym_driver_setup.irq_mode
 #define SYM_SETUP_SCSI_BUS_CHECK	sym_driver_setup.scsi_bus_check
 #define SYM_SETUP_HOST_ID		sym_driver_setup.host_id
+#define boot_verbose			sym_driver_setup.verbose
 
 /* Always enable parity. */
 #define SYM_SETUP_PCI_PARITY		1
@@ -163,54 +161,13 @@
 	.irq_mode	= 0,					\
 	.scsi_bus_check	= 1,					\
 	.host_id	= 7,					\
-	.reverse_probe	= 0,					\
 	.verbose	= 0,					\
-	.debug		= 0,					\
 	.settle_delay	= 3,					\
 	.use_nvram	= 1,					\
 }
 
-/*
- *  Boot fail safe setup.
- *
- *  Override initial setup from boot command line:
- *    sym53c8xx=safe:y
- */
-#define SYM_LINUX_DRIVER_SAFE_SETUP {				\
-	.max_tag	= 0,					\
-	.burst_order	= 0,					\
-	.scsi_led	= 0,					\
-	.scsi_diff	= 1,					\
-	.irq_mode	= 0,					\
-	.scsi_bus_check	= 2,					\
-	.host_id	= 7,					\
-	.reverse_probe	= 0,					\
-	.verbose	= 2,					\
-	.debug		= 0,					\
-	.settle_delay	= 10,					\
-	.use_nvram	= 1,					\
-}
-
-/*
- *  This structure is initialized from linux config options.
- *  It can be overridden at boot-up by the boot command line.
- */
-#ifdef SYM_GLUE_C
-struct sym_driver_setup
-	sym_driver_setup = SYM_LINUX_DRIVER_SETUP;
-#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT
-u_int	sym_debug_flags = 0;
-#endif
-#else
 extern struct sym_driver_setup sym_driver_setup;
-#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT
-extern u_int sym_debug_flags;
-#endif
-#endif /* SYM_GLUE_C */
-
-#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT
+extern unsigned int sym_debug_flags;
 #define DEBUG_FLAGS	sym_debug_flags
-#endif
-#define boot_verbose	sym_driver_setup.verbose
 
 #endif /* SYM53C8XX_H */
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_defs.h b/drivers/scsi/sym53c8xx_2/sym_defs.h
--- a/drivers/scsi/sym53c8xx_2/sym_defs.h	2004-11-09 00:24:04 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym_defs.h	2004-11-09 00:24:04 -08:00
@@ -40,33 +40,28 @@
 #ifndef SYM_DEFS_H
 #define SYM_DEFS_H
 
-#define SYM_VERSION "2.1.18k"
+#define SYM_VERSION "2.1.18m"
 #define SYM_DRIVER_NAME	"sym-" SYM_VERSION
 
 /*
- *  Vendor.
- */
-#define PCI_VENDOR_NCR		0x1000
-
-/*
  *  PCI device identifier of SYMBIOS chips.
  */
-#define PCI_ID_SYM53C810	1
-#define PCI_ID_SYM53C810AP	5
-#define PCI_ID_SYM53C815	4
-#define PCI_ID_SYM53C820	2
-#define PCI_ID_SYM53C825	3
-#define PCI_ID_SYM53C860	6
-#define PCI_ID_SYM53C875	0xf
-#define PCI_ID_SYM53C875_2	0x8f
-#define PCI_ID_SYM53C885	0xd
-#define PCI_ID_SYM53C895	0xc
-#define PCI_ID_SYM53C896	0xb
-#define PCI_ID_SYM53C895A	0x12
-#define PCI_ID_SYM53C875A	0x13
-#define PCI_ID_LSI53C1010_33	0x20
-#define PCI_ID_LSI53C1010_66	0x21
-#define PCI_ID_LSI53C1510D	0xa
+#define PCI_ID_SYM53C810	PCI_DEVICE_ID_NCR_53C810
+#define PCI_ID_SYM53C810AP	PCI_DEVICE_ID_LSI_53C810AP
+#define PCI_ID_SYM53C815	PCI_DEVICE_ID_NCR_53C815
+#define PCI_ID_SYM53C820	PCI_DEVICE_ID_NCR_53C820
+#define PCI_ID_SYM53C825	PCI_DEVICE_ID_NCR_53C825
+#define PCI_ID_SYM53C860	PCI_DEVICE_ID_NCR_53C860
+#define PCI_ID_SYM53C875	PCI_DEVICE_ID_NCR_53C875
+#define PCI_ID_SYM53C875_2	PCI_DEVICE_ID_NCR_53C875J
+#define PCI_ID_SYM53C885	PCI_DEVICE_ID_NCR_53C885
+#define PCI_ID_SYM53C895	PCI_DEVICE_ID_NCR_53C895
+#define PCI_ID_SYM53C896	PCI_DEVICE_ID_NCR_53C896
+#define PCI_ID_SYM53C895A	PCI_DEVICE_ID_LSI_53C895A
+#define PCI_ID_SYM53C875A	PCI_DEVICE_ID_LSI_53C875A
+#define PCI_ID_LSI53C1010_33	PCI_DEVICE_ID_LSI_53C1010_33
+#define PCI_ID_LSI53C1010_66	PCI_DEVICE_ID_LSI_53C1010_66
+#define PCI_ID_LSI53C1510D	PCI_DEVICE_ID_LSI_53C1510
 
 /*
  *	SYM53C8XX device features descriptor.
@@ -763,33 +758,32 @@
  *	Messages
  */
 
-#define	M_COMPLETE	(0x00)
-#define	M_EXTENDED	(0x01)
-#define	M_SAVE_DP	(0x02)
-#define	M_RESTORE_DP	(0x03)
-#define	M_DISCONNECT	(0x04)
-#define	M_ID_ERROR	(0x05)
-#define	M_ABORT		(0x06)
-#define	M_REJECT	(0x07)
-#define	M_NOOP		(0x08)
-#define	M_PARITY	(0x09)
-#define	M_LCOMPLETE	(0x0a)
-#define	M_FCOMPLETE	(0x0b)
-#define	M_RESET		(0x0c)
+#define	M_COMPLETE	COMMAND_COMPLETE
+#define	M_EXTENDED	EXTENDED_MESSAGE
+#define	M_SAVE_DP	SAVE_POINTERS
+#define	M_RESTORE_DP	RESTORE_POINTERS
+#define	M_DISCONNECT	DISCONNECT
+#define	M_ID_ERROR	INITIATOR_ERROR
+#define	M_ABORT		ABORT
+#define	M_REJECT	MESSAGE_REJECT
+#define	M_NOOP		NOP
+#define	M_PARITY	MSG_PARITY_ERROR
+#define	M_LCOMPLETE	LINKED_CMD_COMPLETE
+#define	M_FCOMPLETE	LINKED_FLG_CMD_COMPLETE
+#define	M_RESET		BUS_DEVICE_RESET
 #define	M_ABORT_TAG	(0x0d)
 #define	M_CLEAR_QUEUE	(0x0e)
-#define	M_INIT_REC	(0x0f)
-#define	M_REL_REC	(0x10)
+#define	M_INIT_REC	INITIATE_RECOVERY
+#define	M_REL_REC	RELEASE_RECOVERY
 #define	M_TERMINATE	(0x11)
-#define	M_SIMPLE_TAG	(0x20)
-#define	M_HEAD_TAG	(0x21)
-#define	M_ORDERED_TAG	(0x22)
+#define	M_SIMPLE_TAG	SIMPLE_QUEUE_TAG
+#define	M_HEAD_TAG	HEAD_OF_QUEUE_TAG
+#define	M_ORDERED_TAG	ORDERED_QUEUE_TAG
 #define	M_IGN_RESIDUE	(0x23)
-#define	M_IDENTIFY   	(0x80)
 
-#define	M_X_MODIFY_DP	(0x00)
-#define	M_X_SYNC_REQ	(0x01)
-#define	M_X_WIDE_REQ	(0x03)
+#define	M_X_MODIFY_DP	EXTENDED_MODIFY_DATA_POINTER
+#define	M_X_SYNC_REQ	EXTENDED_SDTR
+#define	M_X_WIDE_REQ	EXTENDED_WDTR
 #define	M_X_PPR_REQ	(0x04)
 
 /*
@@ -804,15 +798,15 @@
  *	Status
  */
 
-#define	S_GOOD		(0x00)
-#define	S_CHECK_COND	(0x02)
-#define	S_COND_MET	(0x04)
-#define	S_BUSY		(0x08)
-#define	S_INT		(0x10)
-#define	S_INT_COND_MET	(0x14)
-#define	S_CONFLICT	(0x18)
-#define	S_TERMINATED	(0x20)
-#define	S_QUEUE_FULL	(0x28)
+#define	S_GOOD		SAM_STAT_GOOD
+#define	S_CHECK_COND	SAM_STAT_CHECK_CONDITION
+#define	S_COND_MET	SAM_STAT_CONDITION_MET
+#define	S_BUSY		SAM_STAT_BUSY
+#define	S_INT		SAM_STAT_INTERMEDIATE
+#define	S_INT_COND_MET	SAM_STAT_INTERMEDIATE_CONDITION_MET
+#define	S_CONFLICT	SAM_STAT_RESERVATION_CONFLICT
+#define	S_TERMINATED	SAM_STAT_COMMAND_TERMINATED
+#define	S_QUEUE_FULL	SAM_STAT_TASK_SET_FULL
 #define	S_ILLEGAL	(0xff)
 
 #endif /* defined SYM_DEFS_H */
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c	2004-11-09 00:24:05 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c	2004-11-09 00:24:05 -08:00
@@ -37,12 +37,11 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#define SYM_GLUE_C
-
 #include <linux/ctype.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/spinlock.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_tcq.h>
@@ -56,6 +55,77 @@
 #define NAME53C		"sym53c"
 #define NAME53C8XX	"sym53c8xx"
 
+struct sym_driver_setup sym_driver_setup = SYM_LINUX_DRIVER_SETUP;
+unsigned int sym_debug_flags = 0;
+
+static char *excl_string;
+static char *safe_string;
+module_param_named(cmd_per_lun, sym_driver_setup.max_tag, ushort, 0);
+module_param_string(tag_ctrl, sym_driver_setup.tag_ctrl, 100, 0);
+module_param_named(burst, sym_driver_setup.burst_order, byte, 0);
+module_param_named(led, sym_driver_setup.scsi_led, byte, 0);
+module_param_named(diff, sym_driver_setup.scsi_diff, byte, 0);
+module_param_named(irqm, sym_driver_setup.irq_mode, byte, 0);
+module_param_named(buschk, sym_driver_setup.scsi_bus_check, byte, 0);
+module_param_named(hostid, sym_driver_setup.host_id, byte, 0);
+module_param_named(verb, sym_driver_setup.verbose, byte, 0);
+module_param_named(debug, sym_debug_flags, uint, 0);
+module_param_named(settle, sym_driver_setup.settle_delay, byte, 0);
+module_param_named(nvram, sym_driver_setup.use_nvram, byte, 0);
+module_param_named(excl, excl_string, charp, 0);
+module_param_named(safe, safe_string, charp, 0);
+
+MODULE_PARM_DESC(cmd_per_lun, "The maximum number of tags to use by default");
+MODULE_PARM_DESC(tag_ctrl, "More detailed control over tags per LUN");
+MODULE_PARM_DESC(burst, "Maximum burst.  0 to disable, 255 to read from registers");
+MODULE_PARM_DESC(led, "Set to 1 to enable LED support");
+MODULE_PARM_DESC(diff, "0 for no differential mode, 1 for BIOS, 2 for always, 3 for not GPIO3");
+MODULE_PARM_DESC(irqm, "0 for open drain, 1 to leave alone, 2 for totem pole");
+MODULE_PARM_DESC(buschk, "0 to not check, 1 for detach on error, 2 for warn on error");
+MODULE_PARM_DESC(hostid, "The SCSI ID to use for the host adapters");
+MODULE_PARM_DESC(verb, "0 for minimal verbosity, 1 for normal, 2 for excessive");
+MODULE_PARM_DESC(debug, "Set bits to enable debugging");
+MODULE_PARM_DESC(settle, "Settle delay in seconds.  Default 3");
+MODULE_PARM_DESC(nvram, "Option currently not used");
+MODULE_PARM_DESC(excl, "List ioport addresses here to prevent controllers from being attached");
+MODULE_PARM_DESC(safe, "Set other settings to a \"safe mode\"");
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION(SYM_VERSION);
+MODULE_AUTHOR("Matthew Wilcox <matthew@wil.cx>");
+MODULE_DESCRIPTION("NCR, Symbios and LSI 8xx and 1010 PCI SCSI adapters");
+
+static void sym2_setup_params(void)
+{
+	char *p = excl_string;
+	int xi = 0;
+
+	while (p && (xi < 8)) {
+		char *next_p;
+		int val = (int) simple_strtoul(p, &next_p, 0);
+		sym_driver_setup.excludes[xi++] = val;
+		p = next_p;
+	}
+
+	if (safe_string) {
+		if (*safe_string == 'y') {
+			sym_driver_setup.max_tag = 0;
+			sym_driver_setup.burst_order = 0;
+			sym_driver_setup.scsi_led = 0;
+			sym_driver_setup.scsi_diff = 1;
+			sym_driver_setup.irq_mode = 0;
+			sym_driver_setup.scsi_bus_check = 2;
+			sym_driver_setup.host_id = 7;
+			sym_driver_setup.verbose = 2;
+			sym_driver_setup.settle_delay = 10;
+			sym_driver_setup.use_nvram = 1;
+		} else if (*safe_string != 'n') {
+			printk(KERN_WARNING NAME53C8XX "Ignoring parameter %s"
+					" passed to safe option", safe_string);
+		}
+	}
+}
+
 static int __devinit
 pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
 {
@@ -135,7 +205,7 @@
  *  It is allocated on the eh thread stack.
  */
 struct sym_eh_wait {
-	struct semaphore sem;
+	struct completion done;
 	struct timer_list timer;
 	void (*old_done)(struct scsi_cmnd *);
 	int to_do;
@@ -146,7 +216,6 @@
  *  Driver private area in the SCSI command structure.
  */
 struct sym_ucmd {		/* Override the SCSI pointer structure */
-	SYM_QUEHEAD link_cmdq;	/* Must stay at offset ZERO */
 	dma_addr_t data_mapping;
 	u_char	data_mapped;
 	struct sym_eh_wait *eh_wait;
@@ -212,7 +281,6 @@
  */
 void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb)
 {
-	sym_remque(&SYM_UCMD_PTR(ccb)->link_cmdq);
 	unmap_scsi_data(np, ccb);
 	ccb->scsi_done(ccb);
 }
@@ -648,31 +716,6 @@
 	}
 }
 
-
-/*
- *  Requeue awaiting commands.
- */
-static void sym_requeue_awaiting_cmds(struct sym_hcb *np)
-{
-	struct sym_ucmd *ucp;
-	SYM_QUEHEAD tmp_cmdq;
-	int sts;
-
-	sym_que_move(&np->s.wait_cmdq, &tmp_cmdq);
-
-	while ((ucp = (struct sym_ucmd *) sym_remque_head(&tmp_cmdq)) != 0) {
-		struct scsi_cmnd *cmd;
-
-		sym_insque_tail(&ucp->link_cmdq, &np->s.busy_cmdq);
-		cmd = SYM_SCMD_PTR(ucp);
-		sts = sym_queue_command(np, cmd);
-		if (sts) {
-			sym_remque(&ucp->link_cmdq);
-			sym_insque_head(&ucp->link_cmdq, &np->s.wait_cmdq);
-		}
-	}
-}
-
 /*
  * queuecommand method.  Entered with the host adapter lock held and
  * interrupts disabled.
@@ -700,18 +743,12 @@
 		}
 	}
 
-	if (np->s.settle_time_valid || !sym_que_empty(&np->s.wait_cmdq)) {
-		sym_insque_tail(&ucp->link_cmdq, &np->s.wait_cmdq);
-		goto out;
-	}
+	if (np->s.settle_time_valid)
+		return SCSI_MLQUEUE_HOST_BUSY;
 
-	sym_insque_tail(&ucp->link_cmdq, &np->s.busy_cmdq);
 	sts = sym_queue_command(np, cmd);
-	if (sts) {
-		sym_remque(&ucp->link_cmdq);
-		sym_insque_tail(&ucp->link_cmdq, &np->s.wait_cmdq);
-	}
-out:
+	if (sts)
+		return SCSI_MLQUEUE_HOST_BUSY;
 	return 0;
 }
 
@@ -726,15 +763,7 @@
 	if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("[");
 
 	spin_lock_irqsave(np->s.host->host_lock, flags);
-
 	sym_interrupt(np);
-
-	/*
-	 * push queue walk-through to tasklet
-	 */
-	if (!sym_que_empty(&np->s.wait_cmdq) && !np->s.settle_time_valid)
-		sym_requeue_awaiting_cmds(np);
-
 	spin_unlock_irqrestore(np->s.host->host_lock, flags);
 
 	if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("]\n");
@@ -751,12 +780,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(np->s.host->host_lock, flags);
-
 	sym_timer(np);
-
-	if (!sym_que_empty(&np->s.wait_cmdq) && !np->s.settle_time_valid)
-		sym_requeue_awaiting_cmds(np);
-
 	spin_unlock_irqrestore(np->s.host->host_lock, flags);
 }
 
@@ -798,7 +822,7 @@
 
 	/* Wake up the eh thread if it wants to sleep */
 	if (ep->to_do == SYM_EH_DO_WAIT)
-		up(&ep->sem);
+		complete(&ep->done);
 }
 
 /*
@@ -834,14 +858,6 @@
 		goto prepare;
 #endif
 
-	/* This one is not queued to the core driver -> to complete here */ 
-	FOR_EACH_QUEUED_ELEMENT(&np->s.wait_cmdq, qp) {
-		if (SYM_SCMD_PTR(qp) == cmd) {
-			to_do = SYM_EH_DO_COMPLETE;
-			goto prepare;
-		}
-	}
-
 	/* This one is queued in some place -> to wait for completion */
 	FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
 		struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
@@ -858,7 +874,7 @@
 	case SYM_EH_DO_IGNORE:
 		break;
 	case SYM_EH_DO_WAIT:
-		init_MUTEX_LOCKED(&ep->sem);
+		init_completion(&ep->done);
 		/* fall through */
 	case SYM_EH_DO_COMPLETE:
 		ep->old_done = cmd->scsi_done;
@@ -909,7 +925,7 @@
 		ep->timed_out = 1;	/* Be pessimistic for once :) */
 		add_timer(&ep->timer);
 		spin_unlock_irq(np->s.host->host_lock);
-		down(&ep->sem);
+		wait_for_completion(&ep->done);
 		spin_lock_irq(np->s.host->host_lock);
 		if (ep->timed_out)
 			sts = -2;
@@ -973,7 +989,6 @@
 	}
 }
 
-#ifdef	SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT
 /*
  *  Linux select queue depths function
  */
@@ -1026,9 +1041,6 @@
 	}
 	return DEF_DEPTH;
 }
-#else
-#define device_queue_depth(np, t, l)	(sym_driver_setup.max_tag)
-#endif	/* SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT */
 
 /*
  * Linux entry point for device queue sizing.
@@ -1164,7 +1176,7 @@
 				if (uc->data <= 9 && np->minsync_dt) {
 					if (uc->data < np->minsync_dt)
 						uc->data = np->minsync_dt;
-					tp->tinfo.goal.options = PPR_OPT_DT;
+					tp->tinfo.goal.options = PPR_OPT_MASK;
 					tp->tinfo.goal.width   = 1;
 					tp->tinfo.goal.period = uc->data;
 					tp->tinfo.goal.offset = np->maxoffs_dt;
@@ -1732,12 +1744,6 @@
 		goto reset_failed;
 
 	/*
-	 *  Initialize some queue headers.
-	 */
-	sym_que_init(&np->s.wait_cmdq);
-	sym_que_init(&np->s.busy_cmdq);
-
-	/*
 	 *  Start the SCRIPTS.
 	 */
 	sym_start_up (np, 1);
@@ -1828,145 +1834,6 @@
 }
 #endif	/* SYM_CONF_NVRAM_SUPPORT */
 
-/*
- *  Driver setup from the boot command line
- */
-#ifdef	SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT
-
-static struct sym_driver_setup
-	sym_driver_safe_setup __initdata = SYM_LINUX_DRIVER_SAFE_SETUP;
-#ifdef	MODULE
-char *sym53c8xx;	/* command line passed by insmod */
-MODULE_PARM(sym53c8xx, "s");
-#endif
-
-#define OPT_MAX_TAG		1
-#define OPT_BURST_ORDER		2
-#define OPT_SCSI_LED		3
-#define OPT_SCSI_DIFF		4
-#define OPT_IRQ_MODE		5
-#define OPT_SCSI_BUS_CHECK	6
-#define	OPT_HOST_ID		7
-#define OPT_REVERSE_PROBE	8
-#define OPT_VERBOSE		9
-#define OPT_DEBUG		10
-#define OPT_SETTLE_DELAY	11
-#define OPT_USE_NVRAM		12
-#define OPT_EXCLUDE		13
-#define OPT_SAFE_SETUP		14
-
-static char setup_token[] __initdata =
-	"tags:"		"burst:"
-	"led:"		"diff:"
-	"irqm:"		"buschk:"
-	"hostid:"	"revprob:"
-	"verb:"		"debug:"
-	"settle:"	"nvram:"
-	"excl:"		"safe:"
-	;
-
-#ifdef MODULE
-#define	ARG_SEP	' '
-#else
-#define	ARG_SEP	','
-#endif
-
-static int __init get_setup_token(char *p)
-{
-	char *cur = setup_token;
-	char *pc;
-	int i = 0;
-
-	while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
-		++pc;
-		++i;
-		if (!strncmp(p, cur, pc - cur))
-			return i;
-		cur = pc;
-	}
-	return 0;
-}
-#endif	/* SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT */
-
-int __init sym53c8xx_setup(char *str)
-{
-#ifdef	SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT
-	char *cur = str;
-	char *pc, *pv;
-	unsigned long val;
-	unsigned int i,  c;
-	int xi = 0;
-
-	while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
-		char *pe;
-
-		val = 0;
-		pv = pc;
-		c = *++pv;
-
-		if	(c == 'n')
-			val = 0;
-		else if	(c == 'y')
-			val = 1;
-		else
-			val = (int) simple_strtoul(pv, &pe, 0);
-
-		switch (get_setup_token(cur)) {
-		case OPT_MAX_TAG:
-			sym_driver_setup.max_tag = val;
-			if (!(pe && *pe == '/'))
-				break;
-			i = 0;
-			while (*pe && *pe != ARG_SEP && 
-				i < sizeof(sym_driver_setup.tag_ctrl)-1) {
-				sym_driver_setup.tag_ctrl[i++] = *pe++;
-			}
-			sym_driver_setup.tag_ctrl[i] = '\0';
-			break;
-		case OPT_SAFE_SETUP:
-			memcpy(&sym_driver_setup, &sym_driver_safe_setup,
-				sizeof(sym_driver_setup));
-			break;
-		case OPT_EXCLUDE:
-			if (xi < 8)
-				sym_driver_setup.excludes[xi++] = val;
-			break;
-
-#define __SIMPLE_OPTION(NAME, name) \
-		case OPT_ ## NAME :		\
-			sym_driver_setup.name = val;\
-			break;
-
-		__SIMPLE_OPTION(BURST_ORDER, burst_order)
-		__SIMPLE_OPTION(SCSI_LED, scsi_led)
-		__SIMPLE_OPTION(SCSI_DIFF, scsi_diff)
-		__SIMPLE_OPTION(IRQ_MODE, irq_mode)
-		__SIMPLE_OPTION(SCSI_BUS_CHECK, scsi_bus_check)
-		__SIMPLE_OPTION(HOST_ID, host_id)
-		__SIMPLE_OPTION(REVERSE_PROBE, reverse_probe)
-		__SIMPLE_OPTION(VERBOSE, verbose)
-		__SIMPLE_OPTION(DEBUG, debug)
-		__SIMPLE_OPTION(SETTLE_DELAY, settle_delay)
-		__SIMPLE_OPTION(USE_NVRAM, use_nvram)
-
-#undef __SIMPLE_OPTION
-
-		default:
-			printk("sym53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
-			break;
-		}
-
-		if ((cur = strchr(cur, ARG_SEP)) != NULL)
-			++cur;
-	}
-#endif	/* SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT */
-	return 1;
-}
-
-#ifndef MODULE
-__setup("sym53c8xx=", sym53c8xx_setup);
-#endif
-
 static int __devinit sym_check_supported(struct sym_device *device)
 {
 	struct sym_pci_chip *chip;
@@ -2029,7 +1896,7 @@
 {
 	unsigned long base_2_c = device->s.base_2_c;
 	unsigned int ram_size, ram_val;
-	void *ram_ptr;
+	void __iomem *ram_ptr;
 
 	if (!base_2_c)
 		return 0;
@@ -2111,6 +1978,7 @@
 	unsigned long base, base_2; 
 	int i;
 
+	device->host_id = SYM_SETUP_HOST_ID;
 	device->pdev = pdev;
 	device->s.irq = pdev->irq;
 
@@ -2145,9 +2013,9 @@
 void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
 {
 	int slot;
+	u8 tmp;
 
 	for (slot = 0; slot < 256; slot++) {
-		u8 tmp;
 		struct pci_dev *memc = pci_get_slot(pdev->bus, slot);
 
 		if (!memc || memc->vendor != 0x101a || memc->device == 0x0009) {
@@ -2155,28 +2023,26 @@
 			continue;
 		}
 
-		/*
-		 * We set these bits in the memory controller once per 875.
-		 * This isn't a problem in practice.
-		 */
-
 		/* bit 1: allow individual 875 configuration */
 		pci_read_config_byte(memc, 0x44, &tmp);
-		tmp |= 0x2;
-		pci_write_config_byte(memc, 0x44, tmp);
+		if ((tmp & 0x2) == 0) {
+			tmp |= 0x2;
+			pci_write_config_byte(memc, 0x44, tmp);
+		}
 
 		/* bit 2: drive individual 875 interrupts to the bus */
 		pci_read_config_byte(memc, 0x45, &tmp);
-		tmp |= 0x4;
-		pci_write_config_byte(memc, 0x45, tmp);
-
-		pci_read_config_byte(pdev, 0x84, &tmp);
-		sym_dev->host_id = tmp;
+		if ((tmp & 0x4) == 0) {
+			tmp |= 0x4;
+			pci_write_config_byte(memc, 0x45, tmp);
+		}
 
 		pci_dev_put(memc);
-
 		break;
 	}
+
+	pci_read_config_byte(pdev, 0x84, &tmp);
+	sym_dev->host_id = tmp;
 }
 
 /*
@@ -2205,9 +2071,6 @@
 	return 1;
 }
 
-MODULE_LICENSE("GPL");
-MODULE_VERSION(SYM_VERSION);
-
 /*
  * Driver host template.
  */
@@ -2249,8 +2112,6 @@
 	if (pci_request_regions(pdev, NAME53C8XX))
 		goto disable;
 
-	sym_dev.host_id = SYM_SETUP_HOST_ID;
-
 	sym_init_device(pdev, &sym_dev);
 	if (sym_check_supported(&sym_dev))
 		goto free;
@@ -2381,9 +2242,10 @@
 	struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
 	struct sym_tcb *tp = &np->target[starget->id];
 
-	/* It is illegal to have DT set on narrow transfers */
+	/* It is illegal to have DT set on narrow transfers.  If DT is
+	 * clear, we must also clear IU and QAS.  */
 	if (width == 0)
-		tp->tinfo.goal.options &= ~PPR_OPT_DT;
+		tp->tinfo.goal.options &= ~PPR_OPT_MASK;
 
 	tp->tinfo.goal.width = width;
 }
@@ -2403,12 +2265,55 @@
 	struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
 	struct sym_tcb *tp = &np->target[starget->id];
 
+	/* We must clear QAS and IU if DT is clear */
 	if (dt)
 		tp->tinfo.goal.options |= PPR_OPT_DT;
 	else
-		tp->tinfo.goal.options &= ~PPR_OPT_DT;
+		tp->tinfo.goal.options &= ~PPR_OPT_MASK;
 }
-	
+
+static void sym2_get_iu(struct scsi_target *starget)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
+	struct sym_tcb *tp = &np->target[starget->id];
+
+	spi_iu(starget) = (tp->tinfo.curr.options & PPR_OPT_IU) ? 1 : 0;
+}
+
+static void sym2_set_iu(struct scsi_target *starget, int iu)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
+	struct sym_tcb *tp = &np->target[starget->id];
+
+	if (iu)
+		tp->tinfo.goal.options |= PPR_OPT_IU | PPR_OPT_DT;
+	else
+		tp->tinfo.goal.options &= ~PPR_OPT_IU;
+}
+
+static void sym2_get_qas(struct scsi_target *starget)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
+	struct sym_tcb *tp = &np->target[starget->id];
+
+	spi_qas(starget) = (tp->tinfo.curr.options & PPR_OPT_QAS) ? 1 : 0;
+}
+
+static void sym2_set_qas(struct scsi_target *starget, int qas)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
+	struct sym_tcb *tp = &np->target[starget->id];
+
+	if (qas)
+		tp->tinfo.goal.options |= PPR_OPT_QAS | PPR_OPT_DT;
+	else
+		tp->tinfo.goal.options &= ~PPR_OPT_QAS;
+}
+
 
 static struct spi_function_template sym2_transport_functions = {
 	.set_offset	= sym2_set_offset,
@@ -2423,6 +2328,12 @@
 	.get_dt		= sym2_get_dt,
 	.set_dt		= sym2_set_dt,
 	.show_dt	= 1,
+	.get_iu		= sym2_get_iu,
+	.set_iu		= sym2_set_iu,
+	.show_iu	= 1,
+	.get_qas	= sym2_get_qas,
+	.set_qas	= sym2_set_qas,
+	.show_qas	= 1,
 	.get_signalling	= sym2_get_signalling,
 };
 
@@ -2475,12 +2386,17 @@
 
 static int __init sym2_init(void)
 {
+	int error;
+
+	sym2_setup_params();
 	sym2_transport_template = spi_attach_transport(&sym2_transport_functions);
 	if (!sym2_transport_template)
 		return -ENODEV;
 
-	pci_register_driver(&sym2_driver);
-	return 0;
+	error = pci_module_init(&sym2_driver);
+	if (error)
+		spi_release_transport(sym2_transport_template);
+	return error;
 }
 
 static void __exit sym2_exit(void)
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h	2004-11-09 00:24:05 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h	2004-11-09 00:24:05 -08:00
@@ -381,9 +381,6 @@
 	u_short		io_ws;		/* IO window size		*/
 	int		irq;		/* IRQ number			*/
 
-	SYM_QUEHEAD	wait_cmdq;	/* Awaiting SCSI commands	*/
-	SYM_QUEHEAD	busy_cmdq;	/* Enqueued SCSI commands	*/
-
 	struct timer_list timer;	/* Timer handler link header	*/
 	u_long		lasttime;
 	u_long		settle_time;	/* Resetting the SCSI BUS	*/
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c	2004-11-09 00:24:04 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c	2004-11-09 00:24:04 -08:00
@@ -1503,6 +1503,7 @@
 		if (st->period > np->maxsync_dt)
 			st->period = np->maxsync_dt;
 	} else {
+		st->options &= ~PPR_OPT_MASK;
 		if (st->offset > np->maxoffs)
 			st->offset = np->maxoffs;
 		if (st->period < np->minsync)
@@ -1510,7 +1511,7 @@
 		if (st->period > np->maxsync)
 			st->period = np->maxsync;
 	}
-}		
+}
 
 /*
  *  Prepare the next negotiation message if needed.
@@ -1575,7 +1576,7 @@
 		msgptr[msglen++] = 0;
 		msgptr[msglen++] = tp->tinfo.goal.offset;
 		msgptr[msglen++] = tp->tinfo.goal.width;
-		msgptr[msglen++] = tp->tinfo.goal.options & PPR_OPT_DT;
+		msgptr[msglen++] = tp->tinfo.goal.options & PPR_OPT_MASK;
 		break;
 	};
 
@@ -2009,7 +2010,7 @@
 /*
  *  Switch trans mode for current job and it's target.
  */
-static void sym_settrans(hcb_p np, int target, u_char dt, u_char ofs,
+static void sym_settrans(hcb_p np, int target, u_char opts, u_char ofs,
 			 u_char per, u_char wide, u_char div, u_char fak)
 {
 	SYM_QUEHEAD *qp;
@@ -2060,7 +2061,7 @@
 	 */
 	if (np->features & FE_C10) {
 		uval = uval & ~(U3EN|AIPCKEN);
-		if (dt)	{
+		if (opts)	{
 			assert(np->features & FE_U3EN);
 			uval |= U3EN;
 		}
@@ -2163,17 +2164,17 @@
  *  Let everything be aware of the changes.
  */
 static void 
-sym_setpprot(hcb_p np, int target, u_char dt, u_char ofs,
+sym_setpprot(hcb_p np, int target, u_char opts, u_char ofs,
              u_char per, u_char wide, u_char div, u_char fak)
 {
 	tcb_p tp = &np->target[target];
 
-	sym_settrans(np, target, dt, ofs, per, wide, div, fak);
+	sym_settrans(np, target, opts, ofs, per, wide, div, fak);
 
 	tp->tinfo.goal.width	= tp->tinfo.curr.width  = wide;
 	tp->tinfo.goal.period	= tp->tinfo.curr.period = per;
 	tp->tinfo.goal.offset	= tp->tinfo.curr.offset = ofs;
-	tp->tinfo.goal.options	= tp->tinfo.curr.options = dt;
+	tp->tinfo.goal.options	= tp->tinfo.curr.options = opts;
 
 	sym_xpt_async_nego_ppr(np, target);
 }
@@ -2734,7 +2735,7 @@
 		if	(dsp == SCRIPTA_BA (np, send_ident)) {
 			if (cp->tag != NO_TAG && olen - rest <= 3) {
 				cp->host_status = HS_BUSY;
-				np->msgout[0] = M_IDENTIFY | cp->lun;
+				np->msgout[0] = IDENTIFY(0, cp->lun);
 				nxtdsp = SCRIPTB_BA (np, ident_break_atn);
 			}
 			else
@@ -3163,10 +3164,7 @@
 		 *  requesting sense data.
 		 */
 
-		/*
-		 *  identify message
-		 */
-		cp->scsi_smsg2[0] = M_IDENTIFY | cp->lun;
+		cp->scsi_smsg2[0] = IDENTIFY(0, cp->lun);
 		msglen = 1;
 
 		/*
@@ -3525,8 +3523,8 @@
 		 */
 		if (lun != -1) {
 			lcb_p lp = sym_lp(np, tp, lun);
-			lp->to_clear = 0; /* We donnot expect to fail here */
-			np->abrt_msg[0] = M_IDENTIFY | lun;
+			lp->to_clear = 0; /* We don't expect to fail here */
+			np->abrt_msg[0] = IDENTIFY(0, lun);
 			np->abrt_msg[1] = M_ABORT;
 			np->abrt_tbl.size = 2;
 			break;
@@ -3567,7 +3565,7 @@
 		 *  We have some task to abort.
 		 *  Set the IDENTIFY(lun)
 		 */
-		np->abrt_msg[0] = M_IDENTIFY | cp->lun;
+		np->abrt_msg[0] = IDENTIFY(0, cp->lun);
 
 		/*
 		 *  If we want to abort an untagged command, we 
@@ -3578,8 +3576,7 @@
 		if (cp->tag == NO_TAG) {
 			np->abrt_msg[1] = M_ABORT;
 			np->abrt_tbl.size = 2;
-		}
-		else {
+		} else {
 			np->abrt_msg[1] = cp->scsi_smsg[1];
 			np->abrt_msg[2] = cp->scsi_smsg[2];
 			np->abrt_msg[3] = M_ABORT_TAG;
@@ -4139,20 +4136,17 @@
 sym_ppr_nego_check(hcb_p np, int req, int target)
 {
 	tcb_p tp = &np->target[target];
-	u_char	chg, ofs, per, fak, dt, div, wide;
+	unsigned char fak, div;
+	int dt, chg = 0;
+
+	unsigned char per = np->msgin[3];
+	unsigned char ofs = np->msgin[5];
+	unsigned char wide = np->msgin[6];
+	unsigned char opts = np->msgin[7] & PPR_OPT_MASK;
 
 	if (DEBUG_FLAGS & DEBUG_NEGO) {
 		sym_print_nego_msg(np, target, "ppr msgin", np->msgin);
-	};
-
-	/*
-	 *  Get requested values.
-	 */
-	chg  = 0;
-	per  = np->msgin[3];
-	ofs  = np->msgin[5];
-	wide = np->msgin[6];
-	dt   = np->msgin[7] & PPR_OPT_DT;
+	}
 
 	/*
 	 *  Check values against our limits.
@@ -4162,29 +4156,30 @@
 		wide = np->maxwide;
 	}
 	if (!wide || !(np->features & FE_ULTRA3))
-		dt &= ~PPR_OPT_DT;
+		opts = 0;
 
 	if (!(np->features & FE_U3EN))	/* Broken U3EN bit not supported */
-		dt &= ~PPR_OPT_DT;
+		opts = 0;
+
+	if (opts != (np->msgin[7] & PPR_OPT_MASK))
+		chg = 1;
 
-	if (dt != (np->msgin[7] & PPR_OPT_MASK)) chg = 1;
+	dt = opts & PPR_OPT_DT;
 
 	if (ofs) {
-		if (dt) {
-			if (ofs > np->maxoffs_dt)
-				{chg = 1; ofs = np->maxoffs_dt;}
+		unsigned char maxoffs = dt ? np->maxoffs_dt : np->maxoffs;
+		if (ofs > maxoffs) {
+			chg = 1;
+			ofs = maxoffs;
 		}
-		else if (ofs > np->maxoffs)
-			{chg = 1; ofs = np->maxoffs;}
 	}
 
 	if (ofs) {
-		if (dt) {
-			if (per < np->minsync_dt)
-				{chg = 1; per = np->minsync_dt;}
+		unsigned char minsync = dt ? np->minsync_dt : np->minsync;
+		if (per < np->minsync_dt) {
+			chg = 1;
+			per = minsync;
 		}
-		else if (per < np->minsync)
-			{chg = 1; per = np->minsync;}
 	}
 
 	/*
@@ -4204,7 +4199,7 @@
 	/*
 	 *  Apply new values.
 	 */
-	sym_setpprot (np, target, dt, ofs, per, wide, div, fak);
+	sym_setpprot(np, target, opts, ofs, per, wide, div, fak);
 
 	/*
 	 *  It was an answer. We are done.
@@ -4222,7 +4217,7 @@
 	np->msgout[4] = 0;
 	np->msgout[5] = ofs;
 	np->msgout[6] = wide;
-	np->msgout[7] = dt;
+	np->msgout[7] = opts;
 
 	if (DEBUG_FLAGS & DEBUG_NEGO) {
 		sym_print_nego_msg(np, target, "ppr msgout", np->msgout);
@@ -4238,7 +4233,7 @@
 	 *  If it is a device response that should result in  
 	 *  ST, we may want to try a legacy negotiation later.
 	 */
-	if (!req && !dt) {
+	if (!req && !opts) {
 		tp->tinfo.goal.options = 0;
 		tp->tinfo.goal.width   = wide;
 		tp->tinfo.goal.period  = per;
@@ -5271,8 +5266,9 @@
 {
 	tcb_p	tp;
 	lcb_p	lp;
-	u_char	idmsg, *msgptr;
+	u_char	*msgptr;
 	u_int   msglen;
+	int can_disconnect;
 
 	/*
 	 *  Keep track of the IO in our CCB.
@@ -5280,25 +5276,21 @@
 	cp->cam_ccb = (cam_ccb_p) csio;
 
 	/*
-	 *  Retreive the target descriptor.
+	 *  Retrieve the target descriptor.
 	 */
 	tp = &np->target[cp->target];
 
 	/*
-	 *  Retreive the lun descriptor.
+	 *  Retrieve the lun descriptor.
 	 */
 	lp = sym_lp(np, tp, cp->lun);
 
-	/*
-	 *  Build the IDENTIFY message.
-	 */
-	idmsg = M_IDENTIFY | cp->lun;
-	if (cp->tag != NO_TAG || (lp && (lp->curr_flags & SYM_DISC_ENABLED)))
-		idmsg |= 0x40;
+	can_disconnect = (cp->tag != NO_TAG) ||
+		(lp && (lp->curr_flags & SYM_DISC_ENABLED));
 
 	msgptr = cp->scsi_smsg;
 	msglen = 0;
-	msgptr[msglen++] = idmsg;
+	msgptr[msglen++] = IDENTIFY(can_disconnect, cp->lun);
 
 	/*
 	 *  Build the tag message if present.
diff -Nru a/drivers/scsi/sym53c8xx_2/sym_misc.c b/drivers/scsi/sym53c8xx_2/sym_misc.c
--- a/drivers/scsi/sym53c8xx_2/sym_misc.c	2004-11-09 00:24:05 -08:00
+++ b/drivers/scsi/sym53c8xx_2/sym_misc.c	2004-11-09 00:24:05 -08:00
@@ -190,10 +190,12 @@
 			mb10 = (f10 + period/2) / period;
 		}
 		printf_info (
-		    "%s:%d: %s %sSCSI %d.%d MB/s %s (%d.%d ns, offset %d)\n",
+		    "%s:%d: %s %sSCSI %d.%d MB/s %s%s%s (%d.%d ns, offset %d)\n",
 		    sym_name(np), target, scsi, __tcurr.width? "WIDE " : "",
 		    mb10/10, mb10%10,
 		    (__tcurr.options & PPR_OPT_DT) ? "DT" : "ST",
+		    (__tcurr.options & PPR_OPT_IU) ? " IU" : "",
+		    (__tcurr.options & PPR_OPT_QAS) ? " QAS" : "",
 		    period/10, period%10, __tcurr.offset);
 	}
 	else
