bk://linux-scsi.bkbits.net/scsi-misc-2.6
bunk@fs.tum.de|ChangeSet|20040802034522|22351 bunk

# This is a BitKeeper generated diff -Nru style patch.
#
# drivers/scsi/scsiiom.c
#   2004/07/16 18:58:28-04:00 g.liakhovetski@gmx.de +40 -50
#   SCSI tmscsim.c: fix inline compile errors
# 
# drivers/scsi/scsiiom.c
#   2004/07/06 04:47:42-05:00 g.liakhovetski@gmx.de +15 -7
#   tmscsim: kernel bugzilla bug #2139
# 
# ChangeSet
#   2004/08/02 13:34:33-07:00 akpm@bix.(none) 
#   Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-scsi
# 
# drivers/scsi/tmscsim.c
#   2004/08/02 13:34:29-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/08/02 13:34:29-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/08/01 23:45:22-04:00 bunk@fs.tum.de 
#   [PATCH] let AIC7{9,X}XX_BUILD_FIRMWARE depend on
#   
#   The patch below lets AIC7{9,X}XX_BUILD_FIRMWARE depend on
#   !PREVENT_FIRMWARE_BUILD.
#   
#   Signed-off-by: Adrian Bunk <bunk@fs.tum.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/aic7xxx/Kconfig.aic7xxx
#   2004/08/01 11:04:40-04:00 bunk@fs.tum.de +1 -1
#   let AIC7{9,X}XX_BUILD_FIRMWARE depend on
# 
# drivers/scsi/aic7xxx/Kconfig.aic79xx
#   2004/08/01 11:04:32-04:00 bunk@fs.tum.de +1 -1
#   let AIC7{9,X}XX_BUILD_FIRMWARE depend on
# 
# ChangeSet
#   2004/08/01 23:35:26-04:00 akpm@osdl.org 
#   [PATCH] sg.c: remove unused sg_jif_to_ms()
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/sg.c
#   2004/07/30 04:04:13-04:00 akpm@osdl.org +0 -13
#   sg.c: remove unused sg_jif_to_ms()
# 
# ChangeSet
#   2004/07/29 23:56:21-07:00 akpm@bix.(none) 
#   Merge bk://linux-scsi.bkbits.net/scsi-misc-2.6
#   into bix.(none):/usr/src/bk-scsi
# 
# MAINTAINERS
#   2004/07/29 23:56:17-07:00 akpm@bix.(none) +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/07/29 16:50:01-04:00 akpm@osdl.org 
#   [PATCH] fix aic driver build for db4
#   
#   From: "J.A. Magallon" <jamagallon@able.es>
#   
#   This allows to build aic with db4.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/aic7xxx/aicasm/Makefile
#   2004/07/26 19:48:36-04:00 akpm@osdl.org +5 -1
#   fix aic driver build for db4
# 
# ChangeSet
#   2004/07/29 16:48:36-04:00 akpm@osdl.org 
#   [PATCH] Fix double reset in aic7xxx driver
#   
#   From: Joe Korty <joe.korty@ccur.com>
#   
#   Fix occasional PCI bus parity errors on the Dell PowerEdge 4600 during
#   boot.
#   
#   Symptoms: The LCD display would turn orange and display "PCI SYSTEM E13F5",
#   and the following message would appear in /var/log/dmesg: "Uhhuh.  NMI
#   received.  Dazed and confused, but trying to continue".
#   
#   By inserting a PCI card with a PDC20268 IDE controller and attaching to
#   that a Sony DRU-510A DVD RW burner with an unloaded tray, the failure can
#   be made to happen on every boot.
#   
#   Cause: The aic7xxx driver was resetting the onboard AIC7891 SCSI controller
#   while waiting for a previous reset to complete.  This second reset confuses
#   the controller causing it to put bad data onto the PCI bus.
#   
#   This is a backport of a RedHat 2.4.21-15.ELsmp fix.  A letter discussing
#   this problem, or one very close to it, may be found at:
#   
#      http://lists.us.dell.com/pipermail/linux-poweredge/2003-May/025010.html
#   
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/aic7xxx/aic7xxx_pci.c
#   2004/07/26 17:54:35-04:00 akpm@osdl.org +3 -1
#   Fix double reset in aic7xxx driver
# 
# drivers/scsi/aic7xxx/aic79xx_pci.c
#   2004/07/26 17:54:35-04:00 akpm@osdl.org +3 -1
#   Fix double reset in aic7xxx driver
# 
# ChangeSet
#   2004/07/29 16:44:58-04:00 akpm@osdl.org 
#   [PATCH] gcc-3.5 fixes to advansys
#   
#   From: Andi Kleen <ak@muc.de>
#   
#   Trivial gcc-3.5 build fixes.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/advansys.c
#   2004/07/10 20:52:16-04:00 akpm@osdl.org +3 -3
#   gcc-3.5 fixes
# 
# ChangeSet
#   2004/07/28 23:08:11-05:00 jejb@raven.il.steeleye.com 
#   Merge
# 
# drivers/scsi/sg.c
#   2004/07/28 23:07:45-05:00 jejb@raven.il.steeleye.com +0 -0
#   SCCS merged
# 
# drivers/scsi/nsp32.c
#   2004/07/28 23:06:57-05:00 jejb@raven.il.steeleye.com +0 -2
#   SCCS merged
# 
# drivers/scsi/sym53c8xx_2/sym_hipd.c
#   2004/07/28 22:59:13-05:00 jejb@raven.il.steeleye.com +0 -0
#   Auto merged
# 
# drivers/scsi/sym53c8xx_2/sym_glue.c
#   2004/07/28 22:59:12-05:00 jejb@raven.il.steeleye.com +0 -0
#   Auto merged
# 
# drivers/scsi/aacraid/linit.c
#   2004/07/28 22:59:11-05:00 jejb@raven.il.steeleye.com +0 -0
#   Auto merged
# 
# drivers/scsi/scsi_sysfs.c
#   2004/07/28 22:59:10-05:00 jejb@raven.il.steeleye.com +0 -0
#   Auto merged
# 
# drivers/scsi/qla1280.c
#   2004/07/28 22:59:10-05:00 jejb@raven.il.steeleye.com +0 -0
#   Auto merged
# 
# drivers/scsi/megaraid.c
#   2004/07/28 22:59:08-05:00 jejb@raven.il.steeleye.com +0 -0
#   Auto merged
# 
# drivers/scsi/eata_pio.c
#   2004/07/28 22:59:07-05:00 jejb@raven.il.steeleye.com +0 -0
#   Auto merged
# 
# drivers/scsi/aic7xxx_old.c
#   2004/07/28 22:59:06-05:00 jejb@raven.il.steeleye.com +0 -0
#   Auto merged
# 
# drivers/scsi/Kconfig
#   2004/07/28 22:59:05-05:00 jejb@raven.il.steeleye.com +0 -0
#   Auto merged
# 
# drivers/message/fusion/mptscsih.c
#   2004/07/28 22:59:04-05:00 jejb@raven.il.steeleye.com +0 -0
#   Auto merged
# 
# MAINTAINERS
#   2004/07/28 22:59:03-05:00 jejb@raven.il.steeleye.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/07/28 17:40:08-04:00 nacc@us.ibm.com 
#   [PATCH] scsi/eata_pio: replace schedule_timeout() with msleep()
#   
#   Use msleep() instead of schedule_timeout() to
#   guarantee the task delays for the desired time.
#   
#   Signed-off-by: Nishanth Aravamudan <nacc@us.ibm.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/eata_pio.c
#   2004/07/02 23:47:44-04:00 nacc@us.ibm.com +1 -2
#   scsi/eata_pio: replace schedule_timeout() with msleep()
# 
# ChangeSet
#   2004/07/28 17:37:56-04:00 Matt_Domsch@dell.com 
#   [PATCH] add MODULE_VERSION to drivers/scsi
#   
#   On Thu, Jul 22, 2004 at 01:28:23PM +0100, Matthew Wilcox wrote:
#   > > +#define SYM_VERSION "2.1.18j"
#   > > +#define SYM_DRIVER_NAME	"sym-" SYM_VERSION
#   >
#   > Umm.  No.  This is ridiculous.  I'm not having a 51 line copyright message
#   > with 2 lines of #define.  It's not even clear to me that these two lines
#   > have artisitic merit.  How about putting these defines in sym_defs.h,
#   > at the top?  It's already included in both sym_glue.c and sym_hipd.c by
#   > being included by sym_glue.h.
#   
#   Indeed, point well taken.  Done, they're now at the top of defines in
#   sym_defs.h, and I've updated my BK tree accordingly.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/sym53c8xx_2/sym_hipd.c
#   2004/07/22 10:12:03-04:00 Matt_Domsch@dell.com +0 -4
#   add MODULE_VERSION to drivers/scsi
# 
# drivers/scsi/sym53c8xx_2/sym_glue.c
#   2004/07/22 10:12:03-04:00 Matt_Domsch@dell.com +1 -0
#   add MODULE_VERSION to drivers/scsi
# 
# drivers/scsi/sym53c8xx_2/sym_defs.h
#   2004/07/22 10:12:03-04:00 Matt_Domsch@dell.com +3 -0
#   add MODULE_VERSION to drivers/scsi
# 
# ChangeSet
#   2004/07/28 17:35:37-04:00 Matt_Domsch@dell.com 
#   [PATCH] add MODULE_VERSION to drivers/scsi
#   
#     Set MODULE_VERSION for drivers/scsi
#   
#     for Adaptec SCSI, megaraid qla1280, qla2x00
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qla2xxx/qla_os.c
#   2004/07/21 17:57:31-04:00 Matt_Domsch@dell.com +1 -0
#   add MODULE_VERSION to drivers/scsi
# 
# drivers/scsi/qla2xxx/ql6322.c
#   2004/07/21 17:57:31-04:00 Matt_Domsch@dell.com +1 -0
#   add MODULE_VERSION to drivers/scsi
# 
# drivers/scsi/qla2xxx/ql6312.c
#   2004/07/21 17:57:31-04:00 Matt_Domsch@dell.com +1 -0
#   add MODULE_VERSION to drivers/scsi
# 
# drivers/scsi/qla2xxx/ql2322.c
#   2004/07/21 17:57:31-04:00 Matt_Domsch@dell.com +1 -0
#   add MODULE_VERSION to drivers/scsi
# 
# drivers/scsi/qla2xxx/ql2300.c
#   2004/07/21 17:57:31-04:00 Matt_Domsch@dell.com +1 -0
#   add MODULE_VERSION to drivers/scsi
# 
# drivers/scsi/qla2xxx/ql2200.c
#   2004/07/21 17:57:31-04:00 Matt_Domsch@dell.com +1 -0
#   add MODULE_VERSION to drivers/scsi
# 
# drivers/scsi/qla2xxx/ql2100.c
#   2004/07/21 17:57:31-04:00 Matt_Domsch@dell.com +1 -0
#   add MODULE_VERSION to drivers/scsi
# 
# drivers/scsi/qla1280.c
#   2004/07/21 17:57:31-04:00 Matt_Domsch@dell.com +1 -0
#   add MODULE_VERSION to drivers/scsi
# 
# drivers/scsi/megaraid.c
#   2004/07/21 17:57:31-04:00 Matt_Domsch@dell.com +3 -0
#   add MODULE_VERSION to drivers/scsi
# 
# drivers/scsi/aic7xxx_old.c
#   2004/07/21 17:57:31-04:00 Matt_Domsch@dell.com +1 -0
#   add MODULE_VERSION to drivers/scsi
# 
# drivers/scsi/aic7xxx/aic7xxx_osm.c
#   2004/07/21 17:57:31-04:00 Matt_Domsch@dell.com +1 -4
#   add MODULE_VERSION to drivers/scsi
# 
# drivers/scsi/aic7xxx/aic79xx_osm.c
#   2004/07/21 17:57:31-04:00 Matt_Domsch@dell.com +1 -4
#   add MODULE_VERSION to drivers/scsi
# 
# drivers/scsi/aacraid/linit.c
#   2004/07/21 17:57:31-04:00 Matt_Domsch@dell.com +1 -0
#   add MODULE_VERSION to drivers/scsi
# 
# ChangeSet
#   2004/07/28 17:33:44-04:00 boutcher@us.ibm.com 
#   [PATCH] ibmvscsi driver v1.5.1
#   
#   Based on comments from hch and jejb, an update to the ibmvscsi
#   driver patch.  Primarily style issues, though the removal of
#   gratuitous casting lead to some significant refactoring
#   of functions.
#   
#   - Moved #include <asm/...> after #include <linux/...>
#   - removed the map_direct_data and map_indirect_data and moved
#      the function inline
#   - Fixed function declaration style issues (static on a line by
#      itself)
#   - Removed bogus cast from dma_map_single
#   - Moved setting of data transfer direction to a single helper
#      function
#   - Fixed up some gratuitous casting of types
#   - Collapsed a couple of other functions inline
#   - Removed bogus check for NULL from remove
#   - Removed the "evt_struct_for" routine as being needlessly obfuscatory
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/ibmvscsi/viosrp.h
#   2004/07/16 18:50:36-04:00 boutcher@us.ibm.com +126 -0
#   ibmvscsi driver v1.5.1
# 
# drivers/scsi/ibmvscsi/srp.h
#   2004/07/16 18:50:36-04:00 boutcher@us.ibm.com +225 -0
#   ibmvscsi driver v1.5.1
# 
# drivers/scsi/ibmvscsi/rpa_vscsi.c
#   2004/07/16 18:50:36-04:00 boutcher@us.ibm.com +260 -0
#   ibmvscsi driver v1.5.1
# 
# drivers/scsi/ibmvscsi/iseries_vscsi.c
#   2004/07/16 18:50:36-04:00 boutcher@us.ibm.com +144 -0
#   ibmvscsi driver v1.5.1
# 
# drivers/scsi/ibmvscsi/ibmvscsi.h
#   2004/07/16 18:50:36-04:00 boutcher@us.ibm.com +108 -0
#   ibmvscsi driver v1.5.1
# 
# drivers/scsi/ibmvscsi/Makefile
#   2004/07/16 18:50:35-04:00 boutcher@us.ibm.com +5 -0
#   ibmvscsi driver v1.5.1
# 
# drivers/scsi/ibmvscsi/viosrp.h
#   2004/07/16 18:50:36-04:00 boutcher@us.ibm.com +0 -0
#   BitKeeper file /home/jejb/BK/scsi-misc-2.6/drivers/scsi/ibmvscsi/viosrp.h
# 
# drivers/scsi/ibmvscsi/srp.h
#   2004/07/16 18:50:36-04:00 boutcher@us.ibm.com +0 -0
#   BitKeeper file /home/jejb/BK/scsi-misc-2.6/drivers/scsi/ibmvscsi/srp.h
# 
# drivers/scsi/ibmvscsi/rpa_vscsi.c
#   2004/07/16 18:50:36-04:00 boutcher@us.ibm.com +0 -0
#   BitKeeper file /home/jejb/BK/scsi-misc-2.6/drivers/scsi/ibmvscsi/rpa_vscsi.c
# 
# drivers/scsi/ibmvscsi/iseries_vscsi.c
#   2004/07/16 18:50:36-04:00 boutcher@us.ibm.com +0 -0
#   BitKeeper file /home/jejb/BK/scsi-misc-2.6/drivers/scsi/ibmvscsi/iseries_vscsi.c
# 
# drivers/scsi/ibmvscsi/ibmvscsi.h
#   2004/07/16 18:50:36-04:00 boutcher@us.ibm.com +0 -0
#   BitKeeper file /home/jejb/BK/scsi-misc-2.6/drivers/scsi/ibmvscsi/ibmvscsi.h
# 
# drivers/scsi/ibmvscsi/ibmvscsi.c
#   2004/07/28 17:33:14-04:00 boutcher@us.ibm.com +1393 -0
#   ibmvscsi driver v1.5.1
# 
# drivers/scsi/ibmvscsi/Makefile
#   2004/07/16 18:50:35-04:00 boutcher@us.ibm.com +0 -0
#   BitKeeper file /home/jejb/BK/scsi-misc-2.6/drivers/scsi/ibmvscsi/Makefile
# 
# drivers/scsi/Makefile
#   2004/06/30 05:13:52-04:00 boutcher@us.ibm.com +1 -0
#   ibmvscsi driver v1.5.1
# 
# drivers/scsi/Kconfig
#   2004/06/30 05:13:51-04:00 boutcher@us.ibm.com +9 -0
#   ibmvscsi driver v1.5.1
# 
# drivers/scsi/ibmvscsi/ibmvscsi.c
#   2004/07/28 17:33:14-04:00 boutcher@us.ibm.com +0 -0
#   BitKeeper file /home/jejb/BK/scsi-misc-2.6/drivers/scsi/ibmvscsi/ibmvscsi.c
# 
# ChangeSet
#   2004/07/28 17:31:21-04:00 g.liakhovetski@gmx.de 
#   [PATCH] SCSI tmscsim.c: fix inline compile errors
#   
#   Original Patch From: Adrian Bunk <bunk@fs.tum.de>
#   
#   I looked at those 3 functions. dc390_EnableMsgOut_Abort is called 5 times
#   in the code and is 0x30 bytes long (as compiled with 3.3.2), so,
#   uninlining it, probably, makes most sense. The other 2 functions are
#   called only ones each and from the interrupt, so, I applied the
#   "alternative approach" to them - moved above the calling functions.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/tmscsim.c
#   2004/07/16 19:01:08-04:00 g.liakhovetski@gmx.de +1 -5
#   SCSI tmscsim.c: fix inline compile errors
# 
# ChangeSet
#   2004/07/28 17:28:42-04:00 g.liakhovetski@gmx.de 
#   [PATCH] tmscsim: MAINTAINERS
#   
#   add new maintainer
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# MAINTAINERS
#   2004/06/26 18:33:30-04:00 g.liakhovetski@gmx.de +2 -0
#   tmscsim: MAINTAINERS
# 
# ChangeSet
#   2004/07/28 17:05:48-04:00 bunk@fs.tum.de 
#   [PATCH] SCSI nsp32.c: remove inlines
#   
#   Trying to compile drivers/scsi/nsp32.c in 2.6.8-rc1-mm1 using gcc 3.4
#   results in compile errors starting with the following:
#   
#   <--  snip  -->
#   
#   ...
#     CC      drivers/scsi/nsp32.o
#   drivers/scsi/nsp32.c: In function `nsp32_prom_start':
#   drivers/scsi/nsp32.c:270: sorry, unimplemented: inlining failed in call
#   to 'nsp32_prom_set': function body not available
#   drivers/scsi/nsp32.c:3348: sorry, unimplemented: called from here
#   drivers/scsi/nsp32.c:270: sorry, unimplemented: inlining failed in call
#   to 'nsp32_prom_set': function body not available
#   drivers/scsi/nsp32.c:3349: sorry, unimplemented: called from here
#   drivers/scsi/nsp32.c:270: sorry, unimplemented: inlining failed in call
#   to 'nsp32_prom_set': function body not available
#   drivers/scsi/nsp32.c:3350: sorry, unimplemented: called from here
#   drivers/scsi/nsp32.c:270: sorry, unimplemented: inlining failed in call
#   to 'nsp32_prom_set': function body not available
#   drivers/scsi/nsp32.c:3351: sorry, unimplemented: called from here
#   drivers/scsi/nsp32.c:270: sorry, unimplemented: inlining failed in call
#   to 'nsp32_prom_set': function body not available
#   drivers/scsi/nsp32.c:3353: sorry, unimplemented: called from here
#   make[2]: *** [drivers/scsi/nsp32.o] Error 1
#   
#   
#   <--  snip  -->
#   
#   
#   The patch below removes the inlines from nsp32_prom_{get,set}.
#   
#   An alternative approach would be to move the functions above the place
#   where they are called the first time.
#   
#   Signed-off-by: Adrian Bunk <bunk@fs.tum.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/nsp32.c
#   2004/07/15 18:37:26-04:00 bunk@fs.tum.de +4 -4
#   SCSI nsp32.c: remove inlines
# 
# ChangeSet
#   2004/07/28 17:00:16-04:00 bunk@fs.tum.de 
#   [PATCH] SCSI dc395x.c: fix inline compile errors
#   
#   Trying to compile drivers/scsi/dc395x.c in 2.6.8-rc1-mm1 using gcc 3.4
#   results in compile errors starting with the following:
#   
#   <--  snip  -->
#   
#   ...
#     CC      drivers/scsi/dc395x.o
#   drivers/scsi/dc395x.c: In function `dc395x_handle_interrupt':
#   drivers/scsi/dc395x.c:388: sorry, unimplemented: inlining failed in call
#   to 'enable_msgout_abort': function body not available
#   drivers/scsi/dc395x.c:1740: sorry, unimplemented: called from here
#   make[2]: *** [drivers/scsi/dc395x.o] Error 1
#   
#   <--  snip  -->
#   
#   
#   The patch below moves enable_msgout_abort above the place where it is
#   called the first time and removes the bogus inline from the prototype of
#   set_xfer_rate (the function itself isn't marked as inline).
#   
#   An alternative approach would be to remove the inline from
#   enable_msgout_abort.
#   
#   Signed-off-by: Adrian Bunk <bunk@fs.tum.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/dc395x.c
#   2004/07/15 18:21:32-04:00 bunk@fs.tum.de +20 -20
#   SCSI dc395x.c: fix inline compile errors
# 
# ChangeSet
#   2004/07/28 16:52:31-04:00 bunk@fs.tum.de 
#   [PATCH] drivers/scsi/sg.c kill local jiffies functions
#   
#   [patch] kill local sg_ms_to_jif/sg_jif_to_ms functions and use
#           msecs_to_jiffies/jiffies_to_msecs instead
#   
#   
#   Signed-off-by: Adrian Bunk <bunk@fs.tum.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/sg.c
#   2004/07/14 14:21:50-04:00 bunk@fs.tum.de +6 -32
#   drivers/scsi/sg.c kill local jiffies functions
# 
# ChangeSet
#   2004/07/28 16:46:32-04:00 andrew.vasquez@qlogic.com 
#   [PATCH] qla2xxx: Update version
#   
#     Update version number to 8.00.00b15-k.
#   
#   Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qla2xxx/qla_version.h
#   2004/07/12 12:55:21-04:00 andrew.vasquez@qlogic.com +2 -2
#   qla2xxx: Update version
# 
# ChangeSet
#   2004/07/28 16:44:41-04:00 andrew.vasquez@qlogic.com 
#   [PATCH] qla2xxx: TCQ fixes
#   
#     Correct usage of tag-command-queueing methods:
#   
#     o Properly call scsi_activate_tcq() rather than
#       scsi_adjust_queue_depth().
#     o Properly retrieve tag message from command via
#       scsi_populate_tag_msg().
#   
#   Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qla2xxx/qla_os.c
#   2004/07/12 12:54:49-04:00 andrew.vasquez@qlogic.com +1 -1
#   qla2xxx: TCQ fixes
# 
# drivers/scsi/qla2xxx/qla_iocb.c
#   2004/07/12 12:54:49-04:00 andrew.vasquez@qlogic.com +11 -5
#   qla2xxx: TCQ fixes
# 
# ChangeSet
#   2004/07/28 16:42:59-04:00 andrew.vasquez@qlogic.com 
#   [PATCH] qla2xxx: Set firmware options fixes
#   
#     Fix issue where firmware options were not properly being
#     set before firmware initialization.
#   
#   Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qla2xxx/qla_init.c
#   2004/07/12 12:54:32-04:00 andrew.vasquez@qlogic.com +4 -6
#   qla2xxx: Set firmware options fixes
# 
# ChangeSet
#   2004/07/28 16:41:09-04:00 andrew.vasquez@qlogic.com 
#   [PATCH] qla2xxx: EH host-reset fixes
#   
#     Fix issue where host-reset would incorrectly return a
#     FAILED status.
#   
#   Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qla2xxx/qla_os.c
#   2004/07/12 12:54:16-04:00 andrew.vasquez@qlogic.com +1 -1
#   qla2xxx: EH host-reset fixes
# 
# ChangeSet
#   2004/07/16 11:08:37-05:00 bunk@fs.tum.de 
#   [PATCH] another small advansys cleanup
#   
#   The patch below does the following small cleanups for the advansys
#   driver:
#   - remove obsolete maintainer information
#   - remove kernel 2.2 code from advansys.h
#   
#   diffstat output:
#    MAINTAINERS             |    7
#    drivers/scsi/advansys.c |  342 +++++++---------------------------------
#    drivers/scsi/advansys.h |   26 ---
#    3 files changed, 60 insertions(+), 315 deletions(-)
#   
#   
#   Signed-off-by: Adrian Bunk <bunk@fs.tum.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/advansys.h
#   2004/05/22 07:47:56-05:00 bunk@fs.tum.de +0 -26
#   another small advansys cleanup
# 
# drivers/scsi/advansys.c
#   2004/05/22 07:47:45-05:00 bunk@fs.tum.de +0 -14
#   another small advansys cleanup
# 
# ChangeSet
#   2004/07/12 10:38:01-05:00 bunk@fs.tum.de 
#   [PATCH] SCSI ips: remove inlines
#   
#   Trying to compile drivers/scsi/ips.c with gcc 3.4 and
#     # define inline         __inline__ __attribute__((always_inline))
#   results in the following error:
#   
#   <--  snip  -->
#   
#   ...
#     CC      drivers/scsi/ips.o
#   drivers/scsi/ips.c: In function `ips_eh_abort':
#   drivers/scsi/ips.c:490: sorry, unimplemented: inlining failed in call to
#   'ips_removeq_copp': function body not available
#   drivers/scsi/ips.c:843: sorry, unimplemented: called from here
#   drivers/scsi/ips.c:488: sorry, unimplemented: inlining failed in call to
#   'ips_removeq_wait': function body not available
#   drivers/scsi/ips.c:847: sorry, unimplemented: called from here
#   make[2]: *** [drivers/scsi/ips.o] Error 1
#   
#   <--  snip  -->
#   
#   
#   The patch below removes all inlines from ips.c. As a side effect, this
#   showed that 3 formerly inlined functions are completely unused which are
#   also removed in the patch.
#   
#   An alternative approach to removing the inlines would be to keep all
#   inlines that are _really_ required and reorder the functions in the file
#   accordingly.
#   
#   
#   diffstat output:
#    drivers/scsi/ips.c |  130 ++++++---------------------------------------
#    1 files changed, 19 insertions(+), 111 deletions(-)
#   
#   
#   Signed-off-by: Adrian Bunk <bunk@fs.tum.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/ips.c
#   2004/07/08 18:24:02-05:00 bunk@fs.tum.de +19 -111
#   SCSI ips: remove inlines
# 
# ChangeSet
#   2004/07/11 09:59:38-05:00 akpm@osdl.org 
#   [PATCH] warning fix to include/scsi/scsi_device.h
#   
#   From: Mika Kukkonen <mika@osdl.org>
#   
#     CC [M]  drivers/block/cciss.o
#   In file included from drivers/scsi/scsi.h:27,
#                    from drivers/block/cciss_scsi.c:31,
#                    from drivers/block/cciss.c:188:
#   include/scsi/scsi_device.h:191: warning: `inline' is not at beginning of declaration
#   
#   Another case of reordering the 'inline' and function return value.
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# include/scsi/scsi_device.h
#   2004/07/07 11:24:13-05:00 akpm@osdl.org +1 -1
#   warning fix to include/scsi/scsi_device.h
# 
# ChangeSet
#   2004/07/10 10:54:58-05:00 bunk@fs.tum.de 
#   [PATCH] update contact address for SCSI megaraid.c
#   
#   If you send an email to linux-megaraid-devel@dell.com, you get an
#   automated response to send the mail to linux-scsi@vger.kernel.org
#   instead.
#   
#   The patch below updates megaraid.c accordingly.
#   
#   Signed-off-by: Adrian Bunk <bunk@fs.tum.de>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/megaraid.c
#   2004/07/10 10:16:51-05:00 bunk@fs.tum.de +2 -5
#   update contact address for SCSI megaraid.c
# 
# ChangeSet
#   2004/07/10 10:53:19-05:00 g.liakhovetski@gmx.de 
#   [PATCH] tmscsim: kernel bugzilla bug #2139
#   
#   > Short: The attached patch fixes the bug-report #2139 from kernel bugzilla.
#   
#   I wasn't quite convenient with the previous version of the patch, but I
#   just wanted to get it working at first and get some comments as to whether
#   the approach (put a workaround vs. blacklisting) is at all valid. Since no
#   objections arrived, I guess, nobody minds this small trick. So, I am
#   enclosing a reworked patch, which does essentially the same, but has some
#   more careful checking, and overall looks saner, than the previous one.
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# ChangeSet
#   2004/07/10 10:50:13-05:00 akpm@osdl.org 
#   [PATCH] mptbase.c warning fix
#   
#   drivers/message/fusion/mptbase.c: In function `GetIocFacts':
#   drivers/message/fusion/mptbase.c:2420: warning: int format, different type arg (arg 4)
#   
#   Signed-off-by: Andrew Morton <akpm@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/message/fusion/mptbase.c
#   2004/07/05 10:11:00-05:00 akpm@osdl.org +1 -1
#   mptbase.c warning fix
# 
# ChangeSet
#   2004/07/10 10:49:20-05:00 jejb@mulgrave.(none) 
#   MPT Fusion driver 3.01.10 update
#   
#   From: "Moore, Eric Dean" <Emoore@lsil.com>
#   
#   This driver incorporates the patches from Christoph Hellwig
#   and Masao Fukuchi.
#   
#   Changelog of this release:
#   
#   * Patch provided by  Masao Fukuchi [fukuchi.masao@jp.fujitsu.com]
#    - mptctl updates for hot plug
#   
#   * Patch provided by Christoph Hellwig [hch@infradead.org]
#    - mptlan updates for hot plug
#    - remove CONFIG_LBD ifdefs from fusion { mptscsih.c}
#   
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/message/fusion/mptscsih.c
#   2004/07/10 10:49:03-05:00 jejb@mulgrave.(none) +1 -10
#   MPT Fusion driver 3.01.10 update
# 
# drivers/message/fusion/mptlan.c
#   2004/07/10 10:49:03-05:00 jejb@mulgrave.(none) +74 -78
#   MPT Fusion driver 3.01.10 update
# 
# drivers/message/fusion/mptctl.c
#   2004/07/10 10:49:03-05:00 jejb@mulgrave.(none) +82 -72
#   MPT Fusion driver 3.01.10 update
# 
# drivers/message/fusion/mptbase.h
#   2004/07/10 10:49:02-05:00 jejb@mulgrave.(none) +4 -2
#   MPT Fusion driver 3.01.10 update
# 
# drivers/message/fusion/mptbase.c
#   2004/07/10 10:49:02-05:00 jejb@mulgrave.(none) +0 -2
#   MPT Fusion driver 3.01.10 update
# 
# ChangeSet
#   2004/07/10 10:42:49-05:00 brking@us.ibm.com 
#   [PATCH] fix scsi_remove_device locking
#   
#   The following patch fixes an oops I was seeing on a machine with
#   misconfigured scsi cables, but could feasibly happen in other paths.
#   The oops was occurring because scsi_remove_device was getting
#   called for a device before scsi_add_device had fully completed.
#   This resulted in sysfs_remove_link being called with a NULL dentry.
#   
#   Signed-off-by: Brian King <brking@us.ibm.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/scsi_sysfs.c
#   2004/07/02 15:29:59-05:00 brking@us.ibm.com +7 -1
#   fix scsi_remove_device locking
# 
# ChangeSet
#   2004/07/10 10:39:57-05:00 markh@osdl.org 
#   [PATCH] aacraid reset handler
#   
#   This restores a fix to the aacraid reset handler.  It makes sure that
#   there are no active commands on any attached device before exiting with
#   SUCCESS.
#   
#   Signed-off-by: Mark Haverkamp <markh@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/aacraid/linit.c
#   2004/06/29 13:22:58-05:00 markh@osdl.org +7 -5
#   aacraid reset handler
# 
# ChangeSet
#   2004/07/10 10:36:32-05:00 rddunlap@osdl.org 
#   [PATCH] fix JAZZ_ESP driver config depends
#   
#   Use correct config symbol name for MACH_JAZZ in JAZZ_ESP driver config.
#   Acked by Ralf.
#   
#   Signed-off-by: Randy Dunlap <rddunlap@osdl.org>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/Kconfig
#   2004/06/30 11:35:12-05:00 rddunlap@osdl.org +1 -1
#   fix JAZZ_ESP driver config depends
# 
# ChangeSet
#   2004/06/28 11:13:18-05:00 hch@lst.de 
#   [PATCH] qla1280: update changelog and version
#   
#   Signed-off-by: Jes Sorensen <jes@wildopensource.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qla1280.c
#   2004/06/06 07:47:45-05:00 hch@lst.de +5 -2
#   update changelog and version
# 
# ChangeSet
#   2004/06/28 11:09:47-05:00 hch@lst.de 
#   [PATCH] qla1280: cleanup qla1280_initialize_adapter
#   
#   no function changes, just some more gotos and less nested ifs to make
#   the code readable.
#   
#   Signed-off-by: Jes Sorensen <jes@wildopensource.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qla1280.c
#   2004/06/06 07:47:27-05:00 hch@lst.de +15 -27
#   cleanup qla1280_initialize_adapter
# 
# ChangeSet
#   2004/06/28 11:08:20-05:00 hch@lst.de 
#   [PATCH] qla1280: cleanup qla1280_nvram_config
#   
#   qla1280_nvram_config is a huge mess.  Split it up into managable
#   subroutines and add suport for the ISP1040 to it.  Add missing call
#   to set the age limit also on 1280/1x160.
#   
#   Signed-off-by: Jes Sorensen <jes@wildopensource.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qla1280.c
#   2004/06/06 07:47:07-05:00 hch@lst.de +255 -231
#   cleanup qla1280_nvram_config
# 
# ChangeSet
#   2004/06/28 10:55:48-05:00 hch@lst.de 
#   [PATCH] qla1280: cleanup firmware loading, add pio-based loading
#   
#   The ISP1040 needs to load firmware by PIO, and while we're at it clean
#   the convoluted mess of firmware loading up by splitting it into
#   managable subroutines.
#   
#   Signed-off-by: Jes Sorensen <jes@wildopensource.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qla1280.c
#   2004/06/06 07:45:10-05:00 hch@lst.de +226 -226
#   cleanup firmware loading, add pio-based loading
# 
# ChangeSet
#   2004/06/28 10:48:11-05:00 hch@lst.de 
#   [PATCH] qla1280: add IS_ISP* helpers
#   
#   The code is already messy due to the explicit pci id checks for
#   1280 vs 1x160, so add some nice helpers for that.
#   
#   Signed-off-by: Jes Sorensen <jes@wildopensource.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qla1280.c
#   2004/06/06 07:44:56-05:00 hch@lst.de +27 -31
#   add IS_ISP* helpers
# 
# ChangeSet
#   2004/06/28 10:33:34-05:00 hch@lst.de 
#   [PATCH] qla1280: add ISP1040 register definitions
#   
#   The old 1020/1040 has some registers where the newer controlers only
#   have reserved space, add that to qla1280.h
#   
#   Signed-off-by: Jes Sorensen <jes@wildopensource.com>
#   Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
# 
# drivers/scsi/qla1280.h
#   2004/06/06 07:45:26-05:00 hch@lst.de +52 -4
#   add ISP1040 register definitions
# 
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	2004-08-04 17:57:40 -07:00
+++ b/MAINTAINERS	2004-08-04 17:57:40 -07:00
@@ -621,6 +621,8 @@
 P:	Kurt Garloff
 M:	garloff@suse.de
 W:	http://www.garloff.de/kurt/linux/dc390/
+P:	Guennadi Liakhovetski
+M:	g.liakhovetski@gmx.de
 S:	Maintained
 
 DECnet NETWORK LAYER
diff -Nru a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c
--- a/drivers/message/fusion/mptbase.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/message/fusion/mptbase.c	2004-08-04 17:57:40 -07:00
@@ -1337,7 +1337,6 @@
 			printk(MYIOC_s_ERR_FMT "Unable to allocate interrupt %s!\n",
 					ioc->name, __irq_itoa(pdev->irq));
 #endif
-			Q_DEL_ITEM(ioc);
 			list_del(&ioc->list);
 			iounmap(mem);
 			kfree(ioc);
@@ -1369,7 +1368,6 @@
 		  ": WARNING - %s did not initialize properly! (%d)\n",
 		  ioc->name, r);
 
-		Q_DEL_ITEM(ioc);
 		list_del(&ioc->list);
 		free_irq(ioc->pci_irq, ioc);
 		iounmap(mem);
@@ -2416,7 +2414,7 @@
 		}
 	} else {
 		printk(MYIOC_s_ERR_FMT 
-		     "Invalid IOC facts reply, msgLength=%d offsetof=%d!\n",
+		     "Invalid IOC facts reply, msgLength=%d offsetof=%zd!\n",
 		     ioc->name, facts->MsgLength, (offsetof(IOCFactsReply_t,
 		     RequestFrameSize)/sizeof(u32)));
 		return -66;
diff -Nru a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h
--- a/drivers/message/fusion/mptbase.h	2004-08-04 17:57:40 -07:00
+++ b/drivers/message/fusion/mptbase.h	2004-08-04 17:57:40 -07:00
@@ -85,8 +85,8 @@
 #define COPYRIGHT	"Copyright (c) 1999-2004 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON	"3.01.09"
-#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.01.09"
+#define MPT_LINUX_VERSION_COMMON	"3.01.10"
+#define MPT_LINUX_PACKAGE_NAME		"@(#)mptlinux-3.01.10"
 #define WHAT_MAGIC_STRING		"@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -523,6 +523,7 @@
 	u8			 target;	/* target for reset */
 	void 			*tmPtr;
 	struct timer_list	 TMtimer;	/* timer function for this adapter */
+	struct semaphore	 sem_ioc;
 } MPT_IOCTL;
 
 /*
@@ -676,6 +677,7 @@
 	u8			 reload_fw;	/* Force a FW Reload on next reset */
 	u8			 pad1[5];
 	struct list_head	 list; 
+	struct net_device	*netdev;
 } MPT_ADAPTER;
 
 
diff -Nru a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
--- a/drivers/message/fusion/mptctl.c	2004-08-04 17:57:39 -07:00
+++ b/drivers/message/fusion/mptctl.c	2004-08-04 17:57:39 -07:00
@@ -111,7 +111,6 @@
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
 static int mptctl_id = -1;
-static struct semaphore mptctl_syscall_sem_ioc[MPT_MAX_ADAPTERS];
 
 static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait );
 
@@ -140,6 +139,9 @@
 static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
 static int mptctl_hp_targetinfo(unsigned long arg);
 
+static int  mptctl_probe(struct pci_dev *, const struct pci_device_id *);
+static void mptctl_remove(struct pci_dev *);
+
 /*
  * Private function calls.
  */
@@ -208,10 +210,10 @@
 	}
 
 	if (nonblock) {
-		if (down_trylock(&mptctl_syscall_sem_ioc[ioc->id]))
+		if (down_trylock(&ioc->ioctl->sem_ioc))
 			rc = -EAGAIN;
 	} else {
-		if (down_interruptible(&mptctl_syscall_sem_ioc[ioc->id]))
+		if (down_interruptible(&ioc->ioctl->sem_ioc))
 			rc = -ERESTARTSYS;
 	}
 	dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
@@ -630,8 +632,7 @@
 	else
 		ret = -EINVAL;
 
-
-	up(&mptctl_syscall_sem_ioc[iocp->id]);
+	up(&iocp->ioctl->sem_ioc);
 
 	return ret;
 }
@@ -2738,7 +2739,7 @@
 
 	ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
 
-	up(&mptctl_syscall_sem_ioc[iocp->id]);
+	up(&iocp->ioctl->sem_ioc);
 
 	return ret;
 }
@@ -2792,55 +2793,91 @@
 	 */
 	ret = mptctl_do_mpt_command (karg, &uarg->MF);
 
-	up(&mptctl_syscall_sem_ioc[iocp->id]);
+	up(&iocp->ioctl->sem_ioc);
 
 	return ret;
 }
 
 #endif
 
+
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-int __init mptctl_init(void)
+/*
+ *	mptctl_probe - Installs ioctl devices per bus.
+ *	@pdev: Pointer to pci_dev structure
+ *
+ *	Returns 0 for success, non-zero for failure.
+ *
+ */
+
+static int
+mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	int err;
-	int i;
-	int where = 1;
 	int sz;
 	u8 *mem;
-	MPT_ADAPTER *ioc = NULL;
-	int iocnum;
+	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
 
-	show_mptmod_ver(my_NAME, my_VERSION);
+	/*
+	 * Allocate and inite a MPT_IOCTL structure
+	*/
+	sz = sizeof (MPT_IOCTL);
+	mem = kmalloc(sz, GFP_KERNEL);
+	if (mem == NULL) {
+		err = -ENOMEM;
+		goto out_fail;
+	}
 
-	for (i=0; i<MPT_MAX_ADAPTERS; i++) {
-		sema_init(&mptctl_syscall_sem_ioc[i], 1);
+	memset(mem, 0, sz);
+	ioc->ioctl = (MPT_IOCTL *) mem;
+	ioc->ioctl->ioc = ioc;
+	init_timer (&ioc->ioctl->timer);
+	ioc->ioctl->timer.data = (unsigned long) ioc->ioctl;
+	ioc->ioctl->timer.function = mptctl_timer_expired;
+	init_timer (&ioc->ioctl->TMtimer);
+	ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl;
+	ioc->ioctl->TMtimer.function = mptctl_timer_expired;
+	sema_init(&ioc->ioctl->sem_ioc, 1);
+	return 0;
 
-		ioc = NULL;
-		if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
-		    (ioc == NULL)) {
-			continue;
-		}
-		else {
-			/* This adapter instance is found.
-			 * Allocate and inite a MPT_IOCTL structure
-			 */
-			sz = sizeof (MPT_IOCTL);
-			mem = kmalloc(sz, GFP_KERNEL);
-			if (mem == NULL) {
-				err = -ENOMEM;
-				goto out_fail;
-			}
-
-			memset(mem, 0, sz);
-			ioc->ioctl = (MPT_IOCTL *) mem;
-			ioc->ioctl->ioc = ioc;
-			init_timer (&ioc->ioctl->timer);
-			ioc->ioctl->timer.data = (unsigned long) ioc->ioctl;
-			ioc->ioctl->timer.function = mptctl_timer_expired;
-			init_timer (&ioc->ioctl->TMtimer);
-			ioc->ioctl->TMtimer.data = (unsigned long) ioc->ioctl;
-			ioc->ioctl->TMtimer.function = mptctl_timer_expired;
-		}
+out_fail:
+
+	mptctl_remove(pdev);
+	return err;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/*
+ *	mptctl_remove - Removed ioctl devices
+ *	@pdev: Pointer to pci_dev structure
+ *
+ *
+ */
+static void
+mptctl_remove(struct pci_dev *pdev)
+{
+	MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+
+	kfree ( ioc->ioctl );
+}
+
+static struct mpt_pci_driver mptctl_driver = {
+  .probe		= mptctl_probe,
+  .remove		= mptctl_remove,
+};
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+int __init mptctl_init(void)
+{
+	int err;
+	int where = 1;
+
+	show_mptmod_ver(my_NAME, my_VERSION);
+
+	if(mpt_device_driver_register(&mptctl_driver,
+	  MPTCTL_DRIVER) != 0 ) {
+		dprintk((KERN_INFO MYNAM
+		": failed to register dd callbacks\n"));
 	}
 
 #ifdef CONFIG_COMPAT
@@ -2922,29 +2959,14 @@
 	unregister_ioctl32_conversion(HP_GETTARGETINFO);
 #endif
 
-	for (i=0; i<MPT_MAX_ADAPTERS; i++) {
-		ioc = NULL;
-		if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
-		    (ioc == NULL)) {
-			continue;
-		}
-		else {
-			if (ioc->ioctl) {
-				kfree ( ioc->ioctl );
-				ioc->ioctl = NULL;
-			}
-		}
-	}
+	mpt_device_driver_deregister(MPTCTL_DRIVER);
+
 	return err;
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 void mptctl_exit(void)
 {
-	int i;
-	MPT_ADAPTER *ioc;
-	int iocnum;
-
 	misc_deregister(&mptctl_miscdev);
 	printk(KERN_INFO MYNAM ": Deregistered /dev/%s @ (major,minor=%d,%d)\n",
 			 mptctl_miscdev.name, MISC_MAJOR, mptctl_miscdev.minor);
@@ -2957,6 +2979,8 @@
 	mpt_deregister(mptctl_id);
 	printk(KERN_INFO MYNAM ": Deregistered from Fusion MPT base driver\n");
 
+        mpt_device_driver_deregister(MPTCTL_DRIVER);
+
 #ifdef CONFIG_COMPAT
 	unregister_ioctl32_conversion(MPTIOCINFO);
 	unregister_ioctl32_conversion(MPTIOCINFO1);
@@ -2973,20 +2997,6 @@
 	unregister_ioctl32_conversion(HP_GETTARGETINFO);
 #endif
 
-	/* Free allocated memory */
-	for (i=0; i<MPT_MAX_ADAPTERS; i++) {
-		ioc = NULL;
-		if (((iocnum = mpt_verify_adapter(i, &ioc)) < 0) ||
-		    (ioc == NULL)) {
-			continue;
-		}
-		else {
-			if (ioc->ioctl) {
-				kfree ( ioc->ioctl );
-				ioc->ioctl = NULL;
-			}
-		}
-	}
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
diff -Nru a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
--- a/drivers/message/fusion/mptlan.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/message/fusion/mptlan.c	2004-08-04 17:57:40 -07:00
@@ -177,11 +177,9 @@
 static u32 max_buckets_out = 127;
 static u32 tx_max_out_p = 127 - 16;
 
-static struct net_device *mpt_landev[MPT_MAX_ADAPTERS+1];
-
 #ifdef QLOGIC_NAA_WORKAROUND
 static struct NAA_Hosed *mpt_bad_naa = NULL;
-rwlock_t bad_naa_lock;
+rwlock_t bad_naa_lock = RW_LOCK_UNLOCKED;
 #endif
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -203,7 +201,7 @@
 static int
 lan_reply (MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply)
 {
-	struct net_device *dev = mpt_landev[ioc->id];
+	struct net_device *dev = ioc->netdev;
 	int FreeReqFrame = 0;
 
 	dioprintk((KERN_INFO MYNAM ": %s/%s: Got reply.\n",
@@ -336,7 +334,7 @@
 static int
 mpt_lan_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
 {
-	struct net_device *dev = mpt_landev[ioc->id];
+	struct net_device *dev = ioc->netdev;
 	struct mpt_lan_priv *priv = netdev_priv(dev);
 
 	dlprintk((KERN_INFO MYNAM ": IOC %s_reset routed to LAN driver!\n",
@@ -1451,20 +1449,74 @@
 	return dev;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-static int __init mpt_lan_init (void)
+static int
+mptlan_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-	struct net_device *dev;
-	MPT_ADAPTER *p;
-	int i, j;
+	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
+	struct net_device	*dev;
+	int			i;
+
+	for (i = 0; i < ioc->facts.NumberOfPorts; i++) {
+		printk(KERN_INFO MYNAM ": %s: PortNum=%x, "
+		       "ProtocolFlags=%02Xh (%c%c%c%c)\n",
+		       ioc->name, ioc->pfacts[i].PortNumber,
+		       ioc->pfacts[i].ProtocolFlags,
+		       MPT_PROTOCOL_FLAGS_c_c_c_c(
+			       ioc->pfacts[i].ProtocolFlags));
+
+		if (!(ioc->pfacts[i].ProtocolFlags &
+					MPI_PORTFACTS_PROTOCOL_LAN)) {
+			printk(KERN_INFO MYNAM ": %s: Hmmm... LAN protocol "
+			       "seems to be disabled on this adapter port!\n",
+			       ioc->name);
+			continue;
+		}
 
-	show_mptmod_ver(LANAME, LANVER);
+		dev = mpt_register_lan_device(ioc, i);
+		if (!dev) {
+			printk(KERN_ERR MYNAM ": %s: Unable to register "
+			       "port%d as a LAN device\n", ioc->name,
+			       ioc->pfacts[i].PortNumber);
+			continue;
+		}
+		
+		printk(KERN_INFO MYNAM ": %s: Fusion MPT LAN device "
+		       "registered as '%s'\n", ioc->name, dev->name);
+		printk(KERN_INFO MYNAM ": %s/%s: "
+		       "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
+		       IOC_AND_NETDEV_NAMES_s_s(dev),
+		       dev->dev_addr[0], dev->dev_addr[1],
+		       dev->dev_addr[2], dev->dev_addr[3],
+		       dev->dev_addr[4], dev->dev_addr[5]);
+	
+		ioc->netdev = dev;
 
-#ifdef QLOGIC_NAA_WORKAROUND
-	/* Init the global r/w lock for the bad_naa list. We want to do this
-	   before any boards are initialized and may be used. */
-	rwlock_init(&bad_naa_lock);
-#endif
+		return 0;
+	}
+
+	return -ENODEV;
+}
+
+static void
+mptlan_remove(struct pci_dev *pdev)
+{
+	MPT_ADAPTER 		*ioc = pci_get_drvdata(pdev);
+	struct net_device	*dev = ioc->netdev;
+
+	if(dev != NULL) {
+		unregister_netdev(dev);
+		free_netdev(dev);
+	}
+}
+
+static struct mpt_pci_driver mptlan_driver = {
+	.probe		= mptlan_probe,
+	.remove		= mptlan_remove,
+};
+
+static int __init mpt_lan_init (void)
+{
+	show_mptmod_ver(LANAME, LANVER);
 
 	if ((LanCtx = mpt_register(lan_reply, MPTLAN_DRIVER)) <= 0) {
 		printk (KERN_ERR MYNAM ": Failed to register with MPT base driver\n");
@@ -1476,87 +1528,31 @@
 
 	dlprintk((KERN_INFO MYNAM ": assigned context of %d\n", LanCtx));
 
-	if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset) == 0) {
-		dlprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n"));
-	} else {
+	if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset)) {
 		printk(KERN_ERR MYNAM ": Eieee! unable to register a reset "
 		       "handler with mptbase! The world is at an end! "
 		       "Everything is fading to black! Goodbye.\n");
 		return -EBUSY;
 	}
 
-	for (j = 0; j < MPT_MAX_ADAPTERS; j++) {
-		mpt_landev[j] = NULL;
-	}
-
-	list_for_each_entry(p, &ioc_list, list) {
-		for (i = 0; i < p->facts.NumberOfPorts; i++) {
-			printk (KERN_INFO MYNAM ": %s: PortNum=%x, ProtocolFlags=%02Xh (%c%c%c%c)\n",
-					p->name,
-					p->pfacts[i].PortNumber,
-					p->pfacts[i].ProtocolFlags,
-					MPT_PROTOCOL_FLAGS_c_c_c_c(p->pfacts[i].ProtocolFlags));
-
-			if (!(p->pfacts[i].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN)) {
-				printk (KERN_INFO MYNAM ": %s: Hmmm... LAN protocol seems to be disabled on this adapter port!\n",
-						p->name);
-				continue;
-			}
-
-			dev = mpt_register_lan_device (p, i);
-			if (!dev) {
-				printk (KERN_ERR MYNAM ": %s: Unable to register port%d as a LAN device\n",
-						p->name,
-						p->pfacts[i].PortNumber);
-			}
-			printk (KERN_INFO MYNAM ": %s: Fusion MPT LAN device registered as '%s'\n",
-					p->name, dev->name);
-			printk (KERN_INFO MYNAM ": %s/%s: LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n",
-					IOC_AND_NETDEV_NAMES_s_s(dev),
-					dev->dev_addr[0], dev->dev_addr[1],
-					dev->dev_addr[2], dev->dev_addr[3],
-					dev->dev_addr[4], dev->dev_addr[5]);
-//					printk (KERN_INFO MYNAM ": %s/%s: Max_TX_outstanding = %d\n",
-//							IOC_AND_NETDEV_NAMES_s_s(dev),
-//							NETDEV_TO_LANPRIV_PTR(dev)->tx_max_out);
-			j = p->id;
-			mpt_landev[j] = dev;
-			dlprintk((KERN_INFO MYNAM "/init: dev_addr=%p, mpt_landev[%d]=%p\n",
-					dev, j,  mpt_landev[j]));
-
-		}
-	}
-
+	dlprintk((KERN_INFO MYNAM ": Registered for IOC reset notifications\n"));
+	
+	if (mpt_device_driver_register(&mptlan_driver, MPTLAN_DRIVER))
+		dprintk((KERN_INFO MYNAM ": failed to register dd callbacks\n"));
 	return 0;
 }
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static void __exit mpt_lan_exit(void)
 {
-	int i;
-
+	mpt_device_driver_deregister(MPTLAN_DRIVER);
 	mpt_reset_deregister(LanCtx);
 
-	for (i = 0; mpt_landev[i] != NULL; i++) {
-		struct net_device *dev = mpt_landev[i];
-
-		printk (KERN_INFO ": %s/%s: Fusion MPT LAN device unregistered\n",
-			       IOC_AND_NETDEV_NAMES_s_s(dev));
-		unregister_netdev(dev);
-		free_netdev(dev);
-		mpt_landev[i] = NULL;
-	}
-
 	if (LanCtx >= 0) {
 		mpt_deregister(LanCtx);
 		LanCtx = -1;
 		mpt_lan_index = 0;
 	}
-
-	/* deregister any send/receive handler structs. I2Oism? */
 }
-
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 
 module_init(mpt_lan_init);
 module_exit(mpt_lan_exit);
diff -Nru a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c
--- a/drivers/message/fusion/mptscsih.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/message/fusion/mptscsih.c	2004-08-04 17:57:40 -07:00
@@ -3058,19 +3058,14 @@
 	int		heads;
 	int		sectors;
 	sector_t	cylinders;
-#ifdef CONFIG_LBD
 	ulong 		dummy;
-#endif
 
 	heads = 64;
 	sectors = 32;
-#ifdef CONFIG_LBD
+
 	dummy = heads * sectors;
 	cylinders = capacity;
 	sector_div(cylinders,dummy);
-#else
-	cylinders = (ulong)capacity / (heads * sectors);
-#endif
 
 	/*
 	 * Handle extended translation size for logical drives
@@ -3079,13 +3074,9 @@
 	if ((ulong)capacity >= 0x200000) {
 		heads = 255;
 		sectors = 63;
-#ifdef CONFIG_LBD
 		dummy = heads * sectors;
 		cylinders = capacity;
 		sector_div(cylinders,dummy);
-#else
-		cylinders = (ulong)capacity / (heads * sectors);
-#endif
 	}
 
 	/* return result */
diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
--- a/drivers/scsi/Kconfig	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/Kconfig	2004-08-04 17:57:40 -07:00
@@ -780,6 +780,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called ips.
 
+config SCSI_IBMVSCSI
+	tristate "IBM Virtual SCSI support"
+	depends on PPC_PSERIES || PPC_ISERIES
+	help
+	  This is the IBM POWER Virtual SCSI Client
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ibmvscsic.
+
 config SCSI_INITIO
 	tristate "Initio 9100U(W) support"
 	depends on PCI && SCSI && BROKEN
@@ -1507,7 +1516,7 @@
 
 config JAZZ_ESP
 	bool "MIPS JAZZ FAS216 SCSI support"
-	depends on MIPS_JAZZ && SCSI
+	depends on MACH_JAZZ && SCSI
 	help
 	  This is the driver for the onboard SCSI host adapter of MIPS Magnum
 	  4000, Acer PICA, Olivetti M700-10 and a few other identical OEM
diff -Nru a/drivers/scsi/Makefile b/drivers/scsi/Makefile
--- a/drivers/scsi/Makefile	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/Makefile	2004-08-04 17:57:40 -07:00
@@ -119,6 +119,7 @@
 obj-$(CONFIG_SCSI_LASI700)	+= 53c700.o lasi700.o
 obj-$(CONFIG_SCSI_NSP32)	+= nsp32.o
 obj-$(CONFIG_SCSI_IPR)		+= ipr.o
+obj-$(CONFIG_SCSI_IBMVSCSI)	+= ibmvscsi/
 obj-$(CONFIG_SCSI_SATA_SVW)	+= libata.o sata_svw.o
 obj-$(CONFIG_SCSI_ATA_PIIX)	+= libata.o ata_piix.o
 obj-$(CONFIG_SCSI_SATA_PROMISE)	+= libata.o sata_promise.o
diff -Nru a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
--- a/drivers/scsi/aacraid/linit.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/aacraid/linit.c	2004-08-04 17:57:40 -07:00
@@ -62,6 +62,7 @@
 		   "Adaptec Advanced Raid Products, "
 		   "and HP NetRAID-4M SCSI driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(AAC_DRIVER_VERSION);
 
 
 int nondasd = -1;
@@ -408,13 +409,15 @@
 				}
 			}
 			spin_unlock_irqrestore(&dev->list_lock, flags);
+			if (active)
+				break;
 
-			/*
-			 * We can exit If all the commands are complete
-			 */
-			if (active == 0)
-				return SUCCESS;
 		}
+		/*
+		 * We can exit If all the commands are complete
+		 */
+		if (active == 0)
+			return SUCCESS;
 		spin_unlock_irq(host->host_lock);
 		scsi_sleep(HZ);
 		spin_lock_irq(host->host_lock);
diff -Nru a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
--- a/drivers/scsi/advansys.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/advansys.c	2004-08-04 17:57:40 -07:00
@@ -15,16 +15,6 @@
  * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
  * changed its name to ConnectCom Solutions, Inc.
  *
- * There is an AdvanSys Linux WWW page at:
- *  http://www.connectcom.net/downloads/software/os/linux.html
- *  http://www.advansys.com/linux.html
- *
- * The latest released version of the AdvanSys driver is available at:
- *  ftp://ftp.advansys.com/pub/linux/linux.tgz
- *  ftp://ftp.connectcom.net/pub/linux/linux.tgz
- *
- * Please send questions, comments, bug reports to:
- *  support@connectcom.net
  */
 
 /*
@@ -41,7 +31,6 @@
   H. Release History
   I. Known Problems/Fix List
   J. Credits (Chronological Order)
-  K. ConnectCom (AdvanSys) Contact Information
 
   A. Linux Kernels Supported by this Driver
 
@@ -2032,9 +2021,6 @@
 #define ADV_LIB_VERSION_MAJOR  5
 #define ADV_LIB_VERSION_MINOR  14
 
-/* d_os_dep.h */
-#define ADV_OS_LINUX
-
 /*
  * Define Adv Library required special types.
  */
@@ -3370,9 +3356,9 @@
 /*
  * Default EEPROM Configuration structure defined in a_init.c.
  */
-extern ADVEEP_3550_CONFIG Default_3550_EEPROM_Config;
-extern ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config;
-extern ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config;
+static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config;
+static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config;
+static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config;
 
 /*
  * DvcGetPhyAddr() flag arguments
diff -Nru a/drivers/scsi/advansys.h b/drivers/scsi/advansys.h
--- a/drivers/scsi/advansys.h	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/advansys.h	2004-08-04 17:57:40 -07:00
@@ -13,36 +13,10 @@
  * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys)
  * changed its name to ConnectCom Solutions, Inc.
  *
- * There is an AdvanSys Linux WWW page at:
- *  http://www.connectcom.net/downloads/software/os/linux.html
- *  http://www.advansys.com/linux.html
- *
- * The latest released version of the AdvanSys driver is available at:
- *  ftp://ftp.advansys.com/pub/linux/linux.tgz
- *  ftp://ftp.connectcom.net/pub/linux/linux.tgz
- *
- * Please send questions, comments, bug reports to:
- *  linux@connectcom.net or bfrey@turbolinux.com.cn
  */
 
 #ifndef _ADVANSYS_H
 #define _ADVANSYS_H
-
-#include <linux/config.h>
-#ifndef LINUX_VERSION_CODE
-#include <linux/version.h>
-#endif /* LINUX_VERSION_CODE */
-
-/* Convert Linux Version, Patch-level, Sub-level to LINUX_VERSION_CODE. */
-#define ASC_LINUX_VERSION(V, P, S)    (((V) * 65536) + ((P) * 256) + (S))
-/* Driver supported only in version 2.2 and version >= 2.4. */
-#if LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,2,0) || \
-    (LINUX_VERSION_CODE > ASC_LINUX_VERSION(2,3,0) && \
-     LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,4,0))
-#error "AdvanSys driver supported only in 2.2 and 2.4 or greater kernels."
-#endif
-#define ASC_LINUX_KERNEL22 (LINUX_VERSION_CODE < ASC_LINUX_VERSION(2,4,0))
-#define ASC_LINUX_KERNEL24 (LINUX_VERSION_CODE >= ASC_LINUX_VERSION(2,4,0))
 
 /*
  * Scsi_Host_Template function prototypes.
diff -Nru a/drivers/scsi/aic7xxx/Kconfig.aic79xx b/drivers/scsi/aic7xxx/Kconfig.aic79xx
--- a/drivers/scsi/aic7xxx/Kconfig.aic79xx	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/aic7xxx/Kconfig.aic79xx	2004-08-04 17:57:40 -07:00
@@ -46,7 +46,7 @@
 
 config AIC79XX_BUILD_FIRMWARE
 	bool "Build Adapter Firmware with Kernel Build"
-	depends on SCSI_AIC79XX
+	depends on SCSI_AIC79XX && !PREVENT_FIRMWARE_BUILD
 	help
 	This option should only be enabled if you are modifying the firmware
 	source to the aic79xx driver and wish to have the generated firmware
diff -Nru a/drivers/scsi/aic7xxx/Kconfig.aic7xxx b/drivers/scsi/aic7xxx/Kconfig.aic7xxx
--- a/drivers/scsi/aic7xxx/Kconfig.aic7xxx	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/aic7xxx/Kconfig.aic7xxx	2004-08-04 17:57:40 -07:00
@@ -61,7 +61,7 @@
 
 config AIC7XXX_BUILD_FIRMWARE
 	bool "Build Adapter Firmware with Kernel Build"
-	depends on SCSI_AIC7XXX
+	depends on SCSI_AIC7XXX && !PREVENT_FIRMWARE_BUILD
 	help
 	This option should only be enabled if you are modifying the firmware
 	source to the aic7xxx driver and wish to have the generated firmware
diff -Nru a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c
--- a/drivers/scsi/aic7xxx/aic79xx_osm.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.c	2004-08-04 17:57:40 -07:00
@@ -415,7 +415,6 @@
 /*
  * Module information and settable options.
  */
-#ifdef MODULE
 static char *aic79xx = NULL;
 /*
  * Just in case someone uses commas to separate items on the insmod
@@ -426,9 +425,8 @@
 
 MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
 MODULE_DESCRIPTION("Adaptec Aic790X U320 SCSI Host Bus Adapter driver");
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual BSD/GPL");
-#endif
+MODULE_VERSION(AIC79XX_DRIVER_VERSION);
 MODULE_PARM(aic79xx, "s");
 MODULE_PARM_DESC(aic79xx,
 "period delimited, options string.\n"
@@ -463,7 +461,6 @@
 "		Change Read Streaming for Controller's 2 and 3\n"
 "\n"
 "	options aic79xx 'aic79xx=rd_strm:{..0xFFF0.0xC0F0}'");
-#endif
 
 static void ahd_linux_handle_scsi_status(struct ahd_softc *,
 					 struct ahd_linux_device *,
diff -Nru a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c	2004-08-04 17:57:40 -07:00
@@ -452,8 +452,10 @@
 	 * or read prefetching could be initiated by the
 	 * CPU or host bridge.  Our device does not support
 	 * either, so look for data corruption and/or flaged
-	 * PCI errors.
+	 * PCI errors.  First pause without causing another
+	 * chip reset.
 	 */
+	hcntrl &= ~CHIPRST;
 	ahd_outb(ahd, HCNTRL, hcntrl|PAUSE);
 	while (ahd_is_paused(ahd) == 0)
 		;
diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.c	2004-08-04 17:57:39 -07:00
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c	2004-08-04 17:57:39 -07:00
@@ -436,7 +436,6 @@
 /*
  * Module information and settable options.
  */
-#ifdef MODULE
 static char *aic7xxx = NULL;
 /*
  * Just in case someone uses commas to separate items on the insmod
@@ -447,9 +446,8 @@
 
 MODULE_AUTHOR("Maintainer: Justin T. Gibbs <gibbs@scsiguy.com>");
 MODULE_DESCRIPTION("Adaptec Aic77XX/78XX SCSI Host Bus Adapter driver");
-#ifdef MODULE_LICENSE
 MODULE_LICENSE("Dual BSD/GPL");
-#endif
+MODULE_VERSION(AIC7XXX_DRIVER_VERSION);
 MODULE_PARM(aic7xxx, "s");
 MODULE_PARM_DESC(aic7xxx,
 "period delimited, options string.\n"
@@ -479,7 +477,6 @@
 "\n"
 "	options aic7xxx 'aic7xxx=probe_eisa_vl.tag_info:{{}.{.10}}.seltime:1'\n"
 );
-#endif
 
 static void ahc_linux_handle_scsi_status(struct ahc_softc *,
 					 struct ahc_linux_device *,
diff -Nru a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c	2004-08-04 17:57:39 -07:00
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c	2004-08-04 17:57:39 -07:00
@@ -1284,8 +1284,10 @@
 	 * or read prefetching could be initiated by the
 	 * CPU or host bridge.  Our device does not support
 	 * either, so look for data corruption and/or flagged
-	 * PCI errors.
+	 * PCI errors.  First pause without causing another
+	 * chip reset.
 	 */
+	hcntrl &= ~CHIPRST;
 	ahc_outb(ahc, HCNTRL, hcntrl|PAUSE);
 	while (ahc_is_paused(ahc) == 0)
 		;
diff -Nru a/drivers/scsi/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile
--- a/drivers/scsi/aic7xxx/aicasm/Makefile	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/aic7xxx/aicasm/Makefile	2004-08-04 17:57:40 -07:00
@@ -34,10 +34,14 @@
 	$(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) $(LIBS)
 
 aicdb.h:
-	@if [ -e "/usr/include/db3/db_185.h" ]; then		\
+	@if [ -e "/usr/include/db4/db_185.h" ]; then		\
+		echo "#include <db4/db_185.h>" > aicdb.h;	\
+	 elif [ -e "/usr/include/db3/db_185.h" ]; then		\
 		echo "#include <db3/db_185.h>" > aicdb.h;	\
 	 elif [ -e "/usr/include/db2/db_185.h" ]; then		\
 		echo "#include <db2/db_185.h>" > aicdb.h;	\
+	 elif [ -e "/usr/include/db1/db_185.h" ]; then		\
+		echo "#include <db1/db_185.h>" > aicdb.h;	\
 	 elif [ -e "/usr/include/db/db_185.h" ]; then		\
 		echo "#include <db/db_185.h>" > aicdb.h;	\
 	 elif [ -e "/usr/include/db_185.h" ]; then		\
diff -Nru a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c
--- a/drivers/scsi/aic7xxx_old.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/aic7xxx_old.c	2004-08-04 17:57:40 -07:00
@@ -11139,6 +11139,7 @@
 #include "aic7xxx_old/aic7xxx_proc.c"
 
 MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(AIC7XXX_H_VERSION);
 
 
 static Scsi_Host_Template driver_template = {
diff -Nru a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
--- a/drivers/scsi/dc395x.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/dc395x.c	2004-08-04 17:57:40 -07:00
@@ -376,6 +376,8 @@
 static void reselect(struct AdapterCtlBlk *acb);
 static u8 start_scsi(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
 		struct ScsiReqBlk *srb);
+static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
+		struct ScsiReqBlk *srb);
 static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb,
 		struct ScsiReqBlk *srb);
 static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_code,
@@ -384,13 +386,11 @@
 static void pci_unmap_srb(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb);
 static void pci_unmap_srb_sense(struct AdapterCtlBlk *acb,
 		struct ScsiReqBlk *srb);
-static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
-		struct ScsiReqBlk *srb);
 static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
 		struct ScsiReqBlk *srb);
 static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb,
 		struct ScsiReqBlk *srb);
-static inline void set_xfer_rate(struct AdapterCtlBlk *acb,
+static void set_xfer_rate(struct AdapterCtlBlk *acb,
 		struct DeviceCtlBlk *dcb);
 static void waiting_timeout(unsigned long ptr);
 
@@ -1676,6 +1676,23 @@
 }
 
 
+#define DC395x_ENABLE_MSGOUT \
+ DC395x_write16 (acb, TRM_S1040_SCSI_CONTROL, DO_SETATN); \
+ srb->state |= SRB_MSGOUT
+
+
+/* abort command */
+static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
+		struct ScsiReqBlk *srb)
+{
+	srb->msgout_buf[0] = ABORT;
+	srb->msg_count = 1;
+	DC395x_ENABLE_MSGOUT;
+	srb->state &= ~SRB_MSGIN;
+	srb->state |= SRB_MSGOUT;
+}
+
+
 /**
  * dc395x_handle_interrupt - Handle an interrupt that has been confirmed to
  *                           have been triggered for this card.
@@ -2583,11 +2600,6 @@
 	return 1;
 }
 
-#define DC395x_ENABLE_MSGOUT \
- DC395x_write16 (acb, TRM_S1040_SCSI_CONTROL, DO_SETATN); \
- srb->state |= SRB_MSGOUT
-
-
 /* reject_msg */
 static inline void msgin_reject(struct AdapterCtlBlk *acb,
 		struct ScsiReqBlk *srb)
@@ -2600,18 +2612,6 @@
 	dprintkl(KERN_INFO, "msgin_reject: 0x%02x <%02i-%i>\n",
 		srb->msgin_buf[0],
 		srb->dcb->target_id, srb->dcb->target_lun);
-}
-
-
-/* abort command */
-static inline void enable_msgout_abort(struct AdapterCtlBlk *acb,
-		struct ScsiReqBlk *srb)
-{
-	srb->msgout_buf[0] = ABORT;
-	srb->msg_count = 1;
-	DC395x_ENABLE_MSGOUT;
-	srb->state &= ~SRB_MSGIN;
-	srb->state |= SRB_MSGOUT;
 }
 
 
diff -Nru a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c
--- a/drivers/scsi/eata_pio.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/eata_pio.c	2004-08-04 17:57:40 -07:00
@@ -511,8 +511,7 @@
 	HD(cmd)->state = RESET;
 
 	spin_unlock_irq(host->host_lock);
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(3 * HZ);
+	msleep(3000);
 	spin_lock_irq(host->host_lock);
 
 	DBG(DBG_ABNORM, printk(KERN_WARNING "eata_pio_reset: interrupts disabled, " "loops %d.\n", limit));
diff -Nru a/drivers/scsi/ibmvscsi/Makefile b/drivers/scsi/ibmvscsi/Makefile
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/ibmvscsi/Makefile	2004-08-04 17:57:40 -07:00
@@ -0,0 +1,5 @@
+obj-$(CONFIG_SCSI_IBMVSCSI)	+= ibmvscsic.o
+
+ibmvscsic-y			+= ibmvscsi.o
+ibmvscsic-$(CONFIG_PPC_ISERIES)	+= iseries_vscsi.o 
+ibmvscsic-$(CONFIG_PPC_PSERIES)	+= rpa_vscsi.o 
diff -Nru a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c	2004-08-04 17:57:40 -07:00
@@ -0,0 +1,1393 @@
+/* ------------------------------------------------------------
+ * ibmvscsi.c
+ * (C) Copyright IBM Corporation 1994, 2004
+ * Authors: Colin DeVilbiss (devilbis@us.ibm.com)
+ *          Santiago Leon (santil@us.ibm.com)
+ *          Dave Boutcher (sleddog@us.ibm.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ * ------------------------------------------------------------
+ * Emulation of a SCSI host adapter for Virtual I/O devices
+ *
+ * This driver supports the SCSI adapter implemented by the IBM
+ * Power5 firmware.  That SCSI adapter is not a physical adapter,
+ * but allows Linux SCSI peripheral drivers to directly
+ * access devices in another logical partition on the physical system.
+ *
+ * The virtual adapter(s) are present in the open firmware device
+ * tree just like real adapters.
+ *
+ * One of the capabilities provided on these systems is the ability
+ * to DMA between partitions.  The architecture states that for VSCSI,
+ * the server side is allowed to DMA to and from the client.  The client
+ * is never trusted to DMA to or from the server directly.
+ *
+ * Messages are sent between partitions on a "Command/Response Queue" 
+ * (CRQ), which is just a buffer of 16 byte entries in the receiver's 
+ * Senders cannot access the buffer directly, but send messages by
+ * making a hypervisor call and passing in the 16 bytes.  The hypervisor
+ * puts the message in the next 16 byte space in round-robbin fashion,
+ * turns on the high order bit of the message (the valid bit), and 
+ * generates an interrupt to the receiver (if interrupts are turned on.) 
+ * The receiver just turns off the valid bit when they have copied out
+ * the message.
+ *
+ * The VSCSI client builds a SCSI Remote Protocol (SRP) Information Unit
+ * (IU) (as defined in the T10 standard available at www.t10.org), gets 
+ * a DMA address for the message, and sends it to the server as the
+ * payload of a CRQ message.  The server DMAs the SRP IU and processes it,
+ * including doing any additional data transfers.  When it is done, it
+ * DMAs the SRP response back to the same address as the request came from,
+ * and sends a CRQ message back to inform the client that the request has
+ * completed.
+ *
+ * Note that some of the underlying infrastructure is different between
+ * machines conforming to the "RS/6000 Platform Architecture" (RPA) and
+ * the older iSeries hypervisor models.  To support both, some low level
+ * routines have been broken out into rpa_vscsi.c and iseries_vscsi.c.
+ * The Makefile should pick one, not two, not zero, of these.
+ *
+ * TODO: This is currently pretty tied to the IBM i/pSeries hypervisor
+ * interfaces.  It would be really nice to abstract this above an RDMA
+ * layer.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/dma-mapping.h>
+#include <asm/vio.h>
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include "ibmvscsi.h"
+
+/* The values below are somewhat arbitrary default values, but 
+ * OS/400 will use 3 busses (disks, CDs, tapes, I think.)
+ * Note that there are 3 bits of channel value, 6 bits of id, and
+ * 5 bits of LUN.
+ */
+static int max_id = 64;
+static int max_channel = 3;
+static int init_timeout = 5;
+static int max_requests = 50;
+
+#define IBMVSCSI_VERSION "1.5.1"
+
+MODULE_DESCRIPTION("IBM Virtual SCSI");
+MODULE_AUTHOR("Dave Boutcher");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(IBMVSCSI_VERSION);
+
+module_param_named(max_id, max_id, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_id, "Largest ID value for each channel");
+module_param_named(max_channel, max_channel, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_channel, "Largest channel value");
+module_param_named(init_timeout, init_timeout, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(init_timeout, "Initialization timeout in seconds");
+module_param_named(max_requests, max_requests, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(max_requests, "Maximum requests for this adapter");
+
+/* ------------------------------------------------------------
+ * Routines for the event pool and event structs
+ */
+/**
+ * initialize_event_pool: - Allocates and initializes the event pool for a host
+ * @pool:	event_pool to be initialized
+ * @size:	Number of events in pool
+ * @hostdata:	ibmvscsi_host_data who owns the event pool
+ *
+ * Returns zero on success.
+*/
+static int initialize_event_pool(struct event_pool *pool,
+				 int size, struct ibmvscsi_host_data *hostdata)
+{
+	int i;
+
+	pool->size = size;
+	pool->next = 0;
+	pool->events = kmalloc(pool->size * sizeof(*pool->events), GFP_KERNEL);
+	if (!pool->events)
+		return -ENOMEM;
+	memset(pool->events, 0x00, pool->size * sizeof(*pool->events));
+
+	pool->iu_storage =
+	    dma_alloc_coherent(hostdata->dev,
+			       pool->size * sizeof(*pool->iu_storage),
+			       &pool->iu_token, 0);
+	if (!pool->iu_storage) {
+		kfree(pool->events);
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < pool->size; ++i) {
+		struct srp_event_struct *evt = &pool->events[i];
+		memset(&evt->crq, 0x00, sizeof(evt->crq));
+		atomic_set(&evt->free, 1);
+		evt->crq.valid = 0x80;
+		evt->crq.IU_length = sizeof(*evt->xfer_iu);
+		evt->crq.IU_data_ptr = pool->iu_token + 
+			sizeof(*evt->xfer_iu) * i;
+		evt->xfer_iu = pool->iu_storage + i;
+		evt->hostdata = hostdata;
+	}
+
+	return 0;
+}
+
+/**
+ * release_event_pool: - Frees memory of an event pool of a host
+ * @pool:	event_pool to be released
+ * @hostdata:	ibmvscsi_host_data who owns the even pool
+ *
+ * Returns zero on success.
+*/
+static void release_event_pool(struct event_pool *pool,
+			       struct ibmvscsi_host_data *hostdata)
+{
+	int i, in_use = 0;
+	for (i = 0; i < pool->size; ++i)
+		if (atomic_read(&pool->events[i].free) != 1)
+			++in_use;
+	if (in_use)
+		printk(KERN_WARNING
+		       "ibmvscsi: releasing event pool with %d "
+		       "events still in use?\n", in_use);
+	kfree(pool->events);
+	dma_free_coherent(hostdata->dev,
+			  pool->size * sizeof(*pool->iu_storage),
+			  pool->iu_storage, pool->iu_token);
+}
+
+/**
+ * valid_event_struct: - Determines if event is valid.
+ * @pool:	event_pool that contains the event
+ * @evt:	srp_event_struct to be checked for validity
+ *
+ * Returns zero if event is invalid, one otherwise.
+*/
+static int valid_event_struct(struct event_pool *pool,
+				struct srp_event_struct *evt)
+{
+	int index = evt - pool->events;
+	if (index < 0 || index >= pool->size)	/* outside of bounds */
+		return 0;
+	if (evt != pool->events + index)	/* unaligned */
+		return 0;
+	return 1;
+}
+
+/**
+ * ibmvscsi_free-event_struct: - Changes status of event to "free"
+ * @pool:	event_pool that contains the event
+ * @evt:	srp_event_struct to be modified
+ *
+*/
+static void free_event_struct(struct event_pool *pool,
+				       struct srp_event_struct *evt)
+{
+	if (!valid_event_struct(pool, evt)) {
+		printk(KERN_ERR
+		       "ibmvscsi: Freeing invalid event_struct %p "
+		       "(not in pool %p)\n", evt, pool->events);
+		return;
+	}
+	if (atomic_inc_return(&evt->free) != 1) {
+		printk(KERN_ERR
+		       "ibmvscsi: Freeing event_struct %p "
+		       "which is not in use!\n", evt);
+		return;
+	}
+}
+
+/**
+ * get_evt_struct: - Gets the next free event in pool
+ * @pool:	event_pool that contains the events to be searched
+ *
+ * Returns the next event in "free" state, and NULL if none are free.
+ * Note that no synchronization is done here, we assume the host_lock
+ * will syncrhonze things.
+*/
+static struct srp_event_struct *get_event_struct(struct event_pool *pool)
+{
+	int i;
+	int poolsize = pool->size;
+	int offset = pool->next;
+
+	for (i = 0; i < poolsize; i++) {
+		offset = (offset + 1) % poolsize;
+		if (!atomic_dec_if_positive(&pool->events[offset].free)) {
+			pool->next = offset;
+			return &pool->events[offset];
+		}
+	}
+
+	printk(KERN_ERR "ibmvscsi: found no event struct in pool!\n");
+	return NULL;
+}
+
+/**
+ * init_event_struct: Initialize fields in an event struct that are always 
+ *                    required.
+ * @evt:        The event
+ * @done:       Routine to call when the event is responded to
+ * @format:     SRP or MAD format
+ * @timeout:    timeout value set in the CRQ
+ */
+static void init_event_struct(struct srp_event_struct *evt_struct,
+			      void (*done) (struct srp_event_struct *),
+			      u8 format,
+			      int timeout)
+{
+	evt_struct->cmnd = NULL;
+	evt_struct->cmnd_done = NULL;
+	evt_struct->crq.format = format;
+	evt_struct->crq.timeout = timeout;
+	evt_struct->done = done;
+}
+
+/* ------------------------------------------------------------
+ * Routines for receiving SCSI responses from the hosting partition
+ */
+
+/**
+ * set_srp_direction: Set the fields in the srp related to data
+ *     direction and number of buffers based on the direction in
+ *     the scsi_cmnd and the number of buffers
+ */
+static void set_srp_direction(struct scsi_cmnd *cmd,
+			      struct srp_cmd *srp_cmd, 
+			      int numbuf)
+{
+	if (numbuf == 0)
+		return;
+	
+	if (numbuf == 1) {
+		if (cmd->sc_data_direction == DMA_TO_DEVICE)
+			srp_cmd->data_out_format = SRP_DIRECT_BUFFER;
+		else 
+			srp_cmd->data_in_format = SRP_DIRECT_BUFFER;
+	} else {
+		if (cmd->sc_data_direction == DMA_TO_DEVICE) {
+			srp_cmd->data_out_format = SRP_INDIRECT_BUFFER;
+			srp_cmd->data_out_count = numbuf;
+		} else {
+			srp_cmd->data_in_format = SRP_INDIRECT_BUFFER;
+			srp_cmd->data_in_count = numbuf;
+		}
+	}
+}
+
+/**
+ * unmap_cmd_data: - Unmap data pointed in srp_cmd based on the format
+ * @cmd:	srp_cmd whose additional_data member will be unmapped
+ * @dev:	device for which the memory is mapped
+ *
+*/
+static void unmap_cmd_data(struct srp_cmd *cmd, struct device *dev)
+{
+	int i;
+
+	if ((cmd->data_out_format == SRP_NO_BUFFER) &&
+	    (cmd->data_in_format == SRP_NO_BUFFER))
+		return;
+	else if ((cmd->data_out_format == SRP_DIRECT_BUFFER) ||
+		 (cmd->data_in_format == SRP_DIRECT_BUFFER)) {
+		struct memory_descriptor *data =
+			(struct memory_descriptor *)cmd->additional_data;
+		dma_unmap_single(dev, data->virtual_address, data->length,
+				 DMA_BIDIRECTIONAL);
+	} else {
+		struct indirect_descriptor *indirect =
+			(struct indirect_descriptor *)cmd->additional_data;
+		int num_mapped = indirect->head.length / 
+			sizeof(indirect->list[0]);
+		for (i = 0; i < num_mapped; ++i) {
+			struct memory_descriptor *data = &indirect->list[i];
+			dma_unmap_single(dev,
+					 data->virtual_address,
+					 data->length, DMA_BIDIRECTIONAL);
+		}
+	}
+}
+
+/**
+ * map_sg_data: - Maps dma for a scatterlist and initializes decriptor fields
+ * @cmd:	Scsi_Cmnd with the scatterlist
+ * @srp_cmd:	srp_cmd that contains the memory descriptor
+ * @dev:	device for which to map dma memory
+ *
+ * Called by map_data_for_srp_cmd() when building srp cmd from scsi cmd.
+ * Returns 1 on success.
+*/
+static int map_sg_data(struct scsi_cmnd *cmd,
+		       struct srp_cmd *srp_cmd, struct device *dev)
+{
+
+	int i, sg_mapped;
+	u64 total_length = 0;
+	struct scatterlist *sg = cmd->request_buffer;
+	struct memory_descriptor *data =
+	    (struct memory_descriptor *)srp_cmd->additional_data;
+	struct indirect_descriptor *indirect =
+	    (struct indirect_descriptor *)data;
+
+	sg_mapped = dma_map_sg(dev, sg, cmd->use_sg, DMA_BIDIRECTIONAL);
+
+	if (sg_mapped == 0)
+		return 0;
+
+	set_srp_direction(cmd, srp_cmd, sg_mapped);
+
+	/* special case; we can use a single direct descriptor */
+	if (sg_mapped == 1) {
+		data->virtual_address = sg_dma_address(&sg[0]);
+		data->length = sg_dma_len(&sg[0]);
+		data->memory_handle = 0;
+		return 1;
+	}
+
+	if (sg_mapped > MAX_INDIRECT_BUFS) {
+		printk(KERN_ERR
+		       "ibmvscsi: More than %d mapped sg entries, got %d\n",
+		       MAX_INDIRECT_BUFS, sg_mapped);
+		return 0;
+	}
+
+	indirect->head.virtual_address = 0;
+	indirect->head.length = sg_mapped * sizeof(indirect->list[0]);
+	indirect->head.memory_handle = 0;
+	for (i = 0; i < sg_mapped; ++i) {
+		struct memory_descriptor *descr = &indirect->list[i];
+		struct scatterlist *sg_entry = &sg[i];
+		descr->virtual_address = sg_dma_address(sg_entry);
+		descr->length = sg_dma_len(sg_entry);
+		descr->memory_handle = 0;
+		total_length += sg_dma_len(sg_entry);
+	}
+	indirect->total_length = total_length;
+
+	return 1;
+}
+
+/**
+ * map_single_data: - Maps memory and initializes memory decriptor fields
+ * @cmd:	struct scsi_cmnd with the memory to be mapped
+ * @srp_cmd:	srp_cmd that contains the memory descriptor
+ * @dev:	device for which to map dma memory
+ *
+ * Called by map_data_for_srp_cmd() when building srp cmd from scsi cmd.
+ * Returns 1 on success.
+*/
+static int map_single_data(struct scsi_cmnd *cmd,
+			   struct srp_cmd *srp_cmd, struct device *dev)
+{
+	struct memory_descriptor *data =
+	    (struct memory_descriptor *)srp_cmd->additional_data;
+
+	data->virtual_address =
+		dma_map_single(dev, cmd->request_buffer,
+			       cmd->request_bufflen,
+			       DMA_BIDIRECTIONAL);
+	if (dma_mapping_error(data->virtual_address)) {
+		printk(KERN_ERR
+		       "ibmvscsi: Unable to map request_buffer for command!\n");
+		return 0;
+	}
+	data->length = cmd->request_bufflen;
+	data->memory_handle = 0;
+
+	set_srp_direction(cmd, srp_cmd, 1);
+
+	return 1;
+}
+
+/**
+ * map_data_for_srp_cmd: - Calls functions to map data for srp cmds
+ * @cmd:	struct scsi_cmnd with the memory to be mapped
+ * @srp_cmd:	srp_cmd that contains the memory descriptor
+ * @dev:	dma device for which to map dma memory
+ *
+ * Called by scsi_cmd_to_srp_cmd() when converting scsi cmds to srp cmds 
+ * Returns 1 on success.
+*/
+static int map_data_for_srp_cmd(struct scsi_cmnd *cmd,
+				struct srp_cmd *srp_cmd, struct device *dev)
+{
+	switch (cmd->sc_data_direction) {
+	case DMA_FROM_DEVICE:
+	case DMA_TO_DEVICE:
+		break;
+	case DMA_NONE:
+		return 1;
+	case DMA_BIDIRECTIONAL:
+		printk(KERN_ERR
+		       "ibmvscsi: Can't map DMA_BIDIRECTIONAL to read/write\n");
+		return 0;
+	default:
+		printk(KERN_ERR
+		       "ibmvscsi: Unknown data direction 0x%02x; can't map!\n",
+		       cmd->sc_data_direction);
+		return 0;
+	}
+
+	if (!cmd->request_buffer)
+		return 1;
+	if (cmd->use_sg)
+		return map_sg_data(cmd, srp_cmd, dev);
+	return map_single_data(cmd, srp_cmd, dev);
+}
+
+/* ------------------------------------------------------------
+ * Routines for sending and receiving SRPs
+ */
+/**
+ * ibmvscsi_send_srp_event: - Transforms event to u64 array and calls send_crq()
+ * @evt_struct:	evt_struct to be sent
+ * @hostdata:	ibmvscsi_host_data of host
+ *
+ * Returns the value returned from ibmvscsi_send_crq(). (Zero for success)
+ * Note that this routine assumes that host_lock is held for synchronization
+*/
+static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct,
+				   struct ibmvscsi_host_data *hostdata)
+{
+	struct scsi_cmnd *cmnd = evt_struct->cmnd;
+	u64 *crq_as_u64 = (u64 *) &evt_struct->crq;
+	int rc;
+
+	/* If we have exhausted our request limit, just fail this request.
+	 * Note that there are rare cases involving driver generated requests 
+	 * (such as task management requests) that the mid layer may think we
+	 * can handle more requests (can_queue) when we actually can't
+	 */
+	if ((evt_struct->crq.format == VIOSRP_SRP_FORMAT) &&
+	    (atomic_dec_if_positive(&hostdata->request_limit) < 0)) {
+		/* See if the adapter is disabled */
+		if (atomic_read(&hostdata->request_limit) < 0) {
+			if (cmnd)
+				cmnd->result = DID_ERROR << 16;
+			if (evt_struct->cmnd_done)
+				evt_struct->cmnd_done(cmnd);
+			unmap_cmd_data(&evt_struct->iu.srp.cmd,
+				       hostdata->dev);
+			free_event_struct(&hostdata->pool, evt_struct);
+			return 0;
+		} else {
+			printk("ibmvscsi: Warning, request_limit exceeded\n");
+			unmap_cmd_data(&evt_struct->iu.srp.cmd,
+				       hostdata->dev);
+			free_event_struct(&hostdata->pool, evt_struct);
+			return SCSI_MLQUEUE_HOST_BUSY;
+		}
+	}
+
+	/* Copy the IU into the transfer area */
+	*evt_struct->xfer_iu = evt_struct->iu;
+	evt_struct->xfer_iu->srp.generic.tag = (u64)evt_struct;
+
+	/* Add this to the sent list.  We need to do this 
+	 * before we actually send 
+	 * in case it comes back REALLY fast
+	 */
+	list_add_tail(&evt_struct->list, &hostdata->sent);
+
+	if ((rc =
+	     ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) {
+		list_del(&evt_struct->list);
+
+		cmnd = evt_struct->cmnd;
+		printk(KERN_ERR "ibmvscsi: failed to send event struct rc %d\n",
+		       rc);
+		unmap_cmd_data(&evt_struct->iu.srp.cmd, hostdata->dev);
+		free_event_struct(&hostdata->pool, evt_struct);
+		if (cmnd)
+			cmnd->result = DID_ERROR << 16;
+		if (evt_struct->cmnd_done)
+			evt_struct->cmnd_done(cmnd);
+	}
+
+	return 0;
+}
+
+/**
+ * handle_cmd_rsp: -  Handle responses from commands
+ * @evt_struct:	srp_event_struct to be handled
+ *
+ * Used as a callback by when sending scsi cmds.
+ * Gets called by ibmvscsi_handle_crq()
+*/
+static void handle_cmd_rsp(struct srp_event_struct *evt_struct)
+{
+	struct srp_rsp *rsp = &evt_struct->xfer_iu->srp.rsp;
+	struct scsi_cmnd *cmnd = evt_struct->cmnd;
+
+	if (cmnd) {
+		cmnd->result = rsp->status;
+		if (((cmnd->result >> 1) & 0x1f) == CHECK_CONDITION)
+			memcpy(cmnd->sense_buffer,
+			       rsp->sense_and_response_data,
+			       rsp->sense_data_list_length);
+		unmap_cmd_data(&evt_struct->iu.srp.cmd, 
+			       evt_struct->hostdata->dev);
+
+		if (rsp->doover)
+			cmnd->resid = rsp->data_out_residual_count;
+		else if (rsp->diover)
+			cmnd->resid = rsp->data_in_residual_count;
+	}
+
+	if (evt_struct->cmnd_done)
+		evt_struct->cmnd_done(cmnd);
+}
+
+/**
+ * lun_from_dev: - Returns the lun of the scsi device
+ * @dev:	struct scsi_device
+ *
+*/
+static inline u16 lun_from_dev(struct scsi_device *dev)
+{
+	return (0x2 << 14) | (dev->id << 8) | (dev->channel << 5) | dev->lun;
+}
+
+/**
+ * ibmvscsi_queue: - The queuecommand function of the scsi template 
+ * @cmd:	struct scsi_cmnd to be executed
+ * @done:	Callback function to be called when cmd is completed
+*/
+static int ibmvscsi_queuecommand(struct scsi_cmnd *cmnd,
+				 void (*done) (struct scsi_cmnd *))
+{
+	struct srp_cmd *srp_cmd;
+	struct srp_event_struct *evt_struct;
+	struct ibmvscsi_host_data *hostdata =
+		(struct ibmvscsi_host_data *)&cmnd->device->host->hostdata;
+	u16 lun = lun_from_dev(cmnd->device);
+
+	evt_struct = get_event_struct(&hostdata->pool);
+	if (!evt_struct)
+		return SCSI_MLQUEUE_HOST_BUSY;
+
+	init_event_struct(evt_struct,
+			  handle_cmd_rsp,
+			  VIOSRP_SRP_FORMAT,
+			  cmnd->timeout);
+
+	evt_struct->cmnd = cmnd;
+	evt_struct->cmnd_done = done;
+
+	/* Set up the actual SRP IU */
+	srp_cmd = &evt_struct->iu.srp.cmd;
+	memset(srp_cmd, 0x00, sizeof(*srp_cmd));
+	srp_cmd->type = SRP_CMD_TYPE;
+	memcpy(srp_cmd->cdb, cmnd->cmnd, sizeof(cmnd->cmnd));
+	srp_cmd->lun = ((u64) lun) << 48;
+
+	if (!map_data_for_srp_cmd(cmnd, srp_cmd, hostdata->dev)) {
+		printk(KERN_ERR "ibmvscsi: couldn't convert cmd to srp_cmd\n");
+		free_event_struct(&hostdata->pool, evt_struct);
+		return SCSI_MLQUEUE_HOST_BUSY;
+	}
+
+	/* Fix up dma address of the buffer itself */
+	if ((srp_cmd->data_out_format == SRP_INDIRECT_BUFFER) ||
+	    (srp_cmd->data_in_format == SRP_INDIRECT_BUFFER)) {
+		struct indirect_descriptor *indirect =
+		    (struct indirect_descriptor *)srp_cmd->additional_data;
+		indirect->head.virtual_address = evt_struct->crq.IU_data_ptr +
+		    offsetof(struct srp_cmd, additional_data) +
+		    offsetof(struct indirect_descriptor, list);
+	}
+
+	return ibmvscsi_send_srp_event(evt_struct, hostdata);
+}
+
+/* ------------------------------------------------------------
+ * Routines for driver initialization
+ */
+/**
+ * adapter_info_rsp: - Handle response to MAD adapter info request
+ * @evt_struct:	srp_event_struct with the response
+ *
+ * Used as a "done" callback by when sending adapter_info. Gets called
+ * by ibmvscsi_handle_crq()
+*/
+static void adapter_info_rsp(struct srp_event_struct *evt_struct)
+{
+	struct ibmvscsi_host_data *hostdata = evt_struct->hostdata;
+	dma_unmap_single(hostdata->dev,
+			 evt_struct->iu.mad.adapter_info.buffer,
+			 evt_struct->iu.mad.adapter_info.common.length,
+			 DMA_BIDIRECTIONAL);
+
+	if (evt_struct->xfer_iu->mad.adapter_info.common.status) {
+		printk("ibmvscsi: error %d getting adapter info\n",
+		       evt_struct->xfer_iu->mad.adapter_info.common.status);
+	} else {
+		printk("ibmvscsi: host srp version: %s, "
+		       "host partition %s (%d), OS %d\n",
+		       hostdata->madapter_info.srp_version,
+		       hostdata->madapter_info.partition_name,
+		       hostdata->madapter_info.partition_number,
+		       hostdata->madapter_info.os_type);
+	}
+}
+
+/**
+ * send_mad_adapter_info: - Sends the mad adapter info request
+ *      and stores the result so it can be retrieved with
+ *      sysfs.  We COULD consider causing a failure if the
+ *      returned SRP version doesn't match ours.
+ * @hostdata:	ibmvscsi_host_data of host
+ * 
+ * Returns zero if successful.
+*/
+static void send_mad_adapter_info(struct ibmvscsi_host_data *hostdata)
+{
+	struct viosrp_adapter_info *req;
+	struct srp_event_struct *evt_struct;
+	
+	memset(&hostdata->madapter_info, 0x00, sizeof(hostdata->madapter_info));
+	
+	evt_struct = get_event_struct(&hostdata->pool);
+	if (!evt_struct) {
+		printk(KERN_ERR "ibmvscsi: couldn't allocate an event "
+		       "for ADAPTER_INFO_REQ!\n");
+		return;
+	}
+
+	init_event_struct(evt_struct,
+			  adapter_info_rsp,
+			  VIOSRP_MAD_FORMAT,
+			  init_timeout * HZ);
+	
+	req = &evt_struct->iu.mad.adapter_info;
+	memset(req, 0x00, sizeof(*req));
+	
+	req->common.type = VIOSRP_ADAPTER_INFO_TYPE;
+	req->common.length = sizeof(hostdata->madapter_info);
+	req->buffer = dma_map_single(hostdata->dev,
+				     &hostdata->madapter_info,
+				     sizeof(hostdata->madapter_info),
+				     DMA_BIDIRECTIONAL);
+
+	if (dma_mapping_error(req->buffer)) {
+		printk(KERN_ERR
+		       "ibmvscsi: Unable to map request_buffer "
+		       "for adapter_info!\n");
+		free_event_struct(&hostdata->pool, evt_struct);
+		return;
+	}
+	
+	if (ibmvscsi_send_srp_event(evt_struct, hostdata))
+		printk(KERN_ERR "ibmvscsi: couldn't send ADAPTER_INFO_REQ!\n");
+};
+
+/**
+ * login_rsp: - Handle response to SRP login request
+ * @evt_struct:	srp_event_struct with the response
+ *
+ * Used as a "done" callback by when sending srp_login. Gets called
+ * by ibmvscsi_handle_crq()
+*/
+static void login_rsp(struct srp_event_struct *evt_struct)
+{
+	struct ibmvscsi_host_data *hostdata = evt_struct->hostdata;
+	switch (evt_struct->xfer_iu->srp.generic.type) {
+	case SRP_LOGIN_RSP_TYPE:	/* it worked! */
+		break;
+	case SRP_LOGIN_REJ_TYPE:	/* refused! */
+		printk(KERN_INFO "ibmvscsi: SRP_LOGIN_REQ rejected\n");
+		/* Login failed.  */
+		atomic_set(&hostdata->request_limit, -1);
+		return;
+	default:
+		printk(KERN_ERR
+		       "ibmvscsi: Invalid login response typecode 0x%02x!\n",
+		       evt_struct->xfer_iu->srp.generic.type);
+		/* Login failed.  */
+		atomic_set(&hostdata->request_limit, -1);
+		return;
+	}
+
+	printk(KERN_INFO "ibmvscsi: SRP_LOGIN succeeded\n");
+
+	if (evt_struct->xfer_iu->srp.login_rsp.request_limit_delta >
+	    (max_requests - 2))
+		evt_struct->xfer_iu->srp.login_rsp.request_limit_delta =
+		    max_requests - 2;
+
+	/* Now we know what the real request-limit is */
+	atomic_set(&hostdata->request_limit,
+		   evt_struct->xfer_iu->srp.login_rsp.request_limit_delta);
+
+	hostdata->host->can_queue =
+	    evt_struct->xfer_iu->srp.login_rsp.request_limit_delta - 2;
+
+	if (hostdata->host->can_queue < 1) {
+		printk(KERN_ERR "ibmvscsi: Invalid request_limit_delta\n");
+		return;
+	}
+
+	send_mad_adapter_info(hostdata);
+	return;
+}
+
+/**
+ * send_srp_login: - Sends the srp login
+ * @hostdata:	ibmvscsi_host_data of host
+ * 
+ * Returns zero if successful.
+*/
+static int send_srp_login(struct ibmvscsi_host_data *hostdata)
+{
+	int rc;
+	unsigned long flags;
+	struct srp_login_req *login;
+	struct srp_event_struct *evt_struct = get_event_struct(&hostdata->pool);
+	if (!evt_struct) {
+		printk(KERN_ERR
+		       "ibmvscsi: couldn't allocate an event for login req!\n");
+		return FAILED;
+	}
+
+	init_event_struct(evt_struct,
+			  login_rsp,
+			  VIOSRP_SRP_FORMAT,
+			  init_timeout * HZ);
+
+	login = &evt_struct->iu.srp.login_req;
+	login->type = SRP_LOGIN_REQ_TYPE;
+	login->max_requested_initiator_to_target_iulen = sizeof(union srp_iu);
+	login->required_buffer_formats = 0x0006;
+	
+	/* Start out with a request limit of 1, since this is negotiated in
+	 * the login request we are just sending
+	 */
+	atomic_set(&hostdata->request_limit, 1);
+
+	spin_lock_irqsave(hostdata->host->host_lock, flags);
+	rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
+	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+	return rc;
+};
+
+/**
+ * sync_completion: Signal that a synchronous command has completed
+ * Note that after returning from this call, the evt_struct is freed.
+ * the caller waiting on this completion shouldn't touch the evt_struct
+ * again.
+ */
+static void sync_completion(struct srp_event_struct *evt_struct)
+{
+	complete(&evt_struct->comp);
+}
+
+/**
+ * ibmvscsi_abort: Abort a command...from scsi host template
+ * send this over to the server and wait synchronously for the response
+ */
+static int ibmvscsi_eh_abort_handler(struct scsi_cmnd *cmd)
+{
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)cmd->device->host->hostdata;
+	struct srp_tsk_mgmt *tsk_mgmt;
+	struct srp_event_struct *evt;
+	struct srp_event_struct *tmp_evt, *found_evt;
+	u16 lun = lun_from_dev(cmd->device);
+
+	/* First, find this command in our sent list so we can figure
+	 * out the correct tag
+	 */
+	found_evt = NULL;
+	list_for_each_entry(tmp_evt, &hostdata->sent, list) {
+		if (tmp_evt->cmnd == cmd) {
+			found_evt = tmp_evt;
+			break;
+		}
+	}
+
+	if (!found_evt) 
+		return FAILED;
+
+	evt = get_event_struct(&hostdata->pool);
+	if (evt == NULL) {
+		printk(KERN_ERR "ibmvscsi: failed to allocate abort event\n");
+		return FAILED;
+	}
+	
+	init_event_struct(evt,
+			  sync_completion,
+			  VIOSRP_SRP_FORMAT,
+			  init_timeout * HZ);
+
+	tsk_mgmt = &evt->iu.srp.tsk_mgmt;
+	
+	/* Set up an abort SRP command */
+	memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
+	tsk_mgmt->type = SRP_TSK_MGMT_TYPE;
+	tsk_mgmt->lun = ((u64) lun) << 48;
+	tsk_mgmt->task_mgmt_flags = 0x01;	/* ABORT TASK */
+	tsk_mgmt->managed_task_tag = (u64) found_evt;
+
+	printk(KERN_INFO "ibmvscsi: aborting command. lun 0x%lx, tag 0x%lx\n",
+	       tsk_mgmt->lun, tsk_mgmt->managed_task_tag);
+
+	init_completion(&evt->comp);
+	if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
+		printk(KERN_ERR "ibmvscsi: failed to send abort() event\n");
+		return FAILED;
+	}
+
+	spin_unlock_irq(hostdata->host->host_lock);
+	wait_for_completion(&evt->comp);
+	spin_lock_irq(hostdata->host->host_lock);
+
+	/* Because we dropped the spinlock above, it's possible
+	 * The event is no longer in our list.  Make sure it didn't
+	 * complete while we were aborting
+	 */
+	found_evt = NULL;
+	list_for_each_entry(tmp_evt, &hostdata->sent, list) {
+		if (tmp_evt->cmnd == cmd) {
+			found_evt = tmp_evt;
+			break;
+		}
+	}
+
+	printk(KERN_INFO
+	       "ibmvscsi: successfully aborted task tag 0x%lx\n",
+	       tsk_mgmt->managed_task_tag);
+
+	if (found_evt == NULL)
+		return SUCCESS;
+
+	cmd->result = (DID_ABORT << 16);
+	list_del(&found_evt->list);
+	unmap_cmd_data(&found_evt->iu.srp.cmd, found_evt->hostdata->dev);
+	free_event_struct(&found_evt->hostdata->pool, found_evt);
+	atomic_inc(&hostdata->request_limit);
+	return SUCCESS;
+}
+
+/**
+ * ibmvscsi_eh_device_reset_handler: Reset a single LUN...from scsi host 
+ * template send this over to the server and wait synchronously for the 
+ * response
+ */
+static int ibmvscsi_eh_device_reset_handler(struct scsi_cmnd *cmd)
+{
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)cmd->device->host->hostdata;
+
+	struct srp_tsk_mgmt *tsk_mgmt;
+	struct srp_event_struct *evt;
+	struct srp_event_struct *tmp_evt, *pos;
+	u16 lun = lun_from_dev(cmd->device);
+
+	evt = get_event_struct(&hostdata->pool);
+	if (evt == NULL) {
+		printk(KERN_ERR "ibmvscsi: failed to allocate reset event\n");
+		return FAILED;
+	}
+	
+	init_event_struct(evt,
+			  sync_completion,
+			  VIOSRP_SRP_FORMAT,
+			  init_timeout * HZ);
+
+	tsk_mgmt = &evt->iu.srp.tsk_mgmt;
+
+	/* Set up a lun reset SRP command */
+	memset(tsk_mgmt, 0x00, sizeof(*tsk_mgmt));
+	tsk_mgmt->type = SRP_TSK_MGMT_TYPE;
+	tsk_mgmt->lun = ((u64) lun) << 48;
+	tsk_mgmt->task_mgmt_flags = 0x08;	/* LUN RESET */
+
+	printk(KERN_INFO "ibmvscsi: resetting device. lun 0x%lx\n",
+	       tsk_mgmt->lun);
+
+	init_completion(&evt->comp);
+	if (ibmvscsi_send_srp_event(evt, hostdata) != 0) {
+		printk(KERN_ERR "ibmvscsi: failed to send reset event\n");
+		return FAILED;
+	}
+
+	spin_unlock_irq(hostdata->host->host_lock);
+	wait_for_completion(&evt->comp);
+	spin_lock_irq(hostdata->host->host_lock);
+
+	/* We need to find all commands for this LUN that have not yet been
+	 * responded to, and fail them with DID_RESET
+	 */
+	list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
+		if ((tmp_evt->cmnd) && (tmp_evt->cmnd->device == cmd->device)) {
+			if (tmp_evt->cmnd)
+				tmp_evt->cmnd->result = (DID_RESET << 16);
+			list_del(&tmp_evt->list);
+			unmap_cmd_data(&tmp_evt->iu.srp.cmd, tmp_evt->hostdata->dev);
+			free_event_struct(&tmp_evt->hostdata->pool,
+						   tmp_evt);
+			atomic_inc(&hostdata->request_limit);
+			if (tmp_evt->cmnd_done)
+				tmp_evt->cmnd_done(tmp_evt->cmnd);
+			else if (tmp_evt->done)
+				tmp_evt->done(tmp_evt);
+		}
+	}
+	return SUCCESS;
+}
+
+/**
+ * purge_requests: Our virtual adapter just shut down.  purge any sent requests
+ * @hostdata:    the adapter
+ */
+static void purge_requests(struct ibmvscsi_host_data *hostdata)
+{
+	struct srp_event_struct *tmp_evt, *pos;
+	unsigned long flags;
+
+	spin_lock_irqsave(hostdata->host->host_lock, flags);
+	list_for_each_entry_safe(tmp_evt, pos, &hostdata->sent, list) {
+		list_del(&tmp_evt->list);
+		if (tmp_evt->cmnd) {
+			tmp_evt->cmnd->result = (DID_ERROR << 16);
+			unmap_cmd_data(&tmp_evt->iu.srp.cmd, 
+				       tmp_evt->hostdata->dev);
+			if (tmp_evt->cmnd_done)
+				tmp_evt->cmnd_done(tmp_evt->cmnd);
+		} else {
+			if (tmp_evt->done) {
+				tmp_evt->done(tmp_evt);
+			}
+		}
+		free_event_struct(&tmp_evt->hostdata->pool, tmp_evt);
+	}
+	spin_unlock_irqrestore(hostdata->host->host_lock, flags);
+}
+
+/**
+ * ibmvscsi_handle_crq: - Handles and frees received events in the CRQ
+ * @crq:	Command/Response queue
+ * @hostdata:	ibmvscsi_host_data of host
+ *
+*/
+void ibmvscsi_handle_crq(struct viosrp_crq *crq,
+			 struct ibmvscsi_host_data *hostdata)
+{
+	unsigned long flags;
+	struct srp_event_struct *evt_struct =
+	    (struct srp_event_struct *)crq->IU_data_ptr;
+	switch (crq->valid) {
+	case 0xC0:		/* initialization */
+		switch (crq->format) {
+		case 0x01:	/* Initialization message */
+			printk(KERN_INFO "ibmvscsi: partner initialized\n");
+			/* Send back a response */
+			if (ibmvscsi_send_crq(hostdata,
+					      0xC002000000000000LL, 0) == 0) {
+				/* Now login */
+				send_srp_login(hostdata);
+			} else {
+				printk(KERN_ERR
+				       "ibmvscsi: Unable to send init rsp\n");
+			}
+
+			break;
+		case 0x02:	/* Initialization response */
+			printk(KERN_INFO
+			       "ibmvscsi: partner initialization complete\n");
+
+			/* Now login */
+			send_srp_login(hostdata);
+			break;
+		default:
+			printk(KERN_ERR "ibmvscsi: unknown crq message type\n");
+		}
+		return;
+	case 0xFF:		/* Hypervisor telling us the connection is closed */
+		printk(KERN_INFO "ibmvscsi: Virtual adapter failed!\n");
+
+		atomic_set(&hostdata->request_limit, -1);
+		purge_requests(hostdata);
+		ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata);
+		return;
+	case 0x80:		/* real payload */
+		break;
+	default:
+		printk(KERN_ERR
+		       "ibmvscsi: got an invalid message type 0x%02x\n",
+		       crq->valid);
+		return;
+	}
+
+	/* The only kind of payload CRQs we should get are responses to
+	 * things we send. Make sure this response is to something we
+	 * actually sent
+	 */
+	if (!valid_event_struct(&hostdata->pool, evt_struct)) {
+		printk(KERN_ERR
+		       "ibmvscsi: returned correlation_token 0x%p is invalid!\n",
+		       (void *)crq->IU_data_ptr);
+		return;
+	}
+
+	if (crq->format == VIOSRP_SRP_FORMAT)
+		atomic_add(evt_struct->xfer_iu->srp.rsp.request_limit_delta,
+			   &hostdata->request_limit);
+
+	if (evt_struct->done)
+		evt_struct->done(evt_struct);
+	else
+		printk(KERN_ERR
+		       "ibmvscsi: returned done() is NULL; not running it!\n");
+
+	/*
+	 * Lock the host_lock before messing with these structures, since we
+	 * are running in a task context
+	 */
+	spin_lock_irqsave(evt_struct->hostdata->host->host_lock, flags);
+	list_del(&evt_struct->list);
+	free_event_struct(&evt_struct->hostdata->pool, evt_struct);
+	spin_unlock_irqrestore(evt_struct->hostdata->host->host_lock, flags);
+}
+
+/**
+ * ibmvscsi_get_host_config: Send the command to the server to get host
+ * configuration data.  The data is opaque to us.
+ */
+static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata,
+				   unsigned char *buffer, int length)
+{
+	struct viosrp_host_config *host_config;
+	struct srp_event_struct *evt_struct;
+	int rc;
+
+	evt_struct = get_event_struct(&hostdata->pool);
+	if (!evt_struct) {
+		printk(KERN_ERR
+		       "ibmvscsi: could't allocate event for HOST_CONFIG!\n");
+		return -1;
+	}
+
+	init_event_struct(evt_struct,
+			  sync_completion,
+			  VIOSRP_MAD_FORMAT,
+			  init_timeout * HZ);
+
+	host_config = &evt_struct->iu.mad.host_config;
+
+	/* Set up a lun reset SRP command */
+	memset(host_config, 0x00, sizeof(*host_config));
+	host_config->common.type = VIOSRP_HOST_CONFIG_TYPE;
+	host_config->common.length = length;
+	host_config->buffer = dma_map_single(hostdata->dev, buffer, length,
+					    DMA_BIDIRECTIONAL);
+
+	if (dma_mapping_error(host_config->buffer)) {
+		printk(KERN_ERR
+		       "ibmvscsi: dma_mapping error " "getting host config\n");
+		free_event_struct(&hostdata->pool, evt_struct);
+		return -1;
+	}
+
+	init_completion(&evt_struct->comp);
+	rc = ibmvscsi_send_srp_event(evt_struct, hostdata);
+	if (rc == 0) {
+		wait_for_completion(&evt_struct->comp);
+		dma_unmap_single(hostdata->dev, host_config->buffer,
+				 length, DMA_BIDIRECTIONAL);
+	}
+
+	return rc;
+}
+
+/* ------------------------------------------------------------
+ * sysfs attributes
+ */
+static ssize_t show_host_srp_version(struct class_device *class_dev, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)shost->hostdata;
+	int len;
+
+	len = snprintf(buf, PAGE_SIZE, "%s\n",
+		       hostdata->madapter_info.srp_version);
+	return len;
+}
+
+static struct class_device_attribute ibmvscsi_host_srp_version = {
+	.attr = {
+		 .name = "srp_version",
+		 .mode = S_IRUGO,
+		 },
+	.show = show_host_srp_version,
+};
+
+static ssize_t show_host_partition_name(struct class_device *class_dev,
+					char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)shost->hostdata;
+	int len;
+
+	len = snprintf(buf, PAGE_SIZE, "%s\n",
+		       hostdata->madapter_info.partition_name);
+	return len;
+}
+
+static struct class_device_attribute ibmvscsi_host_partition_name = {
+	.attr = {
+		 .name = "partition_name",
+		 .mode = S_IRUGO,
+		 },
+	.show = show_host_partition_name,
+};
+
+static ssize_t show_host_partition_number(struct class_device *class_dev,
+					  char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)shost->hostdata;
+	int len;
+
+	len = snprintf(buf, PAGE_SIZE, "%d\n",
+		       hostdata->madapter_info.partition_number);
+	return len;
+}
+
+static struct class_device_attribute ibmvscsi_host_partition_number = {
+	.attr = {
+		 .name = "partition_number",
+		 .mode = S_IRUGO,
+		 },
+	.show = show_host_partition_number,
+};
+
+static ssize_t show_host_mad_version(struct class_device *class_dev, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)shost->hostdata;
+	int len;
+
+	len = snprintf(buf, PAGE_SIZE, "%d\n",
+		       hostdata->madapter_info.mad_version);
+	return len;
+}
+
+static struct class_device_attribute ibmvscsi_host_mad_version = {
+	.attr = {
+		 .name = "mad_version",
+		 .mode = S_IRUGO,
+		 },
+	.show = show_host_mad_version,
+};
+
+static ssize_t show_host_os_type(struct class_device *class_dev, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)shost->hostdata;
+	int len;
+
+	len = snprintf(buf, PAGE_SIZE, "%d\n", hostdata->madapter_info.os_type);
+	return len;
+}
+
+static struct class_device_attribute ibmvscsi_host_os_type = {
+	.attr = {
+		 .name = "os_type",
+		 .mode = S_IRUGO,
+		 },
+	.show = show_host_os_type,
+};
+
+static ssize_t show_host_config(struct class_device *class_dev, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(class_dev);
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)shost->hostdata;
+
+	/* returns null-terminated host config data */
+	if (ibmvscsi_do_host_config(hostdata, buf, PAGE_SIZE) == 0)
+		return strlen(buf);
+	else
+		return 0;
+}
+
+static struct class_device_attribute ibmvscsi_host_config = {
+	.attr = {
+		 .name = "config",
+		 .mode = S_IRUGO,
+		 },
+	.show = show_host_config,
+};
+
+static struct class_device_attribute *ibmvscsi_attrs[] = {
+	&ibmvscsi_host_srp_version,
+	&ibmvscsi_host_partition_name,
+	&ibmvscsi_host_partition_number,
+	&ibmvscsi_host_mad_version,
+	&ibmvscsi_host_os_type,
+	&ibmvscsi_host_config,
+	NULL
+};
+
+/* ------------------------------------------------------------
+ * SCSI driver registration
+ */
+static struct scsi_host_template driver_template = {
+	.module = THIS_MODULE,
+	.name = "IBM POWER Virtual SCSI Adapter " IBMVSCSI_VERSION,
+	.proc_name = "ibmvscsi",
+	.queuecommand = ibmvscsi_queuecommand,
+	.eh_abort_handler = ibmvscsi_eh_abort_handler,
+	.eh_device_reset_handler = ibmvscsi_eh_device_reset_handler,
+	.cmd_per_lun = 16,
+	.can_queue = 1,		/* Updated after SRP_LOGIN */
+	.this_id = -1,
+	.sg_tablesize = MAX_INDIRECT_BUFS,
+	.use_clustering = ENABLE_CLUSTERING,
+	.shost_attrs = ibmvscsi_attrs,
+};
+
+/**
+ * Called by bus code for each adapter
+ */
+static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
+{
+	struct ibmvscsi_host_data *hostdata;
+	struct Scsi_Host *host;
+	struct device *dev = &vdev->dev;
+	unsigned long wait_switch = 0;
+
+	vdev->dev.driver_data = NULL;
+
+	host = scsi_host_alloc(&driver_template, sizeof(*hostdata));
+	if (!host) {
+		printk(KERN_ERR "ibmvscsi: couldn't allocate host data\n");
+		goto scsi_host_alloc_failed;
+	}
+
+	hostdata = (struct ibmvscsi_host_data *)host->hostdata;
+	memset(hostdata, 0x00, sizeof(*hostdata));
+	INIT_LIST_HEAD(&hostdata->sent);
+	hostdata->host = host;
+	hostdata->dev = dev;
+	atomic_set(&hostdata->request_limit, -1);
+
+	if (ibmvscsi_init_crq_queue(&hostdata->queue, hostdata,
+				    max_requests) != 0) {
+		printk(KERN_ERR "ibmvscsi: couldn't initialize crq\n");
+		goto init_crq_failed;
+	}
+	if (initialize_event_pool(&hostdata->pool, max_requests, hostdata) != 0) {
+		printk(KERN_ERR "ibmvscsi: couldn't initialize event pool\n");
+		goto init_pool_failed;
+	}
+
+	host->max_lun = 8;
+	host->max_id = max_id;
+	host->max_channel = max_channel;
+
+	if (scsi_add_host(hostdata->host, hostdata->dev))
+		goto add_host_failed;
+
+	/* Try to send an initialization message.  Note that this is allowed
+	 * to fail if the other end is not acive.  In that case we don't
+	 * want to scan
+	 */
+	if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0) {
+		/*
+		 * Wait around max init_timeout secs for the adapter to finish
+		 * initializing. When we are done initializing, we will have a
+		 * valid request_limit.  We don't want Linux scanning before
+		 * we are ready.
+		 */
+		for (wait_switch = jiffies + (init_timeout * HZ);
+		     time_before(jiffies, wait_switch) &&
+		     atomic_read(&hostdata->request_limit) < 0;) {
+
+			set_current_state(TASK_UNINTERRUPTIBLE);
+			schedule_timeout(HZ / 100);
+		}
+
+		/* if we now have a valid request_limit, initiate a scan */
+		if (atomic_read(&hostdata->request_limit) > 0)
+			scsi_scan_host(host);
+	}
+
+	vdev->dev.driver_data = hostdata;
+	return 0;
+
+      add_host_failed:
+	release_event_pool(&hostdata->pool, hostdata);
+      init_pool_failed:
+	ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, max_requests);
+      init_crq_failed:
+	scsi_host_put(host);
+      scsi_host_alloc_failed:
+	return -1;
+}
+
+static int ibmvscsi_remove(struct vio_dev *vdev)
+{
+	struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data;
+	release_event_pool(&hostdata->pool, hostdata);
+	ibmvscsi_release_crq_queue(&hostdata->queue, hostdata,
+				   max_requests);
+	
+	scsi_remove_host(hostdata->host);
+	scsi_host_put(hostdata->host);
+
+	return 0;
+}
+
+/**
+ * ibmvscsi_device_table: Used by vio.c to match devices in the device tree we 
+ * support.
+ */
+static struct vio_device_id ibmvscsi_device_table[] __devinitdata = {
+	{"vscsi", "IBM,v-scsi"},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(vio, ibmvscsi_device_table);
+static struct vio_driver ibmvscsi_driver = {
+	.name = "ibmvscsi",
+	.id_table = ibmvscsi_device_table,
+	.probe = ibmvscsi_probe,
+	.remove = ibmvscsi_remove
+};
+
+int __init ibmvscsi_module_init(void)
+{
+	return vio_register_driver(&ibmvscsi_driver);
+}
+
+void __exit ibmvscsi_module_exit(void)
+{
+	vio_unregister_driver(&ibmvscsi_driver);
+}
+
+module_init(ibmvscsi_module_init);
+module_exit(ibmvscsi_module_exit);
diff -Nru a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.h	2004-08-04 17:57:40 -07:00
@@ -0,0 +1,108 @@
+/* ------------------------------------------------------------
+ * ibmvscsi.h
+ * (C) Copyright IBM Corporation 1994, 2003
+ * Authors: Colin DeVilbiss (devilbis@us.ibm.com)
+ *          Santiago Leon (santil@us.ibm.com)
+ *          Dave Boutcher (sleddog@us.ibm.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ * ------------------------------------------------------------
+ * Emulation of a SCSI host adapter for Virtual I/O devices
+ *
+ * This driver allows the Linux SCSI peripheral drivers to directly
+ * access devices in the hosting partition, either on an iSeries
+ * hypervisor system or a converged hypervisor system.
+ */
+#ifndef IBMVSCSI_H
+#define IBMVSCSI_H
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include "viosrp.h"
+
+struct scsi_cmnd;
+struct Scsi_Host;
+
+/* Number of indirect bufs...the list of these has to fit in the
+ * additional data of the srp_cmd struct along with the indirect
+ * descriptor
+ */
+#define MAX_INDIRECT_BUFS 10
+
+/* ------------------------------------------------------------
+ * Data Structures
+ */
+/* an RPA command/response transport queue */
+struct crq_queue {
+	struct viosrp_crq *msgs;
+	int size, cur;
+	dma_addr_t msg_token;
+	spinlock_t lock;
+};
+
+/* a unit of work for the hosting partition */
+struct srp_event_struct {
+	union viosrp_iu *xfer_iu;
+	struct scsi_cmnd *cmnd;
+	struct list_head list;
+	void (*done) (struct srp_event_struct *);
+	struct viosrp_crq crq;
+	struct ibmvscsi_host_data *hostdata;
+	atomic_t free;
+	union viosrp_iu iu;
+	void (*cmnd_done) (struct scsi_cmnd *);
+	struct completion comp;
+};
+
+/* a pool of event structs for use */
+struct event_pool {
+	struct srp_event_struct *events;
+	u32 size;
+	int next;
+	union viosrp_iu *iu_storage;
+	dma_addr_t iu_token;
+};
+
+/* all driver data associated with a host adapter */
+struct ibmvscsi_host_data {
+	atomic_t request_limit;
+	struct device *dev;
+	struct event_pool pool;
+	struct crq_queue queue;
+	struct tasklet_struct srp_task;
+	struct list_head sent;
+	struct Scsi_Host *host;
+	struct mad_adapter_info_data madapter_info;
+};
+
+/* routines for managing a command/response queue */
+int ibmvscsi_init_crq_queue(struct crq_queue *queue,
+			    struct ibmvscsi_host_data *hostdata,
+			    int max_requests);
+void ibmvscsi_release_crq_queue(struct crq_queue *queue,
+				struct ibmvscsi_host_data *hostdata,
+				int max_requests);
+void ibmvscsi_reset_crq_queue(struct crq_queue *queue,
+			      struct ibmvscsi_host_data *hostdata);
+
+void ibmvscsi_handle_crq(struct viosrp_crq *crq,
+			 struct ibmvscsi_host_data *hostdata);
+int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata,
+		      u64 word1, u64 word2);
+
+#endif				/* IBMVSCSI_H */
diff -Nru a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c	2004-08-04 17:57:40 -07:00
@@ -0,0 +1,144 @@
+/* ------------------------------------------------------------
+ * iSeries_vscsi.c
+ * (C) Copyright IBM Corporation 1994, 2003
+ * Authors: Colin DeVilbiss (devilbis@us.ibm.com)
+ *          Santiago Leon (santil@us.ibm.com)
+ *          Dave Boutcher (sleddog@us.ibm.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ * ------------------------------------------------------------
+ * iSeries-specific functions of the SCSI host adapter for Virtual I/O devices
+ *
+ * This driver allows the Linux SCSI peripheral drivers to directly
+ * access devices in the hosting partition, either on an iSeries
+ * hypervisor system or a converged hypervisor system.
+ */
+
+#include <asm/iSeries/vio.h>
+#include <asm/iSeries/HvLpEvent.h>
+#include <asm/iSeries/HvTypes.h>
+#include <asm/iSeries/HvLpConfig.h>
+#include <asm/vio.h>
+#include <linux/device.h>
+#include "ibmvscsi.h"
+
+/* global variables */
+static struct ibmvscsi_host_data *single_host_data;
+
+/* ------------------------------------------------------------
+ * Routines for direct interpartition interaction
+ */
+struct srp_lp_event {
+	struct HvLpEvent lpevt;	/* 0x00-0x17          */
+	u32 reserved1;		/* 0x18-0x1B; unused  */
+	u16 version;		/* 0x1C-0x1D; unused  */
+	u16 subtype_rc;		/* 0x1E-0x1F; unused  */
+	struct viosrp_crq crq;	/* 0x20-0x3F          */
+};
+
+/** 
+ * standard interface for handling logical partition events.
+ */
+static void ibmvscsi_handle_event(struct HvLpEvent *lpevt)
+{
+	struct srp_lp_event *evt = (struct srp_lp_event *)lpevt;
+
+	if (!evt) {
+		printk(KERN_ERR "ibmvscsi: received null event\n");
+		return;
+	}
+
+	if (single_host_data == NULL) {
+		printk(KERN_ERR
+		       "ibmvscsi: received event, no adapter present\n");
+		return;
+	}
+
+	ibmvscsi_handle_crq(&evt->crq, single_host_data);
+}
+
+/* ------------------------------------------------------------
+ * Routines for driver initialization
+ */
+int ibmvscsi_init_crq_queue(struct crq_queue *queue,
+			    struct ibmvscsi_host_data *hostdata,
+			    int max_requests)
+{
+	int rc;
+
+	single_host_data = hostdata;
+	rc = viopath_open(viopath_hostLp, viomajorsubtype_scsi, 0);
+	if (rc < 0) {
+		printk("viopath_open failed with rc %d in open_event_path\n",
+		       rc);
+		goto viopath_open_failed;
+	}
+
+	rc = vio_setHandler(viomajorsubtype_scsi, ibmvscsi_handle_event);
+	if (rc < 0) {
+		printk("vio_setHandler failed with rc %d in open_event_path\n",
+		       rc);
+		goto vio_setHandler_failed;
+	}
+	return 0;
+
+      vio_setHandler_failed:
+	viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
+      viopath_open_failed:
+	return -1;
+}
+
+void ibmvscsi_release_crq_queue(struct crq_queue *queue,
+				struct ibmvscsi_host_data *hostdata,
+				int max_requests)
+{
+	vio_clearHandler(viomajorsubtype_scsi);
+	viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests);
+}
+
+/**
+ * reset_crq_queue: - resets a crq after a failure
+ * @queue:	crq_queue to initialize and register
+ * @hostdata:	ibmvscsi_host_data of host
+ *
+ * no-op for iSeries
+ */
+void ibmvscsi_reset_crq_queue(struct crq_queue *queue,
+			      struct ibmvscsi_host_data *hostdata)
+{
+}
+
+/**
+ * ibmvscsi_send_crq: - Send a CRQ
+ * @hostdata:	the adapter
+ * @word1:	the first 64 bits of the data
+ * @word2:	the second 64 bits of the data
+ */
+int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
+{
+	single_host_data = hostdata;
+	return HvCallEvent_signalLpEventFast(viopath_hostLp,
+					     HvLpEvent_Type_VirtualIo,
+					     viomajorsubtype_scsi,
+					     HvLpEvent_AckInd_NoAck,
+					     HvLpEvent_AckType_ImmediateAck,
+					     viopath_sourceinst(viopath_hostLp),
+					     viopath_targetinst(viopath_hostLp),
+					     0,
+					     VIOVERSION << 16, word1, word2, 0,
+					     0);
+}
diff -Nru a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c	2004-08-04 17:57:40 -07:00
@@ -0,0 +1,260 @@
+/* ------------------------------------------------------------
+ * rpa_vscsi.c
+ * (C) Copyright IBM Corporation 1994, 2003
+ * Authors: Colin DeVilbiss (devilbis@us.ibm.com)
+ *          Santiago Leon (santil@us.ibm.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
+ * USA
+ *
+ * ------------------------------------------------------------
+ * RPA-specific functions of the SCSI host adapter for Virtual I/O devices
+ *
+ * This driver allows the Linux SCSI peripheral drivers to directly
+ * access devices in the hosting partition, either on an iSeries
+ * hypervisor system or a converged hypervisor system.
+ */
+
+#include <asm/vio.h>
+#include <asm/iommu.h>
+#include <asm/hvcall.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include "ibmvscsi.h"
+
+/* ------------------------------------------------------------
+ * Routines for managing the command/response queue
+ */
+/**
+ * ibmvscsi_handle_event: - Interrupt handler for crq events
+ * @irq:	number of irq to handle, not used
+ * @dev_instance: ibmvscsi_host_data of host that received interrupt
+ * @regs:	pt_regs with registers
+ *
+ * Disables interrupts and schedules srp_task
+ * Always returns IRQ_HANDLED
+ */
+static irqreturn_t ibmvscsi_handle_event(int irq,
+					 void *dev_instance,
+					 struct pt_regs *regs)
+{
+	struct ibmvscsi_host_data *hostdata =
+	    (struct ibmvscsi_host_data *)dev_instance;
+	vio_disable_interrupts(to_vio_dev(hostdata->dev));
+	tasklet_schedule(&hostdata->srp_task);
+	return IRQ_HANDLED;
+}
+
+/**
+ * release_crq_queue: - Deallocates data and unregisters CRQ
+ * @queue:	crq_queue to initialize and register
+ * @host_data:	ibmvscsi_host_data of host
+ *
+ * Frees irq, deallocates a page for messages, unmaps dma, and unregisters
+ * the crq with the hypervisor.
+ */
+void ibmvscsi_release_crq_queue(struct crq_queue *queue,
+				struct ibmvscsi_host_data *hostdata,
+				int max_requests)
+{
+	long rc;
+	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+	free_irq(vdev->irq, (void *)hostdata);
+	tasklet_kill(&hostdata->srp_task);
+	do {
+		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
+	} while ((rc == H_Busy) || (H_isLongBusy(rc)));
+	dma_unmap_single(hostdata->dev,
+			 queue->msg_token,
+			 queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
+	free_page((unsigned long)queue->msgs);
+}
+
+/**
+ * crq_queue_next_crq: - Returns the next entry in message queue
+ * @queue:	crq_queue to use
+ *
+ * Returns pointer to next entry in queue, or NULL if there are no new 
+ * entried in the CRQ.
+ */
+static struct viosrp_crq *crq_queue_next_crq(struct crq_queue *queue)
+{
+	struct viosrp_crq *crq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&queue->lock, flags);
+	crq = &queue->msgs[queue->cur];
+	if (crq->valid & 0x80) {
+		if (++queue->cur == queue->size)
+			queue->cur = 0;
+	} else
+		crq = NULL;
+	spin_unlock_irqrestore(&queue->lock, flags);
+
+	return crq;
+}
+
+/**
+ * ibmvscsi_send_crq: - Send a CRQ
+ * @hostdata:	the adapter
+ * @word1:	the first 64 bits of the data
+ * @word2:	the second 64 bits of the data
+ */
+int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2)
+{
+	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+
+	return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, word1, word2);
+}
+
+/**
+ * ibmvscsi_task: - Process srps asynchronously
+ * @data:	ibmvscsi_host_data of host
+ */
+static void ibmvscsi_task(void *data)
+{
+	struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data;
+	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+	struct viosrp_crq *crq;
+	int done = 0;
+
+	while (!done) {
+		/* Pull all the valid messages off the CRQ */
+		while ((crq = crq_queue_next_crq(&hostdata->queue)) != NULL) {
+			ibmvscsi_handle_crq(crq, hostdata);
+			crq->valid = 0x00;
+		}
+
+		vio_enable_interrupts(vdev);
+		if ((crq = crq_queue_next_crq(&hostdata->queue)) != NULL) {
+			vio_disable_interrupts(vdev);
+			ibmvscsi_handle_crq(crq, hostdata);
+			crq->valid = 0x00;
+		} else {
+			done = 1;
+		}
+	}
+}
+
+/**
+ * initialize_crq_queue: - Initializes and registers CRQ with hypervisor
+ * @queue:	crq_queue to initialize and register
+ * @hostdata:	ibmvscsi_host_data of host
+ *
+ * Allocates a page for messages, maps it for dma, and registers
+ * the crq with the hypervisor.
+ * Returns zero on success.
+ */
+int ibmvscsi_init_crq_queue(struct crq_queue *queue,
+			    struct ibmvscsi_host_data *hostdata,
+			    int max_requests)
+{
+	int rc;
+	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+
+	queue->msgs = (struct viosrp_crq *)get_zeroed_page(GFP_KERNEL);
+
+	if (!queue->msgs)
+		goto malloc_failed;
+	queue->size = PAGE_SIZE / sizeof(*queue->msgs);
+
+	queue->msg_token = dma_map_single(hostdata->dev, queue->msgs,
+					  queue->size * sizeof(*queue->msgs),
+					  DMA_BIDIRECTIONAL);
+
+	if (dma_mapping_error(queue->msg_token))
+		goto map_failed;
+
+	rc = plpar_hcall_norets(H_REG_CRQ,
+				vdev->unit_address,
+				queue->msg_token, PAGE_SIZE);
+	if (rc == 2) {
+		/* Adapter is good, but other end is not ready */
+		printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
+	} else if (rc != 0) {
+		printk(KERN_WARNING "ibmvscsi: Error %d opening adapter\n", rc);
+		goto reg_crq_failed;
+	}
+
+	if (request_irq(vdev->irq,
+			ibmvscsi_handle_event,
+			0, "ibmvscsi", (void *)hostdata) != 0) {
+		printk(KERN_ERR "ibmvscsi: couldn't register irq 0x%x\n",
+		       vdev->irq);
+		goto req_irq_failed;
+	}
+
+	rc = vio_enable_interrupts(vdev);
+	if (rc != 0) {
+		printk(KERN_ERR "ibmvscsi:  Error %d enabling interrupts!!!\n",
+		       rc);
+		goto req_irq_failed;
+	}
+
+	queue->cur = 0;
+	queue->lock = SPIN_LOCK_UNLOCKED;
+
+	tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task,
+		     (unsigned long)hostdata);
+
+	return 0;
+
+      req_irq_failed:
+	do {
+		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
+	} while ((rc == H_Busy) || (H_isLongBusy(rc)));
+      reg_crq_failed:
+	dma_unmap_single(hostdata->dev,
+			 queue->msg_token,
+			 queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL);
+      map_failed:
+	free_page((unsigned long)queue->msgs);
+      malloc_failed:
+	return -1;
+}
+
+/**
+ * reset_crq_queue: - resets a crq after a failure
+ * @queue:	crq_queue to initialize and register
+ * @hostdata:	ibmvscsi_host_data of host
+ *
+ */
+void ibmvscsi_reset_crq_queue(struct crq_queue *queue,
+			      struct ibmvscsi_host_data *hostdata)
+{
+	int rc;
+	struct vio_dev *vdev = to_vio_dev(hostdata->dev);
+
+	/* Close the CRQ */
+	do {
+		rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
+	} while ((rc == H_Busy) || (H_isLongBusy(rc)));
+
+	/* Clean out the queue */
+	memset(queue->msgs, 0x00, PAGE_SIZE);
+	queue->cur = 0;
+
+	/* And re-open it again */
+	rc = plpar_hcall_norets(H_REG_CRQ,
+				vdev->unit_address,
+				queue->msg_token, PAGE_SIZE);
+	if (rc == 2) {
+		/* Adapter is good, but other end is not ready */
+		printk(KERN_WARNING "ibmvscsi: Partner adapter not ready\n");
+	} else if (rc != 0) {
+		printk(KERN_WARNING
+		       "ibmvscsi: couldn't register crq--rc 0x%x\n", rc);
+	}
+}
diff -Nru a/drivers/scsi/ibmvscsi/srp.h b/drivers/scsi/ibmvscsi/srp.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/ibmvscsi/srp.h	2004-08-04 17:57:40 -07:00
@@ -0,0 +1,225 @@
+/*****************************************************************************/
+/* srp.h -- SCSI RDMA Protocol definitions                                   */
+/*                                                                           */
+/* Written By: Colin Devilbis, IBM Corporation                               */
+/*                                                                           */
+/* Copyright (C) 2003 IBM Corporation                                        */
+/*                                                                           */
+/* This program is free software; you can redistribute it and/or modify      */
+/* it under the terms of the GNU General Public License as published by      */
+/* the Free Software Foundation; either version 2 of the License, or         */
+/* (at your option) any later version.                                       */
+/*                                                                           */
+/* This program is distributed in the hope that it will be useful,           */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
+/* GNU General Public License for more details.                              */
+/*                                                                           */
+/* You should have received a copy of the GNU General Public License         */
+/* along with this program; if not, write to the Free Software               */
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+/*                                                                           */
+/*                                                                           */
+/* This file contains structures and definitions for the SCSI RDMA Protocol  */
+/* (SRP) as defined in the T10 standard available at www.t10.org.  This      */
+/* file was based on the 16a version of the standard                         */
+/*                                                                           */
+/*****************************************************************************/
+#ifndef SRP_H
+#define SRP_H
+
+#define PACKED __attribute__((packed))
+
+enum srp_types {
+	SRP_LOGIN_REQ_TYPE = 0x00,
+	SRP_LOGIN_RSP_TYPE = 0xC0,
+	SRP_LOGIN_REJ_TYPE = 0x80,
+	SRP_I_LOGOUT_TYPE = 0x03,
+	SRP_T_LOGOUT_TYPE = 0x80,
+	SRP_TSK_MGMT_TYPE = 0x01,
+	SRP_CMD_TYPE = 0x02,
+	SRP_RSP_TYPE = 0xC1,
+	SRP_CRED_REQ_TYPE = 0x81,
+	SRP_CRED_RSP_TYPE = 0x41,
+	SRP_AER_REQ_TYPE = 0x82,
+	SRP_AER_RSP_TYPE = 0x42
+};
+
+enum srp_descriptor_formats {
+	SRP_NO_BUFFER = 0x00,
+	SRP_DIRECT_BUFFER = 0x01,
+	SRP_INDIRECT_BUFFER = 0x02
+};
+
+struct memory_descriptor {
+	u64 virtual_address;
+	u32 memory_handle;
+	u32 length;
+};
+
+struct indirect_descriptor {
+	struct memory_descriptor head;
+	u32 total_length;
+	struct memory_descriptor list[1] PACKED;
+};
+
+struct srp_generic {
+	u8 type;
+	u8 reserved1[7];
+	u64 tag;
+};
+
+struct srp_login_req {
+	u8 type;
+	u8 reserved1[7];
+	u64 tag;
+	u32 max_requested_initiator_to_target_iulen;
+	u32 reserved2;
+	u16 required_buffer_formats;
+	u8 reserved3:6;
+	u8 multi_channel_action:2;
+	u8 reserved4;
+	u32 reserved5;
+	u8 initiator_port_identifier[16];
+	u8 target_port_identifier[16];
+};
+
+struct srp_login_rsp {
+	u8 type;
+	u8 reserved1[3];
+	u32 request_limit_delta;
+	u64 tag;
+	u32 max_initiator_to_target_iulen;
+	u32 max_target_to_initiator_iulen;
+	u16 supported_buffer_formats;
+	u8 reserved2:6;
+	u8 multi_channel_result:2;
+	u8 reserved3;
+	u8 reserved4[24];
+};
+
+struct srp_login_rej {
+	u8 type;
+	u8 reserved1[3];
+	u32 reason;
+	u64 tag;
+	u64 reserved2;
+	u16 supported_buffer_formats;
+	u8 reserved3[6];
+};
+
+struct srp_i_logout {
+	u8 type;
+	u8 reserved1[7];
+	u64 tag;
+};
+
+struct srp_t_logout {
+	u8 type;
+	u8 reserved1[3];
+	u32 reason;
+	u64 tag;
+};
+
+struct srp_tsk_mgmt {
+	u8 type;
+	u8 reserved1[7];
+	u64 tag;
+	u32 reserved2;
+	u64 lun PACKED;
+	u8 reserved3;
+	u8 reserved4;
+	u8 task_mgmt_flags;
+	u8 reserved5;
+	u64 managed_task_tag;
+	u64 reserved6;
+};
+
+struct srp_cmd {
+	u8 type;
+	u32 reserved1 PACKED;
+	u8 data_out_format:4;
+	u8 data_in_format:4;
+	u8 data_out_count;
+	u8 data_in_count;
+	u64 tag;
+	u32 reserved2;
+	u64 lun PACKED;
+	u8 reserved3;
+	u8 reserved4:5;
+	u8 task_attribute:3;
+	u8 reserved5;
+	u8 additional_cdb_len;
+	u8 cdb[16];
+	u8 additional_data[0x100 - 0x30];
+};
+
+struct srp_rsp {
+	u8 type;
+	u8 reserved1[3];
+	u32 request_limit_delta;
+	u64 tag;
+	u16 reserved2;
+	u8 reserved3:2;
+	u8 diunder:1;
+	u8 diover:1;
+	u8 dounder:1;
+	u8 doover:1;
+	u8 snsvalid:1;
+	u8 rspvalid:1;
+	u8 status;
+	u32 data_in_residual_count;
+	u32 data_out_residual_count;
+	u32 sense_data_list_length;
+	u32 response_data_list_length;
+	u8 sense_and_response_data[18];
+};
+
+struct srp_cred_req {
+	u8 type;
+	u8 reserved1[3];
+	u32 request_limit_delta;
+	u64 tag;
+};
+
+struct srp_cred_rsp {
+	u8 type;
+	u8 reserved1[7];
+	u64 tag;
+};
+
+struct srp_aer_req {
+	u8 type;
+	u8 reserved1[3];
+	u32 request_limit_delta;
+	u64 tag;
+	u32 reserved2;
+	u64 lun;
+	u32 sense_data_list_length;
+	u32 reserved3;
+	u8 sense_data[20];
+};
+
+struct srp_aer_rsp {
+	u8 type;
+	u8 reserved1[7];
+	u64 tag;
+};
+
+union srp_iu {
+	struct srp_generic generic;
+	struct srp_login_req login_req;
+	struct srp_login_rsp login_rsp;
+	struct srp_login_rej login_rej;
+	struct srp_i_logout i_logout;
+	struct srp_t_logout t_logout;
+	struct srp_tsk_mgmt tsk_mgmt;
+	struct srp_cmd cmd;
+	struct srp_rsp rsp;
+	struct srp_cred_req cred_req;
+	struct srp_cred_rsp cred_rsp;
+	struct srp_aer_req aer_req;
+	struct srp_aer_rsp aer_rsp;
+};
+
+#endif
diff -Nru a/drivers/scsi/ibmvscsi/viosrp.h b/drivers/scsi/ibmvscsi/viosrp.h
--- /dev/null	Wed Dec 31 16:00:00 196900
+++ b/drivers/scsi/ibmvscsi/viosrp.h	2004-08-04 17:57:40 -07:00
@@ -0,0 +1,126 @@
+/*****************************************************************************/
+/* srp.h -- SCSI RDMA Protocol definitions                                   */
+/*                                                                           */
+/* Written By: Colin Devilbis, IBM Corporation                               */
+/*                                                                           */
+/* Copyright (C) 2003 IBM Corporation                                        */
+/*                                                                           */
+/* This program is free software; you can redistribute it and/or modify      */
+/* it under the terms of the GNU General Public License as published by      */
+/* the Free Software Foundation; either version 2 of the License, or         */
+/* (at your option) any later version.                                       */
+/*                                                                           */
+/* This program is distributed in the hope that it will be useful,           */
+/* but WITHOUT ANY WARRANTY; without even the implied warranty of            */
+/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             */
+/* GNU General Public License for more details.                              */
+/*                                                                           */
+/* You should have received a copy of the GNU General Public License         */
+/* along with this program; if not, write to the Free Software               */
+/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
+/*                                                                           */
+/*                                                                           */
+/* This file contains structures and definitions for IBM RPA (RS/6000        */
+/* platform architecture) implementation of the SRP (SCSI RDMA Protocol)     */
+/* standard.  SRP is used on IBM iSeries and pSeries platforms to send SCSI  */
+/* commands between logical partitions.                                      */
+/*                                                                           */
+/* SRP Information Units (IUs) are sent on a "Command/Response Queue" (CRQ)  */
+/* between partitions.  The definitions in this file are architected,        */
+/* and cannot be changed without breaking compatibility with other versions  */
+/* of Linux and other operating systems (AIX, OS/400) that talk this protocol*/
+/* between logical partitions                                                */
+/*****************************************************************************/
+#ifndef VIOSRP_H
+#define VIOSRP_H
+#include "srp.h"
+
+enum viosrp_crq_formats {
+	VIOSRP_SRP_FORMAT = 0x01,
+	VIOSRP_MAD_FORMAT = 0x02,
+	VIOSRP_OS400_FORMAT = 0x03,
+	VIOSRP_AIX_FORMAT = 0x04,
+	VIOSRP_LINUX_FORMAT = 0x06,
+	VIOSRP_INLINE_FORMAT = 0x07
+};
+
+struct viosrp_crq {
+	u8 valid;		/* used by RPA */
+	u8 format;		/* SCSI vs out-of-band */
+	u8 reserved;
+	u8 status;		/* non-scsi failure? (e.g. DMA failure) */
+	u16 timeout;		/* in seconds */
+	u16 IU_length;		/* in bytes */
+	u64 IU_data_ptr;	/* the TCE for transferring data */
+};
+
+/* MADs are Management requests above and beyond the IUs defined in the SRP
+ * standard.  
+ */
+enum viosrp_mad_types {
+	VIOSRP_EMPTY_IU_TYPE = 0x01,
+	VIOSRP_ERROR_LOG_TYPE = 0x02,
+	VIOSRP_ADAPTER_INFO_TYPE = 0x03,
+	VIOSRP_HOST_CONFIG_TYPE = 0x04
+};
+
+/* 
+ * Common MAD header
+ */
+struct mad_common {
+	u32 type;
+	u16 status;
+	u16 length;
+	u64 tag;
+};
+
+/*
+ * All SRP (and MAD) requests normally flow from the
+ * client to the server.  There is no way for the server to send
+ * an asynchronous message back to the client.  The Empty IU is used
+ * to hang out a meaningless request to the server so that it can respond
+ * asynchrouously with something like a SCSI AER 
+ */
+struct viosrp_empty_iu {
+	struct mad_common common;
+	u64 buffer;
+	u32 port;
+};
+
+struct viosrp_error_log {
+	struct mad_common common;
+	u64 buffer;
+};
+
+struct viosrp_adapter_info {
+	struct mad_common common;
+	u64 buffer;
+};
+
+struct viosrp_host_config {
+	struct mad_common common;
+	u64 buffer;
+};
+
+union mad_iu {
+	struct viosrp_empty_iu empty_iu;
+	struct viosrp_error_log error_log;
+	struct viosrp_adapter_info adapter_info;
+	struct viosrp_host_config host_config;
+};
+
+union viosrp_iu {
+	union srp_iu srp;
+	union mad_iu mad;
+};
+
+struct mad_adapter_info_data {
+	char srp_version[8];
+	char partition_name[96];
+	u32 partition_number;
+	u32 mad_version;
+	u32 os_type;
+	u32 port_max_txu[8];	/* per-port maximum transfer */
+};
+
+#endif
diff -Nru a/drivers/scsi/ips.c b/drivers/scsi/ips.c
--- a/drivers/scsi/ips.c	2004-08-04 17:57:39 -07:00
+++ b/drivers/scsi/ips.c	2004-08-04 17:57:39 -07:00
@@ -474,21 +474,17 @@
 static uint32_t ips_statupd_copperhead_memio(ips_ha_t *);
 static uint32_t ips_statupd_morpheus(ips_ha_t *);
 static ips_scb_t *ips_getscb(ips_ha_t *);
-static inline void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
-static inline void ips_putq_scb_tail(ips_scb_queue_t *, ips_scb_t *);
-static inline void ips_putq_wait_head(ips_wait_queue_t *, Scsi_Cmnd *);
-static inline void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
-static inline void ips_putq_copp_head(ips_copp_queue_t *,
+static void ips_putq_scb_head(ips_scb_queue_t *, ips_scb_t *);
+static void ips_putq_wait_tail(ips_wait_queue_t *, Scsi_Cmnd *);
+static void ips_putq_copp_tail(ips_copp_queue_t *,
 				      ips_copp_wait_item_t *);
-static inline void ips_putq_copp_tail(ips_copp_queue_t *,
-				      ips_copp_wait_item_t *);
-static inline ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *);
-static inline ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
-static inline Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
-static inline Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
-static inline ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *,
+static ips_scb_t *ips_removeq_scb_head(ips_scb_queue_t *);
+static ips_scb_t *ips_removeq_scb(ips_scb_queue_t *, ips_scb_t *);
+static Scsi_Cmnd *ips_removeq_wait_head(ips_wait_queue_t *);
+static Scsi_Cmnd *ips_removeq_wait(ips_wait_queue_t *, Scsi_Cmnd *);
+static ips_copp_wait_item_t *ips_removeq_copp(ips_copp_queue_t *,
 						     ips_copp_wait_item_t *);
-static inline ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *);
+static ips_copp_wait_item_t *ips_removeq_copp_head(ips_copp_queue_t *);
 
 static int ips_is_passthru(Scsi_Cmnd *);
 static int ips_make_passthru(ips_ha_t *, Scsi_Cmnd *, ips_scb_t *, int);
@@ -1885,7 +1881,7 @@
 /*   Fill in a single scb sg_list element from an address                   */
 /*   return a -1 if a breakup occurred                                      */
 /****************************************************************************/
-static inline int
+static int
 ips_fill_scb_sg_single(ips_ha_t * ha, dma_addr_t busaddr,
 		       ips_scb_t * scb, int indx, unsigned int e_len)
 {
@@ -2950,7 +2946,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline void
+static void
 ips_putq_scb_head(ips_scb_queue_t * queue, ips_scb_t * item)
 {
 	METHOD_TRACE("ips_putq_scb_head", 1);
@@ -2969,38 +2965,6 @@
 
 /****************************************************************************/
 /*                                                                          */
-/* Routine Name: ips_putq_scb_tail                                          */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Add an item to the tail of the queue                                   */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline void
-ips_putq_scb_tail(ips_scb_queue_t * queue, ips_scb_t * item)
-{
-	METHOD_TRACE("ips_putq_scb_tail", 1);
-
-	if (!item)
-		return;
-
-	item->q_next = NULL;
-
-	if (queue->tail)
-		queue->tail->q_next = item;
-
-	queue->tail = item;
-
-	if (!queue->head)
-		queue->head = item;
-
-	queue->count++;
-}
-
-/****************************************************************************/
-/*                                                                          */
 /* Routine Name: ips_removeq_scb_head                                       */
 /*                                                                          */
 /* Routine Description:                                                     */
@@ -3010,7 +2974,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline ips_scb_t *
+static ips_scb_t *
 ips_removeq_scb_head(ips_scb_queue_t * queue)
 {
 	ips_scb_t *item;
@@ -3045,7 +3009,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline ips_scb_t *
+static ips_scb_t *
 ips_removeq_scb(ips_scb_queue_t * queue, ips_scb_t * item)
 {
 	ips_scb_t *p;
@@ -3082,34 +3046,6 @@
 
 /****************************************************************************/
 /*                                                                          */
-/* Routine Name: ips_putq_wait_head                                         */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Add an item to the head of the queue                                   */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline void
-ips_putq_wait_head(ips_wait_queue_t * queue, Scsi_Cmnd * item)
-{
-	METHOD_TRACE("ips_putq_wait_head", 1);
-
-	if (!item)
-		return;
-
-	item->host_scribble = (char *) queue->head;
-	queue->head = item;
-
-	if (!queue->tail)
-		queue->tail = item;
-
-	queue->count++;
-}
-
-/****************************************************************************/
-/*                                                                          */
 /* Routine Name: ips_putq_wait_tail                                         */
 /*                                                                          */
 /* Routine Description:                                                     */
@@ -3119,7 +3055,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline void
+static void
 ips_putq_wait_tail(ips_wait_queue_t * queue, Scsi_Cmnd * item)
 {
 	METHOD_TRACE("ips_putq_wait_tail", 1);
@@ -3151,7 +3087,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline Scsi_Cmnd *
+static Scsi_Cmnd *
 ips_removeq_wait_head(ips_wait_queue_t * queue)
 {
 	Scsi_Cmnd *item;
@@ -3186,7 +3122,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline Scsi_Cmnd *
+static Scsi_Cmnd *
 ips_removeq_wait(ips_wait_queue_t * queue, Scsi_Cmnd * item)
 {
 	Scsi_Cmnd *p;
@@ -3223,34 +3159,6 @@
 
 /****************************************************************************/
 /*                                                                          */
-/* Routine Name: ips_putq_copp_head                                         */
-/*                                                                          */
-/* Routine Description:                                                     */
-/*                                                                          */
-/*   Add an item to the head of the queue                                   */
-/*                                                                          */
-/* ASSUMED to be called from within the HA lock                             */
-/*                                                                          */
-/****************************************************************************/
-static inline void
-ips_putq_copp_head(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
-{
-	METHOD_TRACE("ips_putq_copp_head", 1);
-
-	if (!item)
-		return;
-
-	item->next = queue->head;
-	queue->head = item;
-
-	if (!queue->tail)
-		queue->tail = item;
-
-	queue->count++;
-}
-
-/****************************************************************************/
-/*                                                                          */
 /* Routine Name: ips_putq_copp_tail                                         */
 /*                                                                          */
 /* Routine Description:                                                     */
@@ -3260,7 +3168,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline void
+static void
 ips_putq_copp_tail(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
 {
 	METHOD_TRACE("ips_putq_copp_tail", 1);
@@ -3292,7 +3200,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline ips_copp_wait_item_t *
+static ips_copp_wait_item_t *
 ips_removeq_copp_head(ips_copp_queue_t * queue)
 {
 	ips_copp_wait_item_t *item;
@@ -3327,7 +3235,7 @@
 /* ASSUMED to be called from within the HA lock                             */
 /*                                                                          */
 /****************************************************************************/
-static inline ips_copp_wait_item_t *
+static ips_copp_wait_item_t *
 ips_removeq_copp(ips_copp_queue_t * queue, ips_copp_wait_item_t * item)
 {
 	ips_copp_wait_item_t *p;
diff -Nru a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c
--- a/drivers/scsi/megaraid.c	2004-08-04 17:57:39 -07:00
+++ b/drivers/scsi/megaraid.c	2004-08-04 17:57:39 -07:00
@@ -25,11 +25,8 @@
  *					518, 520, 531, 532
  *
  * This driver is supported by LSI Logic, with assistance from Red Hat, Dell,
- * and others. Please send updates to the public mailing list
- * linux-megaraid-devel@dell.com, and subscribe to and read archives of this
- * list at http://lists.us.dell.com/.
- *
- * For history of changes, see ChangeLog.megaraid.
+ * and others. Please send updates to the mailing list
+ * linux-scsi@vger.kernel.org .
  *
  */
 
@@ -53,9 +50,12 @@
 
 #include "megaraid.h"
 
+#define MEGARAID_MODULE_VERSION "2.00.3"
+
 MODULE_AUTHOR ("LSI Logic Corporation");
 MODULE_DESCRIPTION ("LSI Logic MegaRAID driver");
 MODULE_LICENSE ("GPL");
+MODULE_VERSION(MEGARAID_MODULE_VERSION);
 
 static unsigned int max_cmd_per_lun = DEF_CMD_PER_LUN;
 MODULE_PARM(max_cmd_per_lun, "i");
diff -Nru a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c
--- a/drivers/scsi/nsp32.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/nsp32.c	2004-08-04 17:57:40 -07:00
@@ -267,8 +267,8 @@
 static        int  nsp32_prom_read     (nsp32_hw_data *, int);
 static        int  nsp32_prom_read_bit (nsp32_hw_data *);
 static        void nsp32_prom_write_bit(nsp32_hw_data *, int);
-static inline void nsp32_prom_set      (nsp32_hw_data *, int, int);
-static inline int  nsp32_prom_get      (nsp32_hw_data *, int);
+static        void nsp32_prom_set      (nsp32_hw_data *, int, int);
+static        int  nsp32_prom_get      (nsp32_hw_data *, int);
 
 /* debug/warning/info message */
 static void nsp32_message (const char *, int, char *, char *, ...);
diff -Nru a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
--- a/drivers/scsi/qla1280.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/qla1280.c	2004-08-04 17:57:40 -07:00
@@ -4,7 +4,7 @@
 * QLogic  QLA1280 (Ultra2)  and  QLA12160 (Ultra3) SCSI driver
 * Copyright (C) 2000 Qlogic Corporation (www.qlogic.com)
 * Copyright (C) 2001-2004 Jes Sorensen, Wild Open Source Inc.
-* Copyright (C) 2003 Christoph Hellwig
+* Copyright (C) 2003-2004 Christoph Hellwig
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
@@ -17,9 +17,12 @@
 * General Public License for more details.
 *
 ******************************************************************************/
-#define QLA1280_VERSION      "3.24.3"
+#define QLA1280_VERSION      "3.24.4"
 /*****************************************************************************
     Revision History:
+    Rev  3.24.4 June 7, 2004 Christoph Hellwig
+	- restructure firmware loading, cleanup initialization code
+	- prepare support for ISP1020/1040 chips
     Rev  3.24.3 January 19, 2004, Jes Sorensen
 	- Handle PCI DMA mask settings correctly
 	- Correct order of error handling in probe_one, free_irq should not
@@ -485,6 +488,14 @@
 #define ia64_platform_is(foo)		(!strcmp(x, platform_name))
 #endif
 
+
+#define IS_ISP1040(ha) (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1020)
+#define IS_ISP1x40(ha) (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1020 || \
+			ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP1240)
+#define IS_ISP1x160(ha)        (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160 || \
+				ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160)
+
+
 static int qla1280_probe_one(struct pci_dev *, const struct pci_device_id *);
 static void qla1280_remove_one(struct pci_dev *);
 
@@ -501,9 +512,7 @@
 /*
  *  QLogic ISP1280 Hardware Support Function Prototypes.
  */
-static int qla1280_isp_firmware(struct scsi_qla_host *);
-static int qla1280_chip_diag(struct scsi_qla_host *);
-static int qla1280_setup_chip(struct scsi_qla_host *);
+static int qla1280_load_firmware(struct scsi_qla_host *);
 static int qla1280_init_rings(struct scsi_qla_host *);
 static int qla1280_nvram_config(struct scsi_qla_host *);
 static int qla1280_mailbox_command(struct scsi_qla_host *,
@@ -1384,16 +1393,10 @@
 	uint8_t mr;
 	uint16_t mb[MAILBOX_REGISTER_COUNT];
 	struct nvram *nv;
-	int is1x160, status;
+	int status;
 
 	nv = &ha->nvram;
 
-	if (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160 ||
-	    ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160)
-		is1x160 = 1;
-	else
-		is1x160 = 0;
-
 	mr = BIT_3 | BIT_2 | BIT_1 | BIT_0;
 
 	/* Set Target Parameters. */
@@ -1403,17 +1406,16 @@
 
 	mb[2] = (nv->bus[bus].target[target].parameter.c << 8);
 
-	if (is1x160)
-		mb[3] =	nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8;
-	else
-		mb[3] =	nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8;
-	mb[3] |= nv->bus[bus].target[target].sync_period;
-
-	if (is1x160) {
+	if (IS_ISP1x160(ha)) {
 		mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5;
-		mb[6] =	nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8;
-		mb[6] |= nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width;
+		mb[3] =	(nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8) |
+			 nv->bus[bus].target[target].sync_period;
+		mb[6] =	(nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8) |
+			 nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width;
 		mr |= BIT_6;
+	} else {
+		mb[3] =	(nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8) |
+			 nv->bus[bus].target[target].sync_period;
 	}
 
 	status = qla1280_mailbox_command(ha, mr, &mb[0]);
@@ -1476,8 +1478,7 @@
 	    (driver_setup.wide_mask &&
 	     (~driver_setup.wide_mask & (1 << target))))
 		nv->bus[bus].target[target].parameter.f.enable_wide = 0;
-	if (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160 ||
-	    ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160) {
+	if (IS_ISP1x160(ha)) {
 		if (driver_setup.no_ppr ||
 		    (driver_setup.ppr_mask &&
 		     (~driver_setup.ppr_mask & (1 << target))))
@@ -1802,17 +1803,8 @@
 	 */
 	spin_lock_irqsave(HOST_LOCK, flags);
 #endif
-	/* If firmware needs to be loaded */
-	if (qla1280_isp_firmware(ha)) {
-		if (!(status = qla1280_chip_diag(ha))) {
-			status = qla1280_setup_chip(ha);
-		}
-	} else {
-		printk(KERN_ERR "scsi(%li): isp_firmware() failed!\n",
-		       ha->host_no);
-		status = 1;
-	}
 
+	status = qla1280_load_firmware(ha);
 	if (status) {
 		printk(KERN_ERR "scsi(%li): initialize: pci probe failed!\n",
 		       ha->host_no);
@@ -1823,36 +1815,24 @@
 	dprintk(1, "scsi(%ld): Configure NVRAM parameters\n", ha->host_no);
 	qla1280_nvram_config(ha);
 
-	if (!ha->flags.disable_host_adapter && !qla1280_init_rings(ha)) {
-		/* Issue SCSI reset. */
-		/* dg 03/13 if we can't reset twice then bus is dead */
-		for (bus = 0; bus < ha->ports; bus++) {
-			if (!ha->bus_settings[bus].disable_scsi_reset){
-				if (qla1280_bus_reset(ha, bus)) {
-					if (qla1280_bus_reset(ha, bus)) {
-						ha->bus_settings[bus].scsi_bus_dead = 1;
-					}
-				}
-			}
-		}
+	if (ha->flags.disable_host_adapter) {
+		status = 1;
+		goto out;
+	}
 
-		/*
-		 * qla1280_bus_reset() will take care of issueing markers,
-		 * no need to do that here as well!
-		 */
-#if 0
-		/* Issue marker command. */
-		ha->flags.reset_marker = 0;
-		for (bus = 0; bus < ha->ports; bus++) {
-			ha->bus_settings[bus].reset_marker = 0;
-			qla1280_marker(ha, bus, 0, 0, MK_SYNC_ALL);
-		}
-#endif
+	status = qla1280_init_rings(ha);
+	if (status)
+		goto out;
 
-		ha->flags.online = 1;
-	} else
-		status = 1;
+	/* Issue SCSI reset, if we can't reset twice then bus is dead */
+	for (bus = 0; bus < ha->ports; bus++) {
+		if (!ha->bus_settings[bus].disable_scsi_reset &&
+		    qla1280_bus_reset(ha, bus) &&
+		    qla1280_bus_reset(ha, bus))
+			ha->bus_settings[bus].scsi_bus_dead = 1;
+	}
 
+	ha->flags.online = 1;
  out:
 #if LINUX_VERSION_CODE >= 0x020500
 	spin_unlock_irqrestore(HOST_LOCK, flags);
@@ -1945,13 +1925,13 @@
 	int status = 0;
 	int cnt;
 	uint16_t data;
-
 	dprintk(3, "qla1280_chip_diag: testing device at 0x%p \n", &reg->id_l);
 
 	dprintk(1, "scsi(%ld): Verifying chip\n", ha->host_no);
 
 	/* Soft reset chip and wait for it to finish. */
 	WRT_REG_WORD(&reg->ictrl, ISP_RESET);
+
 	/*
 	 * We can't do a traditional PCI write flush here by reading
 	 * back the register. The card will not respond once the reset
@@ -1969,145 +1949,138 @@
 		data = RD_REG_WORD(&reg->ictrl);
 	}
 
-	if (cnt) {
-		/* Reset register cleared by chip reset. */
-		dprintk(3, "qla1280_chip_diag: reset register cleared by "
-			"chip reset\n");
+	if (!cnt)
+		goto fail;
 
-		WRT_REG_WORD(&reg->cfg_1, 0);
+	/* Reset register cleared by chip reset. */
+	dprintk(3, "qla1280_chip_diag: reset register cleared by chip reset\n");
 
-		/* Reset RISC and disable BIOS which
-		   allows RISC to execute out of RAM. */
-#if 0
-		WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC);
-		RD_REG_WORD(&reg->id_l);	/* Flush PCI write */
-		WRT_REG_WORD(&reg->host_cmd, HC_RELEASE_RISC);
-		RD_REG_WORD(&reg->id_l);	/* Flush PCI write */
-		WRT_REG_WORD(&reg->host_cmd, HC_DISABLE_BIOS);
-#else
-		WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC |
-			     HC_RELEASE_RISC | HC_DISABLE_BIOS);
-#endif
-		RD_REG_WORD(&reg->id_l);	/* Flush PCI write */
-		data = qla1280_debounce_register(&reg->mailbox0);
-		/*
-		 * I *LOVE* this code!
-		 */
-		for (cnt = 1000000; cnt && data == MBS_BUSY; cnt--) {
-			udelay(5);
-			data = RD_REG_WORD(&reg->mailbox0);
-		}
+	WRT_REG_WORD(&reg->cfg_1, 0);
 
-		if (cnt) {
-			/* Check product ID of chip */
-			dprintk(3, "qla1280_chip_diag: Checking product "
-				"ID of chip\n");
-
-			if (RD_REG_WORD(&reg->mailbox1) != PROD_ID_1 ||
-			    (RD_REG_WORD(&reg->mailbox2) != PROD_ID_2 &&
-			     RD_REG_WORD(&reg->mailbox2) != PROD_ID_2a) ||
-			    RD_REG_WORD(&reg->mailbox3) != PROD_ID_3 ||
-			    RD_REG_WORD(&reg->mailbox4) != PROD_ID_4) {
-				printk(KERN_INFO "qla1280: Wrong product ID = "
-				       "0x%x,0x%x,0x%x,0x%x\n",
-				       RD_REG_WORD(&reg->mailbox1),
-				       RD_REG_WORD(&reg->mailbox2),
-				       RD_REG_WORD(&reg->mailbox3),
-				       RD_REG_WORD(&reg->mailbox4));
-				status = 1;
-			} else {
-				/*
-				 * Enable ints early!!!
-				 */
-				qla1280_enable_intrs(ha);
-
-				dprintk(1, "qla1280_chip_diag: Checking "
-					"mailboxes of chip\n");
-				/* Wrap Incoming Mailboxes Test. */
-				mb[0] = MBC_MAILBOX_REGISTER_TEST;
-				mb[1] = 0xAAAA;
-				mb[2] = 0x5555;
-				mb[3] = 0xAA55;
-				mb[4] = 0x55AA;
-				mb[5] = 0xA5A5;
-				mb[6] = 0x5A5A;
-				mb[7] = 0x2525;
-				if (!(status = qla1280_mailbox_command(ha,
-								       0xff,
-								       &mb
-								       [0]))) {
-					if (mb[1] != 0xAAAA ||
-					    mb[2] != 0x5555 ||
-					    mb[3] != 0xAA55 ||
-					    mb[4] != 0x55AA ||
-					    mb[5] != 0xA5A5 ||
-					    mb[6] != 0x5A5A ||
-					    mb[7] != 0x2525) {
-						status = 1;
-						printk(KERN_INFO "qla1280: "
-						       "Failed mbox check\n");
-					}
-				}
-			}
-		} else
-			status = 1;
-	} else
-		status = 1;
+	/* Reset RISC and disable BIOS which
+	   allows RISC to execute out of RAM. */
+	WRT_REG_WORD(&reg->host_cmd, HC_RESET_RISC |
+		     HC_RELEASE_RISC | HC_DISABLE_BIOS);
+
+	RD_REG_WORD(&reg->id_l);	/* Flush PCI write */
+	data = qla1280_debounce_register(&reg->mailbox0);
+
+	/*
+	 * I *LOVE* this code!
+	 */
+	for (cnt = 1000000; cnt && data == MBS_BUSY; cnt--) {
+		udelay(5);
+		data = RD_REG_WORD(&reg->mailbox0);
+	}
+
+	if (!cnt)
+		goto fail;
+
+	/* Check product ID of chip */
+	dprintk(3, "qla1280_chip_diag: Checking product ID of chip\n");
+
+	if (RD_REG_WORD(&reg->mailbox1) != PROD_ID_1 ||
+	    (RD_REG_WORD(&reg->mailbox2) != PROD_ID_2 &&
+	     RD_REG_WORD(&reg->mailbox2) != PROD_ID_2a) ||
+	    RD_REG_WORD(&reg->mailbox3) != PROD_ID_3 ||
+	    RD_REG_WORD(&reg->mailbox4) != PROD_ID_4) {
+		printk(KERN_INFO "qla1280: Wrong product ID = "
+		       "0x%x,0x%x,0x%x,0x%x\n",
+		       RD_REG_WORD(&reg->mailbox1),
+		       RD_REG_WORD(&reg->mailbox2),
+		       RD_REG_WORD(&reg->mailbox3),
+		       RD_REG_WORD(&reg->mailbox4));
+		goto fail;
+	}
 
+	/*
+	 * Enable ints early!!!
+	 */
+	qla1280_enable_intrs(ha);
+
+	dprintk(1, "qla1280_chip_diag: Checking mailboxes of chip\n");
+	/* Wrap Incoming Mailboxes Test. */
+	mb[0] = MBC_MAILBOX_REGISTER_TEST;
+	mb[1] = 0xAAAA;
+	mb[2] = 0x5555;
+	mb[3] = 0xAA55;
+	mb[4] = 0x55AA;
+	mb[5] = 0xA5A5;
+	mb[6] = 0x5A5A;
+	mb[7] = 0x2525;
+
+	status = qla1280_mailbox_command(ha, 0xff, mb);
 	if (status)
-		dprintk(2, "qla1280_chip_diag: **** FAILED ****\n");
-	else
-		dprintk(3, "qla1280_chip_diag: exiting normally\n");
+		goto fail;
 
+	if (mb[1] != 0xAAAA || mb[2] != 0x5555 || mb[3] != 0xAA55 ||
+	    mb[4] != 0x55AA || mb[5] != 0xA5A5 || mb[6] != 0x5A5A ||
+	    mb[7] != 0x2525) {
+		printk(KERN_INFO "qla1280: Failed mbox check\n");
+		goto fail;
+	}
+
+	dprintk(3, "qla1280_chip_diag: exiting normally\n");
+	return 0;
+ fail:
+	dprintk(2, "qla1280_chip_diag: **** FAILED ****\n");
 	return status;
 }
 
-/*
- * Setup chip
- *      Load and start RISC firmware.
- *
- * Input:
- *      ha = adapter block pointer.
- *
- * Returns:
- *      0 = success.
- */
-#define DUMP_IT_BACK 0		/* for debug of RISC loading */
 static int
-qla1280_setup_chip(struct scsi_qla_host *ha)
+qla1280_load_firmware_pio(struct scsi_qla_host *ha)
 {
-	int status = 0;
-	uint16_t risc_address;
-	uint16_t *risc_code_address;
-	int risc_code_size;
-	uint16_t mb[MAILBOX_REGISTER_COUNT];
-	uint16_t cnt;
-	int num, i;
-#if DUMP_IT_BACK
-	uint8_t *sp;
-	uint8_t *tbuf;
-	dma_addr_t p_tbuf;
-#endif
+	uint16_t risc_address, *risc_code_address, risc_code_size;
+	uint16_t mb[MAILBOX_REGISTER_COUNT], i;
+	int err;
 
-	ENTER("qla1280_setup_chip");
+	/* Load RISC code. */
+	risc_address = *ql1280_board_tbl[ha->devnum].fwstart;
+	risc_code_address = ql1280_board_tbl[ha->devnum].fwcode;
+	risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen;
 
-	dprintk(1, "scsi(%ld): Setup chip\n", ha->host_no);
+	for (i = 0; i < risc_code_size; i++) {
+		mb[0] = MBC_WRITE_RAM_WORD;
+		mb[1] = risc_address + i;
+		mb[2] = risc_code_address[i];
+
+		err = qla1280_mailbox_command(ha, BIT_0 | BIT_1 | BIT_2, mb);
+		if (err) {
+			printk(KERN_ERR "scsi(%li): Failed to load firmware\n",
+					ha->host_no);
+			return err;
+		}
+	}
 
+	return 0;
+}
+
+#define DUMP_IT_BACK 0		/* for debug of RISC loading */
+static int
+qla1280_load_firmware_dma(struct scsi_qla_host *ha)
+{
+	uint16_t risc_address, *risc_code_address, risc_code_size;
+	uint16_t mb[MAILBOX_REGISTER_COUNT], cnt;
+	int err = 0, num, i;
 #if DUMP_IT_BACK
-	/* get consistent memory allocated for setup_chip */
+	uint8_t *sp, *tbuf;
+	dma_addr_t p_tbuf;
+
 	tbuf = pci_alloc_consistent(ha->pdev, 8000, &p_tbuf);
+	if (!tbuf)
+		return -ENOMEM;
 #endif
 
 	/* Load RISC code. */
 	risc_address = *ql1280_board_tbl[ha->devnum].fwstart;
 	risc_code_address = ql1280_board_tbl[ha->devnum].fwcode;
-	risc_code_size = (int) *ql1280_board_tbl[ha->devnum].fwlen;
+	risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen;
 
-	dprintk(1, "qla1280_setup_chip: DMA RISC code (%i) words\n",
-		risc_code_size);
+	dprintk(1, "%s: DMA RISC code (%i) words\n",
+			__FUNCTION__, risc_code_size);
 
 	num = 0;
-	while (risc_code_size > 0 && !status) {
+	while (risc_code_size > 0) {
 		int warn __attribute__((unused)) = 0;
 
 		cnt = 2000 >> 1;
@@ -2129,15 +2102,16 @@
 		mb[2] = (ha->request_dma >> 16) & 0xffff;
 		mb[7] = pci_dma_hi32(ha->request_dma) & 0xffff;
 		mb[6] = pci_dma_hi32(ha->request_dma) >> 16;
-		dprintk(2, "qla1280_setup_chip: op=%d  0x%p = 0x%4x,0x%4x,"
-			"0x%4x,0x%4x\n", mb[0], (void *)(long)ha->request_dma,
-			mb[6], mb[7], mb[2], mb[3]);
-		if ((status = qla1280_mailbox_command(ha, BIT_4 | BIT_3 |
-						      BIT_2 | BIT_1 | BIT_0,
-						      &mb[0]))) {
+		dprintk(2, "%s: op=%d  0x%p = 0x%4x,0x%4x,0x%4x,0x%4x\n",
+				__FUNCTION__, mb[0],
+				(void *)(long)ha->request_dma,
+				mb[6], mb[7], mb[2], mb[3]);
+		err = qla1280_mailbox_command(ha, BIT_4 | BIT_3 | BIT_2 |
+				BIT_1 | BIT_0, mb);
+		if (err) {
 			printk(KERN_ERR "scsi(%li): Failed to load partial "
 			       "segment of f\n", ha->host_no);
-			break;
+			goto out;
 		}
 
 #if DUMP_IT_BACK
@@ -2149,22 +2123,22 @@
 		mb[7] = pci_dma_hi32(p_tbuf) & 0xffff;
 		mb[6] = pci_dma_hi32(p_tbuf) >> 16;
 
-		if ((status = qla1280_mailbox_command(ha,
-						      BIT_4 | BIT_3 | BIT_2 |
-						      BIT_1 | BIT_0,
-						      &mb[0]))) {
+		err = qla1280_mailbox_command(ha, BIT_4 | BIT_3 | BIT_2 |
+				BIT_1 | BIT_0, mb);
+		if (err) {
 			printk(KERN_ERR
 			       "Failed to dump partial segment of f/w\n");
-			break;
+			goto out;
 		}
 		sp = (uint8_t *)ha->request_ring;
 		for (i = 0; i < (cnt << 1); i++) {
 			if (tbuf[i] != sp[i] && warn++ < 10) {
-				printk(KERN_ERR "qla1280_setup_chip: FW "
-				       "compare error @ byte(0x%x) loop#=%x\n",
-				       i, num);
-				printk(KERN_ERR "setup_chip: FWbyte=%x  "
-				       "FWfromChip=%x\n", sp[i], tbuf[i]);
+				printk(KERN_ERR "%s: FW compare error @ "
+						"byte(0x%x) loop#=%x\n",
+						__FUNCTION__, i, num);
+				printk(KERN_ERR "%s: FWbyte=%x  "
+						"FWfromChip=%x\n",
+						__FUNCTION__, sp[i], tbuf[i]);
 				/*break; */
 			}
 		}
@@ -2175,37 +2149,69 @@
 		num++;
 	}
 
-	/* Verify checksum of loaded RISC code. */
-	if (!status) {
-		dprintk(1, "qla1280_setup_chip: Verifying checksum of "
-			"loaded RISC code.\n");
-		mb[0] = MBC_VERIFY_CHECKSUM;
-		/* mb[1] = ql12_risc_code_addr01; */
-		mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
-
-		if (!(status =
-		      qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]))) {
-			/* Start firmware execution. */
-			dprintk(1,
-				"qla1280_setup_chip: start firmware running.\n");
-			mb[0] = MBC_EXECUTE_FIRMWARE;
-			mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
-			qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
-		} else
-			printk(KERN_ERR "scsi(%li): qla1280_setup_chip: "
-			       "Failed checksum\n", ha->host_no);
-	}
-
+ out:
 #if DUMP_IT_BACK
-	/* free consistent memory allocated for setup_chip */
 	pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf);
 #endif
+	return err;
+}
 
-	if (status)
-		dprintk(2, "qla1280_setup_chip: **** FAILED ****\n");
+static int
+qla1280_start_firmware(struct scsi_qla_host *ha)
+{
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	int err;
 
-	LEAVE("qla1280_setup_chip");
-	return status;
+	dprintk(1, "%s: Verifying checksum of loaded RISC code.\n",
+			__FUNCTION__);
+
+	/* Verify checksum of loaded RISC code. */
+	mb[0] = MBC_VERIFY_CHECKSUM;
+	/* mb[1] = ql12_risc_code_addr01; */
+	mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
+	err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
+	if (err) {
+		printk(KERN_ERR "scsi(%li): Failed checksum\n", ha->host_no);
+		return err;
+	}
+
+	/* Start firmware execution. */
+	dprintk(1, "%s: start firmware running.\n", __FUNCTION__);
+	mb[0] = MBC_EXECUTE_FIRMWARE;
+	mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
+	err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+	if (err) {
+		printk(KERN_ERR "scsi(%li): Failed to start firmware\n",
+				ha->host_no);
+	}
+
+	return err;
+}
+
+static int
+qla1280_load_firmware(struct scsi_qla_host *ha)
+{
+	int err = -ENODEV;
+
+	/* If firmware needs to be loaded */
+	if (!qla1280_isp_firmware(ha)) {
+		printk(KERN_ERR "scsi(%li): isp_firmware() failed!\n",
+				ha->host_no);
+		goto out;
+	}
+
+	err = qla1280_chip_diag(ha);
+	if (err)
+		goto out;
+	if (IS_ISP1040(ha))
+		err = qla1280_load_firmware_pio(ha);
+	else
+		err = qla1280_load_firmware_dma(ha);
+	if (err)
+		goto out;
+	err = qla1280_start_firmware(ha);
+ out:
+	return err;
 }
 
 /*
@@ -2271,123 +2277,9 @@
 	return status;
 }
 
-/*
- * NVRAM configuration.
- *
- * Input:
- *      ha                = adapter block pointer.
- *      ha->request_ring  = request ring virtual address
- *
- * Output:
- *      host adapters parameters in host adapter block
- *
- * Returns:
- *      0 = success.
- */
-static int
-qla1280_nvram_config(struct scsi_qla_host *ha)
+static void
+qla1280_print_settings(struct nvram *nv)
 {
-	struct device_reg *reg = ha->iobase;
-	struct nvram *nv;
-	int is1x160, status = 0;
-	int bus, target, lun;
-	uint16_t mb[MAILBOX_REGISTER_COUNT];
-	uint16_t mask;
-
-	ENTER("qla1280_nvram_config");
-
-	if (ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160 ||
-	    ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP10160)
-		is1x160 = 1;
-	else
-		is1x160 = 0;
-
-	nv = &ha->nvram;
-	if (!ha->nvram_valid) {
-		dprintk(1, "Using defaults for NVRAM: \n");
-		memset(nv, 0, sizeof(struct nvram));
-
-		/* nv->cntr_flags_1.disable_loading_risc_code = 1; */
-		nv->firmware_feature.f.enable_fast_posting = 1;
-		nv->firmware_feature.f.disable_synchronous_backoff = 1;
-
-		nv->termination.f.scsi_bus_0_control = 3;
-		nv->termination.f.scsi_bus_1_control = 3;
-		nv->termination.f.auto_term_support = 1;
-
-		/*
-		 * Set default FIFO magic - What appropriate values
-		 * would be here is unknown. This is what I have found
-		 * testing with 12160s.
-		 * Now, I would love the magic decoder ring for this one,
-		 * the header file provided by QLogic seems to be bogus
-		 * or incomplete at best.
-		 */
-		nv->isp_config.c = 0x44;
-
-		if (is1x160)
-			nv->isp_parameter = 0x01;
-
-		for (bus = 0; bus < MAX_BUSES; bus++) {
-			nv->bus[bus].config_1.initiator_id = 7;
-			nv->bus[bus].bus_reset_delay = 5;
-			/* 8 = 5.0 clocks */
-			nv->bus[bus].config_2.async_data_setup_time = 8;
-			nv->bus[bus].config_2.req_ack_active_negation = 1;
-			nv->bus[bus].config_2.data_line_active_negation = 1;
-			nv->bus[bus].selection_timeout = 250;
-			nv->bus[bus].max_queue_depth = 256;
-
-			for (target = 0; target < MAX_TARGETS; target++) {
-				nv->bus[bus].target[target].parameter.f.
-					renegotiate_on_error = 1;
-				nv->bus[bus].target[target].parameter.f.
-					auto_request_sense = 1;
-				nv->bus[bus].target[target].parameter.f.
-					tag_queuing = 1;
-				nv->bus[bus].target[target].parameter.f.
-					enable_sync = 1;
-#if 1	/* Some SCSI Processors do not seem to like this */
-				nv->bus[bus].target[target].parameter.f.
-					enable_wide = 1;
-#endif
-				nv->bus[bus].target[target].parameter.f.
-					parity_checking = 1;
-				nv->bus[bus].target[target].parameter.f.
-					disconnect_allowed = 1;
-				nv->bus[bus].target[target].execution_throttle=
-					nv->bus[bus].max_queue_depth - 1;
-				if (is1x160) {
-					nv->bus[bus].target[target].flags.
-						flags1x160.device_enable = 1;
-					nv->bus[bus].target[target].flags.
-						flags1x160.sync_offset = 0x0e;
-					nv->bus[bus].target[target].
-						sync_period = 9;
-					nv->bus[bus].target[target].
-						ppr_1x160.flags.enable_ppr = 1;
-					nv->bus[bus].target[target].ppr_1x160.
-						flags.ppr_options = 2;
-					nv->bus[bus].target[target].ppr_1x160.
-						flags.ppr_bus_width = 1;
-				} else {
-					nv->bus[bus].target[target].flags.
-						flags1x80.device_enable = 1;
-					nv->bus[bus].target[target].flags.
-						flags1x80.sync_offset = 0x8;
-					nv->bus[bus].target[target].
-						sync_period = 10;
-				}
-			}
-		}
-	} else {
-		/* Always force AUTO sense for LINUX SCSI */
-		for (bus = 0; bus < MAX_BUSES; bus++)
-			for (target = 0; target < MAX_TARGETS; target++) {
-				nv->bus[bus].target[target].parameter.f.
-					auto_request_sense = 1;
-			}
-	}
 	dprintk(1, "qla1280 : initiator scsi id bus[0]=%d\n",
 		nv->bus[0].config_1.initiator_id);
 	dprintk(1, "qla1280 : initiator scsi id bus[1]=%d\n",
@@ -2433,36 +2325,264 @@
 		nv->bus[0].max_queue_depth);
 	dprintk(1, "qla1280 : max queue depth[1]=%d\n",
 		nv->bus[1].max_queue_depth);
+}
+
+static void
+qla1280_set_target_defaults(struct scsi_qla_host *ha, int bus, int target)
+{
+	struct nvram *nv = &ha->nvram;
+
+	nv->bus[bus].target[target].parameter.f.renegotiate_on_error = 1;
+	nv->bus[bus].target[target].parameter.f.auto_request_sense = 1;
+	nv->bus[bus].target[target].parameter.f.tag_queuing = 1;
+	nv->bus[bus].target[target].parameter.f.enable_sync = 1;
+#if 1	/* Some SCSI Processors do not seem to like this */
+	nv->bus[bus].target[target].parameter.f.enable_wide = 1;
+#endif
+	if (!IS_ISP1040(ha))
+		nv->bus[bus].target[target].parameter.f.parity_checking = 1;
+
+	nv->bus[bus].target[target].parameter.f.disconnect_allowed = 1;
+	nv->bus[bus].target[target].execution_throttle =
+		nv->bus[bus].max_queue_depth - 1;
+
+	if (IS_ISP1x160(ha)) {
+		nv->bus[bus].target[target].flags.flags1x160.device_enable = 1;
+		nv->bus[bus].target[target].flags.flags1x160.sync_offset = 0x0e;
+		nv->bus[bus].target[target].sync_period = 9;
+		nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr = 1;
+		nv->bus[bus].target[target].ppr_1x160.flags.ppr_options = 2;
+		nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width = 1;
+	} else {
+		nv->bus[bus].target[target].flags.flags1x80.device_enable = 1;
+		nv->bus[bus].target[target].flags.flags1x80.sync_offset = 12;
+		nv->bus[bus].target[target].sync_period = 10;
+	}
+}
+
+static void
+qla1280_set_defaults(struct scsi_qla_host *ha)
+{
+	struct nvram *nv = &ha->nvram;
+	int bus, target;
+
+	dprintk(1, "Using defaults for NVRAM: \n");
+	memset(nv, 0, sizeof(struct nvram));
+
+	/* nv->cntr_flags_1.disable_loading_risc_code = 1; */
+	nv->firmware_feature.f.enable_fast_posting = 1;
+	nv->firmware_feature.f.disable_synchronous_backoff = 1;
+	nv->termination.f.scsi_bus_0_control = 3;
+	nv->termination.f.scsi_bus_1_control = 3;
+	nv->termination.f.auto_term_support = 1;
+
+	/*
+	 * Set default FIFO magic - What appropriate values would be here
+	 * is unknown. This is what I have found testing with 12160s.
+	 *
+	 * Now, I would love the magic decoder ring for this one, the
+	 * header file provided by QLogic seems to be bogus or incomplete
+	 * at best.
+	 */
+	nv->isp_config.c = ISP_CFG1_BENAB|ISP_CFG1_F128;
+	if (IS_ISP1x160(ha))
+		nv->isp_parameter = 0x01; /* fast memory enable */
+
+	for (bus = 0; bus < MAX_BUSES; bus++) {
+		nv->bus[bus].config_1.initiator_id = 7;
+		nv->bus[bus].config_2.req_ack_active_negation = 1;
+		nv->bus[bus].config_2.data_line_active_negation = 1;
+		nv->bus[bus].selection_timeout = 250;
+		nv->bus[bus].max_queue_depth = 256;
+
+		if (IS_ISP1040(ha)) {
+			nv->bus[bus].bus_reset_delay = 3;
+			nv->bus[bus].config_2.async_data_setup_time = 6;
+			nv->bus[bus].retry_delay = 1;
+		} else {
+			nv->bus[bus].bus_reset_delay = 5;
+			nv->bus[bus].config_2.async_data_setup_time = 8;
+		}
+
+		for (target = 0; target < MAX_TARGETS; target++)
+			qla1280_set_target_defaults(ha, bus, target);
+	}
+}
+
+static int
+qla1280_config_target(struct scsi_qla_host *ha, int bus, int target)
+{
+	struct nvram *nv = &ha->nvram;
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	int status, lun;
+
+	/* Set Target Parameters. */
+	mb[0] = MBC_SET_TARGET_PARAMETERS;
+	mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
+	mb[1] <<= 8;
+
+	/*
+	 * Do not enable wide, sync, and ppr for the initial
+	 * INQUIRY run. We enable this later if we determine
+	 * the target actually supports it.
+	 */
+	nv->bus[bus].target[target].parameter.f.
+		auto_request_sense = 1;
+	nv->bus[bus].target[target].parameter.f.
+		stop_queue_on_check = 0;
+
+	if (IS_ISP1x160(ha))
+		nv->bus[bus].target[target].ppr_1x160.
+			flags.enable_ppr = 0;
+
+	/*
+	 * No sync, wide, etc. while probing
+	 */
+	mb[2] = (nv->bus[bus].target[target].parameter.c << 8) &
+		~(TP_SYNC /*| TP_WIDE | TP_PPR*/);
+
+	if (IS_ISP1x160(ha))
+		mb[3] =	nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8;
+	else
+		mb[3] =	nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8;
+	mb[3] |= nv->bus[bus].target[target].sync_period;
+
+	status = qla1280_mailbox_command(ha, BIT_3 | BIT_2 | BIT_1 | BIT_0, &mb[0]);
+
+	/* Save Tag queuing enable flag. */
+	mb[0] = BIT_0 << target;
+	if (nv->bus[bus].target[target].parameter.f.tag_queuing)
+		ha->bus_settings[bus].qtag_enables |= mb[0];
+
+	/* Save Device enable flag. */
+	if (IS_ISP1x160(ha)) {
+		if (nv->bus[bus].target[target].flags.flags1x160.device_enable)
+			ha->bus_settings[bus].device_enables |= mb[0];
+		ha->bus_settings[bus].lun_disables |= 0;
+	} else {
+		if (nv->bus[bus].target[target].flags.flags1x80.device_enable)
+			ha->bus_settings[bus].device_enables |= mb[0];
+		/* Save LUN disable flag. */
+		if (nv->bus[bus].target[target].flags.flags1x80.lun_disable)
+			ha->bus_settings[bus].lun_disables |= mb[0];
+	}
+
+	/* Set Device Queue Parameters. */
+	for (lun = 0; lun < MAX_LUNS; lun++) {
+		mb[0] = MBC_SET_DEVICE_QUEUE;
+		mb[1] = (uint16_t)(bus ? target | BIT_7 : target);
+		mb[1] = mb[1] << 8 | lun;
+		mb[2] = nv->bus[bus].max_queue_depth;
+		mb[3] = nv->bus[bus].target[target].execution_throttle;
+		status |= qla1280_mailbox_command(ha, 0x0f, &mb[0]);
+	}
+
+	return status;
+}
+
+static int
+qla1280_config_bus(struct scsi_qla_host *ha, int bus)
+{
+	struct nvram *nv = &ha->nvram;
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	int target, status;
+
+	/* SCSI Reset Disable. */
+	ha->bus_settings[bus].disable_scsi_reset =
+		nv->bus[bus].config_1.scsi_reset_disable;
+
+	/* Initiator ID. */
+	ha->bus_settings[bus].id = nv->bus[bus].config_1.initiator_id;
+	mb[0] = MBC_SET_INITIATOR_ID;
+	mb[1] = bus ? ha->bus_settings[bus].id | BIT_7 :
+		ha->bus_settings[bus].id;
+	status = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+
+	/* Reset Delay. */
+	ha->bus_settings[bus].bus_reset_delay =
+		nv->bus[bus].bus_reset_delay;
+
+	/* Command queue depth per device. */
+	ha->bus_settings[bus].hiwat = nv->bus[bus].max_queue_depth - 1;
+
+	/* Set target parameters. */
+	for (target = 0; target < MAX_TARGETS; target++)
+		status |= qla1280_config_target(ha, bus, target);
+
+	return status;
+}
+
+static int
+qla1280_nvram_config(struct scsi_qla_host *ha)
+{
+	struct device_reg *reg = ha->iobase;
+	struct nvram *nv = &ha->nvram;
+	int bus, target, status = 0;
+	uint16_t mb[MAILBOX_REGISTER_COUNT];
+	uint16_t mask;
+
+	ENTER("qla1280_nvram_config");
+
+	if (ha->nvram_valid) {
+		/* Always force AUTO sense for LINUX SCSI */
+		for (bus = 0; bus < MAX_BUSES; bus++)
+			for (target = 0; target < MAX_TARGETS; target++) {
+				nv->bus[bus].target[target].parameter.f.
+					auto_request_sense = 1;
+			}
+	} else {
+		qla1280_set_defaults(ha);
+	}
+
+	qla1280_print_settings(nv);
 
 	/* Disable RISC load of firmware. */
 	ha->flags.disable_risc_code_load =
 		nv->cntr_flags_1.disable_loading_risc_code;
 
-	/* Set ISP hardware DMA burst */
-	mb[0] = nv->isp_config.c;
-	/* Enable DMA arbitration on dual channel controllers */
-	if (ha->ports > 1)
-		mb[0] |= BIT_13;
-	WRT_REG_WORD(&reg->cfg_1, mb[0]);
-
-#if 1	/* Is this safe? */
-	/* Set SCSI termination. */
-	WRT_REG_WORD(&reg->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0));
-	mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0);
-	WRT_REG_WORD(&reg->gpio_data, mb[0]);
-#endif
+	if (IS_ISP1040(ha)) {
+		uint16_t hwrev, cfg1, cdma_conf, ddma_conf;
+
+		hwrev = RD_REG_WORD(&reg->cfg_0) & ISP_CFG0_HWMSK;
+
+		cfg1 = RD_REG_WORD(&reg->cfg_1);
+		cdma_conf = RD_REG_WORD(&reg->cdma_cfg);
+		ddma_conf = RD_REG_WORD(&reg->ddma_cfg);
+
+		/* Busted fifo, says mjacob. */
+		if (hwrev == ISP_CFG0_1040A)
+			WRT_REG_WORD(&reg->cfg_1, cfg1 | ISP_CFG1_F64);
+		else
+			WRT_REG_WORD(&reg->cfg_1, cfg1 | ISP_CFG1_F64 | ISP_CFG1_BENAB);
+
+		WRT_REG_WORD(&reg->cdma_cfg, cdma_conf | CDMA_CONF_BENAB);
+		WRT_REG_WORD(&reg->ddma_cfg, cdma_conf | DDMA_CONF_BENAB);
+	} else {
+		/* Set ISP hardware DMA burst */
+		mb[0] = nv->isp_config.c;
+		/* Enable DMA arbitration on dual channel controllers */
+		if (ha->ports > 1)
+			mb[0] |= BIT_13;
+		WRT_REG_WORD(&reg->cfg_1, mb[0]);
+
+		/* Set SCSI termination. */
+		WRT_REG_WORD(&reg->gpio_enable, (BIT_3 + BIT_2 + BIT_1 + BIT_0));
+		mb[0] = nv->termination.c & (BIT_3 + BIT_2 + BIT_1 + BIT_0);
+		WRT_REG_WORD(&reg->gpio_data, mb[0]);
+	}
 
 	/* ISP parameter word. */
 	mb[0] = MBC_SET_SYSTEM_PARAMETER;
 	mb[1] = nv->isp_parameter;
 	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
 
-#if 0
-	/* clock rate - for qla1240 and older, only */
-	mb[0] = MBC_SET_CLOCK_RATE;
-	mb[1] = 0x50;
- 	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
-#endif
+	if (IS_ISP1x40(ha)) {
+		/* clock rate - for qla1240 and older, only */
+		mb[0] = MBC_SET_CLOCK_RATE;
+		mb[1] = 40;
+	 	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
+	}
+
 	/* Firmware feature word. */
 	mb[0] = MBC_SET_FIRMWARE_FEATURES;
 	mask = BIT_5 | BIT_1 | BIT_0;
@@ -2515,112 +2635,18 @@
 	mb[2] = 2;	/* Command DMA Channel Burst Enable */
 	status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
 
+	mb[0] = MBC_SET_TAG_AGE_LIMIT;
+	mb[1] = 8;
+	status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+
 	/* Selection timeout. */
 	mb[0] = MBC_SET_SELECTION_TIMEOUT;
 	mb[1] = nv->bus[0].selection_timeout;
 	mb[2] = nv->bus[1].selection_timeout;
 	status |= qla1280_mailbox_command(ha, BIT_2 | BIT_1 | BIT_0, &mb[0]);
 
-	for (bus = 0; bus < ha->ports; bus++) {
-		/* SCSI Reset Disable. */
-		ha->bus_settings[bus].disable_scsi_reset =
-			nv->bus[bus].config_1.scsi_reset_disable;
-
-		/* Initiator ID. */
-		ha->bus_settings[bus].id = nv->bus[bus].config_1.initiator_id;
-		mb[0] = MBC_SET_INITIATOR_ID;
-		mb[1] = bus ? ha->bus_settings[bus].id | BIT_7 :
-			ha->bus_settings[bus].id;
-		status |= qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
-
-		/* Reset Delay. */
-		ha->bus_settings[bus].bus_reset_delay =
-			nv->bus[bus].bus_reset_delay;
-
-		/* Command queue depth per device. */
-		ha->bus_settings[bus].hiwat = nv->bus[bus].max_queue_depth - 1;
-
-		/* Set target parameters. */
-		for (target = 0; target < MAX_TARGETS; target++) {
-			uint8_t mr = BIT_2 | BIT_1 | BIT_0;
-
-			/* Set Target Parameters. */
-			mb[0] = MBC_SET_TARGET_PARAMETERS;
-			mb[1] = (uint16_t) (bus ? target | BIT_7 : target);
-			mb[1] <<= 8;
-			/*
-			 * Do not enable wide, sync, and ppr for the initial
-			 * INQUIRY run. We enable this later if we determine
-			 * the target actually supports it.
-			 */
-			nv->bus[bus].target[target].parameter.f.
-				auto_request_sense = 1;
-			nv->bus[bus].target[target].parameter.f.
-				stop_queue_on_check = 0;
-
-			if (is1x160)
-				nv->bus[bus].target[target].ppr_1x160.
-					flags.enable_ppr = 0;
-			/*
-			 * No sync, wide, etc. while probing
-			 */
-			mb[2] = (nv->bus[bus].target[target].parameter.c << 8)&
-				~(TP_SYNC /*| TP_WIDE | TP_PPR*/);
-
-			if (is1x160)
-				mb[3] =	nv->bus[bus].target[target].flags.flags1x160.sync_offset << 8;
-			else
-				mb[3] =	nv->bus[bus].target[target].flags.flags1x80.sync_offset << 8;
-			mb[3] |= nv->bus[bus].target[target].sync_period;
-			mr |= BIT_3;
-
-			/*
-			 * We don't want to enable ppr etc. before we have 
-			 * determined that the target actually supports it
-			 */
-#if 0
-			if (is1x160) {
-				mb[2] |= nv->bus[bus].target[target].ppr_1x160.flags.enable_ppr << 5;
-
-				mb[6] =	nv->bus[bus].target[target].ppr_1x160.flags.ppr_options << 8;
-				mb[6] |= nv->bus[bus].target[target].ppr_1x160.flags.ppr_bus_width;
-				mr |= BIT_6;
-			}
-#endif
-
-			status = qla1280_mailbox_command(ha, mr, &mb[0]);
-
-			/* Save Tag queuing enable flag. */
-			mb[0] = BIT_0 << target;
-			if (nv->bus[bus].target[target].parameter.f.tag_queuing)
-				ha->bus_settings[bus].qtag_enables |= mb[0];
-
-			/* Save Device enable flag. */
-			if (is1x160) {
-				if (nv->bus[bus].target[target].flags.flags1x160.device_enable)
-					ha->bus_settings[bus].device_enables |= mb[0];
-				ha->bus_settings[bus].lun_disables |= 0;
-			} else {
-				if (nv->bus[bus].target[target].flags.flags1x80.device_enable)
-					ha->bus_settings[bus].device_enables |= mb[0];
-				/* Save LUN disable flag. */
-				if (nv->bus[bus].target[target].flags.flags1x80.lun_disable)
-				ha->bus_settings[bus].lun_disables |= mb[0];
-			}
-
-
-			/* Set Device Queue Parameters. */
-			for (lun = 0; lun < MAX_LUNS; lun++) {
-				mb[0] = MBC_SET_DEVICE_QUEUE;
-				mb[1] = (uint16_t)(bus ? target | BIT_7 : target);
-				mb[1] = mb[1] << 8 | lun;
-				mb[2] = nv->bus[bus].max_queue_depth;
-				mb[3] = nv->bus[bus].target[target].execution_throttle;
-				status |= qla1280_mailbox_command(ha, 0x0f,
-								  &mb[0]);
-			}
-		}
-	}
+	for (bus = 0; bus < ha->ports; bus++)
+		status |= qla1280_config_bus(ha, bus);
 
 	if (status)
 		dprintk(2, "qla1280_nvram_config: **** FAILED ****\n");
@@ -4231,6 +4257,7 @@
 static int
 qla1280_abort_isp(struct scsi_qla_host *ha)
 {
+	struct device_reg *reg = ha->iobase;
 	struct srb *sp;
 	int status = 0;
 	int cnt;
@@ -4238,69 +4265,53 @@
 
 	ENTER("qla1280_abort_isp");
 
-	if (!ha->flags.abort_isp_active && ha->flags.online) {
-		struct device_reg *reg = ha->iobase;
-		ha->flags.abort_isp_active = 1;
+	if (ha->flags.abort_isp_active || !ha->flags.online)
+		goto out;
+	
+	ha->flags.abort_isp_active = 1;
 
-		/* Disable ISP interrupts. */
-		qla1280_disable_intrs(ha);
-		WRT_REG_WORD(&reg->host_cmd, HC_PAUSE_RISC);
-		RD_REG_WORD(&reg->id_l);
+	/* Disable ISP interrupts. */
+	qla1280_disable_intrs(ha);
+	WRT_REG_WORD(&reg->host_cmd, HC_PAUSE_RISC);
+	RD_REG_WORD(&reg->id_l);
 
-		printk(KERN_INFO "scsi(%li): dequeuing outstanding commands\n",
-		       ha->host_no);
-		/* Dequeue all commands in outstanding command list. */
-		for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
-			struct scsi_cmnd *cmd;
-			sp = ha->outstanding_cmds[cnt];
-			if (sp) {
+	printk(KERN_INFO "scsi(%li): dequeuing outstanding commands\n",
+	       ha->host_no);
+	/* Dequeue all commands in outstanding command list. */
+	for (cnt = 0; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+		struct scsi_cmnd *cmd;
+		sp = ha->outstanding_cmds[cnt];
+		if (sp) {
 
-				cmd = sp->cmd;
-				CMD_RESULT(cmd) = DID_RESET << 16;
+			cmd = sp->cmd;
+			CMD_RESULT(cmd) = DID_RESET << 16;
 
-				sp->cmd = NULL;
-				ha->outstanding_cmds[cnt] = NULL;
+			sp->cmd = NULL;
+			ha->outstanding_cmds[cnt] = NULL;
 
-				(*cmd->scsi_done)(cmd);
+			(*cmd->scsi_done)(cmd);
 
-				sp->flags = 0;
-			}
+			sp->flags = 0;
 		}
+	}
 
-		/* If firmware needs to be loaded */
-		if (qla1280_isp_firmware (ha)) {
-			if (!(status = qla1280_chip_diag(ha)))
-				status = qla1280_setup_chip(ha);
-		}
+	status = qla1280_load_firmware(ha);
+	if (status)
+		goto out;
 
-		if (!status) {
-			/* Setup adapter based on NVRAM parameters. */
-			qla1280_nvram_config (ha);
-
-			if (!(status = qla1280_init_rings(ha))) {
-				/* Issue SCSI reset. */
-				for (bus = 0; bus < ha->ports; bus++) {
-					qla1280_bus_reset(ha, bus);
-				}
-				/*
-				 * qla1280_bus_reset() will do the marker
-				 * dance - no reason to repeat here!
-				 */
-#if  0
-				/* Issue marker command. */
-				ha->flags.reset_marker = 0;
-				for (bus = 0; bus < ha->ports; bus++) {
-					ha->bus_settings[bus].
-						reset_marker = 0;
-					qla1280_marker(ha, bus, 0, 0,
-						       MK_SYNC_ALL);
-				}
-#endif
-				ha->flags.abort_isp_active = 0;
-			}
-		}
-	}
+	/* Setup adapter based on NVRAM parameters. */
+	qla1280_nvram_config (ha);
 
+	status = qla1280_init_rings(ha);
+	if (status)
+		goto out;
+		
+	/* Issue SCSI reset. */
+	for (bus = 0; bus < ha->ports; bus++)
+		qla1280_bus_reset(ha, bus);
+		
+	ha->flags.abort_isp_active = 0;
+ out:
 	if (status) {
 		printk(KERN_WARNING
 		       "qla1280: ISP error recovery failed, board disabled");
@@ -4936,6 +4947,7 @@
 MODULE_AUTHOR("Qlogic & Jes Sorensen");
 MODULE_DESCRIPTION("Qlogic ISP SCSI (qla1x80/qla1x160) driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA1280_VERSION);
 
 /*
  * Overrides for Emacs so that we almost follow Linus's tabbing style.
diff -Nru a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h
--- a/drivers/scsi/qla1280.h	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/qla1280.h	2004-08-04 17:57:40 -07:00
@@ -126,7 +126,20 @@
 	uint16_t id_l;		/* ID low */
 	uint16_t id_h;		/* ID high */
 	uint16_t cfg_0;		/* Configuration 0 */
+#define ISP_CFG0_HWMSK   0x000f	/* Hardware revision mask */
+#define ISP_CFG0_1020    BIT_0	/* ISP1020 */
+#define ISP_CFG0_1020A	 BIT_1	/* ISP1020A */
+#define ISP_CFG0_1040	 BIT_2	/* ISP1040 */
+#define ISP_CFG0_1040A	 BIT_3	/* ISP1040A */
+#define ISP_CFG0_1040B	 BIT_4	/* ISP1040B */
+#define ISP_CFG0_1040C	 BIT_5	/* ISP1040C */
 	uint16_t cfg_1;		/* Configuration 1 */
+#define ISP_CFG1_F128    BIT_6  /* 128-byte FIFO threshold */
+#define ISP_CFG1_F64     BIT_4|BIT_5 /* 128-byte FIFO threshold */
+#define ISP_CFG1_F32     BIT_5  /* 128-byte FIFO threshold */
+#define ISP_CFG1_F16     BIT_4  /* 128-byte FIFO threshold */
+#define ISP_CFG1_BENAB   BIT_2  /* Global Bus burst enable */
+#define ISP_CFG1_SXP     BIT_0  /* SXP register select */
 	uint16_t ictrl;		/* Interface control */
 #define ISP_RESET        BIT_0	/* ISP soft reset */
 #define ISP_EN_INT       BIT_1	/* ISP enable interrupts. */
@@ -147,7 +160,42 @@
 	uint16_t flash_data;	/* Flash BIOS data */
 	uint16_t flash_address;	/* Flash BIOS address */
 
-	uint16_t unused_1[0x2e];	/* 0x14-0x6f Gap */
+	uint16_t unused_1[0x06];
+	
+	/* cdma_* and ddma_* are 1040 only */
+	uint16_t cdma_cfg;
+#define CDMA_CONF_SENAB  BIT_3	/* SXP to DMA Data enable */
+#define CDMA_CONF_RIRQ   BIT_2	/* RISC interrupt enable */
+#define CDMA_CONF_BENAB  BIT_1	/* Bus burst enable */
+#define CDMA_CONF_DIR    BIT_0	/* DMA direction (0=fifo->host 1=host->fifo) */
+	uint16_t cdma_ctrl; 
+	uint16_t cdma_status;   
+	uint16_t cdma_fifo_status;
+	uint16_t cdma_count;
+	uint16_t cdma_reserved;
+	uint16_t cdma_address_count_0;
+	uint16_t cdma_address_count_1;
+	uint16_t cdma_address_count_2;
+	uint16_t cdma_address_count_3;
+
+	uint16_t unused_2[0x06];
+
+	uint16_t ddma_cfg;
+#define DDMA_CONF_SENAB  BIT_3	/* SXP to DMA Data enable */
+#define DDMA_CONF_RIRQ   BIT_2	/* RISC interrupt enable */
+#define DDMA_CONF_BENAB  BIT_1	/* Bus burst enable */
+#define DDMA_CONF_DIR    BIT_0	/* DMA direction (0=fifo->host 1=host->fifo) */
+	uint16_t ddma_ctrl;
+	uint16_t ddma_status; 
+	uint16_t ddma_fifo_status;
+	uint16_t ddma_xfer_count_low;
+	uint16_t ddma_xfer_count_high;
+	uint16_t ddma_addr_count_0;
+	uint16_t ddma_addr_count_1;
+	uint16_t ddma_addr_count_2;
+	uint16_t ddma_addr_count_3; 
+
+	uint16_t unused_3[0x0e];
 
 	uint16_t mailbox0;	/* Mailbox 0 */
 	uint16_t mailbox1;	/* Mailbox 1 */
@@ -158,18 +206,18 @@
 	uint16_t mailbox6;	/* Mailbox 6 */
 	uint16_t mailbox7;	/* Mailbox 7 */
 
-	uint16_t unused_2[0x20];/* 0x80-0xbf Gap */
+	uint16_t unused_4[0x20];/* 0x80-0xbf Gap */
 
 	uint16_t host_cmd;	/* Host command and control */
 #define HOST_INT      BIT_7	/* host interrupt bit */
 #define BIOS_ENABLE   BIT_0
 
-	uint16_t unused_6[0x5];	/* 0xc2-0xcb Gap */
+	uint16_t unused_5[0x5];	/* 0xc2-0xcb Gap */
 
 	uint16_t gpio_data;
 	uint16_t gpio_enable;
 
-	uint16_t unused_7[0x11];	/* d0-f0 */
+	uint16_t unused_6[0x11];	/* d0-f0 */
 	uint16_t scsiControlPins;	/* f2 */
 };
 
diff -Nru a/drivers/scsi/qla2xxx/ql2100.c b/drivers/scsi/qla2xxx/ql2100.c
--- a/drivers/scsi/qla2xxx/ql2100.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/qla2xxx/ql2100.c	2004-08-04 17:57:40 -07:00
@@ -89,3 +89,4 @@
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP21xx FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff -Nru a/drivers/scsi/qla2xxx/ql2200.c b/drivers/scsi/qla2xxx/ql2200.c
--- a/drivers/scsi/qla2xxx/ql2200.c	2004-08-04 17:57:39 -07:00
+++ b/drivers/scsi/qla2xxx/ql2200.c	2004-08-04 17:57:39 -07:00
@@ -89,3 +89,4 @@
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP22xx FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff -Nru a/drivers/scsi/qla2xxx/ql2300.c b/drivers/scsi/qla2xxx/ql2300.c
--- a/drivers/scsi/qla2xxx/ql2300.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/qla2xxx/ql2300.c	2004-08-04 17:57:40 -07:00
@@ -100,3 +100,4 @@
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP2300 FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff -Nru a/drivers/scsi/qla2xxx/ql2322.c b/drivers/scsi/qla2xxx/ql2322.c
--- a/drivers/scsi/qla2xxx/ql2322.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/qla2xxx/ql2322.c	2004-08-04 17:57:40 -07:00
@@ -105,3 +105,4 @@
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP2322 FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff -Nru a/drivers/scsi/qla2xxx/ql6312.c b/drivers/scsi/qla2xxx/ql6312.c
--- a/drivers/scsi/qla2xxx/ql6312.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/qla2xxx/ql6312.c	2004-08-04 17:57:40 -07:00
@@ -87,3 +87,4 @@
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP6312 FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff -Nru a/drivers/scsi/qla2xxx/ql6322.c b/drivers/scsi/qla2xxx/ql6322.c
--- a/drivers/scsi/qla2xxx/ql6322.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/qla2xxx/ql6322.c	2004-08-04 17:57:40 -07:00
@@ -105,3 +105,4 @@
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic ISP6322 FC-SCSI Host Bus Adapter driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff -Nru a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
--- a/drivers/scsi/qla2xxx/qla_init.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/qla2xxx/qla_init.c	2004-08-04 17:57:40 -07:00
@@ -783,7 +783,6 @@
 static void
 qla2x00_update_fw_options(scsi_qla_host_t *ha)
 {
-	/* Setup seriallink options */
 	uint16_t swing, emphasis;
 
 	memset(ha->fw_options, 0, sizeof(ha->fw_options));
@@ -807,7 +806,6 @@
 	emphasis = ha->fw_seriallink_options[0] & (BIT_4 | BIT_3);
 	emphasis >>= 3;
 	ha->fw_options[10] = (emphasis << 14) | (swing << 8) | 0x3;
-
 	/*  2G settings */
 	swing = ha->fw_seriallink_options[0] & (BIT_7 | BIT_6 | BIT_5);
 	swing >>= 5;
@@ -818,7 +816,7 @@
 	/*  Return command IOCBs without waiting for an ABTS to complete. */
 	ha->fw_options[3] |= BIT_13;
 
-	/* Update Serial Link options. */
+	/* Update firmware options. */
 	qla2x00_set_fw_options(ha, ha->fw_options);
 }
 
@@ -869,15 +867,15 @@
 
 	spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
+	/* Update any ISP specific firmware options before initialization. */
+	qla2x00_update_fw_options(ha);
+
 	DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no));
 	rval = qla2x00_init_firmware(ha, sizeof(init_cb_t));
 	if (rval) {
 		DEBUG2_3(printk("scsi(%ld): Init firmware **** FAILED ****.\n",
 		    ha->host_no));
 	} else {
-		/* Update any ISP specific firmware options. */
-		qla2x00_update_fw_options(ha);
-
 		DEBUG3(printk("scsi(%ld): Init firmware -- success.\n",
 		    ha->host_no));
 	}
diff -Nru a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
--- a/drivers/scsi/qla2xxx/qla_iocb.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/qla2xxx/qla_iocb.c	2004-08-04 17:57:40 -07:00
@@ -22,6 +22,8 @@
 #include <linux/blkdev.h>
 #include <linux/delay.h>
 
+#include <scsi/scsi_tcq.h>
+
 static inline uint16_t qla2x00_get_cmd_direction(struct scsi_cmnd *cmd);
 static inline cont_entry_t *qla2x00_prep_cont_type0_iocb(scsi_qla_host_t *);
 static inline cont_a64_entry_t *qla2x00_prep_cont_type1_iocb(scsi_qla_host_t *);
@@ -337,6 +339,7 @@
 	uint16_t	req_cnt;
 	uint16_t	tot_dsds;
 	device_reg_t	*reg;
+	char		tag[2];
 
 	/* Setup device pointers. */
 	ret = 0;
@@ -415,14 +418,17 @@
 	cmd_pkt->lun = cpu_to_le16(fclun->lun);
 
 	/* Update tagged queuing modifier */
-	cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG);
-	if (cmd->device->tagged_supported) {
-		switch (cmd->tag) {
-		case HEAD_OF_QUEUE_TAG:
+	if (scsi_populate_tag_msg(cmd, tag)) {
+		switch (tag[0]) {
+		case MSG_SIMPLE_TAG:
+			cmd_pkt->control_flags =
+			    __constant_cpu_to_le16(CF_SIMPLE_TAG);
+			break;
+		case MSG_HEAD_TAG:
 			cmd_pkt->control_flags =
 			    __constant_cpu_to_le16(CF_HEAD_TAG);
 			break;
-		case ORDERED_QUEUE_TAG:
+		case MSG_ORDERED_TAG:
 			cmd_pkt->control_flags =
 			    __constant_cpu_to_le16(CF_ORDERED_TAG);
 			break;
diff -Nru a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
--- a/drivers/scsi/qla2xxx/qla_os.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/qla2xxx/qla_os.c	2004-08-04 17:57:40 -07:00
@@ -1663,7 +1663,7 @@
 		goto out;
 
 	/* Waiting for our command in done_queue to be returned to OS.*/
-	if (qla2x00_eh_wait_for_pending_commands(ha))
+	if (!qla2x00_eh_wait_for_pending_commands(ha))
 		rval = FAILED;
 
  out:
@@ -1784,7 +1784,7 @@
 
 		ql2xmaxqdepth = queue_depth;
 
-		scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, queue_depth);
+		scsi_activate_tcq(sdev, queue_depth);
 
 		qla_printk(KERN_INFO, ha,
 		    "scsi(%d:%d:%d:%d): Enabled tagged queuing, queue "
@@ -4517,3 +4517,4 @@
 MODULE_AUTHOR("QLogic Corporation");
 MODULE_DESCRIPTION("QLogic Fibre Channel HBA Driver");
 MODULE_LICENSE("GPL");
+MODULE_VERSION(QLA2XXX_VERSION);
diff -Nru a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
--- a/drivers/scsi/qla2xxx/qla_version.h	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/qla2xxx/qla_version.h	2004-08-04 17:57:40 -07:00
@@ -19,9 +19,9 @@
 /*
  * Driver version 
  */
-#define QLA2XXX_VERSION      "8.00.00b14-k"
+#define QLA2XXX_VERSION      "8.00.00b15-k"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	0
 #define QLA_DRIVER_PATCH_VER	0
-#define QLA_DRIVER_BETA_VER	14
+#define QLA_DRIVER_BETA_VER	15
diff -Nru a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
--- a/drivers/scsi/scsi_sysfs.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/scsi_sysfs.c	2004-08-04 17:57:40 -07:00
@@ -525,8 +525,11 @@
  **/
 void scsi_remove_device(struct scsi_device *sdev)
 {
+	struct Scsi_Host *shost = sdev->host;
+
+	down(&shost->scan_mutex);
 	if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)
-		return;
+		goto out;
 
 	class_device_unregister(&sdev->sdev_classdev);
 	if (sdev->transport_classdev.class)
@@ -538,6 +541,9 @@
 	if (sdev->host->transportt->cleanup)
 		sdev->host->transportt->cleanup(sdev);
 	put_device(&sdev->sdev_gendev);
+
+out:
+	up(&shost->scan_mutex);
 }
 
 int scsi_register_driver(struct device_driver *drv)
diff -Nru a/drivers/scsi/scsiiom.c b/drivers/scsi/scsiiom.c
--- a/drivers/scsi/scsiiom.c	2004-08-04 17:57:39 -07:00
+++ b/drivers/scsi/scsiiom.c	2004-08-04 17:57:39 -07:00
@@ -213,8 +213,17 @@
 }
 #endif
 
+
+static void __inline__
+dc390_InvalidCmd(struct dc390_acb* pACB)
+{
+	if (pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_ | SRB_MSGOUT))
+		DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
+}
+
+
 static irqreturn_t __inline__
-DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs)
+DC390_Interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
     struct dc390_acb *pACB, *pACB2;
     struct dc390_dcb *pDCB;
@@ -594,7 +603,7 @@
 }
 
 /* abort command */
-static void __inline__
+static void
 dc390_EnableMsgOut_Abort ( struct dc390_acb* pACB, struct dc390_srb* pSRB )
 {
     pSRB->MsgOutBuf[0] = ABORT; 
@@ -890,14 +899,22 @@
 
     if (pSRB == pACB->pTmpSRB)
     {
-	if (pDCB) printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n",
-			  pDCB->TargetID, pDCB->TargetLUN);
-	else printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n");
-
-	pSRB->pSRBDCB = pDCB;
-	dc390_EnableMsgOut_Abort (pACB, pSRB);
-	if (pDCB) pDCB->DCBFlag |= ABORT_DEV;
-	return;
+	if (pDCB)
+		printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n", pDCB->TargetID, pDCB->TargetLUN);
+	else
+		printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n");
+
+	/* Try to recover - some broken disks react badly to tagged INQUIRY */
+	if (pDCB && pACB->scan_devices && pDCB->GoingSRBCnt == 1) {
+		pSRB = pDCB->pGoingSRB;
+		pDCB->pActiveSRB = pSRB;
+	} else {
+		pSRB->pSRBDCB = pDCB;
+		dc390_EnableMsgOut_Abort(pACB, pSRB);
+		if (pDCB)
+			pDCB->DCBFlag |= ABORT_DEV;
+		return;
+	}
     }
 
     if( pSRB->SGIndex < pSRB->SGcount )
@@ -1325,6 +1342,35 @@
 }
 
 
+static void __inline__
+dc390_RequestSense(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
+{
+	struct scsi_cmnd *pcmd;
+
+	pcmd = pSRB->pcmd;
+
+	REMOVABLEDEBUG(printk(KERN_INFO "DC390: RequestSense(Cmd %02x, Id %02x, LUN %02x)\n",\
+			      pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
+
+	pSRB->SRBFlag |= AUTO_REQSENSE;
+	pSRB->SavedSGCount = pcmd->use_sg;
+	pSRB->SavedTotXLen = pSRB->TotalXferredLen;
+	pSRB->AdaptStatus = 0;
+	pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
+
+	/* We are called from SRBdone, original PCI mapping has been removed
+	 * already, new one is set up from StartSCSI */
+	pSRB->SGIndex = 0;
+
+	pSRB->TotalXferredLen = 0;
+	pSRB->SGToBeXferLen = 0;
+	if (dc390_StartSCSI(pACB, pDCB, pSRB)) {
+		dc390_Going_to_Waiting(pDCB, pSRB);
+		dc390_waiting_timer(pACB, HZ/5);
+	}
+}
+
+
 static void
 dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
 {
@@ -1653,52 +1699,4 @@
 	dc390_Waiting_process( pACB );
     }
     return;
-}
-
-
-static void __inline__
-dc390_RequestSense( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
-{
-    struct scsi_cmnd *pcmd;
-
-    pcmd = pSRB->pcmd;
-
-    REMOVABLEDEBUG(printk (KERN_INFO "DC390: RequestSense (Cmd %02x, Id %02x, LUN %02x)\n",\
-	    pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
-
-    pSRB->SRBFlag |= AUTO_REQSENSE;
-    //pSRB->Segment0[0] = (u32) pSRB->CmdBlock[0];
-    //pSRB->Segment0[1] = (u32) pSRB->CmdBlock[4];
-    //pSRB->Segment1[0] = ((u32)(pcmd->cmd_len) << 8) + pSRB->SGcount;
-    //pSRB->Segment1[1] = pSRB->TotalXferredLen;
-    pSRB->SavedSGCount = pcmd->use_sg;
-    pSRB->SavedTotXLen = pSRB->TotalXferredLen;
-    pSRB->AdaptStatus = 0;
-    pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
-
-    /* We are called from SRBdone, original PCI mapping has been removed
-     * already, new one is set up from StartSCSI */
-    pSRB->SGIndex = 0;
-
-    //pSRB->CmdBlock[0] = REQUEST_SENSE;
-    //pSRB->CmdBlock[1] = pDCB->TargetLUN << 5;
-    //(u16) pSRB->CmdBlock[2] = 0;
-    //(u16) pSRB->CmdBlock[4] = sizeof(pcmd->sense_buffer);
-    //pSRB->ScsiCmdLen = 6;
-
-    pSRB->TotalXferredLen = 0;
-    pSRB->SGToBeXferLen = 0;
-    if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) {
-	dc390_Going_to_Waiting ( pDCB, pSRB );
-	dc390_waiting_timer (pACB, HZ/5);
-    }
-}
-
-
-
-static void __inline__
-dc390_InvalidCmd( struct dc390_acb* pACB )
-{
-    if( pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_+SRB_MSGOUT) )
-	DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
 }
diff -Nru a/drivers/scsi/sg.c b/drivers/scsi/sg.c
--- a/drivers/scsi/sg.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/sg.c	2004-08-04 17:57:40 -07:00
@@ -205,8 +205,6 @@
 static Sg_request *sg_add_request(Sg_fd * sfp);
 static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
 static int sg_res_in_use(Sg_fd * sfp);
-static int sg_ms_to_jif(unsigned int msecs);
-static inline unsigned sg_jif_to_ms(int jifs);
 static int sg_allow_access(unsigned char opcode, char dev_type);
 static int sg_build_direct(Sg_request * srp, Sg_fd * sfp, int dxfer_len);
 static Sg_device *sg_get_dev(int dev);
@@ -612,7 +610,7 @@
 			return -EBUSY;	/* reserve buffer already being used */
 		}
 	}
-	timeout = sg_ms_to_jif(srp->header.timeout);
+	timeout = msecs_to_jiffies(srp->header.timeout);
 	if ((!hp->cmdp) || (hp->cmd_len < 6) || (hp->cmd_len > sizeof (cmnd))) {
 		sg_remove_request(sfp, srp);
 		return -EMSGSIZE;
@@ -720,19 +718,6 @@
 	return 0;
 }
 
-static inline unsigned
-sg_jif_to_ms(int jifs)
-{
-	if (jifs <= 0)
-		return 0U;
-	else {
-		unsigned int j = (unsigned int) jifs;
-		return (j <
-			(UINT_MAX / 1000)) ? ((j * 1000) / HZ) : ((j / HZ) *
-								  1000);
-	}
-}
-
 static int
 sg_ioctl(struct inode *inode, struct file *filp,
 	 unsigned int cmd_in, unsigned long arg)
@@ -942,7 +927,7 @@
 					    srp->header.driver_status;
 					rinfo[val].duration =
 					    srp->done ? srp->header.duration :
-					    sg_jif_to_ms(
+					    jiffies_to_msecs(
 						jiffies - srp->header.duration);
 					rinfo[val].orphan = srp->orphan;
 					rinfo[val].sg_io_owned = srp->sg_io_owned;
@@ -1264,7 +1249,7 @@
 	srp->header.resid = SCpnt->resid;
 	/* N.B. unit of duration changes here from jiffies to millisecs */
 	srp->header.duration =
-	    sg_jif_to_ms(jiffies - (int) srp->header.duration);
+	    jiffies_to_msecs(jiffies - srp->header.duration);
 	if (0 != SRpnt->sr_result) {
 		memcpy(srp->sense_b, SRpnt->sr_sense_buffer,
 		       sizeof (srp->sense_b));
@@ -2588,17 +2573,6 @@
 	free_pages((unsigned long) buff, order);
 }
 
-static int
-sg_ms_to_jif(unsigned int msecs)
-{
-	if ((UINT_MAX / 2U) < msecs)
-		return INT_MAX;	/* special case, set largest possible */
-	else
-		return ((int) msecs <
-			(INT_MAX / 1000)) ? (((int) msecs * HZ) / 1000)
-		    : (((int) msecs / 1000) * HZ);
-}
-
 static unsigned char allow_ops[] = { TEST_UNIT_READY, REQUEST_SENSE,
 	INQUIRY, READ_CAPACITY, READ_BUFFER, READ_6, READ_10, READ_12,
 	MODE_SENSE, MODE_SENSE_10, LOG_SENSE
@@ -2961,7 +2935,7 @@
 	for (k = 0; (fp = sg_get_nth_sfp(sdp, k)); ++k) {
 		seq_printf(s, "   FD(%d): timeout=%dms bufflen=%d "
 			   "(res)sgat=%d low_dma=%d\n", k + 1,
-			   sg_jif_to_ms(fp->timeout),
+			   jiffies_to_msecs(fp->timeout),
 			   fp->reserve.bufflen,
 			   (int) fp->reserve.k_use_sg,
 			   (int) fp->low_dma);
@@ -2997,8 +2971,8 @@
 				seq_printf(s, " dur=%d", hp->duration);
 			else
 				seq_printf(s, " t_o/elap=%d/%d",
-				  new_interface ? hp->timeout : sg_jif_to_ms(fp->timeout),
-				  sg_jif_to_ms(hp->duration ? (jiffies - hp->duration) : 0));
+				  new_interface ? hp->timeout : jiffies_to_msecs(fp->timeout),
+				  jiffies_to_msecs(hp->duration ? (jiffies - hp->duration) : 0));
 			seq_printf(s, "ms sgat=%d op=0x%02x\n", usg,
 				   (int) srp->data.cmd_opcode);
 		}
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-08-04 17:57:40 -07:00
+++ b/drivers/scsi/sym53c8xx_2/sym_defs.h	2004-08-04 17:57:40 -07:00
@@ -53,6 +53,9 @@
 #ifndef SYM_DEFS_H
 #define SYM_DEFS_H
 
+#define SYM_VERSION "2.1.18j"
+#define SYM_DRIVER_NAME	"sym-" SYM_VERSION
+
 /*
  *  Vendor.
  */
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-08-04 17:57:40 -07:00
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c	2004-08-04 17:57:40 -07:00
@@ -2283,6 +2283,7 @@
 }
 
 MODULE_LICENSE("Dual BSD/GPL");
+MODULE_VERSION(SYM_VERSION);
 
 /*
  * Driver host template.
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-08-04 17:57:39 -07:00
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c	2004-08-04 17:57:39 -07:00
@@ -49,10 +49,6 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
-
-#define SYM_VERSION "2.1.18j"
-#define SYM_DRIVER_NAME	"sym-" SYM_VERSION
-
 #include "sym_glue.h"
 #include "sym_nvram.h"
 
diff -Nru a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
--- a/drivers/scsi/tmscsim.c	2004-08-04 17:57:40 -07:00
+++ b/drivers/scsi/tmscsim.c	2004-08-04 17:57:40 -07:00
@@ -291,9 +291,7 @@
 static void dc390_DoingSRB_Done( struct dc390_acb* pACB, struct scsi_cmnd * cmd);
 static void dc390_ScsiRstDetect( struct dc390_acb* pACB );
 static void dc390_ResetSCSIBus( struct dc390_acb* pACB );
-static void __inline__ dc390_RequestSense( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB );
-static void __inline__ dc390_InvalidCmd( struct dc390_acb* pACB );
-static void __inline__ dc390_EnableMsgOut_Abort (struct dc390_acb*, struct dc390_srb*);
+static void dc390_EnableMsgOut_Abort(struct dc390_acb*, struct dc390_srb*);
 static irqreturn_t do_DC390_Interrupt( int, void *, struct pt_regs *);
 
 static int    dc390_initAdapter(struct Scsi_Host *psh, unsigned long io_port, u8 Irq, u8 index );
@@ -942,8 +940,6 @@
 {
     pSRB->pSRBDCB = pDCB;
     pSRB->pcmd = pcmd;
-    //pSRB->ScsiCmdLen = pcmd->cmd_len;
-    //memcpy (pSRB->CmdBlock, pcmd->cmnd, pcmd->cmd_len);
     
     pSRB->SGIndex = 0;
     pSRB->AdaptStatus = 0;
diff -Nru a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
--- a/include/scsi/scsi_device.h	2004-08-04 17:57:39 -07:00
+++ b/include/scsi/scsi_device.h	2004-08-04 17:57:39 -07:00
@@ -188,7 +188,7 @@
 extern int scsi_device_quiesce(struct scsi_device *sdev);
 extern void scsi_device_resume(struct scsi_device *sdev);
 extern const char *scsi_device_state_name(enum scsi_device_state);
-static int inline scsi_device_online(struct scsi_device *sdev)
+static inline int scsi_device_online(struct scsi_device *sdev)
 {
 	return sdev->sdev_state != SDEV_OFFLINE;
 }