Merge master.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
authorLinus Torvalds <torvalds@g5.osdl.org>
Sat, 14 Jan 2006 20:16:07 +0000 (12:16 -0800)
committerLinus Torvalds <torvalds@g5.osdl.org>
Sat, 14 Jan 2006 20:16:07 +0000 (12:16 -0800)
103 files changed:
Documentation/scsi/aacraid.txt [new file with mode: 0644]
drivers/message/fusion/Kconfig
drivers/message/fusion/lsi/mpi.h
drivers/message/fusion/lsi/mpi_cnfg.h
drivers/message/fusion/lsi/mpi_history.txt
drivers/message/fusion/lsi/mpi_init.h
drivers/message/fusion/lsi/mpi_ioc.h
drivers/message/fusion/lsi/mpi_log_fc.h [new file with mode: 0644]
drivers/message/fusion/lsi/mpi_log_sas.h [new file with mode: 0644]
drivers/message/fusion/lsi/mpi_sas.h
drivers/message/fusion/mptbase.c
drivers/message/fusion/mptbase.h
drivers/message/fusion/mptctl.c
drivers/message/fusion/mptfc.c
drivers/message/fusion/mptlan.c
drivers/message/fusion/mptsas.c
drivers/message/fusion/mptscsih.c
drivers/message/fusion/mptspi.c
drivers/message/i2o/pci.c
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_fsf.h
drivers/s390/scsi/zfcp_scsi.c
drivers/s390/scsi/zfcp_sysfs_adapter.c
drivers/s390/scsi/zfcp_sysfs_port.c
drivers/s390/scsi/zfcp_sysfs_unit.c
drivers/scsi/3w-9xxx.c
drivers/scsi/3w-9xxx.h
drivers/scsi/3w-xxxx.c
drivers/scsi/3w-xxxx.h
drivers/scsi/BusLogic.c
drivers/scsi/Makefile
drivers/scsi/aacraid/README [deleted file]
drivers/scsi/aacraid/aacraid.h
drivers/scsi/aacraid/commctrl.c
drivers/scsi/aacraid/linit.c
drivers/scsi/aic7xxx/Kconfig.aic7xxx
drivers/scsi/aic7xxx/aic79xx.h
drivers/scsi/aic7xxx/aic79xx.reg
drivers/scsi/aic7xxx/aic79xx.seq
drivers/scsi/aic7xxx/aic79xx_core.c
drivers/scsi/aic7xxx/aic79xx_inline.h
drivers/scsi/aic7xxx/aic79xx_osm.c
drivers/scsi/aic7xxx/aic79xx_osm.h
drivers/scsi/aic7xxx/aic79xx_pci.c
drivers/scsi/aic7xxx/aic79xx_pci.h
drivers/scsi/aic7xxx/aic79xx_reg.h_shipped
drivers/scsi/aic7xxx/aic79xx_reg_print.c_shipped
drivers/scsi/aic7xxx/aic79xx_seq.h_shipped
drivers/scsi/aic7xxx/aic7xxx_osm.c
drivers/scsi/aic7xxx/aic7xxx_osm.h
drivers/scsi/aic7xxx/aic7xxx_pci.c
drivers/scsi/aic7xxx/aic7xxx_pci.h
drivers/scsi/ch.c
drivers/scsi/dpt_i2o.c
drivers/scsi/hosts.c
drivers/scsi/ips.c
drivers/scsi/iscsi_tcp.c
drivers/scsi/iscsi_tcp.h
drivers/scsi/lpfc/lpfc_scsi.c
drivers/scsi/megaraid.c
drivers/scsi/megaraid.h
drivers/scsi/megaraid/megaraid_sas.c
drivers/scsi/qla2xxx/Kconfig
drivers/scsi/qla2xxx/Makefile
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_dbg.c
drivers/scsi/qla2xxx/qla_dbg.h
drivers/scsi/qla2xxx/qla_gbl.h
drivers/scsi/qla2xxx/qla_gs.c
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/qla2xxx/qla_sup.c
drivers/scsi/qla2xxx/qla_version.h
drivers/scsi/raid_class.c
drivers/scsi/scsi.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_priv.h
drivers/scsi/scsi_proc.c
drivers/scsi/scsi_scan.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/scsi_transport_fc.c
drivers/scsi/scsi_transport_iscsi.c
drivers/scsi/scsi_transport_sas.c
drivers/scsi/scsi_transport_spi.c
drivers/scsi/sd.c
drivers/scsi/sr.c
drivers/scsi/sr_ioctl.c
drivers/scsi/st.c
include/linux/pci_ids.h
include/linux/raid_class.h
include/scsi/iscsi_if.h
include/scsi/scsi.h
include/scsi/scsi_cmnd.h
include/scsi/scsi_host.h
include/scsi/scsi_transport.h
include/scsi/scsi_transport_fc.h
include/scsi/scsi_transport_iscsi.h
include/scsi/scsi_transport_spi.h

diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.txt
new file mode 100644 (file)
index 0000000..820fd07
--- /dev/null
@@ -0,0 +1,108 @@
+AACRAID Driver for Linux (take two)
+
+Introduction
+-------------------------
+The aacraid driver adds support for Adaptec (http://www.adaptec.com)
+RAID controllers. This is a major rewrite from the original
+Adaptec supplied driver. It has signficantly cleaned up both the code
+and the running binary size (the module is less than half the size of
+the original).
+
+Supported Cards/Chipsets
+-------------------------
+       PCI ID (pci.ids)        OEM     Product
+       9005:0285:9005:028a     Adaptec 2020ZCR (Skyhawk)
+       9005:0285:9005:028e     Adaptec 2020SA (Skyhawk)
+       9005:0285:9005:028b     Adaptec 2025ZCR (Terminator)
+       9005:0285:9005:028f     Adaptec 2025SA (Terminator)
+       9005:0285:9005:0286     Adaptec 2120S (Crusader)
+       9005:0286:9005:028d     Adaptec 2130S (Lancer)
+       9005:0285:9005:0285     Adaptec 2200S (Vulcan)
+       9005:0285:9005:0287     Adaptec 2200S (Vulcan-2m)
+       9005:0286:9005:028c     Adaptec 2230S (Lancer)
+       9005:0286:9005:028c     Adaptec 2230SLP (Lancer)
+       9005:0285:9005:0296     Adaptec 2240S (SabreExpress)
+       9005:0285:9005:0290     Adaptec 2410SA (Jaguar)
+       9005:0285:9005:0293     Adaptec 21610SA (Corsair-16)
+       9005:0285:103c:3227     Adaptec 2610SA (Bearcat)
+       9005:0285:9005:0292     Adaptec 2810SA (Corsair-8)
+       9005:0285:9005:0294     Adaptec Prowler
+       9005:0286:9005:029d     Adaptec 2420SA (Intruder)
+       9005:0286:9005:029c     Adaptec 2620SA (Intruder)
+       9005:0286:9005:029b     Adaptec 2820SA (Intruder)
+       9005:0286:9005:02a7     Adaptec 2830SA (Skyray)
+       9005:0286:9005:02a8     Adaptec 2430SA (Skyray)
+       9005:0285:9005:0288     Adaptec 3230S (Harrier)
+       9005:0285:9005:0289     Adaptec 3240S (Tornado)
+       9005:0285:9005:0298     Adaptec 4000SAS (BlackBird)
+       9005:0285:9005:0297     Adaptec 4005SAS (AvonPark)
+       9005:0285:9005:0299     Adaptec 4800SAS (Marauder-X)
+       9005:0285:9005:029a     Adaptec 4805SAS (Marauder-E)
+       9005:0286:9005:02a2     Adaptec 4810SAS (Hurricane)
+       1011:0046:9005:0364     Adaptec 5400S (Mustang)
+       1011:0046:9005:0365     Adaptec 5400S (Mustang)
+       9005:0283:9005:0283     Adaptec Catapult (3210S with arc firmware)
+       9005:0284:9005:0284     Adaptec Tomcat (3410S with arc firmware)
+       9005:0287:9005:0800     Adaptec Themisto (Jupiter)
+       9005:0200:9005:0200     Adaptec Themisto (Jupiter)
+       9005:0286:9005:0800     Adaptec Callisto (Jupiter)
+       1011:0046:9005:1364     Dell    PERC 2/QC (Quad Channel, Mustang)
+       1028:0001:1028:0001     Dell    PERC 2/Si (Iguana)
+       1028:0003:1028:0003     Dell    PERC 3/Si (SlimFast)
+       1028:0002:1028:0002     Dell    PERC 3/Di (Opal)
+       1028:0004:1028:0004     Dell    PERC 3/DiF (Iguana)
+       1028:0002:1028:00d1     Dell    PERC 3/DiV (Viper)
+       1028:0002:1028:00d9     Dell    PERC 3/DiL (Lexus)
+       1028:000a:1028:0106     Dell    PERC 3/DiJ (Jaguar)
+       1028:000a:1028:011b     Dell    PERC 3/DiD (Dagger)
+       1028:000a:1028:0121     Dell    PERC 3/DiB (Boxster)
+       9005:0285:1028:0287     Dell    PERC 320/DC (Vulcan)
+       9005:0285:1028:0291     Dell    CERC 2 (DellCorsair)
+       1011:0046:103c:10c2     HP      NetRAID-4M (Mustang)
+       9005:0285:17aa:0286     Legend  S220 (Crusader)
+       9005:0285:17aa:0287     Legend  S230 (Vulcan)
+       9005:0285:9005:0290     IBM     ServeRAID 7t (Jaguar)
+       9005:0285:1014:02F2     IBM     ServeRAID 8i (AvonPark)
+       9005:0285:1014:0312     IBM     ServeRAID 8i (AvonParkLite)
+       9005:0286:1014:9580     IBM     ServeRAID 8k/8k-l8 (Aurora)
+       9005:0286:1014:9540     IBM     ServeRAID 8k/8k-l4 (AuroraLite)
+       9005:0286:9005:029f     ICP     ICP9014R0 (Lancer)
+       9005:0286:9005:029e     ICP     ICP9024R0 (Lancer)
+       9005:0286:9005:02a0     ICP     ICP9047MA (Lancer)
+       9005:0286:9005:02a1     ICP     ICP9087MA (Lancer)
+       9005:0286:9005:02a4     ICP     ICP9085LI (Marauder-X)
+       9005:0286:9005:02a5     ICP     ICP5085BR (Marauder-E)
+       9005:0286:9005:02a3     ICP     ICP5085AU (Hurricane)
+       9005:0286:9005:02a6     ICP     ICP9067MA (Intruder-6)
+       9005:0286:9005:02a9     ICP     ICP5087AU (Skyray)
+       9005:0286:9005:02aa     ICP     ICP5047AU (Skyray)
+
+People
+-------------------------
+Alan Cox <alan@redhat.com>
+Christoph Hellwig <hch@infradead.org>  (updates for new-style PCI probing and SCSI host registration,
+                                        small cleanups/fixes)
+Matt Domsch <matt_domsch@dell.com>     (revision ioctl, adapter messages)
+Deanna Bonds                            (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers
+                                        added new ioctls, changed scsi interface to use new error handler,
+                                        increased the number of fibs and outstanding commands to a container)
+
+                                       (fixed 64bit and 64G memory model, changed confusing naming convention
+                                        where fibs that go to the hardware are consistently called hw_fibs and
+                                        not just fibs like the name of the driver tracking structure)
+Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations.
+
+Original Driver
+-------------------------
+Adaptec Unix OEM Product Group
+
+Mailing List
+-------------------------
+linux-scsi@vger.kernel.org (Interested parties troll here)
+Also note this is very different to Brian's original driver
+so don't expect him to support it.
+Adaptec does support this driver.  Contact Adaptec tech support or
+aacraid@adaptec.com
+
+Original by Brian Boerner February 2001
+Rewritten by Alan Cox, November 2001
index 1883d22cffeb100a73bf3ea1479722aad93f0b98..e67cf15e9c3961af697067c4007e78ffd359da4b 100644 (file)
@@ -23,6 +23,7 @@ config FUSION_FC
        tristate "Fusion MPT ScsiHost drivers for FC"
        depends on PCI && SCSI
        select FUSION
+       select SCSI_FC_ATTRS
        ---help---
          SCSI HOST support for a Fiber Channel host adapters.
 
index b61e3d175070f6cefec9ce17f6eaf8ae3f8b8b54..02cdc840a06b0ab3c6c2d114c18699ac8b2430ad 100644 (file)
@@ -6,7 +6,7 @@
  *          Title:  MPI Message independent structures and definitions
  *  Creation Date:  July 27, 2000
  *
- *    mpi.h Version:  01.05.08
+ *    mpi.h Version:  01.05.10
  *
  *  Version History
  *  ---------------
@@ -74,6 +74,8 @@
  *  06-24-05  01.05.08  Added function codes for SCSI IO 32 and
  *                      TargetAssistExtended requests.
  *                      Added EEDP IOCStatus codes.
+ *  08-03-05  01.05.09  Bumped MPI_HEADER_VERSION_UNIT.
+ *  08-30-05  01.05.10  Added 2 new IOCStatus codes for Target.
  *  --------------------------------------------------------------------------
  */
 
 /* Note: The major versions of 0xe0 through 0xff are reserved */
 
 /* versioning for this MPI header set */
-#define MPI_HEADER_VERSION_UNIT             (0x0A)
+#define MPI_HEADER_VERSION_UNIT             (0x0C)
 #define MPI_HEADER_VERSION_DEV              (0x00)
 #define MPI_HEADER_VERSION_UNIT_MASK        (0xFF00)
 #define MPI_HEADER_VERSION_UNIT_SHIFT       (8)
@@ -711,6 +713,8 @@ typedef struct _MSG_DEFAULT_REPLY
 #define MPI_IOCSTATUS_TARGET_DATA_OFFSET_ERROR   (0x006D)
 #define MPI_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E)
 #define MPI_IOCSTATUS_TARGET_IU_TOO_SHORT        (0x006F)
+#define MPI_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT     (0x0070)
+#define MPI_IOCSTATUS_TARGET_NAK_RECEIVED        (0x0071)
 
 /****************************************************************************/
 /*  Additional FCP target values (obsolete)                                 */
@@ -745,7 +749,7 @@ typedef struct _MSG_DEFAULT_REPLY
 #define MPI_IOCSTATUS_LAN_CANCELED              (0x0087)
 
 /****************************************************************************/
-/*  Serial Attached SCSI values                                                              */
+/*  Serial Attached SCSI values                                             */
 /****************************************************************************/
 
 #define MPI_IOCSTATUS_SAS_SMP_REQUEST_FAILED    (0x0090)
index d8339896f7343c60732c3f0f5f6c92bf8391373f..b1becec27e1bf021af9fde7bfb4d08d9b19d34b7 100644 (file)
@@ -6,7 +6,7 @@
  *          Title:  MPI Config message, structures, and Pages
  *  Creation Date:  July 27, 2000
  *
- *    mpi_cnfg.h Version:  01.05.09
+ *    mpi_cnfg.h Version:  01.05.11
  *
  *  Version History
  *  ---------------
  *                      Added OwnerDevHandle and Flags field to SAS PHY Page 0.
  *                      Added IOC GPIO Flags define to SAS Enclosure Page 0.
  *                      Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT.
+ *  08-03-05  01.05.10  Removed ISDataScrubRate and ISResyncRate from
+ *                      Manufacturing Page 4.
+ *                      Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit.
+ *                      Added NumDevsPerEnclosure field to SAS IO Unit page 2.
+ *                      Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP
+ *                      define.
+ *                      Added EnclosureHandle field to SAS Expander page 0.
+ *                      Removed redundant NumTableEntriesProg field from SAS
+ *                      Expander Page 1.
+ *  08-30-05  01.05.11  Added DeviceID for FC949E and changed the DeviceID for
+ *                      SAS1078.
+ *                      Added more defines for Manufacturing Page 4 Flags field.
+ *                      Added more defines for IOCSettings and added
+ *                      ExpanderSpinup field to Bios Page 1.
+ *                      Added postpone SATA Init bit to SAS IO Unit Page 1
+ *                      ControlFlags.
+ *                      Changed LogEntry format for Log Page 0.
  *  --------------------------------------------------------------------------
  */
 
@@ -494,7 +511,7 @@ typedef struct _MSG_CONFIG_REPLY
 #define MPI_MANUFACTPAGE_DEVICEID_FC929X            (0x0626)
 #define MPI_MANUFACTPAGE_DEVICEID_FC939X            (0x0642)
 #define MPI_MANUFACTPAGE_DEVICEID_FC949X            (0x0640)
-#define MPI_MANUFACTPAGE_DEVICEID_FC949ES           (0x0646)
+#define MPI_MANUFACTPAGE_DEVICEID_FC949E            (0x0646)
 /* SCSI */
 #define MPI_MANUFACTPAGE_DEVID_53C1030              (0x0030)
 #define MPI_MANUFACTPAGE_DEVID_53C1030ZC            (0x0031)
@@ -510,7 +527,7 @@ typedef struct _MSG_CONFIG_REPLY
 #define MPI_MANUFACTPAGE_DEVID_SAS1066E             (0x005A)
 #define MPI_MANUFACTPAGE_DEVID_SAS1068              (0x0054)
 #define MPI_MANUFACTPAGE_DEVID_SAS1068E             (0x0058)
-#define MPI_MANUFACTPAGE_DEVID_SAS1078              (0x0060)
+#define MPI_MANUFACTPAGE_DEVID_SAS1078              (0x0062)
 
 
 typedef struct _CONFIG_PAGE_MANUFACTURING_0
@@ -602,9 +619,7 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4
     U32                             IMVolumeSettings;   /* 50h */
     U32                             Reserved3;          /* 54h */
     U32                             Reserved4;          /* 58h */
-    U8                              ISDataScrubRate;    /* 5Ch */
-    U8                              ISResyncRate;       /* 5Dh */
-    U16                             Reserved5;          /* 5Eh */
+    U32                             Reserved5;          /* 5Ch */
     U8                              IMEDataScrubRate;   /* 60h */
     U8                              IMEResyncRate;      /* 61h */
     U16                             Reserved6;          /* 62h */
@@ -616,9 +631,14 @@ typedef struct _CONFIG_PAGE_MANUFACTURING_4
 } CONFIG_PAGE_MANUFACTURING_4, MPI_POINTER PTR_CONFIG_PAGE_MANUFACTURING_4,
   ManufacturingPage4_t, MPI_POINTER pManufacturingPage4_t;
 
-#define MPI_MANUFACTURING4_PAGEVERSION                  (0x02)
+#define MPI_MANUFACTURING4_PAGEVERSION                  (0x03)
 
 /* defines for the Flags field */
+#define MPI_MANPAGE4_IME_DISABLE                        (0x20)
+#define MPI_MANPAGE4_IM_DISABLE                         (0x10)
+#define MPI_MANPAGE4_IS_DISABLE                         (0x08)
+#define MPI_MANPAGE4_IR_MODEPAGE8_DISABLE               (0x04)
+#define MPI_MANPAGE4_IM_RESYNC_CACHE_ENABLE             (0x02)
 #define MPI_MANPAGE4_IR_NO_MIX_SAS_SATA                 (0x01)
 
 
@@ -669,7 +689,7 @@ typedef struct _CONFIG_PAGE_IO_UNIT_1
 } CONFIG_PAGE_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_IO_UNIT_1,
   IOUnitPage1_t, MPI_POINTER pIOUnitPage1_t;
 
-#define MPI_IOUNITPAGE1_PAGEVERSION                     (0x01)
+#define MPI_IOUNITPAGE1_PAGEVERSION                     (0x02)
 
 /* IO Unit Page 1 Flags defines */
 #define MPI_IOUNITPAGE1_MULTI_FUNCTION                  (0x00000000)
@@ -681,7 +701,7 @@ typedef struct _CONFIG_PAGE_IO_UNIT_1
 #define MPI_IOUNITPAGE1_DISABLE_IR                      (0x00000040)
 #define MPI_IOUNITPAGE1_FORCE_32                        (0x00000080)
 #define MPI_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE        (0x00000100)
-
+#define MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE        (0x00000200)
 
 typedef struct _MPI_ADAPTER_INFO
 {
@@ -968,7 +988,8 @@ typedef struct _CONFIG_PAGE_BIOS_1
     U32                     Reserved1;                  /* 0Ch */
     U32                     DeviceSettings;             /* 10h */
     U16                     NumberOfDevices;            /* 14h */
-    U16                     Reserved2;                  /* 16h */
+    U8                      ExpanderSpinup;             /* 16h */
+    U8                      Reserved2;                  /* 17h */
     U16                     IOTimeoutBlockDevicesNonRM; /* 18h */
     U16                     IOTimeoutSequential;        /* 1Ah */
     U16                     IOTimeoutOther;             /* 1Ch */
@@ -976,7 +997,7 @@ typedef struct _CONFIG_PAGE_BIOS_1
 } CONFIG_PAGE_BIOS_1, MPI_POINTER PTR_CONFIG_PAGE_BIOS_1,
   BIOSPage1_t, MPI_POINTER pBIOSPage1_t;
 
-#define MPI_BIOSPAGE1_PAGEVERSION                       (0x02)
+#define MPI_BIOSPAGE1_PAGEVERSION                       (0x03)
 
 /* values for the BiosOptions field */
 #define MPI_BIOSPAGE1_OPTIONS_SPI_ENABLE                (0x00000400)
@@ -985,8 +1006,15 @@ typedef struct _CONFIG_PAGE_BIOS_1
 #define MPI_BIOSPAGE1_OPTIONS_DISABLE_BIOS              (0x00000001)
 
 /* values for the IOCSettings field */
+#define MPI_BIOSPAGE1_IOCSET_MASK_INITIAL_SPINUP_DELAY  (0x0F000000)
+#define MPI_BIOSPAGE1_IOCSET_SHIFT_INITIAL_SPINUP_DELAY (24)
+
 #define MPI_BIOSPAGE1_IOCSET_MASK_PORT_ENABLE_DELAY     (0x00F00000)
 #define MPI_BIOSPAGE1_IOCSET_SHIFT_PORT_ENABLE_DELAY    (20)
+
+#define MPI_BIOSPAGE1_IOCSET_AUTO_PORT_ENABLE           (0x00080000)
+#define MPI_BIOSPAGE1_IOCSET_DIRECT_ATTACH_SPINUP_MODE  (0x00040000)
+
 #define MPI_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE       (0x00030000)
 #define MPI_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT        (0x00000000)
 #define MPI_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT           (0x00010000)
@@ -1016,6 +1044,11 @@ typedef struct _CONFIG_PAGE_BIOS_1
 #define MPI_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN         (0x00000002)
 #define MPI_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN          (0x00000001)
 
+/* defines for the ExpanderSpinup field */
+#define MPI_BIOSPAGE1_EXPSPINUP_MASK_MAX_TARGET         (0xF0)
+#define MPI_BIOSPAGE1_EXPSPINUP_SHIFT_MAX_TARGET        (4)
+#define MPI_BIOSPAGE1_EXPSPINUP_MASK_DELAY              (0x0F)
+
 typedef struct _MPI_BOOT_DEVICE_ADAPTER_ORDER
 {
     U32         Reserved1;                              /* 00h */
@@ -1233,13 +1266,13 @@ typedef struct _CONFIG_PAGE_SCSI_PORT_0
 
 #define MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD     (8)
 #define MPI_SCSIPORTPAGE0_CAP_GET_MIN_SYNC_PERIOD(Cap)      \
-    (  ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MIN_SYNC_PERIOD) \
+    (  ((Cap) & MPI_SCSIPORTPAGE0_CAP_MIN_SYNC_PERIOD_MASK) \
     >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MIN_SYNC_PERIOD          \
     )
 #define MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK      (0x00FF0000)
 #define MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET     (16)
 #define MPI_SCSIPORTPAGE0_CAP_GET_MAX_SYNC_OFFSET(Cap)      \
-    (  ((Cap) & MPI_SCSIPORTPAGE0_CAP_MASK_MAX_SYNC_OFFSET) \
+    (  ((Cap) & MPI_SCSIPORTPAGE0_CAP_MAX_SYNC_OFFSET_MASK) \
     >> MPI_SCSIPORTPAGE0_CAP_SHIFT_MAX_SYNC_OFFSET          \
     )
 #define MPI_SCSIPORTPAGE0_CAP_IDP                       (0x08000000)
@@ -2370,47 +2403,48 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
 } CONFIG_PAGE_SAS_IO_UNIT_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_1,
   SasIOUnitPage1_t, MPI_POINTER pSasIOUnitPage1_t;
 
-#define MPI_SASIOUNITPAGE1_PAGEVERSION      (0x04)
+#define MPI_SASIOUNITPAGE1_PAGEVERSION      (0x05)
 
 /* values for SAS IO Unit Page 1 ControlFlags */
-#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST        (0x8000)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX            (0x4000)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX            (0x2000)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE        (0x1000)
-#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH        (0x0800)
-
-#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT        (0x0600)
-#define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT       (9)
-#define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH        (0x00)
-#define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT         (0x01)
-#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT        (0x02)
-
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED     (0x0040)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED       (0x0020)
-#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED       (0x0010)
-#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH   (0x0008)
-#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL     (0x0004)
-#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY     (0x0002)
-#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION       (0x0001)
+#define MPI_SAS_IOUNIT1_CONTROL_DEVICE_SELF_TEST            (0x8000)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_3_0_MAX                (0x4000)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_1_5_MAX                (0x2000)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_SW_PRESERVE            (0x1000)
+#define MPI_SAS_IOUNIT1_CONTROL_DISABLE_SAS_HASH            (0x0800)
+
+#define MPI_SAS_IOUNIT1_CONTROL_MASK_DEV_SUPPORT            (0x0600)
+#define MPI_SAS_IOUNIT1_CONTROL_SHIFT_DEV_SUPPORT           (9)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SUPPORT_BOTH            (0x00)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SAS_SUPPORT             (0x01)
+#define MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT            (0x02)
+
+#define MPI_SAS_IOUNIT1_CONTROL_POSTPONE_SATA_INIT          (0x0100)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED     (0x0080)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_SMART_REQUIRED         (0x0040)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_NCQ_REQUIRED           (0x0020)
+#define MPI_SAS_IOUNIT1_CONTROL_SATA_FUA_REQUIRED           (0x0010)
+#define MPI_SAS_IOUNIT1_CONTROL_PHY_ENABLE_ORDER_HIGH       (0x0008)
+#define MPI_SAS_IOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL         (0x0004)
+#define MPI_SAS_IOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY         (0x0002)
+#define MPI_SAS_IOUNIT1_CONTROL_CLEAR_AFFILIATION           (0x0001)
 
 /* values for SAS IO Unit Page 1 PortFlags */
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM     (0x00)
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM     (0x04)
-#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG     (0x01)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_0_TARGET_IOC_NUM         (0x00)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_1_TARGET_IOC_NUM         (0x04)
+#define MPI_SAS_IOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG         (0x01)
 
 /* values for SAS IO Unit Page 0 PhyFlags */
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE           (0x04)
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT             (0x02)
-#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT             (0x01)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_PHY_DISABLE               (0x04)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_TX_INVERT                 (0x02)
+#define MPI_SAS_IOUNIT1_PHY_FLAGS_RX_INVERT                 (0x01)
 
 /* values for SAS IO Unit Page 0 MaxMinLinkRate */
-#define MPI_SAS_IOUNIT1_MAX_RATE_MASK                   (0xF0)
-#define MPI_SAS_IOUNIT1_MAX_RATE_1_5                    (0x80)
-#define MPI_SAS_IOUNIT1_MAX_RATE_3_0                    (0x90)
-#define MPI_SAS_IOUNIT1_MIN_RATE_MASK                   (0x0F)
-#define MPI_SAS_IOUNIT1_MIN_RATE_1_5                    (0x08)
-#define MPI_SAS_IOUNIT1_MIN_RATE_3_0                    (0x09)
+#define MPI_SAS_IOUNIT1_MAX_RATE_MASK                       (0xF0)
+#define MPI_SAS_IOUNIT1_MAX_RATE_1_5                        (0x80)
+#define MPI_SAS_IOUNIT1_MAX_RATE_3_0                        (0x90)
+#define MPI_SAS_IOUNIT1_MIN_RATE_MASK                       (0x0F)
+#define MPI_SAS_IOUNIT1_MIN_RATE_1_5                        (0x08)
+#define MPI_SAS_IOUNIT1_MIN_RATE_3_0                        (0x09)
 
 /* see mpi_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
 
@@ -2418,16 +2452,18 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_1
 typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
 {
     CONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
-    U32                                 Reserved1;              /* 08h */
+    U8                                  NumDevsPerEnclosure;    /* 08h */
+    U8                                  Reserved1;              /* 09h */
+    U16                                 Reserved2;              /* 0Ah */
     U16                                 MaxPersistentIDs;       /* 0Ch */
     U16                                 NumPersistentIDsUsed;   /* 0Eh */
     U8                                  Status;                 /* 10h */
     U8                                  Flags;                  /* 11h */
-    U16                                 MaxNumPhysicalMappedIDs;/* 12h */              /* 12h */
+    U16                                 MaxNumPhysicalMappedIDs;/* 12h */
 } CONFIG_PAGE_SAS_IO_UNIT_2, MPI_POINTER PTR_CONFIG_PAGE_SAS_IO_UNIT_2,
   SasIOUnitPage2_t, MPI_POINTER pSasIOUnitPage2_t;
 
-#define MPI_SASIOUNITPAGE2_PAGEVERSION      (0x04)
+#define MPI_SASIOUNITPAGE2_PAGEVERSION      (0x05)
 
 /* values for SAS IO Unit Page 2 Status field */
 #define MPI_SAS_IOUNIT2_STATUS_DISABLED_PERSISTENT_MAPPINGS (0x02)
@@ -2441,6 +2477,7 @@ typedef struct _CONFIG_PAGE_SAS_IO_UNIT_2
 #define MPI_SAS_IOUNIT2_FLAGS_NO_PHYS_MAP                   (0x00)
 #define MPI_SAS_IOUNIT2_FLAGS_DIRECT_ATTACH_PHYS_MAP        (0x01)
 #define MPI_SAS_IOUNIT2_FLAGS_ENCLOSURE_SLOT_PHYS_MAP       (0x02)
+#define MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP        (0x07)
 
 #define MPI_SAS_IOUNIT2_FLAGS_RESERVE_ID_0_FOR_BOOT         (0x10)
 #define MPI_SAS_IOUNIT2_FLAGS_DA_STARTING_SLOT              (0x20)
@@ -2473,7 +2510,7 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_0
     CONFIG_EXTENDED_PAGE_HEADER         Header;                 /* 00h */
     U8                                  PhysicalPort;           /* 08h */
     U8                                  Reserved1;              /* 09h */
-    U16                                 Reserved2;              /* 0Ah */
+    U16                                 EnclosureHandle;        /* 0Ah */
     U64                                 SASAddress;             /* 0Ch */
     U32                                 DiscoveryStatus;        /* 14h */
     U16                                 DevHandle;              /* 18h */
@@ -2487,7 +2524,7 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_0
 } CONFIG_PAGE_SAS_EXPANDER_0, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_0,
   SasExpanderPage0_t, MPI_POINTER pSasExpanderPage0_t;
 
-#define MPI_SASEXPANDER0_PAGEVERSION        (0x02)
+#define MPI_SASEXPANDER0_PAGEVERSION        (0x03)
 
 /* values for SAS Expander Page 0 DiscoveryStatus field */
 #define MPI_SAS_EXPANDER0_DS_LOOP_DETECTED              (0x00000001)
@@ -2527,9 +2564,9 @@ typedef struct _CONFIG_PAGE_SAS_EXPANDER_1
     U8                          NegotiatedLinkRate;     /* 1Fh */
     U8                          PhyIdentifier;          /* 20h */
     U8                          AttachedPhyIdentifier;  /* 21h */
-    U8                          NumTableEntriesProg;    /* 22h */
+    U8                          Reserved3;              /* 22h */
     U8                          DiscoveryInfo;          /* 23h */
-    U32                         Reserved3;              /* 24h */
+    U32                         Reserved4;              /* 24h */
 } CONFIG_PAGE_SAS_EXPANDER_1, MPI_POINTER PTR_CONFIG_PAGE_SAS_EXPANDER_1,
   SasExpanderPage1_t, MPI_POINTER pSasExpanderPage1_t;
 
@@ -2766,16 +2803,15 @@ typedef struct _CONFIG_PAGE_SAS_ENCLOSURE_0
 #define MPI_LOG_0_NUM_LOG_ENTRIES        (1)
 #endif
 
-#define MPI_LOG_0_LOG_DATA_LENGTH        (20)
+#define MPI_LOG_0_LOG_DATA_LENGTH        (0x1C)
 
 typedef struct _MPI_LOG_0_ENTRY
 {
-    U64         WWID;                               /* 00h */
-    U32         TimeStamp;                          /* 08h */
-    U32         Reserved1;                          /* 0Ch */
-    U16         LogSequence;                        /* 10h */
-    U16         LogEntryQualifier;                  /* 12h */
-    U8          LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 14h */
+    U32         TimeStamp;                          /* 00h */
+    U32         Reserved1;                          /* 04h */
+    U16         LogSequence;                        /* 08h */
+    U16         LogEntryQualifier;                  /* 0Ah */
+    U8          LogData[MPI_LOG_0_LOG_DATA_LENGTH]; /* 0Ch */
 } MPI_LOG_0_ENTRY, MPI_POINTER PTR_MPI_LOG_0_ENTRY,
   MpiLog0Entry_t, MPI_POINTER pMpiLog0Entry_t;
 
@@ -2794,7 +2830,7 @@ typedef struct _CONFIG_PAGE_LOG_0
 } CONFIG_PAGE_LOG_0, MPI_POINTER PTR_CONFIG_PAGE_LOG_0,
   LogPage0_t, MPI_POINTER pLogPage0_t;
 
-#define MPI_LOG_0_PAGEVERSION               (0x00)
+#define MPI_LOG_0_PAGEVERSION               (0x01)
 
 
 #endif
index 1a30ef16adb4d58911967f5cf585c0c7306cbf94..4a5f8dd1d7666711ccc0f29ad1395e88e30a7a4a 100644 (file)
@@ -6,25 +6,25 @@
  Copyright (c) 2000-2005 LSI Logic Corporation.
 
  ---------------------------------------
- Header Set Release Version:    01.05.10
- Header Set Release Date:       03-11-05
+ Header Set Release Version:    01.05.12
+ Header Set Release Date:       08-30-05
  ---------------------------------------
 
  Filename               Current version     Prior version
  ----------             ---------------     -------------
- mpi.h                  01.05.08            01.05.07
- mpi_ioc.h              01.05.09            01.05.08
- mpi_cnfg.h             01.05.09            01.05.08
- mpi_init.h             01.05.05            01.05.04
- mpi_targ.h             01.05.05            01.05.04
+ mpi.h                  01.05.10            01.05.09
+ mpi_ioc.h              01.05.10            01.05.09
+ mpi_cnfg.h             01.05.11            01.05.10
+ mpi_init.h             01.05.06            01.05.06
+ mpi_targ.h             01.05.05            01.05.05
  mpi_fc.h               01.05.01            01.05.01
  mpi_lan.h              01.05.01            01.05.01
  mpi_raid.h             01.05.02            01.05.02
  mpi_tool.h             01.05.03            01.05.03
  mpi_inb.h              01.05.01            01.05.01
- mpi_sas.h              01.05.01            01.05.01
- mpi_type.h             01.05.01            01.05.01
- mpi_history.txt        01.05.09            01.05.09
+ mpi_sas.h              01.05.02            01.05.01
+ mpi_type.h             01.05.02            01.05.01
+ mpi_history.txt        01.05.12            01.05.11
 
 
  *  Date      Version   Description
@@ -91,6 +91,8 @@ mpi.h
  *  06-24-05  01.05.08  Added function codes for SCSI IO 32 and
  *                      TargetAssistExtended requests.
  *                      Added EEDP IOCStatus codes.
+ *  08-03-05  01.05.09  Bumped MPI_HEADER_VERSION_UNIT.
+ *  08-30-05  01.05.10  Added 2 new IOCStatus codes for Target.
  *  --------------------------------------------------------------------------
 
 mpi_ioc.h
@@ -164,6 +166,10 @@ mpi_ioc.h
  *                      Removed IOCFacts Reply EEDP Capability bit.
  *  06-24-05  01.05.09  Added 5 new IOCFacts Reply IOCCapabilities bits.
  *                      Added Max SATA Targets to SAS Discovery Error event.
+ *  08-30-05  01.05.10  Added 4 new events and their event data structures.
+ *                      Added new ReasonCode value for SAS Device Status Change
+ *                      event.
+ *                      Added new family code for FC949E.
  *  --------------------------------------------------------------------------
 
 mpi_cnfg.h
@@ -402,6 +408,23 @@ mpi_cnfg.h
  *                      Added OwnerDevHandle and Flags field to SAS PHY Page 0.
  *                      Added IOC GPIO Flags define to SAS Enclosure Page 0.
  *                      Fixed the value for MPI_SAS_IOUNIT1_CONTROL_DEV_SATA_SUPPORT.
+ *  08-03-05  01.05.10  Removed ISDataScrubRate and ISResyncRate from
+ *                      Manufacturing Page 4.
+ *                      Added MPI_IOUNITPAGE1_SATA_WRITE_CACHE_DISABLE bit.
+ *                      Added NumDevsPerEnclosure field to SAS IO Unit page 2.
+ *                      Added MPI_SAS_IOUNIT2_FLAGS_HOST_ASSIGNED_PHYS_MAP
+ *                      define.
+ *                      Added EnclosureHandle field to SAS Expander page 0.
+ *                      Removed redundant NumTableEntriesProg field from SAS
+ *                      Expander Page 1.
+ *  08-30-05  01.05.11  Added DeviceID for FC949E and changed the DeviceID for
+ *                      SAS1078.
+ *                      Added more defines for Manufacturing Page 4 Flags field.
+ *                      Added more defines for IOCSettings and added
+ *                      ExpanderSpinup field to Bios Page 1.
+ *                      Added postpone SATA Init bit to SAS IO Unit Page 1
+ *                      ControlFlags.
+ *                      Changed LogEntry format for Log Page 0.
  *  --------------------------------------------------------------------------
 
 mpi_init.h
@@ -442,6 +465,8 @@ mpi_init.h
  *                      addressing.
  *  06-24-05  01.05.05  Added SCSI IO 32 structures and defines.
  *                      Added four new defines for SEP SlotStatus.
+ *  08-03-05  01.05.06  Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
+ *                      unique in the first 32 characters.
  *  --------------------------------------------------------------------------
 
 mpi_targ.h
@@ -582,6 +607,9 @@ mpi_inb.h
 
 mpi_sas.h
  *  08-19-04  01.05.01  Original release.
+ *  08-30-05  01.05.02  Added DeviceInfo bit for SEP.
+ *                      Added PrimFlags and Primitive field to SAS IO Unit
+ *                      Control request, and added a new operation code.
  *  --------------------------------------------------------------------------
 
 mpi_type.h
@@ -592,24 +620,25 @@ mpi_type.h
  *  08-08-01  01.02.01  Original release for v1.2 work.
  *  05-11-04  01.03.01  Original release for MPI v1.3.
  *  08-19-04  01.05.01  Original release for MPI v1.5.
+ *  08-30-05  01.05.02  Added PowerPC option to #ifdef's.
  *  --------------------------------------------------------------------------
 
 mpi_history.txt         Parts list history
 
-Filename    01.05.10  01.05.09
-----------  --------  --------
-mpi.h       01.05.08  01.05.07
-mpi_ioc.h   01.05.09  01.05.08
-mpi_cnfg.h  01.05.09  01.05.08
-mpi_init.h  01.05.05  01.05.04
-mpi_targ.h  01.05.05  01.05.04
-mpi_fc.h    01.05.01  01.05.01
-mpi_lan.h   01.05.01  01.05.01
-mpi_raid.h  01.05.02  01.05.02
-mpi_tool.h  01.05.03  01.05.03
-mpi_inb.h   01.05.01  01.05.01
-mpi_sas.h   01.05.01  01.05.01
-mpi_type.h  01.05.01  01.05.01
+Filename    01.05.12  01.05.11  01.05.10  01.05.09
+----------  --------  --------  --------  --------
+mpi.h       01.05.10  01.05.09  01.05.08  01.05.07
+mpi_ioc.h   01.05.10  01.05.09  01.05.09  01.05.08
+mpi_cnfg.h  01.05.11  01.05.10  01.05.09  01.05.08
+mpi_init.h  01.05.06  01.05.06  01.05.05  01.05.04
+mpi_targ.h  01.05.05  01.05.05  01.05.05  01.05.04
+mpi_fc.h    01.05.01  01.05.01  01.05.01  01.05.01
+mpi_lan.h   01.05.01  01.05.01  01.05.01  01.05.01
+mpi_raid.h  01.05.02  01.05.02  01.05.02  01.05.02
+mpi_tool.h  01.05.03  01.05.03  01.05.03  01.05.03
+mpi_inb.h   01.05.01  01.05.01  01.05.01  01.05.01
+mpi_sas.h   01.05.02  01.05.01  01.05.01  01.05.01
+mpi_type.h  01.05.02  01.05.01  01.05.01  01.05.01
 
 Filename    01.05.08   01.05.07   01.05.06   01.05.05   01.05.04   01.05.03
 ----------  --------   --------   --------   --------   --------   --------
index d5af75afbd94a8545b163012be4aef243dc7f36d..68941f459ca33e3ae41ca0f26b886ecdea6c464d 100644 (file)
@@ -6,7 +6,7 @@
  *          Title:  MPI initiator mode messages and structures
  *  Creation Date:  June 8, 2000
  *
- *    mpi_init.h Version:  01.05.05
+ *    mpi_init.h Version:  01.05.06
  *
  *  Version History
  *  ---------------
@@ -50,6 +50,8 @@
  *                      addressing.
  *  06-24-05  01.05.05  Added SCSI IO 32 structures and defines.
  *                      Added four new defines for SEP SlotStatus.
+ *  08-03-05  01.05.06  Fixed some MPI_SCSIIO32_MSGFLGS_ defines to make them
+ *                      unique in the first 32 characters.
  *  --------------------------------------------------------------------------
  */
 
@@ -290,8 +292,8 @@ typedef struct _MSG_SCSI_IO32_REQUEST
 
 /* SCSI IO 32 MsgFlags bits */
 #define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH                (0x01)
-#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_32             (0x00)
-#define MPI_SCSIIO32_MSGFLGS_SENSE_WIDTH_64             (0x01)
+#define MPI_SCSIIO32_MSGFLGS_32_SENSE_WIDTH             (0x00)
+#define MPI_SCSIIO32_MSGFLGS_64_SENSE_WIDTH             (0x01)
 
 #define MPI_SCSIIO32_MSGFLGS_SENSE_LOCATION             (0x02)
 #define MPI_SCSIIO32_MSGFLGS_SENSE_LOC_HOST             (0x00)
index 93b70e2b426623813c290bca3315ac36705e1f24..2c5f43fa7c73d742522b1cc00e0163731f398fa1 100644 (file)
@@ -6,7 +6,7 @@
  *          Title:  MPI IOC, Port, Event, FW Download, and FW Upload messages
  *  Creation Date:  August 11, 2000
  *
- *    mpi_ioc.h Version:  01.05.09
+ *    mpi_ioc.h Version:  01.05.10
  *
  *  Version History
  *  ---------------
  *                      Removed IOCFacts Reply EEDP Capability bit.
  *  06-24-05  01.05.09  Added 5 new IOCFacts Reply IOCCapabilities bits.
  *                      Added Max SATA Targets to SAS Discovery Error event.
+ *  08-30-05  01.05.10  Added 4 new events and their event data structures.
+ *                      Added new ReasonCode value for SAS Device Status Change
+ *                      event.
+ *                      Added new family code for FC949E.
  *  --------------------------------------------------------------------------
  */
 
@@ -464,6 +468,10 @@ typedef struct _MSG_EVENT_ACK_REPLY
 #define MPI_EVENT_PERSISTENT_TABLE_FULL     (0x00000011)
 #define MPI_EVENT_SAS_PHY_LINK_STATUS       (0x00000012)
 #define MPI_EVENT_SAS_DISCOVERY_ERROR       (0x00000013)
+#define MPI_EVENT_IR_RESYNC_UPDATE          (0x00000014)
+#define MPI_EVENT_IR2                       (0x00000015)
+#define MPI_EVENT_SAS_DISCOVERY             (0x00000016)
+#define MPI_EVENT_LOG_ENTRY_ADDED           (0x00000021)
 
 /* AckRequired field values */
 
@@ -480,6 +488,29 @@ typedef struct _EVENT_DATA_EVENT_CHANGE
 } EVENT_DATA_EVENT_CHANGE, MPI_POINTER PTR_EVENT_DATA_EVENT_CHANGE,
   EventDataEventChange_t, MPI_POINTER pEventDataEventChange_t;
 
+/* LogEntryAdded Event data */
+
+/* this structure matches MPI_LOG_0_ENTRY in mpi_cnfg.h */
+#define MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH    (0x1C)
+typedef struct _EVENT_DATA_LOG_ENTRY
+{
+    U32         TimeStamp;                          /* 00h */
+    U32         Reserved1;                          /* 04h */
+    U16         LogSequence;                        /* 08h */
+    U16         LogEntryQualifier;                  /* 0Ah */
+    U8          LogData[MPI_EVENT_DATA_LOG_ENTRY_DATA_LENGTH]; /* 0Ch */
+} EVENT_DATA_LOG_ENTRY, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY,
+  MpiEventDataLogEntry_t, MPI_POINTER pMpiEventDataLogEntry_t;
+
+typedef struct _EVENT_DATA_LOG_ENTRY_ADDED
+{
+    U16                     LogSequence;            /* 00h */
+    U16                     Reserved1;              /* 02h */
+    U32                     Reserved2;              /* 04h */
+    EVENT_DATA_LOG_ENTRY    LogEntry;               /* 08h */
+} EVENT_DATA_LOG_ENTRY_ADDED, MPI_POINTER PTR_EVENT_DATA_LOG_ENTRY_ADDED,
+  MpiEventDataLogEntryAdded_t, MPI_POINTER pMpiEventDataLogEntryAdded_t;
+
 /* SCSI Event data for Port, Bus and Device forms */
 
 typedef struct _EVENT_DATA_SCSI
@@ -538,6 +569,7 @@ typedef struct _EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
 #define MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA            (0x05)
 #define MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED      (0x06)
 #define MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED           (0x07)
+#define MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08)
 
 
 /* SCSI Event data for Queue Full event */
@@ -579,6 +611,79 @@ typedef struct _EVENT_DATA_RAID
 #define MPI_EVENT_RAID_RC_SMART_DATA                    (0x0A)
 #define MPI_EVENT_RAID_RC_REPLACE_ACTION_STARTED        (0x0B)
 
+
+/* MPI Integrated RAID Resync Update Event data */
+
+typedef struct _MPI_EVENT_DATA_IR_RESYNC_UPDATE
+{
+    U8                      VolumeID;                   /* 00h */
+    U8                      VolumeBus;                  /* 01h */
+    U8                      ResyncComplete;             /* 02h */
+    U8                      Reserved1;                  /* 03h */
+    U32                     Reserved2;                  /* 04h */
+} MPI_EVENT_DATA_IR_RESYNC_UPDATE,
+  MPI_POINTER PTR_MPI_EVENT_DATA_IR_RESYNC_UPDATE,
+  MpiEventDataIrResyncUpdate_t, MPI_POINTER pMpiEventDataIrResyncUpdate_t;
+
+/* MPI IR2 Event data */
+
+/* MPI_LD_STATE or MPI_PD_STATE */
+typedef struct _IR2_STATE_CHANGED
+{
+    U16                 PreviousState;  /* 00h */
+    U16                 NewState;       /* 02h */
+} IR2_STATE_CHANGED, MPI_POINTER PTR_IR2_STATE_CHANGED;
+
+typedef struct _IR2_PD_INFO
+{
+    U16                 DeviceHandle;           /* 00h */
+    U8                  TruncEnclosureHandle;   /* 02h */
+    U8                  TruncatedSlot;          /* 03h */
+} IR2_PD_INFO, MPI_POINTER PTR_IR2_PD_INFO;
+
+typedef union _MPI_IR2_RC_EVENT_DATA
+{
+    IR2_STATE_CHANGED   StateChanged;
+    U32                 Lba;
+    IR2_PD_INFO         PdInfo;
+} MPI_IR2_RC_EVENT_DATA, MPI_POINTER PTR_MPI_IR2_RC_EVENT_DATA;
+
+typedef struct _MPI_EVENT_DATA_IR2
+{
+    U8                      TargetID;             /* 00h */
+    U8                      Bus;                  /* 01h */
+    U8                      ReasonCode;           /* 02h */
+    U8                      PhysDiskNum;          /* 03h */
+    MPI_IR2_RC_EVENT_DATA   IR2EventData;         /* 04h */
+} MPI_EVENT_DATA_IR2, MPI_POINTER PTR_MPI_EVENT_DATA_IR2,
+  MpiEventDataIR2_t, MPI_POINTER pMpiEventDataIR2_t;
+
+/* MPI IR2 Event data ReasonCode values */
+#define MPI_EVENT_IR2_RC_LD_STATE_CHANGED           (0x01)
+#define MPI_EVENT_IR2_RC_PD_STATE_CHANGED           (0x02)
+#define MPI_EVENT_IR2_RC_BAD_BLOCK_TABLE_FULL       (0x03)
+#define MPI_EVENT_IR2_RC_PD_INSERTED                (0x04)
+#define MPI_EVENT_IR2_RC_PD_REMOVED                 (0x05)
+#define MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED       (0x06)
+#define MPI_EVENT_IR2_RC_REBUILD_MEDIUM_ERROR       (0x07)
+
+/* defines for logical disk states */
+#define MPI_LD_STATE_OPTIMAL                        (0x00)
+#define MPI_LD_STATE_DEGRADED                       (0x01)
+#define MPI_LD_STATE_FAILED                         (0x02)
+#define MPI_LD_STATE_MISSING                        (0x03)
+#define MPI_LD_STATE_OFFLINE                        (0x04)
+
+/* defines for physical disk states */
+#define MPI_PD_STATE_ONLINE                         (0x00)
+#define MPI_PD_STATE_MISSING                        (0x01)
+#define MPI_PD_STATE_NOT_COMPATIBLE                 (0x02)
+#define MPI_PD_STATE_FAILED                         (0x03)
+#define MPI_PD_STATE_INITIALIZING                   (0x04)
+#define MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST        (0x05)
+#define MPI_PD_STATE_FAILED_AT_HOST_REQUEST         (0x06)
+#define MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON     (0xFF)
+
 /* MPI Link Status Change Event data */
 
 typedef struct _EVENT_DATA_LINK_STATUS
@@ -660,6 +765,20 @@ typedef struct _EVENT_DATA_SAS_PHY_LINK_STATUS
 #define MPI_EVENT_SAS_PLS_LR_RATE_1_5                       (0x08)
 #define MPI_EVENT_SAS_PLS_LR_RATE_3_0                       (0x09)
 
+/* SAS Discovery Event data */
+
+typedef struct _EVENT_DATA_SAS_DISCOVERY
+{
+    U32                     DiscoveryStatus;            /* 00h */
+    U32                     Reserved1;                  /* 04h */
+} EVENT_DATA_SAS_DISCOVERY, MPI_POINTER PTR_EVENT_DATA_SAS_DISCOVERY,
+  EventDataSasDiscovery_t, MPI_POINTER pEventDataSasDiscovery_t;
+
+#define MPI_EVENT_SAS_DSCVRY_COMPLETE                       (0x00000000)
+#define MPI_EVENT_SAS_DSCVRY_IN_PROGRESS                    (0x00000001)
+#define MPI_EVENT_SAS_DSCVRY_PHY_BITS_MASK                  (0xFFFF0000)
+#define MPI_EVENT_SAS_DSCVRY_PHY_BITS_SHIFT                 (16)
+
 /* SAS Discovery Errror Event data */
 
 typedef struct _EVENT_DATA_DISCOVERY_ERROR
@@ -869,6 +988,7 @@ typedef struct _MPI_FW_HEADER
 #define MPI_FW_HEADER_PID_FAMILY_919XL_FC       (0x0003) /* 919XL and 929XL */
 #define MPI_FW_HEADER_PID_FAMILY_939X_FC        (0x0004) /* 939X and 949X   */
 #define MPI_FW_HEADER_PID_FAMILY_959_FC         (0x0005)
+#define MPI_FW_HEADER_PID_FAMILY_949E_FC        (0x0006)
 /* SAS */
 #define MPI_FW_HEADER_PID_FAMILY_1064_SAS       (0x0001)
 #define MPI_FW_HEADER_PID_FAMILY_1068_SAS       (0x0002)
diff --git a/drivers/message/fusion/lsi/mpi_log_fc.h b/drivers/message/fusion/lsi/mpi_log_fc.h
new file mode 100644 (file)
index 0000000..dc98d46
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ *  Copyright (c) 2000-2001 LSI Logic Corporation. All rights reserved.
+ *
+ *  NAME:           fc_log.h
+ *  SUMMARY:        MPI IocLogInfo definitions for the SYMFC9xx chips
+ *  DESCRIPTION:    Contains the enumerated list of values that may be returned
+ *                  in the IOCLogInfo field of a MPI Default Reply Message.
+ *
+ *  CREATION DATE:  6/02/2000
+ *  ID:             $Id: fc_log.h,v 4.6 2001/07/26 14:41:33 sschremm Exp $
+ */
+
+
+/*
+ * MpiIocLogInfo_t enum
+ *
+ * These 32 bit values are used in the IOCLogInfo field of the MPI reply
+ * messages.
+ * The value is 0xabcccccc where
+ *          a = The type of log info as per the MPI spec. Since these codes are
+ *              all for Fibre Channel this value will always be 2.
+ *          b = Specifies a subclass of the firmware where
+ *                  0 = FCP Initiator
+ *                  1 = FCP Target
+ *                  2 = LAN
+ *                  3 = MPI Message Layer
+ *                  4 = FC Link
+ *                  5 = Context Manager
+ *                  6 = Invalid Field Offset
+ *                  7 = State Change Info
+ *                  all others are reserved for future use
+ *          c = A specific value within the subclass.
+ *
+ * NOTE: Any new values should be added to the end of each subclass so that the
+ *       codes remain consistent across firmware releases.
+ */
+typedef enum _MpiIocLogInfoFc
+{
+    MPI_IOCLOGINFO_FC_INIT_BASE                     = 0x20000000,
+    MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primative */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME   = 0x20000003, /* Bad Rx Frame, bad end of frame primative */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN           = 0x20000004, /* Bad Rx Frame, overrun */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER           = 0x20000005, /* Other errors caught by IOC which require retries */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD       = 0x20000006, /* Main processor could not initialize sub-processor */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OVERRUN         = 0x20000007, /* Scatter Gather overrun  */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_RX_BAD_STATUS      = 0x20000008, /* Receiver detected context mismatch via invalid header */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_RX_UNEXPECTED_FRAME= 0x20000009, /* CtxMgr detected unsupported frame type  */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_LINK_FAILURE       = 0x2000000A, /* Link failure occurred  */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_TX_TIMEOUT         = 0x2000000B, /* Transmitter timeout error */
+
+    MPI_IOCLOGINFO_FC_TARGET_BASE                   = 0x21000000,
+    MPI_IOCLOGINFO_FC_TARGET_NO_PDISC               = 0x21000001, /* not sent because we are waiting for a PDISC from the initiator */
+    MPI_IOCLOGINFO_FC_TARGET_NO_LOGIN               = 0x21000002, /* not sent because we are not logged in to the remote node */
+    MPI_IOCLOGINFO_FC_TARGET_DOAR_KILLED_BY_LIP     = 0x21000003, /* Data Out, Auto Response, not sent due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_DIAR_KILLED_BY_LIP     = 0x21000004, /* Data In, Auto Response, not sent due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_DIAR_MISSING_DATA      = 0x21000005, /* Data In, Auto Response, missing data frames */
+    MPI_IOCLOGINFO_FC_TARGET_DONR_KILLED_BY_LIP     = 0x21000006, /* Data Out, No Response, not sent due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_WRSP_KILLED_BY_LIP     = 0x21000007, /* Auto-response after a write not sent due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_DINR_KILLED_BY_LIP     = 0x21000008, /* Data In, No Response, not completed due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_DINR_MISSING_DATA      = 0x21000009, /* Data In, No Response, missing data frames */
+    MPI_IOCLOGINFO_FC_TARGET_MRSP_KILLED_BY_LIP     = 0x2100000a, /* Manual Response not sent due to a LIP */
+    MPI_IOCLOGINFO_FC_TARGET_NO_CLASS_3             = 0x2100000b, /* not sent because remote node does not support Class 3 */
+    MPI_IOCLOGINFO_FC_TARGET_LOGIN_NOT_VALID        = 0x2100000c, /* not sent because login to remote node not validated */
+    MPI_IOCLOGINFO_FC_TARGET_FROM_OUTBOUND          = 0x2100000e, /* cleared from the outbound queue after a logout */
+    MPI_IOCLOGINFO_FC_TARGET_WAITING_FOR_DATA_IN    = 0x2100000f, /* cleared waiting for data after a logout */
+
+    MPI_IOCLOGINFO_FC_LAN_BASE                      = 0x22000000,
+    MPI_IOCLOGINFO_FC_LAN_TRANS_SGL_MISSING         = 0x22000001, /* Transaction Context Sgl Missing */
+    MPI_IOCLOGINFO_FC_LAN_TRANS_WRONG_PLACE         = 0x22000002, /* Transaction Context found before an EOB */
+    MPI_IOCLOGINFO_FC_LAN_TRANS_RES_BITS_SET        = 0x22000003, /* Transaction Context value has reserved bits set */
+    MPI_IOCLOGINFO_FC_LAN_WRONG_SGL_FLAG            = 0x22000004, /* Invalid SGL Flags */
+
+    MPI_IOCLOGINFO_FC_MSG_BASE                      = 0x23000000,
+
+    MPI_IOCLOGINFO_FC_LINK_BASE                     = 0x24000000,
+    MPI_IOCLOGINFO_FC_LINK_LOOP_INIT_TIMEOUT        = 0x24000001, /* Loop initialization timed out */
+    MPI_IOCLOGINFO_FC_LINK_ALREADY_INITIALIZED      = 0x24000002, /* Another system controller already initialized the loop */
+    MPI_IOCLOGINFO_FC_LINK_LINK_NOT_ESTABLISHED     = 0x24000003, /* Not synchronized to signal or still negotiating (possible cable problem) */
+    MPI_IOCLOGINFO_FC_LINK_CRC_ERROR                = 0x24000004, /* CRC check detected error on received frame */
+
+    MPI_IOCLOGINFO_FC_CTX_BASE                      = 0x25000000,
+
+    MPI_IOCLOGINFO_FC_INVALID_FIELD_BYTE_OFFSET     = 0x26000000, /* The lower 24 bits give the byte offset of the field in the request message that is invalid */
+    MPI_IOCLOGINFO_FC_INVALID_FIELD_MAX_OFFSET      = 0x26ffffff,
+
+    MPI_IOCLOGINFO_FC_STATE_CHANGE                  = 0x27000000  /* The lower 24 bits give additional information concerning state change */
+
+} MpiIocLogInfoFc_t;
diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h
new file mode 100644 (file)
index 0000000..9259d1a
--- /dev/null
@@ -0,0 +1,162 @@
+
+/***************************************************************************
+ *                                                                         *
+ *  Copyright 2003 LSI Logic Corporation.  All rights reserved.            *
+ *                                                                         *
+ *  This file is confidential and a trade secret of LSI Logic.  The        *
+ *  receipt of or possession of this file does not convey any rights to    *
+ *  reproduce or disclose its contents or to manufacture, use, or sell     *
+ *  anything it may describe, in whole, or in part, without the specific   *
+ *  written consent of LSI Logic Corporation.                              *
+ *                                                                         *
+ ***************************************************************************
+ *
+ *           Name:  iopiIocLogInfo.h
+ *          Title:  SAS Firmware IOP Interface IOC Log Info Definitions
+ *     Programmer:  Guy Kendall
+ *  Creation Date:  September 24, 2003
+ *
+ *  Version History
+ *  ---------------
+ *
+ *  Last Updated
+ *  -------------
+ *  Version         %version: 22 %
+ *  Date Updated    %date_modified: %
+ *  Programmer      %created_by: nperucca %
+ *
+ *  Date      Who   Description
+ *  --------  ---   -------------------------------------------------------
+ *  09/24/03  GWK   Initial version
+ *
+ *
+ * Description
+ * ------------
+ * This include file contains SAS firmware interface IOC Log Info codes
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#ifndef IOPI_IOCLOGINFO_H_INCLUDED
+#define IOPI_IOCLOGINFO_H_INCLUDED
+
+
+/****************************************************************************/
+/*  IOC LOGINFO defines, 0x00000000 - 0x0FFFFFFF                            */
+/*  Format:                                                                 */
+/*      Bits 31-28: MPI_IOCLOGINFO_TYPE_SAS (3)                             */
+/*      Bits 27-24: IOC_LOGINFO_ORIGINATOR: 0=IOP, 1=PL, 2=IR               */
+/*      Bits 23-16: LOGINFO_CODE                                            */
+/*      Bits 15-0:  LOGINFO_CODE Specific                                   */
+/****************************************************************************/
+
+/****************************************************************************/
+/* IOC_LOGINFO_ORIGINATOR defines                                           */
+/****************************************************************************/
+#define IOC_LOGINFO_ORIGINATOR_IOP                      (0x00000000)
+#define IOC_LOGINFO_ORIGINATOR_PL                       (0x01000000)
+#define IOC_LOGINFO_ORIGINATOR_IR                       (0x02000000)
+
+/****************************************************************************/
+/* LOGINFO_CODE defines                                                     */
+/****************************************************************************/
+#define IOC_LOGINFO_CODE_MASK                           (0x00FF0000)
+#define IOC_LOGINFO_CODE_SHIFT                          (16)
+
+/****************************************************************************/
+/* IOP LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IOP          */
+/****************************************************************************/
+#define IOP_LOGINFO_CODE_INVALID_SAS_ADDRESS            (0x00010000)
+#define IOP_LOGINFO_CODE_UNUSED2                        (0x00020000)
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE            (0x00030000)
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_RT         (0x00030100) /* Route Table Entry not found */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PN         (0x00030200) /* Invalid Page Number */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM       (0x00030300) /* Invalid FORM */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT         (0x00030400) /* Invalid Page Type */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DNM        (0x00030500) /* Device Not Mapped */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_PERSIST    (0x00030600) /* Persistent Page not found */
+#define IOP_LOGINFO_CODE_CONFIG_INVALID_PAGE_DEFAULT    (0x00030700) /* Default Page not found */
+#define IOP_LOGINFO_CODE_TASK_TERMINATED                (0x00050000)
+
+
+/****************************************************************************/
+/* PL LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = PL            */
+/****************************************************************************/
+#define PL_LOGINFO_CODE_OPEN_FAILURE                        (0x00010000)
+#define PL_LOGINFO_CODE_INVALID_SGL                         (0x00020000)
+#define PL_LOGINFO_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH       (0x00030000)
+#define PL_LOGINFO_CODE_FRAME_XFER_ERROR                    (0x00040000)
+#define PL_LOGINFO_CODE_TX_FM_CONNECTED_LOW                 (0x00050000)
+#define PL_LOGINFO_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET         (0x00060000)
+#define PL_LOGINFO_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR      (0x00070000)
+#define PL_LOGINFO_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR     (0x00080000)
+#define PL_LOGINFO_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS     (0x00090000)
+#define PL_LOGINFO_CODE_RX_FM_INVALID_MESSAGE               (0x000A0000)
+#define PL_LOGINFO_CODE_RX_CTX_MESSAGE_VALID_ERROR          (0x000B0000)
+#define PL_LOGINFO_CODE_RX_FM_CURRENT_FRAME_ERROR           (0x000C0000)
+#define PL_LOGINFO_CODE_SATA_LINK_DOWN                      (0x000D0000)
+#define PL_LOGINFO_CODE_DISCOVERY_SATA_INIT_W_IOS           (0x000E0000)
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE                 (0x000F0000)
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PT              (0x000F0100) /* Invalid Page Type */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NUM_PHYS        (0x000F0200) /* Invalid Number of Phys */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NOT_IMP         (0x000F0300) /* Case Not Handled */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_DEV          (0x000F0400) /* No Device Found */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_FORM            (0x000F0500) /* Invalid FORM */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_PHY             (0x000F0600) /* Invalid Phy */
+#define PL_LOGINFO_CODE_CONFIG_INVALID_PAGE_NO_OWNER        (0x000F0700) /* No Owner Found */
+#define PL_LOGINFO_CODE_DSCVRY_SATA_INIT_TIMEOUT            (0x00100000)
+#define PL_LOGINFO_CODE_RESET                               (0x00110000)
+#define PL_LOGINFO_CODE_ABORT                               (0x00120000)
+#define PL_LOGINFO_CODE_IO_NOT_YET_EXECUTED                 (0x00130000)
+#define PL_LOGINFO_CODE_IO_EXECUTED                         (0x00140000)
+#define PL_LOGINFO_SUB_CODE_OPEN_FAILURE                    (0x00000100)
+#define PL_LOGINFO_SUB_CODE_INVALID_SGL                     (0x00000200)
+#define PL_LOGINFO_SUB_CODE_WRONG_REL_OFF_OR_FRAME_LENGTH   (0x00000300)
+#define PL_LOGINFO_SUB_CODE_FRAME_XFER_ERROR                (0x00000400)
+#define PL_LOGINFO_SUB_CODE_TX_FM_CONNECTED_LOW             (0x00000500)
+#define PL_LOGINFO_SUB_CODE_SATA_NON_NCQ_RW_ERR_BIT_SET     (0x00000600)
+#define PL_LOGINFO_SUB_CODE_SATA_READ_LOG_RECEIVE_DATA_ERR  (0x00000700)
+#define PL_LOGINFO_SUB_CODE_SATA_NCQ_FAIL_ALL_CMDS_AFTR_ERR (0x00000800)
+#define PL_LOGINFO_SUB_CODE_SATA_ERR_IN_RCV_SET_DEV_BIT_FIS (0x00000900)
+#define PL_LOGINFO_SUB_CODE_RX_FM_INVALID_MESSAGE           (0x00000A00)
+#define PL_LOGINFO_SUB_CODE_RX_CTX_MESSAGE_VALID_ERROR      (0x00000B00)
+#define PL_LOGINFO_SUB_CODE_RX_FM_CURRENT_FRAME_ERROR       (0x00000C00)
+#define PL_LOGINFO_SUB_CODE_SATA_LINK_DOWN                  (0x00000D00)
+#define PL_LOGINFO_SUB_CODE_DISCOVERY_SATA_INIT_W_IOS       (0x00000E00)
+#define PL_LOGINFO_SUB_CODE_DSCVRY_SATA_INIT_TIMEOUT        (0x00001000)
+
+
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE         (0x00200000) /* Can't get SMP Frame */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR            (0x00200001) /* Error occured on SMP Read */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR           (0x00200002) /* Error occured on SMP Write */
+#define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL     (0x00200004) /* Encl Mgmt services not available for this WWID */
+#define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED   (0x00200005) /* Address Mode not suppored */
+#define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM              (0x00200006) /* Invalid Slot Number in SEP Msg */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SGPIO_NOT_PRESENT         (0x00200007) /* SGPIO not present/enabled */
+
+#define PL_LOGINFO_DA_SEP_NOT_PRESENT                       (0x00200100) /* SEP not present when msg received */
+#define PL_LOGINFO_DA_SEP_SINGLE_THREAD_ERROR               (0x00200101) /* Can only accept 1 msg at a time */
+#define PL_LOGINFO_DA_SEP_ISTWI_INTR_IN_IDLE_STATE          (0x00200102) /* ISTWI interrupt recvd. while IDLE */
+#define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE          (0x00200103) /* SEP NACK'd, it is busy */
+#define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM             (0x00200104) /* SEP stopped or sent bad chksum in Hdr */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1         (0x00200105) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2         (0x00200106) /* SEP returned unknown scsi status */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP           (0x00200107) /* SEP returned bad chksum after STOP */
+#define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP_GETDATA   (0x00200108) /* SEP returned bad chksum after STOP while gettin data*/
+
+
+/****************************************************************************/
+/* IR LOGINFO_CODE defines, valid if IOC_LOGINFO_ORIGINATOR = IR            */
+/****************************************************************************/
+#define IR_LOGINFO_CODE_UNUSED1                         (0x00010000)
+#define IR_LOGINFO_CODE_UNUSED2                         (0x00020000)
+
+/****************************************************************************/
+/* Defines for convienence                                                  */
+/****************************************************************************/
+#define IOC_LOGINFO_PREFIX_IOP                          ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IOP)
+#define IOC_LOGINFO_PREFIX_PL                           ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_PL)
+#define IOC_LOGINFO_PREFIX_IR                           ((MPI_IOCLOGINFO_TYPE_SAS << MPI_IOCLOGINFO_TYPE_SHIFT) | IOC_LOGINFO_ORIGINATOR_IR)
+
+#endif /* end of file */
+
index 230fa69b5353426566599270d0ce117d8a7c4279..70514867bddf3befa735d75404b88c5d8bd84ea1 100644 (file)
@@ -6,7 +6,7 @@
  *          Title:  MPI Serial Attached SCSI structures and definitions
  *  Creation Date:  August 19, 2004
  *
- *    mpi_sas.h Version:  01.05.01
+ *    mpi_sas.h Version:  01.05.02
  *
  *  Version History
  *  ---------------
@@ -14,6 +14,9 @@
  *  Date      Version   Description
  *  --------  --------  ------------------------------------------------------
  *  08-19-04  01.05.01  Original release.
+ *  08-30-05  01.05.02  Added DeviceInfo bit for SEP.
+ *                      Added PrimFlags and Primitive field to SAS IO Unit
+ *                      Control request, and added a new operation code.
  *  --------------------------------------------------------------------------
  */
 
@@ -51,6 +54,7 @@
  * Values for the SAS DeviceInfo field used in SAS Device Status Change Event
  * data and SAS IO Unit Configuration pages.
  */
+#define MPI_SAS_DEVICE_INFO_SEP                 (0x00004000)
 #define MPI_SAS_DEVICE_INFO_ATAPI_DEVICE        (0x00002000)
 #define MPI_SAS_DEVICE_INFO_LSI_DEVICE          (0x00001000)
 #define MPI_SAS_DEVICE_INFO_DIRECT_ATTACH       (0x00000800)
@@ -212,20 +216,26 @@ typedef struct _MSG_SAS_IOUNIT_CONTROL_REQUEST
     U8                      TargetID;           /* 0Ch */
     U8                      Bus;                /* 0Dh */
     U8                      PhyNum;             /* 0Eh */
-    U8                      Reserved4;          /* 0Fh */
-    U32                     Reserved5;          /* 10h */
+    U8                      PrimFlags;          /* 0Fh */
+    U32                     Primitive;          /* 10h */
     U64                     SASAddress;         /* 14h */
-    U32                     Reserved6;          /* 1Ch */
+    U32                     Reserved4;          /* 1Ch */
 } MSG_SAS_IOUNIT_CONTROL_REQUEST, MPI_POINTER PTR_MSG_SAS_IOUNIT_CONTROL_REQUEST,
   SasIoUnitControlRequest_t, MPI_POINTER pSasIoUnitControlRequest_t;
 
 /* values for the Operation field */
-#define MPI_SAS_OP_CLEAR_NOT_PRESENT             (0x01)
-#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT          (0x02)
-#define MPI_SAS_OP_PHY_LINK_RESET                (0x06)
-#define MPI_SAS_OP_PHY_HARD_RESET                (0x07)
-#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG           (0x08)
-#define MPI_SAS_OP_MAP_CURRENT                   (0x09)
+#define MPI_SAS_OP_CLEAR_NOT_PRESENT            (0x01)
+#define MPI_SAS_OP_CLEAR_ALL_PERSISTENT         (0x02)
+#define MPI_SAS_OP_PHY_LINK_RESET               (0x06)
+#define MPI_SAS_OP_PHY_HARD_RESET               (0x07)
+#define MPI_SAS_OP_PHY_CLEAR_ERROR_LOG          (0x08)
+#define MPI_SAS_OP_MAP_CURRENT                  (0x09)
+#define MPI_SAS_OP_SEND_PRIMITIVE               (0x0A)
+
+/* values for the PrimFlags field */
+#define MPI_SAS_PRIMFLAGS_SINGLE                (0x08)
+#define MPI_SAS_PRIMFLAGS_TRIPLE                (0x02)
+#define MPI_SAS_PRIMFLAGS_REDUNDANT             (0x01)
 
 
 /* SAS IO Unit Control Reply */
index 537836068c493736d1efc7a3139974d16faeacc1..d890b2b8a93e94973f345068f95b75e9121b679d 100644 (file)
@@ -148,7 +148,6 @@ static int  WaitForDoorbellAck(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
 static int     WaitForDoorbellInt(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
 static int     WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag);
 static int     GetLanConfigPages(MPT_ADAPTER *ioc);
-static int     GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
 static int     GetIoUnitPage2(MPT_ADAPTER *ioc);
 int            mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
 static int     mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum);
@@ -1232,12 +1231,11 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
                dprintk((KERN_INFO MYNAM
                        ": Not using 64 bit consistent mask\n"));
 
-       ioc = kmalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
+       ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC);
        if (ioc == NULL) {
                printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n");
                return -ENOMEM;
        }
-       memset(ioc, 0, sizeof(MPT_ADAPTER));
        ioc->alloc_total = sizeof(MPT_ADAPTER);
        ioc->req_sz = MPT_DEFAULT_FRAME_SIZE;           /* avoid div by zero! */
        ioc->reply_sz = MPT_REPLY_FRAME_SIZE;
@@ -1245,6 +1243,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
        ioc->pcidev = pdev;
        ioc->diagPending = 0;
        spin_lock_init(&ioc->diagLock);
+       spin_lock_init(&ioc->fc_rescan_work_lock);
+       spin_lock_init(&ioc->fc_rport_lock);
        spin_lock_init(&ioc->initializing_hba_lock);
 
        /* Initialize the event logging.
@@ -1268,6 +1268,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
         */
        INIT_LIST_HEAD(&ioc->configQ);
 
+       /* Initialize the fc rport list head.
+        */
+       INIT_LIST_HEAD(&ioc->fc_rports);
+
        /* Find lookup slot. */
        INIT_LIST_HEAD(&ioc->list);
        ioc->id = mpt_ids++;
@@ -1374,6 +1378,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id)
                ioc->bus_type = FC;
                ioc->errata_flag_1064 = 1;
        }
+       else if (pdev->device == MPI_MANUFACTPAGE_DEVICEID_FC949E) {
+               ioc->prod_name = "LSIFC949E";
+               ioc->bus_type = FC;
+       }
        else if (pdev->device == MPI_MANUFACTPAGE_DEVID_53C1030) {
                ioc->prod_name = "LSI53C1030";
                ioc->bus_type = SPI;
@@ -1622,7 +1630,7 @@ mpt_resume(struct pci_dev *pdev)
        pci_enable_device(pdev);
 
        /* enable interrupts */
-       CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
+       CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
        ioc->active = 1;
 
        /* F/W not running */
@@ -1715,7 +1723,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
                                /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */
                                dprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
                                                ioc->alt_ioc->name));
-                               CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
+                               CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
                                ioc->alt_ioc->active = 1;
                        }
 
@@ -1831,7 +1839,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
 
        if (ret == 0) {
                /* Enable! (reply interrupt) */
-               CHIPREG_WRITE32(&ioc->chip->IntMask, ~(MPI_HIM_RIM));
+               CHIPREG_WRITE32(&ioc->chip->IntMask, MPI_HIM_DIM);
                ioc->active = 1;
        }
 
@@ -1839,7 +1847,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
                /* (re)Enable alt-IOC! (reply interrupt) */
                dinitprintk((KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n",
                                ioc->alt_ioc->name));
-               CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, ~(MPI_HIM_RIM));
+               CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM);
                ioc->alt_ioc->active = 1;
        }
 
@@ -1880,7 +1888,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag)
                         *  (FCPortPage0_t stuff)
                         */
                        for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
-                               (void) GetFcPortPage0(ioc, ii);
+                               (void) mptbase_GetFcPortPage0(ioc, ii);
                        }
 
                        if ((ioc->pfacts[0].ProtocolFlags & MPI_PORTFACTS_PROTOCOL_LAN) &&
@@ -4199,7 +4207,7 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
- *     GetFcPortPage0 - Fetch FCPort config Page0.
+ *     mptbase_GetFcPortPage0 - Fetch FCPort config Page0.
  *     @ioc: Pointer to MPT_ADAPTER structure
  *     @portnum: IOC Port number
  *
@@ -4209,8 +4217,8 @@ GetLanConfigPages(MPT_ADAPTER *ioc)
  *             -EAGAIN if no msg frames currently available
  *             -EFAULT for non-successful reply or no reply (timeout)
  */
-static int
-GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
+int
+mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
 {
        ConfigPageHeader_t       hdr;
        CONFIGPARMS              cfg;
@@ -4220,6 +4228,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
        int                      data_sz;
        int                      copy_sz;
        int                      rc;
+       int                      count = 400;
+
 
        /* Get FCPort Page 0 header */
        hdr.PageVersion = 0;
@@ -4243,6 +4253,8 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
        rc = -ENOMEM;
        ppage0_alloc = (FCPortPage0_t *) pci_alloc_consistent(ioc->pcidev, data_sz, &page0_dma);
        if (ppage0_alloc) {
+
+ try_again:
                memset((u8 *)ppage0_alloc, 0, data_sz);
                cfg.physAddr = page0_dma;
                cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
@@ -4274,6 +4286,19 @@ GetFcPortPage0(MPT_ADAPTER *ioc, int portnum)
                        pp0dest->DiscoveredPortsCount = le32_to_cpu(pp0dest->DiscoveredPortsCount);
                        pp0dest->MaxInitiators = le32_to_cpu(pp0dest->MaxInitiators);
 
+                       /*
+                        * if still doing discovery,
+                        * hang loose a while until finished
+                        */
+                       if (pp0dest->PortState == MPI_FCPORTPAGE0_PORTSTATE_UNKNOWN) {
+                               if (count-- > 0) {
+                                       msleep_interruptible(100);
+                                       goto try_again;
+                               }
+                               printk(MYIOC_s_INFO_FMT "Firmware discovery not"
+                                                       " complete.\n",
+                                               ioc->name);
+                       }
                }
 
                pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma);
@@ -6358,6 +6383,7 @@ EXPORT_SYMBOL(mpt_alloc_fw_memory);
 EXPORT_SYMBOL(mpt_free_fw_memory);
 EXPORT_SYMBOL(mptbase_sas_persist_operation);
 EXPORT_SYMBOL(mpt_alt_ioc_wait);
+EXPORT_SYMBOL(mptbase_GetFcPortPage0);
 
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
index 6c48d1f54ac92552b4fdf42f4ebbf66c74d5eda9..47053ac65068566fa6675fa2a5ed08eb8199684e 100644 (file)
@@ -76,8 +76,8 @@
 #define COPYRIGHT      "Copyright (c) 1999-2005 " MODULEAUTHOR
 #endif
 
-#define MPT_LINUX_VERSION_COMMON       "3.03.05"
-#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.03.05"
+#define MPT_LINUX_VERSION_COMMON       "3.03.06"
+#define MPT_LINUX_PACKAGE_NAME         "@(#)mptlinux-3.03.06"
 #define WHAT_MAGIC_STRING              "@" "(" "#" ")"
 
 #define show_mptmod_ver(s,ver)  \
@@ -413,7 +413,7 @@ typedef struct _MPT_IOCTL {
        u8                       status;        /* current command status */
        u8                       reset;         /* 1 if bus reset allowed */
        u8                       target;        /* target for reset */
-       struct semaphore         sem_ioc;
+       struct mutex             ioctl_mutex;
 } MPT_IOCTL;
 
 #define MPT_SAS_MGMT_STATUS_RF_VALID   0x02    /* The Reply Frame is VALID */
@@ -421,7 +421,7 @@ typedef struct _MPT_IOCTL {
 #define MPT_SAS_MGMT_STATUS_TM_FAILED  0x40    /* User TM request failed */
 
 typedef struct _MPT_SAS_MGMT {
-       struct semaphore         mutex;
+       struct mutex             mutex;
        struct completion        done;
        u8                       reply[MPT_DEFAULT_FRAME_SIZE]; /* reply frame data */
        u8                       status;        /* current command status */
@@ -499,6 +499,22 @@ typedef    struct _RaidCfgData {
        int              isRaid;                /* bit field, 1 if RAID */
 }RaidCfgData;
 
+#define MPT_RPORT_INFO_FLAGS_REGISTERED        0x01    /* rport registered */
+#define MPT_RPORT_INFO_FLAGS_MISSING   0x02    /* missing from DevPage0 scan */
+#define MPT_RPORT_INFO_FLAGS_MAPPED_VDEV 0x04  /* target mapped in vdev */
+
+/*
+ * data allocated for each fc rport device
+ */
+struct mptfc_rport_info
+{
+       struct list_head list;
+       struct fc_rport *rport;
+       VirtDevice      *vdev;
+       FCDevicePage0_t pg0;
+       u8              flags;
+};
+
 /*
  *  Adapter Structure - pci_dev specific. Maximum: MPT_MAX_ADAPTERS
  */
@@ -612,7 +628,16 @@ typedef struct _MPT_ADAPTER
        struct list_head         list;
        struct net_device       *netdev;
        struct list_head         sas_topology;
+       struct mutex             sas_topology_mutex;
        MPT_SAS_MGMT             sas_mgmt;
+       int                      num_ports;
+
+       struct list_head         fc_rports;
+       spinlock_t               fc_rport_lock; /* list and ri flags */
+       spinlock_t               fc_rescan_work_lock;
+       int                      fc_rescan_work_count;
+       struct work_struct       fc_rescan_work;
+
 } MPT_ADAPTER;
 
 /*
@@ -999,6 +1024,7 @@ extern void         mpt_free_fw_memory(MPT_ADAPTER *ioc);
 extern int      mpt_findImVolumes(MPT_ADAPTER *ioc);
 extern int      mpt_read_ioc_pg_3(MPT_ADAPTER *ioc);
 extern int      mptbase_sas_persist_operation(MPT_ADAPTER *ioc, u8 persist_opcode);
+extern int      mptbase_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum);
 extern int      mpt_alt_ioc_wait(MPT_ADAPTER *ioc);
 
 /*
index 7c340240a50e94f1258fd3c2b5d19c3f079740d0..bdf709987982b37509646e553f2482dd2d3d60c7 100644 (file)
@@ -177,10 +177,10 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock)
        dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock));
 
        if (nonblock) {
-               if (down_trylock(&ioc->ioctl->sem_ioc))
+               if (!mutex_trylock(&ioc->ioctl->ioctl_mutex))
                        rc = -EAGAIN;
        } else {
-               if (down_interruptible(&ioc->ioctl->sem_ioc))
+               if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex))
                        rc = -ERESTARTSYS;
        }
        dctlprintk((KERN_INFO MYNAM "::mptctl_syscall_down return %d\n", rc));
@@ -557,7 +557,7 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        else
                ret = -EINVAL;
 
-       up(&iocp->ioctl->sem_ioc);
+       mutex_unlock(&iocp->ioctl->ioctl_mutex);
 
        return ret;
 }
@@ -2619,7 +2619,7 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
 
        ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
 
-       up(&iocp->ioctl->sem_ioc);
+       mutex_unlock(&iocp->ioctl->ioctl_mutex);
 
        return ret;
 }
@@ -2673,7 +2673,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd,
         */
        ret = mptctl_do_mpt_command (karg, &uarg->MF);
 
-       up(&iocp->ioctl->sem_ioc);
+       mutex_unlock(&iocp->ioctl->ioctl_mutex);
 
        return ret;
 }
@@ -2743,7 +2743,7 @@ mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        memset(mem, 0, sz);
        ioc->ioctl = (MPT_IOCTL *) mem;
        ioc->ioctl->ioc = ioc;
-       sema_init(&ioc->ioctl->sem_ioc, 1);
+       mutex_init(&ioc->ioctl->ioctl_mutex);
        return 0;
 
 out_fail:
index ba61e18288585679d4915c9ec22abd82804496b7..b102c7666d0efcaf44f8a6e534ff340352b23489 100644 (file)
 #include <linux/reboot.h>      /* notifier code */
 #include <linux/sched.h>
 #include <linux/workqueue.h>
+#include <linux/sort.h>
 
 #include <scsi/scsi.h>
 #include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport_fc.h>
 
 #include "mptbase.h"
 #include "mptscsih.h"
@@ -79,19 +81,34 @@ static int mpt_pq_filter = 0;
 module_param(mpt_pq_filter, int, 0);
 MODULE_PARM_DESC(mpt_pq_filter, " Enable peripheral qualifier filter: enable=1  (default=0)");
 
+#define MPTFC_DEV_LOSS_TMO (60)
+static int mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;    /* reasonable default */
+module_param(mptfc_dev_loss_tmo, int, 0);
+MODULE_PARM_DESC(mptfc_dev_loss_tmo, " Initial time the driver programs the "
+                                    " transport to wait for an rport to "
+                                    " return following a device loss event."
+                                    "  Default=60.");
+
 static int     mptfcDoneCtx = -1;
 static int     mptfcTaskCtx = -1;
 static int     mptfcInternalCtx = -1; /* Used only for internal commands */
 
+int mptfc_slave_alloc(struct scsi_device *device);
+static int mptfc_qcmd(struct scsi_cmnd *SCpnt,
+    void (*done)(struct scsi_cmnd *));
+
+static void mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout);
+static void __devexit mptfc_remove(struct pci_dev *pdev);
+
 static struct scsi_host_template mptfc_driver_template = {
        .module                         = THIS_MODULE,
        .proc_name                      = "mptfc",
        .proc_info                      = mptscsih_proc_info,
        .name                           = "MPT FC Host",
        .info                           = mptscsih_info,
-       .queuecommand                   = mptscsih_qcmd,
+       .queuecommand                   = mptfc_qcmd,
        .target_alloc                   = mptscsih_target_alloc,
-       .slave_alloc                    = mptscsih_slave_alloc,
+       .slave_alloc                    = mptfc_slave_alloc,
        .slave_configure                = mptscsih_slave_configure,
        .target_destroy                 = mptscsih_target_destroy,
        .slave_destroy                  = mptscsih_slave_destroy,
@@ -128,19 +145,478 @@ static struct pci_device_id mptfc_pci_table[] = {
                PCI_ANY_ID, PCI_ANY_ID },
        { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949X,
                PCI_ANY_ID, PCI_ANY_ID },
+       { PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FC949ES,
+               PCI_ANY_ID, PCI_ANY_ID },
        {0}     /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(pci, mptfc_pci_table);
 
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
-/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+static struct scsi_transport_template *mptfc_transport_template = NULL;
+
+struct fc_function_template mptfc_transport_functions = {
+       .dd_fcrport_size = 8,
+       .show_host_node_name = 1,
+       .show_host_port_name = 1,
+       .show_host_supported_classes = 1,
+       .show_host_port_id = 1,
+       .show_rport_supported_classes = 1,
+       .show_starget_node_name = 1,
+       .show_starget_port_name = 1,
+       .show_starget_port_id = 1,
+       .set_rport_dev_loss_tmo = mptfc_set_rport_loss_tmo,
+       .show_rport_dev_loss_tmo = 1,
+
+};
+
+/* FIXME! values controlling firmware RESCAN event
+ * need to be set low to allow dev_loss_tmo to
+ * work as expected.  Currently, firmware doesn't
+ * notify driver of RESCAN event until some number
+ * of seconds elapse.  This value can be set via
+ * lsiutil.
+ */
+static void
+mptfc_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout)
+{
+       if (timeout > 0)
+               rport->dev_loss_tmo = timeout;
+       else
+               rport->dev_loss_tmo = mptfc_dev_loss_tmo;
+}
+
+static int
+mptfc_FcDevPage0_cmp_func(const void *a, const void *b)
+{
+       FCDevicePage0_t **aa = (FCDevicePage0_t **)a;
+       FCDevicePage0_t **bb = (FCDevicePage0_t **)b;
+
+       if ((*aa)->CurrentBus == (*bb)->CurrentBus) {
+               if ((*aa)->CurrentTargetID == (*bb)->CurrentTargetID)
+                       return 0;
+               if ((*aa)->CurrentTargetID < (*bb)->CurrentTargetID)
+                       return -1;
+               return 1;
+       }
+       if ((*aa)->CurrentBus < (*bb)->CurrentBus)
+               return -1;
+       return 1;
+}
+
+static int
+mptfc_GetFcDevPage0(MPT_ADAPTER *ioc, int ioc_port,
+       void(*func)(MPT_ADAPTER *ioc,int channel, FCDevicePage0_t *arg))
+{
+       ConfigPageHeader_t       hdr;
+       CONFIGPARMS              cfg;
+       FCDevicePage0_t         *ppage0_alloc, *fc;
+       dma_addr_t               page0_dma;
+       int                      data_sz;
+       int                      ii;
+
+       FCDevicePage0_t         *p0_array=NULL, *p_p0;
+       FCDevicePage0_t         **pp0_array=NULL, **p_pp0;
+
+       int                      rc = -ENOMEM;
+       U32                      port_id = 0xffffff;
+       int                      num_targ = 0;
+       int                      max_bus = ioc->facts.MaxBuses;
+       int                      max_targ = ioc->facts.MaxDevices;
+
+       if (max_bus == 0 || max_targ == 0)
+               goto out;
+
+       data_sz = sizeof(FCDevicePage0_t) * max_bus * max_targ;
+       p_p0 = p0_array =  kzalloc(data_sz, GFP_KERNEL);
+       if (!p0_array)
+               goto out;
+
+       data_sz = sizeof(FCDevicePage0_t *) * max_bus * max_targ;
+       p_pp0 = pp0_array = kzalloc(data_sz, GFP_KERNEL);
+       if (!pp0_array)
+               goto out;
+
+       do {
+               /* Get FC Device Page 0 header */
+               hdr.PageVersion = 0;
+               hdr.PageLength = 0;
+               hdr.PageNumber = 0;
+               hdr.PageType = MPI_CONFIG_PAGETYPE_FC_DEVICE;
+               cfg.cfghdr.hdr = &hdr;
+               cfg.physAddr = -1;
+               cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
+               cfg.dir = 0;
+               cfg.pageAddr = port_id;
+               cfg.timeout = 0;
+
+               if ((rc = mpt_config(ioc, &cfg)) != 0)
+                       break;
+
+               if (hdr.PageLength <= 0)
+                       break;
+
+               data_sz = hdr.PageLength * 4;
+               ppage0_alloc = pci_alloc_consistent(ioc->pcidev, data_sz,
+                                                       &page0_dma);
+               rc = -ENOMEM;
+               if (!ppage0_alloc)
+                       break;
+
+               cfg.physAddr = page0_dma;
+               cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
+
+               if ((rc = mpt_config(ioc, &cfg)) == 0) {
+                       ppage0_alloc->PortIdentifier =
+                               le32_to_cpu(ppage0_alloc->PortIdentifier);
+
+                       ppage0_alloc->WWNN.Low =
+                               le32_to_cpu(ppage0_alloc->WWNN.Low);
+
+                       ppage0_alloc->WWNN.High =
+                               le32_to_cpu(ppage0_alloc->WWNN.High);
+
+                       ppage0_alloc->WWPN.Low =
+                               le32_to_cpu(ppage0_alloc->WWPN.Low);
+
+                       ppage0_alloc->WWPN.High =
+                               le32_to_cpu(ppage0_alloc->WWPN.High);
+
+                       ppage0_alloc->BBCredit =
+                               le16_to_cpu(ppage0_alloc->BBCredit);
+
+                       ppage0_alloc->MaxRxFrameSize =
+                               le16_to_cpu(ppage0_alloc->MaxRxFrameSize);
+
+                       port_id = ppage0_alloc->PortIdentifier;
+                       num_targ++;
+                       *p_p0 = *ppage0_alloc;  /* save data */
+                       *p_pp0++ = p_p0++;      /* save addr */
+               }
+               pci_free_consistent(ioc->pcidev, data_sz,
+                                       (u8 *) ppage0_alloc, page0_dma);
+               if (rc != 0)
+                       break;
+
+       } while (port_id <= 0xff0000);
+
+       if (num_targ) {
+               /* sort array */
+               if (num_targ > 1)
+                       sort (pp0_array, num_targ, sizeof(FCDevicePage0_t *),
+                               mptfc_FcDevPage0_cmp_func, NULL);
+               /* call caller's func for each targ */
+               for (ii = 0; ii < num_targ;  ii++) {
+                       fc = *(pp0_array+ii);
+                       func(ioc, ioc_port, fc);
+               }
+       }
+
+ out:
+       if (pp0_array)
+               kfree(pp0_array);
+       if (p0_array)
+               kfree(p0_array);
+       return rc;
+}
+
+static int
+mptfc_generate_rport_ids(FCDevicePage0_t *pg0, struct fc_rport_identifiers *rid)
+{
+       /* not currently usable */
+       if (pg0->Flags & (MPI_FC_DEVICE_PAGE0_FLAGS_PLOGI_INVALID |
+                         MPI_FC_DEVICE_PAGE0_FLAGS_PRLI_INVALID))
+               return -1;
+
+       if (!(pg0->Flags & MPI_FC_DEVICE_PAGE0_FLAGS_TARGETID_BUS_VALID))
+               return -1;
+
+       if (!(pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_TARGET))
+               return -1;
+
+       /*
+        * board data structure already normalized to platform endianness
+        * shifted to avoid unaligned access on 64 bit architecture
+        */
+       rid->node_name = ((u64)pg0->WWNN.High) << 32 | (u64)pg0->WWNN.Low;
+       rid->port_name = ((u64)pg0->WWPN.High) << 32 | (u64)pg0->WWPN.Low;
+       rid->port_id =   pg0->PortIdentifier;
+       rid->roles = FC_RPORT_ROLE_UNKNOWN;
+       rid->roles |= FC_RPORT_ROLE_FCP_TARGET;
+       if (pg0->Protocol & MPI_FC_DEVICE_PAGE0_PROT_FCP_INITIATOR)
+               rid->roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+
+       return 0;
+}
+
+static void
+mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0)
+{
+       struct fc_rport_identifiers rport_ids;
+       struct fc_rport         *rport;
+       struct mptfc_rport_info *ri;
+       int                     match = 0;
+       u64                     port_name;
+       unsigned long           flags;
+
+       if (mptfc_generate_rport_ids(pg0, &rport_ids) < 0)
+               return;
+
+       /* scan list looking for a match */
+       spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+       list_for_each_entry(ri, &ioc->fc_rports, list) {
+               port_name = (u64)ri->pg0.WWPN.High << 32 | (u64)ri->pg0.WWPN.Low;
+               if (port_name == rport_ids.port_name) { /* match */
+                       list_move_tail(&ri->list, &ioc->fc_rports);
+                       match = 1;
+                       break;
+               }
+       }
+       if (!match) {   /* allocate one */
+               spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
+               ri = kzalloc(sizeof(struct mptfc_rport_info), GFP_KERNEL);
+               if (!ri)
+                       return;
+               spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+               list_add_tail(&ri->list, &ioc->fc_rports);
+       }
+
+       ri->pg0 = *pg0; /* add/update pg0 data */
+       ri->flags &= ~MPT_RPORT_INFO_FLAGS_MISSING;
+
+       if (!(ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED)) {
+               ri->flags |= MPT_RPORT_INFO_FLAGS_REGISTERED;
+               spin_unlock_irqrestore(&ioc->fc_rport_lock, flags);
+               rport = fc_remote_port_add(ioc->sh,channel, &rport_ids);
+               spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+               if (rport) {
+                       if (*((struct mptfc_rport_info **)rport->dd_data) != ri) {
+                               ri->flags &= ~MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
+                               ri->vdev = NULL;
+                               ri->rport = rport;
+                               *((struct mptfc_rport_info **)rport->dd_data) = ri;
+                       }
+                       rport->dev_loss_tmo = mptfc_dev_loss_tmo;
+                       /*
+                        * if already mapped, remap here.  If not mapped,
+                        * slave_alloc will allocate vdev and map
+                        */
+                       if (ri->flags & MPT_RPORT_INFO_FLAGS_MAPPED_VDEV) {
+                               ri->vdev->target_id = ri->pg0.CurrentTargetID;
+                               ri->vdev->bus_id = ri->pg0.CurrentBus;
+                               ri->vdev->vtarget->target_id = ri->vdev->target_id;
+                               ri->vdev->vtarget->bus_id = ri->vdev->bus_id;
+                       }
+                       #ifdef MPT_DEBUG
+                       printk ("mptfc_reg_dev.%d: %x, %llx / %llx, tid %d, "
+                               "rport tid %d, tmo %d\n",
+                                       ioc->sh->host_no,
+                                       pg0->PortIdentifier,
+                                       pg0->WWNN,
+                                       pg0->WWPN,
+                                       pg0->CurrentTargetID,
+                                       ri->rport->scsi_target_id,
+                                       ri->rport->dev_loss_tmo);
+                       #endif
+               } else {
+                       list_del(&ri->list);
+                       kfree(ri);
+                       ri = NULL;
+               }
+       }
+       spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+}
+
 /*
- *     mptfc_probe - Installs scsi devices per bus.
- *     @pdev: Pointer to pci_dev structure
- *
- *     Returns 0 for success, non-zero for failure.
- *
+ *     OS entry point to allow host driver to alloc memory
+ *     for each scsi device. Called once per device the bus scan.
+ *     Return non-zero if allocation fails.
+ *     Init memory once per LUN.
  */
+int
+mptfc_slave_alloc(struct scsi_device *sdev)
+{
+       MPT_SCSI_HOST           *hd;
+       VirtTarget              *vtarget;
+       VirtDevice              *vdev;
+       struct scsi_target      *starget;
+       struct fc_rport         *rport;
+       struct mptfc_rport_info *ri;
+       unsigned long           flags;
+
+
+       rport = starget_to_rport(scsi_target(sdev));
+
+       if (!rport || fc_remote_port_chkready(rport))
+               return -ENXIO;
+
+       hd = (MPT_SCSI_HOST *)sdev->host->hostdata;
+
+       vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+       if (!vdev) {
+               printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
+                               hd->ioc->name, sizeof(VirtDevice));
+               return -ENOMEM;
+       }
+       memset(vdev, 0, sizeof(VirtDevice));
+
+       spin_lock_irqsave(&hd->ioc->fc_rport_lock,flags);
+
+       if (!(ri = *((struct mptfc_rport_info **)rport->dd_data))) {
+               spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
+               kfree(vdev);
+               return -ENODEV;
+       }
+
+       sdev->hostdata = vdev;
+       starget = scsi_target(sdev);
+       vtarget = starget->hostdata;
+       if (vtarget->num_luns == 0) {
+               vtarget->tflags = MPT_TARGET_FLAGS_Q_YES |
+                                 MPT_TARGET_FLAGS_VALID_INQUIRY;
+               hd->Targets[sdev->id] = vtarget;
+       }
+
+       vtarget->target_id = vdev->target_id;
+       vtarget->bus_id = vdev->bus_id;
+
+       vdev->vtarget = vtarget;
+       vdev->ioc_id = hd->ioc->id;
+       vdev->lun = sdev->lun;
+       vdev->target_id = ri->pg0.CurrentTargetID;
+       vdev->bus_id = ri->pg0.CurrentBus;
+
+       ri->flags |= MPT_RPORT_INFO_FLAGS_MAPPED_VDEV;
+       ri->vdev = vdev;
+
+       spin_unlock_irqrestore(&hd->ioc->fc_rport_lock,flags);
+
+       vtarget->num_luns++;
+
+#ifdef MPT_DEBUG
+       printk ("mptfc_slv_alloc.%d: num_luns %d, sdev.id %d, "
+               "CurrentTargetID %d, %x %llx %llx\n",
+                       sdev->host->host_no,
+                       vtarget->num_luns,
+                       sdev->id, ri->pg0.CurrentTargetID,
+                       ri->pg0.PortIdentifier, ri->pg0.WWPN, ri->pg0.WWNN);
+#endif
+
+       return 0;
+}
+
+static int
+mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
+{
+       struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device));
+       int             err;
+
+       err = fc_remote_port_chkready(rport);
+       if (unlikely(err)) {
+               SCpnt->result = err;
+               done(SCpnt);
+               return 0;
+       }
+       return mptscsih_qcmd(SCpnt,done);
+}
+
+static void
+mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum)
+{
+       unsigned class = 0, cos = 0;
+
+       /* don't know what to do as only one scsi (fc) host was allocated */
+       if (portnum != 0)
+               return;
+
+       class = ioc->fc_port_page0[portnum].SupportedServiceClass;
+       if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_1)
+               cos |= FC_COS_CLASS1;
+       if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_2)
+               cos |= FC_COS_CLASS2;
+       if (class & MPI_FCPORTPAGE0_SUPPORT_CLASS_3)
+               cos |= FC_COS_CLASS3;
+
+       fc_host_node_name(ioc->sh) =
+               (u64)ioc->fc_port_page0[portnum].WWNN.High << 32
+                   | (u64)ioc->fc_port_page0[portnum].WWNN.Low;
+
+       fc_host_port_name(ioc->sh) =
+               (u64)ioc->fc_port_page0[portnum].WWPN.High << 32
+                   | (u64)ioc->fc_port_page0[portnum].WWPN.Low;
+
+       fc_host_port_id(ioc->sh) = ioc->fc_port_page0[portnum].PortIdentifier;
+
+       fc_host_supported_classes(ioc->sh) = cos;
+
+       fc_host_tgtid_bind_type(ioc->sh) = FC_TGTID_BIND_BY_WWPN;
+}
+
+static void
+mptfc_rescan_devices(void *arg)
+{
+       MPT_ADAPTER             *ioc = (MPT_ADAPTER *)arg;
+       int                     ii;
+       int                     work_to_do;
+       unsigned long           flags;
+       struct mptfc_rport_info *ri;
+
+       do {
+               /* start by tagging all ports as missing */
+               spin_lock_irqsave(&ioc->fc_rport_lock,flags);
+               list_for_each_entry(ri, &ioc->fc_rports, list) {
+                       if (ri->flags & MPT_RPORT_INFO_FLAGS_REGISTERED) {
+                               ri->flags |= MPT_RPORT_INFO_FLAGS_MISSING;
+                       }
+               }
+               spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+               /*
+                * now rescan devices known to adapter,
+                * will reregister existing rports
+                */
+               for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+                       (void) mptbase_GetFcPortPage0(ioc, ii);
+                       mptfc_init_host_attr(ioc,ii);   /* refresh */
+                       mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
+               }
+
+               /* delete devices still missing */
+               spin_lock_irqsave(&ioc->fc_rport_lock, flags);
+               list_for_each_entry(ri, &ioc->fc_rports, list) {
+                       /* if newly missing, delete it */
+                       if ((ri->flags & (MPT_RPORT_INFO_FLAGS_REGISTERED |
+                                         MPT_RPORT_INFO_FLAGS_MISSING))
+                         == (MPT_RPORT_INFO_FLAGS_REGISTERED |
+                             MPT_RPORT_INFO_FLAGS_MISSING)) {
+
+                               ri->flags &= ~(MPT_RPORT_INFO_FLAGS_REGISTERED|
+                                              MPT_RPORT_INFO_FLAGS_MISSING);
+                               fc_remote_port_delete(ri->rport);
+                               /*
+                                * remote port not really deleted 'cause
+                                * binding is by WWPN and driver only
+                                * registers FCP_TARGETs
+                                */
+                               #ifdef MPT_DEBUG
+                               printk ("mptfc_rescan.%d: %llx deleted\n",
+                                       ioc->sh->host_no, ri->pg0.WWPN);
+                               #endif
+                       }
+               }
+               spin_unlock_irqrestore(&ioc->fc_rport_lock,flags);
+
+               /*
+                * allow multiple passes as target state
+                * might have changed during scan
+                */
+               spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+               if (ioc->fc_rescan_work_count > 2)      /* only need one more */
+                       ioc->fc_rescan_work_count = 2;
+               work_to_do = --ioc->fc_rescan_work_count;
+               spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+       } while (work_to_do);
+}
+
 static int
 mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
@@ -148,17 +624,16 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        MPT_SCSI_HOST           *hd;
        MPT_ADAPTER             *ioc;
        unsigned long            flags;
-       int                      sz, ii;
+       int                      ii;
        int                      numSGE = 0;
        int                      scale;
        int                      ioc_cap;
-       u8                      *mem;
        int                     error=0;
        int                     r;
-               
+
        if ((r = mpt_attach(pdev,id)) != 0)
                return r;
-       
+
        ioc = pci_get_drvdata(pdev);
        ioc->DoneCtx = mptfcDoneCtx;
        ioc->TaskCtx = mptfcTaskCtx;
@@ -194,7 +669,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                printk(MYIOC_s_WARN_FMT
                        "Skipping ioc=%p because SCSI Initiator mode is NOT enabled!\n",
                        ioc->name, ioc);
-               return 0;
+               return -ENODEV;
        }
 
        sh = scsi_host_alloc(&mptfc_driver_template, sizeof(MPT_SCSI_HOST));
@@ -207,6 +682,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto out_mptfc_probe;
         }
 
+       INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices,(void *)ioc);
+
        spin_lock_irqsave(&ioc->FreeQlock, flags);
 
        /* Attach the SCSI Host to the IOC structure
@@ -268,36 +745,27 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        /* SCSI needs scsi_cmnd lookup table!
         * (with size equal to req_depth*PtrSz!)
         */
-       sz = ioc->req_depth * sizeof(void *);
-       mem = kmalloc(sz, GFP_ATOMIC);
-       if (mem == NULL) {
+       hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+       if (!hd->ScsiLookup) {
                error = -ENOMEM;
                goto out_mptfc_probe;
        }
 
-       memset(mem, 0, sz);
-       hd->ScsiLookup = (struct scsi_cmnd **) mem;
-
-       dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
-                ioc->name, hd->ScsiLookup, sz));
+       dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
+                ioc->name, hd->ScsiLookup));
 
        /* Allocate memory for the device structures.
         * A non-Null pointer at an offset
         * indicates a device exists.
         * max_id = 1 + maximum id (hosts.h)
         */
-       sz = sh->max_id * sizeof(void *);
-       mem = kmalloc(sz, GFP_ATOMIC);
-       if (mem == NULL) {
+       hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
+       if (!hd->Targets) {
                error = -ENOMEM;
                goto out_mptfc_probe;
        }
 
-       memset(mem, 0, sz);
-       hd->Targets = (VirtTarget **) mem;
-
-       dprintk((KERN_INFO
-         "  vdev @ %p, sz=%d\n", hd->Targets, sz));
+       dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));
 
        /* Clear the TM flags
         */
@@ -332,6 +800,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        hd->scandv_wait_done = 0;
        hd->last_queue_full = 0;
 
+       sh->transportt = mptfc_transport_template;
        error = scsi_add_host (sh, &ioc->pcidev->dev);
        if(error) {
                dprintk((KERN_ERR MYNAM
@@ -339,7 +808,11 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto out_mptfc_probe;
        }
 
-       scsi_scan_host(sh);
+       for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) {
+               mptfc_init_host_attr(ioc,ii);
+               mptfc_GetFcDevPage0(ioc,ii,mptfc_register_dev);
+       }
+
        return 0;
 
 out_mptfc_probe:
@@ -352,7 +825,7 @@ static struct pci_driver mptfc_driver = {
        .name           = "mptfc",
        .id_table       = mptfc_pci_table,
        .probe          = mptfc_probe,
-       .remove         = __devexit_p(mptscsih_remove),
+       .remove         = __devexit_p(mptfc_remove),
        .shutdown       = mptscsih_shutdown,
 #ifdef CONFIG_PM
        .suspend        = mptscsih_suspend,
@@ -370,9 +843,20 @@ static struct pci_driver mptfc_driver = {
 static int __init
 mptfc_init(void)
 {
+       int error;
 
        show_mptmod_ver(my_NAME, my_VERSION);
 
+       /* sanity check module parameter */
+       if (mptfc_dev_loss_tmo == 0)
+               mptfc_dev_loss_tmo = MPTFC_DEV_LOSS_TMO;
+
+       mptfc_transport_template =
+               fc_attach_transport(&mptfc_transport_functions);
+
+       if (!mptfc_transport_template)
+               return -ENODEV;
+
        mptfcDoneCtx = mpt_register(mptscsih_io_done, MPTFC_DRIVER);
        mptfcTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTFC_DRIVER);
        mptfcInternalCtx = mpt_register(mptscsih_scandv_complete, MPTFC_DRIVER);
@@ -387,7 +871,33 @@ mptfc_init(void)
                  ": Registered for IOC reset notifications\n"));
        }
 
-       return pci_register_driver(&mptfc_driver);
+       error = pci_register_driver(&mptfc_driver);
+       if (error) {
+               fc_release_transport(mptfc_transport_template);
+       }
+
+       return error;
+}
+
+/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
+/**
+ *     mptfc_remove - Removed fc infrastructure for devices
+ *     @pdev: Pointer to pci_dev structure
+ *
+ */
+static void __devexit mptfc_remove(struct pci_dev *pdev)
+{
+       MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
+       struct mptfc_rport_info *p, *n;
+
+       fc_remove_host(ioc->sh);
+
+       list_for_each_entry_safe(p, n, &ioc->fc_rports, list) {
+               list_del(&p->list);
+               kfree(p);
+       }
+
+       mptscsih_remove(pdev);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -400,7 +910,8 @@ static void __exit
 mptfc_exit(void)
 {
        pci_unregister_driver(&mptfc_driver);
-       
+       fc_release_transport(mptfc_transport_template);
+
        mpt_reset_deregister(mptfcDoneCtx);
        dprintk((KERN_INFO MYNAM
          ": Deregistered for IOC reset notifications\n"));
index 014085d8ec85cfd370fb15b4add8f59e0015931b..0b1b72825ae2063829846a815dc9bb71127b94db 100644 (file)
@@ -411,14 +411,12 @@ mpt_lan_open(struct net_device *dev)
                goto out;
        priv->mpt_txfidx_tail = -1;
 
-       priv->SendCtl = kmalloc(priv->tx_max_out * sizeof(struct BufferControl),
+       priv->SendCtl = kcalloc(priv->tx_max_out, sizeof(struct BufferControl),
                                GFP_KERNEL);
        if (priv->SendCtl == NULL)
                goto out_mpt_txfidx;
-       for (i = 0; i < priv->tx_max_out; i++) {
-               memset(&priv->SendCtl[i], 0, sizeof(struct BufferControl));
+       for (i = 0; i < priv->tx_max_out; i++)
                priv->mpt_txfidx[++priv->mpt_txfidx_tail] = i;
-       }
 
        dlprintk((KERN_INFO MYNAM "@lo: Finished initializing SendCtl\n"));
 
@@ -428,15 +426,13 @@ mpt_lan_open(struct net_device *dev)
                goto out_SendCtl;
        priv->mpt_rxfidx_tail = -1;
 
-       priv->RcvCtl = kmalloc(priv->max_buckets_out *
-                                               sizeof(struct BufferControl),
+       priv->RcvCtl = kcalloc(priv->max_buckets_out,
+                              sizeof(struct BufferControl),
                               GFP_KERNEL);
        if (priv->RcvCtl == NULL)
                goto out_mpt_rxfidx;
-       for (i = 0; i < priv->max_buckets_out; i++) {
-               memset(&priv->RcvCtl[i], 0, sizeof(struct BufferControl));
+       for (i = 0; i < priv->max_buckets_out; i++)
                priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = i;
-       }
 
 /**/   dlprintk((KERN_INFO MYNAM "/lo: txfidx contains - "));
 /**/   for (i = 0; i < priv->tx_max_out; i++)
index 17e9757e728be780211d1e7a0008aaa9e2724d18..5a06d8d8694eb3cff0322e479a089ffb5d7021c1 100644 (file)
@@ -5,7 +5,7 @@
  *
  *  Copyright (c) 1999-2005 LSI Logic Corporation
  *  (mailto:mpt_linux_developer@lsil.com)
- *  Copyright (c) 2005 Dell
+ *  Copyright (c) 2005-2006 Dell
  */
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 /*
@@ -86,6 +86,24 @@ static int   mptsasInternalCtx = -1; /* Used only for internal commands */
 static int     mptsasMgmtCtx = -1;
 
 
+enum mptsas_hotplug_action {
+       MPTSAS_ADD_DEVICE,
+       MPTSAS_DEL_DEVICE,
+};
+
+struct mptsas_hotplug_event {
+       struct work_struct      work;
+       MPT_ADAPTER             *ioc;
+       enum mptsas_hotplug_action event_type;
+       u64                     sas_address;
+       u32                     channel;
+       u32                     id;
+       u32                     device_info;
+       u16                     handle;
+       u16                     parent_handle;
+       u8                      phy_id;
+};
+
 /*
  * SAS topology structures
  *
@@ -99,8 +117,8 @@ struct mptsas_devinfo {
        u8      phy_id;         /* phy number of parent device */
        u8      port_id;        /* sas physical port this device
                                   is assoc'd with */
-       u8      target;         /* logical target id of this device */
-       u8      bus;            /* logical bus number of this device */
+       u8      id;             /* logical target id of this device */
+       u8      channel;        /* logical bus number of this device */
        u64     sas_address;    /* WWN of this device,
                                   SATA is assigned by HBA,expander */
        u32     device_info;    /* bitfield detailed info about this device */
@@ -114,6 +132,7 @@ struct mptsas_phyinfo {
        u8      programmed_link_rate;   /* programmed max/min phy link rate */
        struct mptsas_devinfo identify; /* point to phy device info */
        struct mptsas_devinfo attached; /* point to attached device info */
+       struct sas_phy *phy;
        struct sas_rphy *rphy;
 };
 
@@ -239,13 +258,12 @@ mptsas_slave_alloc(struct scsi_device *sdev)
        struct scsi_target      *starget;
        int i;
 
-       vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+       vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
        if (!vdev) {
                printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
                                hd->ioc->name, sizeof(VirtDevice));
                return -ENOMEM;
        }
-       memset(vdev, 0, sizeof(VirtDevice));
        vdev->ioc_id = hd->ioc->id;
        sdev->hostdata = vdev;
        starget = scsi_target(sdev);
@@ -256,19 +274,32 @@ mptsas_slave_alloc(struct scsi_device *sdev)
                hd->Targets[sdev->id] = vtarget;
        }
 
+       /*
+         RAID volumes placed beyond the last expected port.
+       */
+       if (sdev->channel == hd->ioc->num_ports) {
+               vdev->target_id = sdev->id;
+               vdev->bus_id = 0;
+               vdev->lun = 0;
+               goto out;
+       }
+
        rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
+       mutex_lock(&hd->ioc->sas_topology_mutex);
        list_for_each_entry(p, &hd->ioc->sas_topology, list) {
                for (i = 0; i < p->num_phys; i++) {
                        if (p->phy_info[i].attached.sas_address ==
                                        rphy->identify.sas_address) {
                                vdev->target_id =
-                                       p->phy_info[i].attached.target;
-                               vdev->bus_id = p->phy_info[i].attached.bus;
+                                       p->phy_info[i].attached.id;
+                               vdev->bus_id = p->phy_info[i].attached.channel;
                                vdev->lun = sdev->lun;
+       mutex_unlock(&hd->ioc->sas_topology_mutex);
                                goto out;
                        }
                }
        }
+       mutex_unlock(&hd->ioc->sas_topology_mutex);
 
        printk("No matching SAS device found!!\n");
        kfree(vdev);
@@ -282,6 +313,42 @@ mptsas_slave_alloc(struct scsi_device *sdev)
        return 0;
 }
 
+static void
+mptsas_slave_destroy(struct scsi_device *sdev)
+{
+       struct Scsi_Host *host = sdev->host;
+       MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
+       struct sas_rphy *rphy;
+       struct mptsas_portinfo *p;
+       int i;
+
+       /*
+        * Handle hotplug removal case.
+        * We need to clear out attached data structure.
+        */
+       rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
+
+       mutex_lock(&hd->ioc->sas_topology_mutex);
+       list_for_each_entry(p, &hd->ioc->sas_topology, list) {
+               for (i = 0; i < p->num_phys; i++) {
+                       if (p->phy_info[i].attached.sas_address ==
+                                       rphy->identify.sas_address) {
+                               memset(&p->phy_info[i].attached, 0,
+                                   sizeof(struct mptsas_devinfo));
+                               p->phy_info[i].rphy = NULL;
+                               goto out;
+                       }
+               }
+       }
+
+ out:
+       mutex_unlock(&hd->ioc->sas_topology_mutex);
+       /*
+        * TODO: Issue target reset to flush firmware outstanding commands.
+        */
+       mptscsih_slave_destroy(sdev);
+}
+
 static struct scsi_host_template mptsas_driver_template = {
        .module                         = THIS_MODULE,
        .proc_name                      = "mptsas",
@@ -293,7 +360,7 @@ static struct scsi_host_template mptsas_driver_template = {
        .slave_alloc                    = mptsas_slave_alloc,
        .slave_configure                = mptscsih_slave_configure,
        .target_destroy                 = mptscsih_target_destroy,
-       .slave_destroy                  = mptscsih_slave_destroy,
+       .slave_destroy                  = mptsas_slave_destroy,
        .change_queue_depth             = mptscsih_change_queue_depth,
        .eh_abort_handler               = mptscsih_abort,
        .eh_device_reset_handler        = mptscsih_dev_reset,
@@ -399,7 +466,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
        if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
                return -ENXIO;
 
-       if (down_interruptible(&ioc->sas_mgmt.mutex))
+       if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
                goto out;
 
        mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
@@ -450,7 +517,7 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
        error = 0;
 
  out_unlock:
-       up(&ioc->sas_mgmt.mutex);
+       mutex_unlock(&ioc->sas_mgmt.mutex);
  out:
        return error;
 }
@@ -649,8 +716,8 @@ mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
        device_info->handle = le16_to_cpu(buffer->DevHandle);
        device_info->phy_id = buffer->PhyNum;
        device_info->port_id = buffer->PhysicalPort;
-       device_info->target = buffer->TargetID;
-       device_info->bus = buffer->Bus;
+       device_info->id = buffer->TargetID;
+       device_info->channel = buffer->Bus;
        memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
        device_info->sas_address = le64_to_cpu(sas_address);
        device_info->device_info =
@@ -858,36 +925,36 @@ mptsas_parse_device_info(struct sas_identify *identify,
 static int mptsas_probe_one_phy(struct device *dev,
                struct mptsas_phyinfo *phy_info, int index, int local)
 {
-       struct sas_phy *port;
+       struct sas_phy *phy;
        int error;
 
-       port = sas_phy_alloc(dev, index);
-       if (!port)
+       phy = sas_phy_alloc(dev, index);
+       if (!phy)
                return -ENOMEM;
 
-       port->port_identifier = phy_info->port_id;
-       mptsas_parse_device_info(&port->identify, &phy_info->identify);
+       phy->port_identifier = phy_info->port_id;
+       mptsas_parse_device_info(&phy->identify, &phy_info->identify);
 
        /*
         * Set Negotiated link rate.
         */
        switch (phy_info->negotiated_link_rate) {
        case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
-               port->negotiated_linkrate = SAS_PHY_DISABLED;
+               phy->negotiated_linkrate = SAS_PHY_DISABLED;
                break;
        case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
-               port->negotiated_linkrate = SAS_LINK_RATE_FAILED;
+               phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
                break;
        case MPI_SAS_IOUNIT0_RATE_1_5:
-               port->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
+               phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
                break;
        case MPI_SAS_IOUNIT0_RATE_3_0:
-               port->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
+               phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
                break;
        case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
        case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
        default:
-               port->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
+               phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
                break;
        }
 
@@ -896,10 +963,10 @@ static int mptsas_probe_one_phy(struct device *dev,
         */
        switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
        case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
-               port->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
+               phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
                break;
        case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
-               port->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
+               phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
                break;
        default:
                break;
@@ -911,10 +978,10 @@ static int mptsas_probe_one_phy(struct device *dev,
        switch (phy_info->programmed_link_rate &
                        MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
        case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
-               port->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
+               phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
                break;
        case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
-               port->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
+               phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
                break;
        default:
                break;
@@ -925,10 +992,10 @@ static int mptsas_probe_one_phy(struct device *dev,
         */
        switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
        case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
-               port->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
+               phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
                break;
        case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
-               port->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
+               phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
                break;
        default:
                break;
@@ -940,28 +1007,29 @@ static int mptsas_probe_one_phy(struct device *dev,
        switch (phy_info->programmed_link_rate &
                        MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
        case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
-               port->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
+               phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
                break;
        case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
-               port->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
+               phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
                break;
        default:
                break;
        }
 
        if (local)
-               port->local_attached = 1;
+               phy->local_attached = 1;
 
-       error = sas_phy_add(port);
+       error = sas_phy_add(phy);
        if (error) {
-               sas_phy_free(port);
+               sas_phy_free(phy);
                return error;
        }
+       phy_info->phy = phy;
 
        if (phy_info->attached.handle) {
                struct sas_rphy *rphy;
 
-               rphy = sas_rphy_alloc(port);
+               rphy = sas_rphy_alloc(phy);
                if (!rphy)
                        return 0; /* non-fatal: an rphy can be added later */
 
@@ -985,16 +1053,19 @@ mptsas_probe_hba_phys(MPT_ADAPTER *ioc, int *index)
        u32 handle = 0xFFFF;
        int error = -ENOMEM, i;
 
-       port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
+       port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
        if (!port_info)
                goto out;
-       memset(port_info, 0, sizeof(*port_info));
 
        error = mptsas_sas_io_unit_pg0(ioc, port_info);
        if (error)
                goto out_free_port_info;
 
+       ioc->num_ports = port_info->num_phys;
+       mutex_lock(&ioc->sas_topology_mutex);
        list_add_tail(&port_info->list, &ioc->sas_topology);
+       mutex_unlock(&ioc->sas_topology_mutex);
+
        for (i = 0; i < port_info->num_phys; i++) {
                mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
                        (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
@@ -1034,10 +1105,9 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
        struct mptsas_portinfo *port_info, *p;
        int error = -ENOMEM, i, j;
 
-       port_info = kmalloc(sizeof(*port_info), GFP_KERNEL);
+       port_info = kzalloc(sizeof(*port_info), GFP_KERNEL);
        if (!port_info)
                goto out;
-       memset(port_info, 0, sizeof(*port_info));
 
        error = mptsas_sas_expander_pg0(ioc, port_info,
                (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
@@ -1047,7 +1117,10 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
 
        *handle = port_info->handle;
 
+       mutex_lock(&ioc->sas_topology_mutex);
        list_add_tail(&port_info->list, &ioc->sas_topology);
+       mutex_unlock(&ioc->sas_topology_mutex);
+
        for (i = 0; i < port_info->num_phys; i++) {
                struct device *parent;
 
@@ -1079,6 +1152,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
                 * HBA phys.
                 */
                parent = &ioc->sh->shost_gendev;
+               mutex_lock(&ioc->sas_topology_mutex);
                list_for_each_entry(p, &ioc->sas_topology, list) {
                        for (j = 0; j < p->num_phys; j++) {
                                if (port_info->phy_info[i].identify.handle ==
@@ -1086,6 +1160,7 @@ mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle, int *index)
                                        parent = &p->phy_info[j].rphy->dev;
                        }
                }
+               mutex_unlock(&ioc->sas_topology_mutex);
 
                mptsas_probe_one_phy(parent, &port_info->phy_info[i],
                                     *index, 0);
@@ -1111,6 +1186,211 @@ mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
                ;
 }
 
+static struct mptsas_phyinfo *
+mptsas_find_phyinfo_by_parent(MPT_ADAPTER *ioc, u16 parent_handle, u8 phy_id)
+{
+       struct mptsas_portinfo *port_info;
+       struct mptsas_devinfo device_info;
+       struct mptsas_phyinfo *phy_info = NULL;
+       int i, error;
+
+       /*
+        * Retrieve the parent sas_address
+        */
+       error = mptsas_sas_device_pg0(ioc, &device_info,
+               (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
+                MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
+               parent_handle);
+       if (error) {
+               printk("mptsas: failed to retrieve device page\n");
+               return NULL;
+       }
+
+       /*
+        * The phy_info structures are never deallocated during lifetime of
+        * a host, so the code below is safe without additional refcounting.
+        */
+       mutex_lock(&ioc->sas_topology_mutex);
+       list_for_each_entry(port_info, &ioc->sas_topology, list) {
+               for (i = 0; i < port_info->num_phys; i++) {
+                       if (port_info->phy_info[i].identify.sas_address ==
+                           device_info.sas_address &&
+                           port_info->phy_info[i].phy_id == phy_id) {
+                               phy_info = &port_info->phy_info[i];
+                               break;
+                       }
+               }
+       }
+       mutex_unlock(&ioc->sas_topology_mutex);
+
+       return phy_info;
+}
+
+static struct mptsas_phyinfo *
+mptsas_find_phyinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
+{
+       struct mptsas_portinfo *port_info;
+       struct mptsas_phyinfo *phy_info = NULL;
+       int i;
+
+       /*
+        * The phy_info structures are never deallocated during lifetime of
+        * a host, so the code below is safe without additional refcounting.
+        */
+       mutex_lock(&ioc->sas_topology_mutex);
+       list_for_each_entry(port_info, &ioc->sas_topology, list) {
+               for (i = 0; i < port_info->num_phys; i++) {
+                       if (port_info->phy_info[i].attached.handle == handle) {
+                               phy_info = &port_info->phy_info[i];
+                               break;
+                       }
+               }
+       }
+       mutex_unlock(&ioc->sas_topology_mutex);
+
+       return phy_info;
+}
+
+static void
+mptsas_hotplug_work(void *arg)
+{
+       struct mptsas_hotplug_event *ev = arg;
+       MPT_ADAPTER *ioc = ev->ioc;
+       struct mptsas_phyinfo *phy_info;
+       struct sas_rphy *rphy;
+       char *ds = NULL;
+
+       if (ev->device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
+               ds = "ssp";
+       if (ev->device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
+               ds = "stp";
+       if (ev->device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
+               ds = "sata";
+
+       switch (ev->event_type) {
+       case MPTSAS_DEL_DEVICE:
+               printk(MYIOC_s_INFO_FMT
+                      "removing %s device, channel %d, id %d, phy %d\n",
+                      ioc->name, ds, ev->channel, ev->id, ev->phy_id);
+
+               phy_info = mptsas_find_phyinfo_by_handle(ioc, ev->handle);
+               if (!phy_info) {
+                       printk("mptsas: remove event for non-existant PHY.\n");
+                       break;
+               }
+
+               if (phy_info->rphy) {
+                       sas_rphy_delete(phy_info->rphy);
+                       phy_info->rphy = NULL;
+               }
+               break;
+       case MPTSAS_ADD_DEVICE:
+               printk(MYIOC_s_INFO_FMT
+                      "attaching %s device, channel %d, id %d, phy %d\n",
+                      ioc->name, ds, ev->channel, ev->id, ev->phy_id);
+
+               phy_info = mptsas_find_phyinfo_by_parent(ioc,
+                               ev->parent_handle, ev->phy_id);
+               if (!phy_info) {
+                       printk("mptsas: add event for non-existant PHY.\n");
+                       break;
+               }
+
+               if (phy_info->rphy) {
+                       printk("mptsas: trying to add existing device.\n");
+                       break;
+               }
+
+               /* fill attached info */
+               phy_info->attached.handle = ev->handle;
+               phy_info->attached.phy_id = ev->phy_id;
+               phy_info->attached.port_id = phy_info->identify.port_id;
+               phy_info->attached.id = ev->id;
+               phy_info->attached.channel = ev->channel;
+               phy_info->attached.sas_address = ev->sas_address;
+               phy_info->attached.device_info = ev->device_info;
+
+               rphy = sas_rphy_alloc(phy_info->phy);
+               if (!rphy)
+                       break; /* non-fatal: an rphy can be added later */
+
+               mptsas_parse_device_info(&rphy->identify, &phy_info->attached);
+               if (sas_rphy_add(rphy)) {
+                       sas_rphy_free(rphy);
+                       break;
+               }
+
+               phy_info->rphy = rphy;
+               break;
+       }
+
+       kfree(ev);
+}
+
+static void
+mptscsih_send_sas_event(MPT_ADAPTER *ioc,
+               EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
+{
+       struct mptsas_hotplug_event *ev;
+       u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
+       __le64 sas_address;
+
+       if ((device_info &
+            (MPI_SAS_DEVICE_INFO_SSP_TARGET |
+             MPI_SAS_DEVICE_INFO_STP_TARGET |
+             MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
+               return;
+
+       if ((sas_event_data->ReasonCode &
+            (MPI_EVENT_SAS_DEV_STAT_RC_ADDED |
+             MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING)) == 0)
+               return;
+
+       ev = kmalloc(sizeof(*ev), GFP_ATOMIC);
+       if (!ev) {
+               printk(KERN_WARNING "mptsas: lost hotplug event\n");
+               return;
+       }
+
+
+       INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
+       ev->ioc = ioc;
+       ev->handle = le16_to_cpu(sas_event_data->DevHandle);
+       ev->parent_handle = le16_to_cpu(sas_event_data->ParentDevHandle);
+       ev->channel = sas_event_data->Bus;
+       ev->id = sas_event_data->TargetID;
+       ev->phy_id = sas_event_data->PhyNum;
+       memcpy(&sas_address, &sas_event_data->SASAddress, sizeof(__le64));
+       ev->sas_address = le64_to_cpu(sas_address);
+       ev->device_info = device_info;
+
+       if (sas_event_data->ReasonCode & MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
+               ev->event_type = MPTSAS_ADD_DEVICE;
+       else
+               ev->event_type = MPTSAS_DEL_DEVICE;
+
+       schedule_work(&ev->work);
+}
+
+static int
+mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
+{
+       u8 event = le32_to_cpu(reply->Event) & 0xFF;
+
+       if (!ioc->sh)
+               return 1;
+
+       switch (event) {
+       case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
+               mptscsih_send_sas_event(ioc,
+                       (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
+               return 1;               /* currently means nothing really */
+
+       default:
+               return mptscsih_event_process(ioc, reply);
+       }
+}
+
 static int
 mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
@@ -1118,11 +1398,10 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        MPT_SCSI_HOST           *hd;
        MPT_ADAPTER             *ioc;
        unsigned long            flags;
-       int                      sz, ii;
+       int                      ii;
        int                      numSGE = 0;
        int                      scale;
        int                      ioc_cap;
-       u8                      *mem;
        int                     error=0;
        int                     r;
 
@@ -1203,7 +1482,9 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        sh->unique_id = ioc->id;
 
        INIT_LIST_HEAD(&ioc->sas_topology);
-       init_MUTEX(&ioc->sas_mgmt.mutex);
+       mutex_init(&ioc->sas_topology_mutex);
+
+       mutex_init(&ioc->sas_mgmt.mutex);
        init_completion(&ioc->sas_mgmt.done);
 
        /* Verify that we won't exceed the maximum
@@ -1244,36 +1525,27 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        /* SCSI needs scsi_cmnd lookup table!
         * (with size equal to req_depth*PtrSz!)
         */
-       sz = ioc->req_depth * sizeof(void *);
-       mem = kmalloc(sz, GFP_ATOMIC);
-       if (mem == NULL) {
+       hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+       if (!hd->ScsiLookup) {
                error = -ENOMEM;
                goto out_mptsas_probe;
        }
 
-       memset(mem, 0, sz);
-       hd->ScsiLookup = (struct scsi_cmnd **) mem;
-
-       dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
-                ioc->name, hd->ScsiLookup, sz));
+       dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
+                ioc->name, hd->ScsiLookup));
 
        /* Allocate memory for the device structures.
         * A non-Null pointer at an offset
         * indicates a device exists.
         * max_id = 1 + maximum id (hosts.h)
         */
-       sz = sh->max_id * sizeof(void *);
-       mem = kmalloc(sz, GFP_ATOMIC);
-       if (mem == NULL) {
+       hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
+       if (!hd->Targets) {
                error = -ENOMEM;
                goto out_mptsas_probe;
        }
 
-       memset(mem, 0, sz);
-       hd->Targets = (VirtTarget **) mem;
-
-       dprintk((KERN_INFO
-         "  vtarget @ %p, sz=%d\n", hd->Targets, sz));
+       dprintk((KERN_INFO "  vtarget @ %p\n", hd->Targets));
 
        /* Clear the TM flags
         */
@@ -1324,6 +1596,20 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        mptsas_scan_sas_topology(ioc);
 
+       /*
+         Reporting RAID volumes.
+       */
+       if (!ioc->raid_data.pIocPg2)
+               return 0;
+       if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
+               return 0;
+       for (ii=0;ii<ioc->raid_data.pIocPg2->NumActiveVolumes;ii++) {
+               scsi_add_device(sh,
+                       ioc->num_ports,
+                       ioc->raid_data.pIocPg2->RaidVolume[ii].VolumeID,
+                       0);
+       }
+
        return 0;
 
 out_mptsas_probe:
@@ -1339,10 +1625,12 @@ static void __devexit mptsas_remove(struct pci_dev *pdev)
 
        sas_remove_host(ioc->sh);
 
+       mutex_lock(&ioc->sas_topology_mutex);
        list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
                list_del(&p->list);
                kfree(p);
        }
+       mutex_unlock(&ioc->sas_topology_mutex);
 
        mptscsih_remove(pdev);
 }
@@ -1393,7 +1681,7 @@ mptsas_init(void)
                mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
        mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
 
-       if (mpt_event_register(mptsasDoneCtx, mptscsih_event_process) == 0) {
+       if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
                devtprintk((KERN_INFO MYNAM
                  ": Registered for IOC event notifications\n"));
        }
index 93a16fa3c4baeab822056108f9e622e906b10d5c..cdac5578fdf220caefb48a3356710393558372ff 100644 (file)
@@ -893,6 +893,7 @@ mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd)
  *             when a lun is disable by mid-layer.
  *             Do NOT access the referenced scsi_cmnd structure or
  *             members. Will cause either a paging or NULL ptr error.
+ *             (BUT, BUT, BUT, the code does reference it! - mdr)
  *      @hd: Pointer to a SCSI HOST structure
  *     @vdevice: per device private data
  *
@@ -2162,10 +2163,9 @@ mptscsih_target_alloc(struct scsi_target *starget)
 {
        VirtTarget              *vtarget;
 
-       vtarget = kmalloc(sizeof(VirtTarget), GFP_KERNEL);
+       vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
        if (!vtarget)
                return -ENOMEM;
-       memset(vtarget, 0, sizeof(VirtTarget));
        starget->hostdata = vtarget;
        return 0;
 }
@@ -2185,14 +2185,13 @@ mptscsih_slave_alloc(struct scsi_device *sdev)
        VirtDevice              *vdev;
        struct scsi_target      *starget;
 
-       vdev = kmalloc(sizeof(VirtDevice), GFP_KERNEL);
+       vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
        if (!vdev) {
                printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n",
                                hd->ioc->name, sizeof(VirtDevice));
                return -ENOMEM;
        }
 
-       memset(vdev, 0, sizeof(VirtDevice));
        vdev->ioc_id = hd->ioc->id;
        vdev->target_id = sdev->id;
        vdev->bus_id = sdev->channel;
@@ -2559,13 +2558,25 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
                        hd->cmdPtr = NULL;
                }
 
-               /* 7. Set flag to force DV and re-read IOC Page 3
+               /* 7. SPI: Set flag to force DV and re-read IOC Page 3
                 */
                if (ioc->bus_type == SPI) {
                        ioc->spi_data.forceDv = MPT_SCSICFG_NEED_DV | MPT_SCSICFG_RELOAD_IOC_PG3;
                        ddvtprintk(("Set reload IOC Pg3 Flag\n"));
                }
 
+               /* 7. FC: Rescan for blocked rports which might have returned.
+                */
+               else if (ioc->bus_type == FC) {
+                       int work_count;
+                       unsigned long flags;
+
+                       spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+                       work_count = ++ioc->fc_rescan_work_count;
+                       spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+                       if (work_count == 1)
+                               schedule_work(&ioc->fc_rescan_work);
+               }
                dtmprintk((MYIOC_s_WARN_FMT "Post-Reset complete.\n", ioc->name));
 
        }
@@ -2589,6 +2600,8 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
 {
        MPT_SCSI_HOST *hd;
        u8 event = le32_to_cpu(pEvReply->Event) & 0xFF;
+       int work_count;
+       unsigned long flags;
 
        devtprintk((MYIOC_s_INFO_FMT "MPT event (=%02Xh) routed to SCSI host driver!\n",
                        ioc->name, event));
@@ -2610,11 +2623,18 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply)
                /* FIXME! */
                break;
 
+       case MPI_EVENT_RESCAN:                          /* 06 */
+               spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags);
+               work_count = ++ioc->fc_rescan_work_count;
+               spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags);
+               if (work_count == 1)
+                       schedule_work(&ioc->fc_rescan_work);
+               break;
+
                /*
                 *  CHECKME! Don't think we need to do
                 *  anything for these, but...
                 */
-       case MPI_EVENT_RESCAN:                          /* 06 */
        case MPI_EVENT_LINK_STATUS_CHANGE:              /* 07 */
        case MPI_EVENT_LOOP_STATE_CHANGE:               /* 08 */
                /*
@@ -3952,8 +3972,6 @@ mptscsih_synchronize_cache(MPT_SCSI_HOST *hd, VirtDevice *vdevice)
                mptscsih_do_cmd(hd, &iocmd);
 }
 
-/* Search IOC page 3 to determine if this is hidden physical disk
- */
 /* Search IOC page 3 to determine if this is hidden physical disk
  */
 static int
index ce332a6085e5345e2b64a259da1d44a04eec693d..7dce29277cb748e51e1ef8a3956f618cddc28818 100644 (file)
@@ -158,11 +158,10 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        MPT_SCSI_HOST           *hd;
        MPT_ADAPTER             *ioc;
        unsigned long            flags;
-       int                      sz, ii;
+       int                      ii;
        int                      numSGE = 0;
        int                      scale;
        int                      ioc_cap;
-       u8                      *mem;
        int                     error=0;
        int                     r;
 
@@ -288,36 +287,27 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        /* SCSI needs scsi_cmnd lookup table!
         * (with size equal to req_depth*PtrSz!)
         */
-       sz = ioc->req_depth * sizeof(void *);
-       mem = kmalloc(sz, GFP_ATOMIC);
-       if (mem == NULL) {
+       hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
+       if (!hd->ScsiLookup) {
                error = -ENOMEM;
                goto out_mptspi_probe;
        }
 
-       memset(mem, 0, sz);
-       hd->ScsiLookup = (struct scsi_cmnd **) mem;
-
-       dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p, sz=%d\n",
-                ioc->name, hd->ScsiLookup, sz));
+       dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
+                ioc->name, hd->ScsiLookup));
 
        /* Allocate memory for the device structures.
         * A non-Null pointer at an offset
         * indicates a device exists.
         * max_id = 1 + maximum id (hosts.h)
         */
-       sz = sh->max_id * sizeof(void *);
-       mem = kmalloc(sz, GFP_ATOMIC);
-       if (mem == NULL) {
+       hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
+       if (!hd->Targets) {
                error = -ENOMEM;
                goto out_mptspi_probe;
        }
 
-       memset(mem, 0, sz);
-       hd->Targets = (VirtTarget **) mem;
-
-       dprintk((KERN_INFO
-         "  vdev @ %p, sz=%d\n", hd->Targets, sz));
+       dprintk((KERN_INFO "  vdev @ %p\n", hd->Targets));
 
        /* Clear the TM flags
         */
index c5b656cdea7cf2b72a88267343a159deb01efd75..d698d7709c31c8d6073a58e3893de2c723f760f5 100644 (file)
@@ -88,11 +88,6 @@ static int __devinit i2o_pci_alloc(struct i2o_controller *c)
        struct device *dev = &pdev->dev;
        int i;
 
-       if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
-               printk(KERN_ERR "%s: device already claimed\n", c->name);
-               return -ENODEV;
-       }
-
        for (i = 0; i < 6; i++) {
                /* Skip I/O spaces */
                if (!(pci_resource_flags(pdev, i) & IORESOURCE_IO)) {
@@ -319,6 +314,11 @@ static int __devinit i2o_pci_probe(struct pci_dev *pdev,
                return rc;
        }
 
+       if (pci_request_regions(pdev, OSM_DESCRIPTION)) {
+               printk(KERN_ERR "i2o: device already claimed\n");
+               return -ENODEV;
+       }
+
        if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) {
                printk(KERN_WARNING "i2o: no suitable DMA found for %s\n",
                       pci_name(pdev));
index 5e84c5aa777977fac96b7b86d42be9547b70f779..167fef39d8a789400d0a41968e23d64f7972ef79 100644 (file)
@@ -1125,6 +1125,8 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter)
        zfcp_free_low_mem_buffers(adapter);
        /* free memory of adapter data structure and queues */
        zfcp_qdio_free_queues(adapter);
+       kfree(adapter->fc_stats);
+       kfree(adapter->stats_reset_data);
        ZFCP_LOG_TRACE("freeing adapter structure\n");
        kfree(adapter);
  out:
index d81b737d68ccafa8c92b3afe7738e7587ecfd596..9bb511083a261a4a40c9506a26d0f26a8a1d559a 100644 (file)
@@ -921,7 +921,6 @@ struct zfcp_adapter {
        u32                     physical_s_id;     /* local FC port ID */
        struct ccw_device       *ccw_device;       /* S/390 ccw device */
        u8                      fc_service_class;
-       u32                     fc_topology;       /* FC topology */
        u32                     hydra_version;     /* Hydra version */
        u32                     fsf_lic_version;
        u32                     adapter_features;  /* FCP channel features */
@@ -978,6 +977,9 @@ struct zfcp_adapter {
        struct zfcp_adapter_mempool     pool;      /* Adapter memory pools */
        struct qdio_initialize  qdio_init_data;    /* for qdio_establish */
        struct device           generic_services;  /* directory for WKA ports */
+       struct fc_host_statistics *fc_stats;
+       struct fsf_qtcb_bottom_port *stats_reset_data;
+       unsigned long           stats_reset;
 };
 
 /*
index ee7314d8c2da8bed70dbb84345ca1fab25053d03..7bdb00b5aeb2092bf5eb70fcc25fae4b239a59c0 100644 (file)
@@ -2613,7 +2613,7 @@ zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *erp_action)
        case ZFCP_ERP_STEP_UNINITIALIZED:
        case ZFCP_ERP_STEP_PHYS_PORT_CLOSING:
        case ZFCP_ERP_STEP_PORT_CLOSING:
-               if (adapter->fc_topology == FSF_TOPO_P2P) {
+               if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP) {
                        if (port->wwpn != adapter->peer_wwpn) {
                                ZFCP_LOG_NORMAL("Failed to open port 0x%016Lx "
                                                "on adapter %s.\nPeer WWPN "
index 59587951c847cae2a6eb48baadaa3d64ba0136b4..cbfab09899c89ca7104dd3bfb4abc8c28f5e279b 100644 (file)
@@ -964,6 +964,40 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req)
                                        | ZFCP_STATUS_COMMON_ERP_FAILED);
                break;
 
+       case FSF_STATUS_READ_NOTIFICATION_LOST:
+               ZFCP_LOG_NORMAL("Unsolicited status notification(s) lost: "
+                               "adapter %s%s%s%s%s%s%s%s%s\n",
+                               zfcp_get_busid_by_adapter(adapter),
+                               (status_buffer->status_subtype &
+                                       FSF_STATUS_READ_SUB_INCOMING_ELS) ?
+                                       ", incoming ELS" : "",
+                               (status_buffer->status_subtype &
+                                       FSF_STATUS_READ_SUB_SENSE_DATA) ?
+                                       ", sense data" : "",
+                               (status_buffer->status_subtype &
+                                       FSF_STATUS_READ_SUB_LINK_STATUS) ?
+                                       ", link status change" : "",
+                               (status_buffer->status_subtype &
+                                       FSF_STATUS_READ_SUB_PORT_CLOSED) ?
+                                       ", port close" : "",
+                               (status_buffer->status_subtype &
+                                       FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD) ?
+                                       ", bit error exception" : "",
+                               (status_buffer->status_subtype &
+                                       FSF_STATUS_READ_SUB_ACT_UPDATED) ?
+                                       ", ACT update" : "",
+                               (status_buffer->status_subtype &
+                                       FSF_STATUS_READ_SUB_ACT_HARDENED) ?
+                                       ", ACT hardening" : "",
+                               (status_buffer->status_subtype &
+                                       FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT) ?
+                                       ", adapter feature change" : "");
+
+               if (status_buffer->status_subtype &
+                   FSF_STATUS_READ_SUB_ACT_UPDATED)
+                       zfcp_erp_adapter_access_changed(adapter);
+               break;
+
        case FSF_STATUS_READ_CFDC_UPDATED:
                ZFCP_LOG_NORMAL("CFDC has been updated on the adapter %s\n",
                              zfcp_get_busid_by_adapter(adapter));
@@ -1954,6 +1988,7 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action)
        erp_action->fsf_req->qtcb->bottom.config.feature_selection =
                        FSF_FEATURE_CFDC |
                        FSF_FEATURE_LUN_SHARING |
+                       FSF_FEATURE_NOTIFICATION_LOST |
                        FSF_FEATURE_UPDATE_ALERT;
 
        /* start QDIO request for this FSF request */
@@ -2008,27 +2043,30 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
                fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK;
                fc_host_speed(shost) = bottom->fc_link_speed;
                fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3;
-               adapter->fc_topology = bottom->fc_topology;
                adapter->hydra_version = bottom->adapter_type;
-               if (adapter->physical_wwpn == 0)
-                       adapter->physical_wwpn = fc_host_port_name(shost);
-               if (adapter->physical_s_id == 0)
-                       adapter->physical_s_id = fc_host_port_id(shost);
+               if (fc_host_permanent_port_name(shost) == -1)
+                       fc_host_permanent_port_name(shost) =
+                               fc_host_port_name(shost);
+               if (bottom->fc_topology == FSF_TOPO_P2P) {
+                       adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
+                       adapter->peer_wwpn = bottom->plogi_payload.wwpn;
+                       adapter->peer_wwnn = bottom->plogi_payload.wwnn;
+                       fc_host_port_type(shost) = FC_PORTTYPE_PTP;
+               } else if (bottom->fc_topology == FSF_TOPO_FABRIC)
+                       fc_host_port_type(shost) = FC_PORTTYPE_NPORT;
+               else if (bottom->fc_topology == FSF_TOPO_AL)
+                       fc_host_port_type(shost) = FC_PORTTYPE_NLPORT;
+               else
+                       fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
        } else {
                fc_host_node_name(shost) = 0;
                fc_host_port_name(shost) = 0;
                fc_host_port_id(shost) = 0;
                fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN;
-               adapter->fc_topology = 0;
+               fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN;
                adapter->hydra_version = 0;
        }
 
-       if (adapter->fc_topology == FSF_TOPO_P2P) {
-               adapter->peer_d_id = bottom->peer_d_id & ZFCP_DID_MASK;
-               adapter->peer_wwpn = bottom->plogi_payload.wwpn;
-               adapter->peer_wwnn = bottom->plogi_payload.wwnn;
-       }
-
        if (adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT) {
                adapter->hardware_version = bottom->hardware_version;
                memcpy(fc_host_serial_number(shost), bottom->serial_number,
@@ -2097,8 +2135,8 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
                if (zfcp_fsf_exchange_config_evaluate(fsf_req, 1))
                        return -EIO;
 
-               switch (adapter->fc_topology) {
-               case FSF_TOPO_P2P:
+               switch (fc_host_port_type(adapter->scsi_host)) {
+               case FC_PORTTYPE_PTP:
                        ZFCP_LOG_NORMAL("Point-to-Point fibrechannel "
                                        "configuration detected at adapter %s\n"
                                        "Peer WWNN 0x%016llx, "
@@ -2111,7 +2149,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
                        debug_text_event(fsf_req->adapter->erp_dbf, 0,
                                         "top-p-to-p");
                        break;
-               case FSF_TOPO_AL:
+               case FC_PORTTYPE_NLPORT:
                        ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel "
                                        "topology detected at adapter %s "
                                        "unsupported, shutting down adapter\n",
@@ -2120,7 +2158,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
                                         "top-al");
                        zfcp_erp_adapter_shutdown(adapter, 0);
                        return -EIO;
-               case FSF_TOPO_FABRIC:
+               case FC_PORTTYPE_NPORT:
                        ZFCP_LOG_NORMAL("Switched fabric fibrechannel "
                                      "network detected at adapter %s.\n",
                                      zfcp_get_busid_by_adapter(adapter));
@@ -2133,7 +2171,6 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req)
                                        "of a type known to the zfcp "
                                        "driver, shutting down adapter\n",
                                        zfcp_get_busid_by_adapter(adapter));
-                       adapter->fc_topology = FSF_TOPO_ERROR;
                        debug_text_exception(fsf_req->adapter->erp_dbf, 0,
                                             "unknown-topo");
                        zfcp_erp_adapter_shutdown(adapter, 0);
@@ -2293,14 +2330,13 @@ zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req)
                data = (struct fsf_qtcb_bottom_port*) fsf_req->data;
                if (data)
                        memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port));
-               if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) {
-                       adapter->physical_wwpn = bottom->wwpn;
-                       adapter->physical_s_id = bottom->fc_port_id;
-               } else {
-                       adapter->physical_wwpn = fc_host_port_name(shost);
-                       adapter->physical_s_id = fc_host_port_id(shost);
-               }
+               if (adapter->connection_features & FSF_FEATURE_NPIV_MODE)
+                       fc_host_permanent_port_name(shost) = bottom->wwpn;
+               else
+                       fc_host_permanent_port_name(shost) =
+                               fc_host_port_name(shost);
                fc_host_maxframe_size(shost) = bottom->maximum_frame_size;
+               fc_host_supported_speeds(shost) = bottom->supported_speed;
                break;
 
        case FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE:
index 48719f0559527b93eef93c442087d6517bc5f9fd..e734415cae6d631c28654f3135711de2e093b7c5 100644 (file)
 #define FSF_STATUS_READ_BIT_ERROR_THRESHOLD    0x00000004
 #define FSF_STATUS_READ_LINK_DOWN              0x00000005
 #define FSF_STATUS_READ_LINK_UP                0x00000006
+#define FSF_STATUS_READ_NOTIFICATION_LOST      0x00000009
 #define FSF_STATUS_READ_CFDC_UPDATED           0x0000000A
 #define FSF_STATUS_READ_CFDC_HARDENED          0x0000000B
 #define FSF_STATUS_READ_FEATURE_UPDATE_ALERT   0x0000000C
 #define FSF_STATUS_READ_SUB_FDISC_FAILED       0x00000001
 #define FSF_STATUS_READ_SUB_FIRMWARE_UPDATE    0x00000002
 
+/* status subtypes for unsolicited status notification lost */
+#define FSF_STATUS_READ_SUB_INCOMING_ELS       0x00000001
+#define FSF_STATUS_READ_SUB_SENSE_DATA         0x00000002
+#define FSF_STATUS_READ_SUB_LINK_STATUS                0x00000004
+#define FSF_STATUS_READ_SUB_PORT_CLOSED                0x00000008
+#define FSF_STATUS_READ_SUB_BIT_ERROR_THRESHOLD        0x00000010
+#define FSF_STATUS_READ_SUB_ACT_UPDATED                0x00000020
+#define FSF_STATUS_READ_SUB_ACT_HARDENED       0x00000040
+#define FSF_STATUS_READ_SUB_FEATURE_UPDATE_ALERT 0x00000080
+
 /* status subtypes for CFDC */
 #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE        0x00000002
 #define FSF_STATUS_READ_SUB_CFDC_HARDENED_ON_SE2 0x0000000F
 #define FSF_TOPO_P2P                           0x00000001
 #define FSF_TOPO_FABRIC                                0x00000002
 #define FSF_TOPO_AL                            0x00000003
-#define FSF_TOPO_FABRIC_VIRT                   0x00000004
 
 /* data direction for FCP commands */
 #define FSF_DATADIR_WRITE                      0x00000001
 /* channel features */
 #define FSF_FEATURE_CFDC                       0x00000002
 #define FSF_FEATURE_LUN_SHARING                        0x00000004
+#define FSF_FEATURE_NOTIFICATION_LOST          0x00000008
 #define FSF_FEATURE_HBAAPI_MANAGEMENT           0x00000010
 #define FSF_FEATURE_ELS_CT_CHAINED_SBALS        0x00000020
 #define FSF_FEATURE_UPDATE_ALERT               0x00000100
index 66608d13a63497b40c4b6002bfad94d30c014728..3c2cbcccbf54c559598e663cc5caa522b2f42f55 100644 (file)
@@ -49,8 +49,6 @@ static int zfcp_task_management_function(struct zfcp_unit *, u8,
 
 static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t,
                                          scsi_lun_t);
-static struct zfcp_port *zfcp_port_lookup(struct zfcp_adapter *, int,
-                                         scsi_id_t);
 
 static struct device_attribute *zfcp_sysfs_sdev_attrs[];
 
@@ -406,18 +404,6 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id,
        return retval;
 }
 
-static struct zfcp_port *
-zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id)
-{
-       struct zfcp_port *port;
-
-       list_for_each_entry(port, &adapter->port_list_head, list) {
-               if (port->rport && (id == port->rport->scsi_target_id))
-                       return port;
-       }
-       return (struct zfcp_port *) NULL;
-}
-
 /**
  * zfcp_scsi_eh_abort_handler - abort the specified SCSI command
  * @scpnt: pointer to scsi_cmnd to be aborted 
@@ -731,70 +717,164 @@ zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter)
 /*
  * Support functions for FC transport class
  */
-static void
-zfcp_get_port_id(struct scsi_target *starget)
+static struct fc_host_statistics*
+zfcp_init_fc_host_stats(struct zfcp_adapter *adapter)
 {
-       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-       struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0];
-       struct zfcp_port *port;
-       unsigned long flags;
+       struct fc_host_statistics *fc_stats;
 
-       read_lock_irqsave(&zfcp_data.config_lock, flags);
-       port = zfcp_port_lookup(adapter, starget->channel, starget->id);
-       if (port)
-               fc_starget_port_id(starget) = port->d_id;
-       else
-               fc_starget_port_id(starget) = -1;
-       read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+       if (!adapter->fc_stats) {
+               fc_stats = kmalloc(sizeof(*fc_stats), GFP_KERNEL);
+               if (!fc_stats)
+                       return NULL;
+               adapter->fc_stats = fc_stats; /* freed in adater_dequeue */
+       }
+       memset(adapter->fc_stats, 0, sizeof(*adapter->fc_stats));
+       return adapter->fc_stats;
 }
 
 static void
-zfcp_get_port_name(struct scsi_target *starget)
+zfcp_adjust_fc_host_stats(struct fc_host_statistics *fc_stats,
+                         struct fsf_qtcb_bottom_port *data,
+                         struct fsf_qtcb_bottom_port *old)
 {
-       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-       struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0];
-       struct zfcp_port *port;
-       unsigned long flags;
+       fc_stats->seconds_since_last_reset = data->seconds_since_last_reset -
+               old->seconds_since_last_reset;
+       fc_stats->tx_frames = data->tx_frames - old->tx_frames;
+       fc_stats->tx_words = data->tx_words - old->tx_words;
+       fc_stats->rx_frames = data->rx_frames - old->rx_frames;
+       fc_stats->rx_words = data->rx_words - old->rx_words;
+       fc_stats->lip_count = data->lip - old->lip;
+       fc_stats->nos_count = data->nos - old->nos;
+       fc_stats->error_frames = data->error_frames - old->error_frames;
+       fc_stats->dumped_frames = data->dumped_frames - old->dumped_frames;
+       fc_stats->link_failure_count = data->link_failure - old->link_failure;
+       fc_stats->loss_of_sync_count = data->loss_of_sync - old->loss_of_sync;
+       fc_stats->loss_of_signal_count = data->loss_of_signal -
+               old->loss_of_signal;
+       fc_stats->prim_seq_protocol_err_count = data->psp_error_counts -
+               old->psp_error_counts;
+       fc_stats->invalid_tx_word_count = data->invalid_tx_words -
+               old->invalid_tx_words;
+       fc_stats->invalid_crc_count = data->invalid_crcs - old->invalid_crcs;
+       fc_stats->fcp_input_requests = data->input_requests -
+               old->input_requests;
+       fc_stats->fcp_output_requests = data->output_requests -
+               old->output_requests;
+       fc_stats->fcp_control_requests = data->control_requests -
+               old->control_requests;
+       fc_stats->fcp_input_megabytes = data->input_mb - old->input_mb;
+       fc_stats->fcp_output_megabytes = data->output_mb - old->output_mb;
+}
 
-       read_lock_irqsave(&zfcp_data.config_lock, flags);
-       port = zfcp_port_lookup(adapter, starget->channel, starget->id);
-       if (port)
-               fc_starget_port_name(starget) = port->wwpn;
-       else
-               fc_starget_port_name(starget) = -1;
-       read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+static void
+zfcp_set_fc_host_stats(struct fc_host_statistics *fc_stats,
+                      struct fsf_qtcb_bottom_port *data)
+{
+       fc_stats->seconds_since_last_reset = data->seconds_since_last_reset;
+       fc_stats->tx_frames = data->tx_frames;
+       fc_stats->tx_words = data->tx_words;
+       fc_stats->rx_frames = data->rx_frames;
+       fc_stats->rx_words = data->rx_words;
+       fc_stats->lip_count = data->lip;
+       fc_stats->nos_count = data->nos;
+       fc_stats->error_frames = data->error_frames;
+       fc_stats->dumped_frames = data->dumped_frames;
+       fc_stats->link_failure_count = data->link_failure;
+       fc_stats->loss_of_sync_count = data->loss_of_sync;
+       fc_stats->loss_of_signal_count = data->loss_of_signal;
+       fc_stats->prim_seq_protocol_err_count = data->psp_error_counts;
+       fc_stats->invalid_tx_word_count = data->invalid_tx_words;
+       fc_stats->invalid_crc_count = data->invalid_crcs;
+       fc_stats->fcp_input_requests = data->input_requests;
+       fc_stats->fcp_output_requests = data->output_requests;
+       fc_stats->fcp_control_requests = data->control_requests;
+       fc_stats->fcp_input_megabytes = data->input_mb;
+       fc_stats->fcp_output_megabytes = data->output_mb;
+}
+
+/**
+ * zfcp_get_fc_host_stats - provide fc_host_statistics for scsi_transport_fc
+ *
+ * assumption: scsi_transport_fc synchronizes calls of
+ *             get_fc_host_stats and reset_fc_host_stats
+ *             (XXX to be checked otherwise introduce locking)
+ */
+static struct fc_host_statistics *
+zfcp_get_fc_host_stats(struct Scsi_Host *shost)
+{
+       struct zfcp_adapter *adapter;
+       struct fc_host_statistics *fc_stats;
+       struct fsf_qtcb_bottom_port *data;
+       int ret;
+
+       adapter = (struct zfcp_adapter *)shost->hostdata[0];
+       fc_stats = zfcp_init_fc_host_stats(adapter);
+       if (!fc_stats)
+               return NULL;
+
+       data = kmalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return NULL;
+       memset(data, 0, sizeof(*data));
+
+       ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
+       if (ret) {
+               kfree(data);
+               return NULL; /* XXX return zeroed fc_stats? */
+       }
+
+       if (adapter->stats_reset &&
+           ((jiffies/HZ - adapter->stats_reset) <
+            data->seconds_since_last_reset)) {
+               zfcp_adjust_fc_host_stats(fc_stats, data,
+                                         adapter->stats_reset_data);
+       } else
+               zfcp_set_fc_host_stats(fc_stats, data);
+
+       kfree(data);
+       return fc_stats;
 }
 
 static void
-zfcp_get_node_name(struct scsi_target *starget)
+zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
 {
-       struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
-       struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0];
-       struct zfcp_port *port;
-       unsigned long flags;
+       struct zfcp_adapter *adapter;
+       struct fsf_qtcb_bottom_port *data, *old_data;
+       int ret;
 
-       read_lock_irqsave(&zfcp_data.config_lock, flags);
-       port = zfcp_port_lookup(adapter, starget->channel, starget->id);
-       if (port)
-               fc_starget_node_name(starget) = port->wwnn;
-       else
-               fc_starget_node_name(starget) = -1;
-       read_unlock_irqrestore(&zfcp_data.config_lock, flags);
+       adapter = (struct zfcp_adapter *)shost->hostdata[0];
+       data = kmalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return;
+       memset(data, 0, sizeof(*data));
+
+       ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
+       if (ret == 0) {
+               adapter->stats_reset = jiffies/HZ;
+               old_data = adapter->stats_reset_data;
+               adapter->stats_reset_data = data; /* finally freed in
+                                                    adater_dequeue */
+               kfree(old_data);
+       }
 }
 
 struct fc_function_template zfcp_transport_functions = {
-       .get_starget_port_id = zfcp_get_port_id,
-       .get_starget_port_name = zfcp_get_port_name,
-       .get_starget_node_name = zfcp_get_node_name,
        .show_starget_port_id = 1,
        .show_starget_port_name = 1,
        .show_starget_node_name = 1,
        .show_rport_supported_classes = 1,
        .show_host_node_name = 1,
        .show_host_port_name = 1,
+       .show_host_permanent_port_name = 1,
        .show_host_supported_classes = 1,
+       .show_host_supported_speeds = 1,
        .show_host_maxframe_size = 1,
        .show_host_serial_number = 1,
+       .get_fc_host_stats = zfcp_get_fc_host_stats,
+       .reset_fc_host_stats = zfcp_reset_fc_host_stats,
+       /* no functions registered for following dynamic attributes but
+          directly set by LLDD */
+       .show_host_port_type = 1,
        .show_host_speed = 1,
        .show_host_port_id = 1,
 };
index 0cd435280e7db00947a8d02d21a536fef5ee9762..9f262250043a5d006e99b0b3850f3a351b4821f1 100644 (file)
 
 #define ZFCP_LOG_AREA                   ZFCP_LOG_AREA_CONFIG
 
-static const char fc_topologies[5][25] = {
-       "<error>",
-       "point-to-point",
-       "fabric",
-       "arbitrated loop",
-       "fabric (virt. adapter)"
-};
-
 /**
  * ZFCP_DEFINE_ADAPTER_ATTR
  * @_name:   name of show attribute
@@ -69,12 +61,8 @@ ZFCP_DEFINE_ADAPTER_ATTR(physical_wwpn, "0x%016llx\n", adapter->physical_wwpn);
 ZFCP_DEFINE_ADAPTER_ATTR(physical_s_id, "0x%06x\n", adapter->physical_s_id);
 ZFCP_DEFINE_ADAPTER_ATTR(card_version, "0x%04x\n", adapter->hydra_version);
 ZFCP_DEFINE_ADAPTER_ATTR(lic_version, "0x%08x\n", adapter->fsf_lic_version);
-ZFCP_DEFINE_ADAPTER_ATTR(fc_service_class, "%d\n", adapter->fc_service_class);
-ZFCP_DEFINE_ADAPTER_ATTR(fc_topology, "%s\n",
-                        fc_topologies[adapter->fc_topology]);
 ZFCP_DEFINE_ADAPTER_ATTR(hardware_version, "0x%08x\n",
                         adapter->hardware_version);
-ZFCP_DEFINE_ADAPTER_ATTR(scsi_host_no, "0x%x\n", adapter->scsi_host_no);
 ZFCP_DEFINE_ADAPTER_ATTR(in_recovery, "%d\n", atomic_test_mask
                         (ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status));
 
@@ -259,9 +247,6 @@ static struct attribute *zfcp_adapter_attrs[] = {
        &dev_attr_physical_s_id.attr,
        &dev_attr_card_version.attr,
        &dev_attr_lic_version.attr,
-       &dev_attr_fc_service_class.attr,
-       &dev_attr_fc_topology.attr,
-       &dev_attr_scsi_host_no.attr,
        &dev_attr_status.attr,
        &dev_attr_hardware_version.attr,
        NULL
index c55e82d91deb103133047d823ce3b122de097271..3924eb38805c5e24cae27b148af445f20ce73477 100644 (file)
@@ -65,8 +65,6 @@ static ssize_t zfcp_sysfs_port_##_name##_show(struct device *dev, struct device_
 static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_port_##_name##_show, NULL);
 
 ZFCP_DEFINE_PORT_ATTR(status, "0x%08x\n", atomic_read(&port->status));
-ZFCP_DEFINE_PORT_ATTR(wwnn, "0x%016llx\n", port->wwnn);
-ZFCP_DEFINE_PORT_ATTR(d_id, "0x%06x\n", port->d_id);
 ZFCP_DEFINE_PORT_ATTR(in_recovery, "%d\n", atomic_test_mask
                      (ZFCP_STATUS_COMMON_ERP_INUSE, &port->status));
 ZFCP_DEFINE_PORT_ATTR(access_denied, "%d\n", atomic_test_mask
@@ -245,8 +243,6 @@ static struct attribute *zfcp_port_common_attrs[] = {
        &dev_attr_failed.attr,
        &dev_attr_in_recovery.attr,
        &dev_attr_status.attr,
-       &dev_attr_wwnn.attr,
-       &dev_attr_d_id.attr,
        &dev_attr_access_denied.attr,
        NULL
 };
index 0556642c9e1d5ed7cf94d83bf3ff5e8358df7dd4..2f50815f65c746d386d051545fe540637676ea9b 100644 (file)
@@ -65,7 +65,6 @@ static ssize_t zfcp_sysfs_unit_##_name##_show(struct device *dev, struct device_
 static DEVICE_ATTR(_name, S_IRUGO, zfcp_sysfs_unit_##_name##_show, NULL);
 
 ZFCP_DEFINE_UNIT_ATTR(status, "0x%08x\n", atomic_read(&unit->status));
-ZFCP_DEFINE_UNIT_ATTR(scsi_lun, "0x%x\n", unit->scsi_lun);
 ZFCP_DEFINE_UNIT_ATTR(in_recovery, "%d\n", atomic_test_mask
                      (ZFCP_STATUS_COMMON_ERP_INUSE, &unit->status));
 ZFCP_DEFINE_UNIT_ATTR(access_denied, "%d\n", atomic_test_mask
@@ -138,7 +137,6 @@ static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_unit_failed_show,
                   zfcp_sysfs_unit_failed_store);
 
 static struct attribute *zfcp_unit_attrs[] = {
-       &dev_attr_scsi_lun.attr,
        &dev_attr_failed.attr,
        &dev_attr_in_recovery.attr,
        &dev_attr_status.attr,
index 3ff74f472249bb638a30933389b9046e75862633..31c4975422729d46a47802e975c58c0cc8d46f6a 100644 (file)
@@ -73,6 +73,7 @@
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/time.h>
+#include <linux/mutex.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
@@ -615,7 +616,7 @@ static int twa_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
        void __user *argp = (void __user *)arg;
 
        /* Only let one of these through at a time */
-       if (down_interruptible(&tw_dev->ioctl_sem)) {
+       if (mutex_lock_interruptible(&tw_dev->ioctl_lock)) {
                retval = TW_IOCTL_ERROR_OS_EINTR;
                goto out;
        }
@@ -852,7 +853,7 @@ out3:
        /* Now free ioctl buf memory */
        dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_Ioctl_Buf_Apache) - 1, cpu_addr, dma_handle);
 out2:
-       up(&tw_dev->ioctl_sem);
+       mutex_unlock(&tw_dev->ioctl_lock);
 out:
        return retval;
 } /* End twa_chrdev_ioctl() */
@@ -1182,7 +1183,7 @@ static int twa_initialize_device_extension(TW_Device_Extension *tw_dev)
        tw_dev->error_sequence_id = 1;
        tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
 
-       init_MUTEX(&tw_dev->ioctl_sem);
+       mutex_init(&tw_dev->ioctl_lock);
        init_waitqueue_head(&tw_dev->ioctl_wqueue);
 
        retval = 0;
index 46f22cdc82985d91bbad87fe3df4a0e8e090cc5d..1b16d57f0314b239d2833a49c063f26e18c6234f 100644 (file)
@@ -672,7 +672,7 @@ typedef struct TAG_TW_Device_Extension {
        u32                     ioctl_msec;
        int                     chrdev_request_id;
        wait_queue_head_t       ioctl_wqueue;
-       struct semaphore        ioctl_sem;
+       struct mutex            ioctl_lock;
        char                    aen_clobber;
        unsigned short          working_srl;
        unsigned short          working_branch;
index 283f6d25892b9c7d97dfd97fe3643ad12d7d0c47..25f678d0780b2e1bb2dcf12a767b8607739db150 100644 (file)
 #include <linux/delay.h>
 #include <linux/pci.h>
 #include <linux/time.h>
+#include <linux/mutex.h>
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
@@ -888,7 +889,7 @@ static int tw_chrdev_ioctl(struct inode *inode, struct file *file, unsigned int
        dprintk(KERN_WARNING "3w-xxxx: tw_chrdev_ioctl()\n");
 
        /* Only let one of these through at a time */
-       if (down_interruptible(&tw_dev->ioctl_sem))
+       if (mutex_lock_interruptible(&tw_dev->ioctl_lock))
                return -EINTR;
 
        /* First copy down the buffer length */
@@ -1029,7 +1030,7 @@ out2:
        /* Now free ioctl buf memory */
        dma_free_coherent(&tw_dev->tw_pci_dev->dev, data_buffer_length_adjusted+sizeof(TW_New_Ioctl) - 1, cpu_addr, dma_handle);
 out:
-       up(&tw_dev->ioctl_sem);
+       mutex_unlock(&tw_dev->ioctl_lock);
        return retval;
 } /* End tw_chrdev_ioctl() */
 
@@ -1270,7 +1271,7 @@ static int tw_initialize_device_extension(TW_Device_Extension *tw_dev)
        tw_dev->pending_tail = TW_Q_START;
        tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE;
 
-       init_MUTEX(&tw_dev->ioctl_sem);
+       mutex_init(&tw_dev->ioctl_lock);
        init_waitqueue_head(&tw_dev->ioctl_wqueue);
 
        return 0;
index 4f81fc39ec57d7525a506021433aaefec0707702..31fe5ea159205bb15b861a615d39b7405679c728 100644 (file)
@@ -420,7 +420,7 @@ typedef struct TAG_TW_Device_Extension {
        u32                     max_sector_count;
        u32                     aen_count;
        struct Scsi_Host        *host;
-       struct semaphore        ioctl_sem;
+       struct mutex            ioctl_lock;
        unsigned short          aen_queue[TW_Q_LENGTH];
        unsigned char           aen_head;
        unsigned char           aen_tail;
index 9d6040bfa0646ae32283be9f1ffde0e974172594..1c459343292bb6b910cf28322293df912bfb9323 100644 (file)
@@ -2216,6 +2216,7 @@ static int __init BusLogic_init(void)
                HostAdapter->PCI_Address = ProbeInfo->PCI_Address;
                HostAdapter->Bus = ProbeInfo->Bus;
                HostAdapter->Device = ProbeInfo->Device;
+               HostAdapter->PCI_Device = ProbeInfo->PCI_Device;
                HostAdapter->IRQ_Channel = ProbeInfo->IRQ_Channel;
                HostAdapter->AddressCount = BusLogic_HostAdapterAddressCount[HostAdapter->HostAdapterType];
                /*
@@ -2296,7 +2297,7 @@ static int __init BusLogic_init(void)
                                scsi_host_put(Host);
                        } else {
                                BusLogic_InitializeHostStructure(HostAdapter, Host);
-                               scsi_add_host(Host, NULL);
+                               scsi_add_host(Host, HostAdapter->PCI_Device ? &HostAdapter->PCI_Device->dev : NULL);
                                scsi_scan_host(Host);
                                BusLogicHostAdapterCount++;
                        }
index 6e0c059df6a5339da1349164aa59cb46ae5733a8..320e765fa0cd97b873e62b6c805d07c52aab67d1 100644 (file)
@@ -80,7 +80,7 @@ obj-$(CONFIG_SCSI_QLOGIC_FAS) += qlogicfas408.o       qlogicfas.o
 obj-$(CONFIG_PCMCIA_QLOGIC)    += qlogicfas408.o
 obj-$(CONFIG_SCSI_QLOGIC_FC)   += qlogicfc.o 
 obj-$(CONFIG_SCSI_QLOGIC_1280) += qla1280.o 
-obj-$(CONFIG_SCSI_QLA2XXX)     += qla2xxx/
+obj-$(CONFIG_SCSI_QLA_FC)      += qla2xxx/
 obj-$(CONFIG_SCSI_LPFC)                += lpfc/
 obj-$(CONFIG_SCSI_PAS16)       += pas16.o
 obj-$(CONFIG_SCSI_SEAGATE)     += seagate.o
diff --git a/drivers/scsi/aacraid/README b/drivers/scsi/aacraid/README
deleted file mode 100644 (file)
index 4193865..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-AACRAID Driver for Linux (take two)
-
-Introduction
--------------------------
-The aacraid driver adds support for Adaptec (http://www.adaptec.com)
-RAID controllers. This is a major rewrite from the original 
-Adaptec supplied driver. It has signficantly cleaned up both the code
-and the running binary size (the module is less than half the size of
-the original).
-
-Supported Cards/Chipsets
--------------------------
-       Adaptec 2020S
-       Adaptec 2025S
-       Adaptec 2120S
-       Adaptec 2130S
-       Adaptec 2200S
-       Adaptec 2230S
-       Adaptec 2240S
-       Adaptec 2410SA
-       Adaptec 2610SA
-       Adaptec 2810SA
-       Adaptec 21610SA
-       Adaptec 3230S
-       Adaptec 3240S
-       Adaptec 4000SAS
-       Adaptec 4005SAS
-       Adaptec 4800SAS
-       Adaptec 4805SAS
-       Adaptec 5400S
-       Dell PERC 2 Quad Channel
-       Dell PERC 2/Si
-       Dell PERC 3/Si
-       Dell PERC 3/Di
-       Dell CERC 2
-       HP NetRAID-4M
-       Legend S220
-       Legend S230
-       IBM ServeRAID 8i
-       ICP 9014R0
-       ICP 9024R0
-       ICP 9047MA
-       ICP 9087MA
-       ICP 9085LI
-       ICP 5085AU
-
-People
--------------------------
-Alan Cox <alan@redhat.com>
-Christoph Hellwig <hch@infradead.org>  (updates for new-style PCI probing and SCSI host registration,
-                                        small cleanups/fixes)
-Matt Domsch <matt_domsch@dell.com>     (revision ioctl, adapter messages)
-Deanna Bonds                            (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers
-                                        added new ioctls, changed scsi interface to use new error handler,
-                                        increased the number of fibs and outstanding commands to a container)
-
-                                       (fixed 64bit and 64G memory model, changed confusing naming convention
-                                        where fibs that go to the hardware are consistently called hw_fibs and
-                                        not just fibs like the name of the driver tracking structure)
-Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations.
-
-Original Driver
--------------------------
-Adaptec Unix OEM Product Group
-
-Mailing List
--------------------------
-linux-scsi@vger.kernel.org (Interested parties troll here)
-Also note this is very different to Brian's original driver
-so don't expect him to support it.
-Adaptec does support this driver.  Contact either tech support or Mark Salyzyn.
-
-Original by Brian Boerner February 2001
-Rewritten by Alan Cox, November 2001
index 30fd8d6e3f31081042f56ba897a87bae84fa9dab..66dbb6d2c506afe1ce904b66db2aa76f3b93c72e 100644 (file)
@@ -531,6 +531,13 @@ struct aac_driver_ident
  */
 #define AAC_QUIRK_MASTER 0x0008
 
+/*
+ * Some adapter firmware perform poorly when it must split up scatter gathers
+ * in order to deal with the limits of the underlying CHIM. This limit in this
+ * class of adapters is 17 scatter gather elements.
+ */
+#define AAC_QUIRK_17SG 0x0010
+
 /*
  *     The adapter interface specs all queues to be located in the same
  *     physically contigous block. The host structure that defines the
index ef623bd965f52fade74db0e16e8a7a61f29610f8..4fe79cd7c957664bf8a686b18d46fe490b131d7a 100644 (file)
@@ -85,6 +85,10 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
        if (size < le16_to_cpu(kfib->header.SenderSize))
                size = le16_to_cpu(kfib->header.SenderSize);
        if (size > dev->max_fib_size) {
+               if (size > 2048) {
+                       retval = -EINVAL;
+                       goto cleanup;
+               }
                /* Highjack the hw_fib */
                hw_fib = fibptr->hw_fib;
                hw_fib_pa = fibptr->hw_fib_pa;
index 9b9062f02462534a216e2099ae7fa93d5ea0d3c0..0bf5f9a943e8a548d779b022246d63348f5c3c77 100644 (file)
@@ -200,10 +200,10 @@ static struct aac_driver_ident aac_drivers[] = {
        { aac_rkt_init, "aacraid",  "ADAPTEC ", "Callisto        ", 2, AAC_QUIRK_MASTER }, /* Jupiter Platform */
        { aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2020SA       ", 1 }, /* ASR-2020SA SATA PCI-X ZCR (Skyhawk) */
        { aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2025SA       ", 1 }, /* ASR-2025SA SATA SO-DIMM PCI-X ZCR (Terminator) */
-       { aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2410SA SATA ", 1 }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
-       { aac_rx_init, "aacraid",  "DELL    ", "CERC SR2        ", 1 }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
-       { aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2810SA SATA ", 1 }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
-       { aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-21610SA SATA", 1 }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
+       { aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2410SA SATA ", 1, AAC_QUIRK_17SG }, /* AAR-2410SA PCI SATA 4ch (Jaguar II) */
+       { aac_rx_init, "aacraid",  "DELL    ", "CERC SR2        ", 1, AAC_QUIRK_17SG }, /* CERC SATA RAID 2 PCI SATA 6ch (DellCorsair) */
+       { aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2810SA SATA ", 1, AAC_QUIRK_17SG }, /* AAR-2810SA PCI SATA 8ch (Corsair-8) */
+       { aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-21610SA SATA", 1, AAC_QUIRK_17SG }, /* AAR-21610SA PCI SATA 16ch (Corsair-16) */
        { aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2026ZCR     ", 1 }, /* ESD SO-DIMM PCI-X SATA ZCR (Prowler) */
        { aac_rx_init, "aacraid",  "ADAPTEC ", "AAR-2610SA      ", 1 }, /* SATA 6Ch (Bearcat) */
        { aac_rx_init, "aacraid",  "ADAPTEC ", "ASR-2240S       ", 1 }, /* ASR-2240S (SabreExpress) */
@@ -574,7 +574,15 @@ static ssize_t aac_show_model(struct class_device *class_dev,
        struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
        int len;
 
-       len = snprintf(buf, PAGE_SIZE, "%s\n",
+       if (dev->supplement_adapter_info.AdapterTypeText[0]) {
+               char * cp = dev->supplement_adapter_info.AdapterTypeText;
+               while (*cp && *cp != ' ')
+                       ++cp;
+               while (*cp == ' ')
+                       ++cp;
+               len = snprintf(buf, PAGE_SIZE, "%s\n", cp);
+       } else
+               len = snprintf(buf, PAGE_SIZE, "%s\n",
                  aac_drivers[dev->cardtype].model);
        return len;
 }
@@ -585,7 +593,15 @@ static ssize_t aac_show_vendor(struct class_device *class_dev,
        struct aac_dev *dev = (struct aac_dev*)class_to_shost(class_dev)->hostdata;
        int len;
 
-       len = snprintf(buf, PAGE_SIZE, "%s\n",
+       if (dev->supplement_adapter_info.AdapterTypeText[0]) {
+               char * cp = dev->supplement_adapter_info.AdapterTypeText;
+               while (*cp && *cp != ' ')
+                       ++cp;
+               len = snprintf(buf, PAGE_SIZE, "%.*s\n",
+                 (int)(cp - (char *)dev->supplement_adapter_info.AdapterTypeText),
+                 dev->supplement_adapter_info.AdapterTypeText);
+       } else
+               len = snprintf(buf, PAGE_SIZE, "%s\n",
                  aac_drivers[dev->cardtype].vname);
        return len;
 }
@@ -837,6 +853,13 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
                  = (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
        }
 
+       if ((aac_drivers[index].quirks & AAC_QUIRK_17SG) &&
+                       (aac->scsi_host_ptr->sg_tablesize > 17)) {
+               aac->scsi_host_ptr->sg_tablesize = 17;
+               aac->scsi_host_ptr->max_sectors
+                 = (aac->scsi_host_ptr->sg_tablesize * 8) + 112;
+       }
+
        /*
         * Firware printf works only with older firmware.
         */
index ac8de03c9fa2b6f4b0e99f6708c0772743145410..6c2c395554ff3d37b7f7673a01327d59c976a55a 100644 (file)
@@ -42,13 +42,13 @@ config AIC7XXX_CMDS_PER_DEVICE
 config AIC7XXX_RESET_DELAY_MS
        int "Initial bus reset delay in milli-seconds"
        depends on SCSI_AIC7XXX
-       default "15000"
+       default "5000"
        ---help---
        The number of milliseconds to delay after an initial bus reset.
        The bus settle delay following all error recovery actions is
        dictated by the SCSI layer and is not affected by this value.
 
-       Default: 15000 (15 seconds)
+       Default: 5000 (5 seconds)
 
 config AIC7XXX_PROBE_EISA_VL
        bool "Probe for EISA and VL AIC7XXX Adapters"
index 653fb0b42aeac3283a0796336588560b81c5a173..2cfdbef447db6ba7c4f7b774fcce47fe5f53e409 100644 (file)
@@ -37,7 +37,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#95 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.h#108 $
  *
  * $FreeBSD$
  */
@@ -75,8 +75,7 @@ struct scb_platform_data;
 #define INITIATOR_WILDCARD     (~0)
 #define        SCB_LIST_NULL           0xFF00
 #define        SCB_LIST_NULL_LE        (ahd_htole16(SCB_LIST_NULL))
-#define QOUTFIFO_ENTRY_VALID 0x8000
-#define QOUTFIFO_ENTRY_VALID_LE (ahd_htole16(0x8000))
+#define QOUTFIFO_ENTRY_VALID 0x80
 #define SCBID_IS_NULL(scbid) (((scbid) & 0xFF00 ) == SCB_LIST_NULL)
 
 #define SCSIID_TARGET(ahd, scsiid)     \
@@ -1053,6 +1052,13 @@ typedef uint8_t ahd_mode_state;
 
 typedef void ahd_callback_t (void *);
 
+struct ahd_completion
+{
+       uint16_t        tag;
+       uint8_t         sg_status;
+       uint8_t         valid_tag;
+};
+
 struct ahd_softc {
        bus_space_tag_t           tags[2];
        bus_space_handle_t        bshs[2];
@@ -1062,6 +1068,7 @@ struct ahd_softc {
        struct scb_data           scb_data;
 
        struct hardware_scb      *next_queued_hscb;
+       struct map_node          *next_queued_hscb_map;
 
        /*
         * SCBs that have been sent to the controller
@@ -1140,16 +1147,23 @@ struct ahd_softc {
        ahd_flag                  flags;
        struct seeprom_config    *seep_config;
 
-       /* Values to store in the SEQCTL register for pause and unpause */
-       uint8_t                   unpause;
-       uint8_t                   pause;
-
        /* Command Queues */
+       struct ahd_completion     *qoutfifo;
        uint16_t                  qoutfifonext;
        uint16_t                  qoutfifonext_valid_tag;
        uint16_t                  qinfifonext;
        uint16_t                  qinfifo[AHD_SCB_MAX];
-       uint16_t                 *qoutfifo;
+
+       /*
+        * Our qfreeze count.  The sequencer compares
+        * this value with its own counter to determine
+        * whether to allow selections to occur.
+        */
+       uint16_t                  qfreeze_cnt;
+
+       /* Values to store in the SEQCTL register for pause and unpause */
+       uint8_t                   unpause;
+       uint8_t                   pause;
 
        /* Critical Section Data */
        struct cs                *critical_sections;
@@ -1197,8 +1211,7 @@ struct ahd_softc {
         */
        bus_dma_tag_t             parent_dmat;
        bus_dma_tag_t             shared_data_dmat;
-       bus_dmamap_t              shared_data_dmamap;
-       dma_addr_t                shared_data_busaddr;
+       struct map_node           shared_data_map;
 
        /* Information saved through suspend/resume cycles */
        struct ahd_suspend_state  suspend_state;
@@ -1296,9 +1309,9 @@ struct ahd_devinfo {
 };
 
 /****************************** PCI Structures ********************************/
-#define AHD_PCI_IOADDR0        PCIR_MAPS       /* I/O BAR*/
-#define AHD_PCI_MEMADDR        (PCIR_MAPS + 4) /* Memory BAR */
-#define AHD_PCI_IOADDR1        (PCIR_MAPS + 12)/* Second I/O BAR */
+#define AHD_PCI_IOADDR0        PCIR_BAR(0)     /* I/O BAR*/
+#define AHD_PCI_MEMADDR        PCIR_BAR(1)     /* Memory BAR */
+#define AHD_PCI_IOADDR1        PCIR_BAR(3)     /* Second I/O BAR */
 
 typedef int (ahd_device_setup_t)(struct ahd_softc *);
 
index cca58edc8648c4e68256a26d0eeb173f34bb0f39..3a3204703b155f374a7cf99cb86dcb2b028f8c05 100644 (file)
@@ -39,7 +39,7 @@
  *
  * $FreeBSD$
  */
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#76 $"
 
 /*
  * This file is processed by the aic7xxx_asm utility for use in assembling
@@ -65,13 +65,6 @@ VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.reg#70 $"
                mvi     MODE_PTR, MK_MODE(src, dst);                    \
        }
 
-#define TOGGLE_DFF_MODE                                                        \
-       if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) {                      \
-               call    toggle_dff_mode_work_around;                    \
-       } else {                                                        \
-               xor     MODE_PTR, MK_MODE(M_DFF1, M_DFF1);              \
-       }
-       
 #define RESTORE_MODE(mode)                                             \
        if ((ahd->bugs & AHD_SET_MODE_BUG) != 0) {                      \
                mov     mode call set_mode_work_around;                 \
@@ -1199,7 +1192,7 @@ register TARGPCISTAT {
 
 /*
  * LQ Packet In
- * The last LQ Packet received
+ * The last LQ Packet recieved
  */
 register LQIN {
        address                 0x020
@@ -3542,10 +3535,34 @@ scratch_ram {
        COMPLETE_DMA_SCB_HEAD {
                size            2
        }
-       /* Counting semaphore to prevent new select-outs */
+       /*
+        * tail of list of SCBs that have
+        * completed but need to be uploaded
+        * to the host prior to being completed.
+        */
+       COMPLETE_DMA_SCB_TAIL {
+               size            2
+       }
+       /*
+        * head of list of SCBs that have
+        * been uploaded to the host, but cannot
+        * be completed until the QFREEZE is in
+        * full effect (i.e. no selections pending).
+        */
+       COMPLETE_ON_QFREEZE_HEAD {
+               size            2
+       }
+       /*
+        * Counting semaphore to prevent new select-outs
+        * The queue is frozen so long as the sequencer
+        * and kernel freeze counts differ.
+        */
        QFREEZE_COUNT {
                size            2
        }
+       KERNEL_QFREEZE_COUNT {
+               size            2
+       }
        /*
         * Mode to restore on legacy idle loop exit.
         */
@@ -3624,6 +3641,17 @@ scratch_ram {
        QOUTFIFO_ENTRY_VALID_TAG {
                size            1
        }
+       /*
+        * Kernel and sequencer offsets into the queue of
+        * incoming target mode command descriptors.  The
+        * queue is full when the KERNEL_TQINPOS == TQINPOS.
+        */
+       KERNEL_TQINPOS {
+               size            1
+       }
+       TQINPOS {                
+               size            1
+       }
        /*
         * Base address of our shared data with the kernel driver in host
         * memory.  This includes the qoutfifo and target mode
@@ -3639,17 +3667,6 @@ scratch_ram {
        QOUTFIFO_NEXT_ADDR {
                size            4
        }
-       /*
-        * Kernel and sequencer offsets into the queue of
-        * incoming target mode command descriptors.  The
-        * queue is full when the KERNEL_TQINPOS == TQINPOS.
-        */
-       KERNEL_TQINPOS {
-               size            1
-       }
-       TQINPOS {                
-               size            1
-       }
        ARG_1 {
                size            1
                mask    SEND_MSG                0x80
@@ -3951,6 +3968,7 @@ const SG_PREFETCH_ADDR_MASK download
 const SG_SIZEOF download
 const PKT_OVERRUN_BUFOFFSET download
 const SCB_TRANSFER_SIZE        download
+const CACHELINE_MASK download
 
 /*
  * BIOS SCB offsets
index 65339bc1ca99cd3f9b960703aa2b5e3c1520d452..bef1f9d369b6b90779d13f3ee54a53c7a105bb3a 100644 (file)
@@ -40,7 +40,7 @@
  * $FreeBSD$
  */
 
-VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#99 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic79xx.seq#119 $"
 PATCH_ARG_LIST = "struct ahd_softc *ahd"
 PREFIX = "ahd_"
 
@@ -68,13 +68,47 @@ no_error_set:
        }
        SET_MODE(M_SCSI, M_SCSI)
        test    SCSISEQ0, ENSELO|ENARBO jnz idle_loop_checkbus;
-       test    SEQ_FLAGS2, SELECTOUT_QFROZEN jnz idle_loop_checkbus;
+       test    SEQ_FLAGS2, SELECTOUT_QFROZEN jz check_waiting_list;
+       /*
+        * If the kernel has caught up with us, thaw the queue.
+        */
+       mov     A, KERNEL_QFREEZE_COUNT;
+       cmp     QFREEZE_COUNT, A jne check_frozen_completions;
+       mov     A, KERNEL_QFREEZE_COUNT[1];
+       cmp     QFREEZE_COUNT[1], A jne check_frozen_completions;
+       and     SEQ_FLAGS2, ~SELECTOUT_QFROZEN;
+       jmp     check_waiting_list;
+check_frozen_completions:
+       test    SSTAT0, SELDO|SELINGO jnz idle_loop_checkbus;
+BEGIN_CRITICAL;
+       /*
+        * If we have completions stalled waiting for the qfreeze
+        * to take effect, move them over to the complete_scb list
+        * now that no selections are pending.
+        */
+       cmp     COMPLETE_ON_QFREEZE_HEAD[1],SCB_LIST_NULL je idle_loop_checkbus;
+       /*
+        * Find the end of the qfreeze list.  The first element has
+        * to be treated specially.
+        */
+       bmov    SCBPTR, COMPLETE_ON_QFREEZE_HEAD, 2;
+       cmp     SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je join_lists;
+       /*
+        * Now the normal loop.
+        */
+       bmov    SCBPTR, SCB_NEXT_COMPLETE, 2;
+       cmp     SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . - 1;
+join_lists:
+       bmov    SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
+       bmov    COMPLETE_SCB_HEAD, COMPLETE_ON_QFREEZE_HEAD, 2;
+       mvi     COMPLETE_ON_QFREEZE_HEAD[1], SCB_LIST_NULL;
+       jmp     idle_loop_checkbus;
+check_waiting_list:
        cmp     WAITING_TID_HEAD[1], SCB_LIST_NULL je idle_loop_checkbus;
        /*
         * ENSELO is cleared by a SELDO, so we must test for SELDO
         * one last time.
         */
-BEGIN_CRITICAL;
        test    SSTAT0, SELDO jnz select_out;
 END_CRITICAL;
        call    start_selection;
@@ -90,6 +124,13 @@ idle_loop_check_nonpackreq:
        test    SSTAT2, NONPACKREQ jz . + 2;
        call    unexpected_nonpkt_phase_find_ctxt;
        if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
+               /*
+                * On Rev A. hardware, the busy LED is only
+                * turned on automaically during selections
+                * and re-selections.  Make the LED status
+                * more useful by forcing it to be on so
+                * long as one of our data FIFOs is active.
+                */
                and     A, FIFO0FREE|FIFO1FREE, DFFSTAT;
                cmp     A, FIFO0FREE|FIFO1FREE jne . + 3;
                and     SBLKCTL, ~DIAGLEDEN|DIAGLEDON;
@@ -101,9 +142,9 @@ idle_loop_check_nonpackreq:
        call    idle_loop_cchan;
        jmp     idle_loop;
 
-BEGIN_CRITICAL;
 idle_loop_gsfifo:
        SET_MODE(M_SCSI, M_SCSI)
+BEGIN_CRITICAL;
 idle_loop_gsfifo_in_scsi_mode:
        test    LQISTAT2, LQIGSAVAIL jz return;
        /*
@@ -152,11 +193,15 @@ END_CRITICAL;
 
 idle_loop_service_fifos:
        SET_MODE(M_DFF0, M_DFF0)
+BEGIN_CRITICAL;
        test    LONGJMP_ADDR[1], INVALID_ADDR jnz idle_loop_next_fifo;
        call    longjmp;
+END_CRITICAL;
 idle_loop_next_fifo:
        SET_MODE(M_DFF1, M_DFF1)
+BEGIN_CRITICAL;
        test    LONGJMP_ADDR[1], INVALID_ADDR jz longjmp;
+END_CRITICAL;
 return:
        ret;
 
@@ -170,7 +215,6 @@ BEGIN_CRITICAL;
        test    CCSCBCTL, CCARREN|CCSCBEN jz scbdma_idle;
        test    CCSCBCTL, CCSCBDIR jnz fetch_new_scb_inprog;
        test    CCSCBCTL, CCSCBDONE jz return;
-END_CRITICAL;
        /* FALLTHROUGH */
 scbdma_tohost_done:
        test    CCSCBCTL, CCARREN jz fill_qoutfifo_dmadone;
@@ -180,26 +224,18 @@ scbdma_tohost_done:
         * bad SCSI status (currently only for underruns), we
         * queue the SCB for normal completion.  Otherwise, we
         * wait until any select-out activity has halted, and
-        * then notify the host so that the transaction can be
-        * dealt with.
+        * then queue the completion.
         */
-       test    SCB_SCSI_STATUS, 0xff jnz scbdma_notify_host;
        and     CCSCBCTL, ~(CCARREN|CCSCBEN);
        bmov    COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
+       cmp     SCB_NEXT_COMPLETE[1], SCB_LIST_NULL jne . + 2;
+       mvi     COMPLETE_DMA_SCB_TAIL[1], SCB_LIST_NULL;
+       test    SCB_SCSI_STATUS, 0xff jz scbdma_queue_completion;
+       bmov    SCB_NEXT_COMPLETE, COMPLETE_ON_QFREEZE_HEAD, 2;
+       bmov    COMPLETE_ON_QFREEZE_HEAD, SCBPTR, 2 ret;
+scbdma_queue_completion:
        bmov    SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
        bmov    COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
-scbdma_notify_host:
-       SET_MODE(M_SCSI, M_SCSI)
-       test    SCSISEQ0, ENSELO jnz return;
-       test    SSTAT0, (SELDO|SELINGO) jnz return;
-       SET_MODE(M_CCHAN, M_CCHAN)
-       /*
-        * Remove SCB and notify host.
-        */
-       and     CCSCBCTL, ~(CCARREN|CCSCBEN);
-       bmov    COMPLETE_DMA_SCB_HEAD, SCB_NEXT_COMPLETE, 2;
-       SET_SEQINTCODE(BAD_SCB_STATUS)
-       ret;
 fill_qoutfifo_dmadone:
        and     CCSCBCTL, ~(CCARREN|CCSCBEN);
        call    qoutfifo_updated;
@@ -208,6 +244,7 @@ fill_qoutfifo_dmadone:
        test    QOFF_CTLSTA, SDSCB_ROLLOVR jz return;
        bmov    QOUTFIFO_NEXT_ADDR, SHARED_DATA_ADDR, 4;
        xor     QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID_TOGGLE ret;
+END_CRITICAL;
 
 qoutfifo_updated:
        /*
@@ -324,14 +361,15 @@ fill_qoutfifo:
         * Keep track of the SCBs we are dmaing just
         * in case the DMA fails or is aborted.
         */
-       mov     A, QOUTFIFO_ENTRY_VALID_TAG;
        bmov    COMPLETE_SCB_DMAINPROG_HEAD, COMPLETE_SCB_HEAD, 2;
        mvi     CCSCBCTL, CCSCBRESET;
        bmov    SCBHADDR, QOUTFIFO_NEXT_ADDR, 4;
+       mov     A, QOUTFIFO_NEXT_ADDR;
        bmov    SCBPTR, COMPLETE_SCB_HEAD, 2;
 fill_qoutfifo_loop:
-       mov     CCSCBRAM, SCBPTR;
-       or      CCSCBRAM, A, SCBPTR[1];
+       bmov    CCSCBRAM, SCBPTR, 2;
+       mov     CCSCBRAM, SCB_SGPTR[0];
+       mov     CCSCBRAM, QOUTFIFO_ENTRY_VALID_TAG;
        mov     NONE, SDSCB_QOFF;
        inc     INT_COALESCING_CMDCOUNT;
        add     CMDS_PENDING, -1;
@@ -339,6 +377,18 @@ fill_qoutfifo_loop:
        cmp     SCB_NEXT_COMPLETE[1], SCB_LIST_NULL je fill_qoutfifo_done;
        cmp     CCSCBADDR, CCSCBADDR_MAX je fill_qoutfifo_done;
        test    QOFF_CTLSTA, SDSCB_ROLLOVR jnz fill_qoutfifo_done;
+       /*
+        * Don't cross an ADB or Cachline boundary when DMA'ing
+        * completion entries.  In PCI mode, at least in 32/33
+        * configurations, the SCB DMA engine may lose its place
+        * in the data-stream should the target force a retry on
+        * something other than an 8byte aligned boundary. In
+        * PCI-X mode, we do this to avoid split transactions since
+        * many chipsets seem to be unable to format proper split
+        * completions to continue the data transfer.
+        */
+       add     SINDEX, A, CCSCBADDR;
+       test    SINDEX, CACHELINE_MASK jz fill_qoutfifo_done;
        bmov    SCBPTR, SCB_NEXT_COMPLETE, 2;
        jmp     fill_qoutfifo_loop;
 fill_qoutfifo_done:
@@ -354,7 +404,6 @@ dma_complete_scb:
        bmov    SCBPTR, COMPLETE_DMA_SCB_HEAD, 2;
        bmov    SCBHADDR, SCB_BUSADDR, 4;
        mvi     CCARREN|CCSCBEN|CCSCBRESET jmp dma_scb;
-END_CRITICAL;
 
 /*
  * Either post or fetch an SCB from host memory.  The caller
@@ -371,9 +420,19 @@ dma_scb:
        mvi     SCBHCNT, SCB_TRANSFER_SIZE;
        mov     CCSCBCTL, SINDEX ret;
 
-BEGIN_CRITICAL;
 setjmp:
-       bmov    LONGJMP_ADDR, STACK, 2 ret;
+       /*
+        * At least on the A, a return in the same
+        * instruction as the bmov results in a return
+        * to the caller, not to the new address at the
+        * top of the stack.  Since we want the latter
+        * (we use setjmp to register a handler from an
+        * interrupt context but not invoke that handler
+        * until we return to our idle loop), use a
+        * separate ret instruction.
+        */
+       bmov    LONGJMP_ADDR, STACK, 2;
+       ret;
 setjmp_inline:
        bmov    LONGJMP_ADDR, STACK, 2;
 longjmp:
@@ -392,11 +451,6 @@ set_mode_work_around:
        mvi     SEQINTCTL, INTVEC1DSL;
        mov     MODE_PTR, SINDEX;
        clr     SEQINTCTL ret;
-
-toggle_dff_mode_work_around:
-       mvi     SEQINTCTL, INTVEC1DSL;
-       xor     MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
-       clr     SEQINTCTL ret;
 }
 
 
@@ -490,6 +544,21 @@ allocate_fifo1:
 SET_SRC_MODE   M_SCSI;
 SET_DST_MODE   M_SCSI;
 select_in:
+       if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
+               /*
+                * On Rev A. hardware, the busy LED is only
+                * turned on automaically during selections
+                * and re-selections.  Make the LED status
+                * more useful by forcing it to be on from
+                * the point of selection until our idle
+                * loop determines that neither of our FIFOs
+                * are busy.  This handles the non-packetized
+                * case nicely as we will not return to the
+                * idle loop until the busfree at the end of
+                * each transaction.
+                */
+               or      SBLKCTL, DIAGLEDEN|DIAGLEDON;
+       }
        if ((ahd->bugs & AHD_BUSFREEREV_BUG) != 0) {
                /*
                 * Test to ensure that the bus has not
@@ -528,6 +597,21 @@ SET_SRC_MODE       M_SCSI;
 SET_DST_MODE   M_SCSI;
 select_out:
 BEGIN_CRITICAL;
+       if ((ahd->bugs & AHD_FAINT_LED_BUG) != 0) {
+               /*
+                * On Rev A. hardware, the busy LED is only
+                * turned on automaically during selections
+                * and re-selections.  Make the LED status
+                * more useful by forcing it to be on from
+                * the point of re-selection until our idle
+                * loop determines that neither of our FIFOs
+                * are busy.  This handles the non-packetized
+                * case nicely as we will not return to the
+                * idle loop until the busfree at the end of
+                * each transaction.
+                */
+               or      SBLKCTL, DIAGLEDEN|DIAGLEDON;
+       }
        /* Clear out all SCBs that have been successfully sent. */
        if ((ahd->bugs & AHD_SENT_SCB_UPDATE_BUG) != 0) {
                /*
@@ -1000,15 +1084,9 @@ not_found_ITloop:
 /*
  * We received a "command complete" message.  Put the SCB on the complete
  * queue and trigger a completion interrupt via the idle loop.  Before doing
- * so, check to see if there
- * is a residual or the status byte is something other than STATUS_GOOD (0).
- * In either of these conditions, we upload the SCB back to the host so it can
- * process this information.  In the case of a non zero status byte, we 
- * additionally interrupt the kernel driver synchronously, allowing it to
- * decide if sense should be retrieved.  If the kernel driver wishes to request
- * sense, it will fill the kernel SCB with a request sense command, requeue
- * it to the QINFIFO and tell us not to post to the QOUTFIFO by setting 
- * RETURN_1 to SEND_SENSE.
+ * so, check to see if there is a residual or the status byte is something
+ * other than STATUS_GOOD (0).  In either of these conditions, we upload the
+ * SCB back to the host so it can process this information.
  */
 mesgin_complete:
 
@@ -1053,6 +1131,7 @@ complete_nomsg:
        call    queue_scb_completion;
        jmp     await_busfree;
 
+BEGIN_CRITICAL;
 freeze_queue:
        /* Cancel any pending select-out. */
        test    SSTAT0, SELDO|SELINGO jnz . + 2;
@@ -1063,6 +1142,7 @@ freeze_queue:
        adc     QFREEZE_COUNT[1], A;
        or      SEQ_FLAGS2, SELECTOUT_QFROZEN;
        mov     A, ACCUM_SAVE ret;
+END_CRITICAL;
 
 /*
  * Complete the current FIFO's SCB if data for this same
@@ -1085,8 +1165,10 @@ queue_scb_completion:
        test    SCB_SGPTR, SG_FULL_RESID jnz upload_scb;/* Never xfered */
        test    SCB_RESIDUAL_SGPTR, SG_LIST_NULL jz upload_scb;
 complete:
+BEGIN_CRITICAL;
        bmov    SCB_NEXT_COMPLETE, COMPLETE_SCB_HEAD, 2;
        bmov    COMPLETE_SCB_HEAD, SCBPTR, 2 ret;
+END_CRITICAL;
 bad_status:
        cmp     SCB_SCSI_STATUS, STATUS_PKT_SENSE je upload_scb;
        call    freeze_queue;
@@ -1097,9 +1179,18 @@ upload_scb:
         * it on the host.
         */
        bmov    SCB_TAG, SCBPTR, 2;
-       bmov    SCB_NEXT_COMPLETE, COMPLETE_DMA_SCB_HEAD, 2;
+BEGIN_CRITICAL;
+       or      SCB_SGPTR, SG_STATUS_VALID;
+       mvi     SCB_NEXT_COMPLETE[1], SCB_LIST_NULL;
+       cmp     COMPLETE_DMA_SCB_HEAD[1], SCB_LIST_NULL jne add_dma_scb_tail;
        bmov    COMPLETE_DMA_SCB_HEAD, SCBPTR, 2;
-       or      SCB_SGPTR, SG_STATUS_VALID ret;
+       bmov    COMPLETE_DMA_SCB_TAIL, SCBPTR, 2 ret;
+add_dma_scb_tail:
+       bmov    REG0, SCBPTR, 2;
+       bmov    SCBPTR, COMPLETE_DMA_SCB_TAIL, 2;
+       bmov    SCB_NEXT_COMPLETE, REG0, 2;
+       bmov    COMPLETE_DMA_SCB_TAIL, REG0, 2 ret;
+END_CRITICAL;
 
 /*
  * Is it a disconnect message?  Set a flag in the SCB to remind us
@@ -1146,8 +1237,18 @@ SET_DST_MODE     M_DFF1;
 await_busfree_clrchn:
        mvi     DFFSXFRCTL, CLRCHN;
 await_busfree_not_m_dff:
-       call    clear_target_state;
+       /* clear target specific flags */
+       mvi     SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT;
        test    SSTAT1,REQINIT|BUSFREE  jz .;
+       /*
+        * We only set BUSFREE status once either a new
+        * phase has been detected or we are really
+        * BUSFREE.  This allows the driver to know
+        * that we are active on the bus even though
+        * no identified transaction exists should a
+        * timeout occur while awaiting busfree.
+        */
+       mvi     LASTPHASE, P_BUSFREE;
        test    SSTAT1, BUSFREE jnz idle_loop;
        SET_SEQINTCODE(MISSED_BUSFREE)
 
@@ -1202,11 +1303,6 @@ msgin_rdptrs_get_fifo:
        call    allocate_fifo;
        jmp     mesgin_done;
 
-clear_target_state:
-       mvi     LASTPHASE, P_BUSFREE;
-       /* clear target specific flags */
-       mvi     SEQ_FLAGS, NOT_IDENTIFIED|NO_CDB_SENT ret;
-
 phase_lock:     
        if ((ahd->bugs & AHD_EARLY_REQ_BUG) != 0) {
                /*
@@ -1297,6 +1393,47 @@ service_fifo:
        /* Are we actively fetching segments? */
        test    CCSGCTL, CCSGENACK jnz return;
 
+       /*
+        * Should the other FIFO get the S/G cache first?  If
+        * both FIFOs have been allocated since we last checked
+        * any FIFO, it is important that we service a FIFO
+        * that is not actively on the bus first.  This guarantees
+        * that a FIFO will be freed to handle snapshot requests for
+        * any FIFO that is still on the bus.  Chips with RTI do not
+        * perform snapshots, so don't bother with this test there.
+        */
+       if ((ahd->features & AHD_RTI) == 0) {
+               /*
+                * If we're not still receiving SCSI data,
+                * it is safe to allocate the S/G cache to
+                * this FIFO.
+                */
+               test    DFCNTRL, SCSIEN jz idle_sgfetch_start;
+
+               /*
+                * Switch to the other FIFO.  Non-RTI chips
+                * also have the "set mode" bug, so we must
+                * disable interrupts during the switch.
+                */
+               mvi     SEQINTCTL, INTVEC1DSL;
+               xor     MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
+
+               /*
+                * If the other FIFO needs loading, then it
+                * must not have claimed the S/G cache yet
+                * (SG_CACHE_AVAIL would have been cleared in
+                * the orginal FIFO mode and we test this above).
+                * Return to the idle loop so we can process the
+                * FIFO not currently on the bus first.
+                */
+               test    SG_STATE, LOADING_NEEDED jz idle_sgfetch_okay;
+               clr     SEQINTCTL ret;
+idle_sgfetch_okay:
+               xor     MODE_PTR, MK_MODE(M_DFF1, M_DFF1);
+               clr     SEQINTCTL;
+       }
+
+idle_sgfetch_start:
        /*
         * We fetch a "cacheline aligned" and sized amount of data
         * so we don't end up referencing a non-existant page.
@@ -1308,7 +1445,7 @@ service_fifo:
        mvi     SGHCNT, SG_PREFETCH_CNT;
        if ((ahd->bugs & AHD_REG_SLOW_SETTLE_BUG) != 0) {
                /*
-                * Need two instruction between "touches" of SGHADDR.
+                * Need two instructions between "touches" of SGHADDR.
                 */
                nop;
        }
@@ -1658,7 +1795,7 @@ export seq_isr:
                 * savepointer in the current FIFO.  We do this so that
                 * a pending CTXTDONE or SAVEPTR is visible in the active
                 * FIFO.  This status is the only way we can detect if we
-                * have lost the race (e.g. host paused us) and our attepts
+                * have lost the race (e.g. host paused us) and our attempts
                 * to disable the channel occurred after all REQs were
                 * already seen and acked (REQINIT never comes true).
                 */
@@ -1667,7 +1804,7 @@ export seq_isr:
                test    DFCNTRL, DIRECTION jz interrupt_return;
                and     DFCNTRL, ~SCSIEN;
 snapshot_wait_data_valid:
-               test    SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz snapshot_data_valid;
+               test    SEQINTSRC, (CTXTDONE|SAVEPTRS) jnz interrupt_return;
                test    SSTAT1, REQINIT jz snapshot_wait_data_valid;
 snapshot_data_valid:
                or      DFCNTRL, SCSIEN;
@@ -1834,7 +1971,6 @@ pkt_saveptrs_check_status:
        dec     SCB_FIFO_USE_COUNT;
        test    SCB_CONTROL, STATUS_RCVD jnz pkt_complete_scb_if_fifos_idle;
        mvi     DFFSXFRCTL, CLRCHN ret;
-END_CRITICAL;
 
 /*
  * LAST_SEG_DONE status has been seen in the current FIFO.
@@ -1843,7 +1979,6 @@ END_CRITICAL;
  * Check for overrun and see if we can complete this command.
  */
 pkt_last_seg_done:
-BEGIN_CRITICAL;
        /*
         * Mark transfer as completed.
         */
index 4e8f00df978dab2ad226e1566f118b7108165081..db8f5ce99ee3f815a018a1264bb3c50299a7ce99 100644 (file)
@@ -37,9 +37,7 @@
  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  * POSSIBILITY OF SUCH DAMAGES.
  *
- * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#202 $
- *
- * $FreeBSD$
+ * $Id: //depot/aic7xxx/aic7xxx/aic79xx.c#247 $
  */
 
 #ifdef __linux__
@@ -332,6 +330,14 @@ ahd_restart(struct ahd_softc *ahd)
        ahd_outb(ahd, SCSISEQ1,
                 ahd_inb(ahd, SCSISEQ_TEMPLATE) & (ENSELI|ENRSELI|ENAUTOATNP));
        ahd_set_modes(ahd, AHD_MODE_CCHAN, AHD_MODE_CCHAN);
+
+       /*
+        * Clear any pending sequencer interrupt.  It is no
+        * longer relevant since we're resetting the Program
+        * Counter.
+        */
+       ahd_outb(ahd, CLRINT, CLRSEQINT);
+
        ahd_outb(ahd, SEQCTL0, FASTMODE|SEQRESET);
        ahd_unpause(ahd);
 }
@@ -373,13 +379,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
        saved_modes = ahd_save_modes(ahd);
 
        /*
-        * Complete any SCBs that just finished being
-        * DMA'ed into the qoutfifo.
-        */
-       ahd_run_qoutfifo(ahd);
-
-       /*
-        * Flush the good status FIFO for compelted packetized commands.
+        * Flush the good status FIFO for completed packetized commands.
         */
        ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
        saved_scbptr = ahd_get_scbptr(ahd);
@@ -387,8 +387,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
                u_int fifo_mode;
                u_int i;
                
-               scbid = (ahd_inb(ahd, GSFIFO+1) << 8)
-                     | ahd_inb(ahd, GSFIFO);
+               scbid = ahd_inw(ahd, GSFIFO);
                scb = ahd_lookup_scb(ahd, scbid);
                if (scb == NULL) {
                        printf("%s: Warning - GSFIFO SCB %d invalid\n",
@@ -401,22 +400,33 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
                 * the host before completing the  command.
                 */
                fifo_mode = 0;
+rescan_fifos:
                for (i = 0; i < 2; i++) {
                        /* Toggle to the other mode. */
                        fifo_mode ^= 1;
                        ahd_set_modes(ahd, fifo_mode, fifo_mode);
+
                        if (ahd_scb_active_in_fifo(ahd, scb) == 0)
                                continue;
 
                        ahd_run_data_fifo(ahd, scb);
 
                        /*
-                        * Clearing this transaction in this FIFO may
-                        * cause a CFG4DATA for this same transaction
-                        * to assert in the other FIFO.  Make sure we
-                        * loop one more time and check the other FIFO.
+                        * Running this FIFO may cause a CFG4DATA for
+                        * this same transaction to assert in the other
+                        * FIFO or a new snapshot SAVEPTRS interrupt
+                        * in this FIFO.  Even running a FIFO may not
+                        * clear the transaction if we are still waiting
+                        * for data to drain to the host. We must loop
+                        * until the transaction is not active in either
+                        * FIFO just to be sure.  Reset our loop counter
+                        * so we will visit both FIFOs again before
+                        * declaring this transaction finished.  We
+                        * also delay a bit so that status has a chance
+                        * to change before we look at this FIFO again.
                         */
-                       i = 0;
+                       ahd_delay(200);
+                       goto rescan_fifos;
                }
                ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
                ahd_set_scbptr(ahd, scbid);
@@ -429,19 +439,28 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
                        /*
                         * The transfer completed with a residual.
                         * Place this SCB on the complete DMA list
-                        * so that we Update our in-core copy of the
+                        * so that we update our in-core copy of the
                         * SCB before completing the command.
                         */
                        ahd_outb(ahd, SCB_SCSI_STATUS, 0);
                        ahd_outb(ahd, SCB_SGPTR,
                                 ahd_inb_scbram(ahd, SCB_SGPTR)
                                 | SG_STATUS_VALID);
-                       ahd_outw(ahd, SCB_TAG, SCB_GET_TAG(scb));
+                       ahd_outw(ahd, SCB_TAG, scbid);
+                       ahd_outw(ahd, SCB_NEXT_COMPLETE, SCB_LIST_NULL);
                        comp_head = ahd_inw(ahd, COMPLETE_DMA_SCB_HEAD);
-                       ahd_outw(ahd, SCB_NEXT_COMPLETE, comp_head);
-                       if (SCBID_IS_NULL(comp_head))
-                               ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD,
-                                        SCB_GET_TAG(scb));
+                       if (SCBID_IS_NULL(comp_head)) {
+                               ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, scbid);
+                               ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
+                       } else {
+                               u_int tail;
+
+                               tail = ahd_inw(ahd, COMPLETE_DMA_SCB_TAIL);
+                               ahd_set_scbptr(ahd, tail);
+                               ahd_outw(ahd, SCB_NEXT_COMPLETE, scbid);
+                               ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, scbid);
+                               ahd_set_scbptr(ahd, scbid);
+                       }
                } else
                        ahd_complete_scb(ahd, scb);
        }
@@ -465,9 +484,22 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
                        break;
                ahd_delay(200);
        }
-       if ((ccscbctl & CCSCBDIR) != 0)
+       /*
+        * We leave the sequencer to cleanup in the case of DMA's to
+        * update the qoutfifo.  In all other cases (DMA's to the
+        * chip or a push of an SCB from the COMPLETE_DMA_SCB list),
+        * we disable the DMA engine so that the sequencer will not
+        * attempt to handle the DMA completion.
+        */
+       if ((ccscbctl & CCSCBDIR) != 0 || (ccscbctl & ARRDONE) != 0)
                ahd_outb(ahd, CCSCBCTL, ccscbctl & ~(CCARREN|CCSCBEN));
 
+       /*
+        * Complete any SCBs that just finished
+        * being DMA'ed into the qoutfifo.
+        */
+       ahd_run_qoutfifo(ahd);
+
        saved_scbptr = ahd_get_scbptr(ahd);
        /*
         * Manually update/complete any completed SCBs that are waiting to be
@@ -494,6 +526,24 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
                scbid = next_scbid;
        }
        ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
+       ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
+
+       scbid = ahd_inw(ahd, COMPLETE_ON_QFREEZE_HEAD);
+       while (!SCBID_IS_NULL(scbid)) {
+
+               ahd_set_scbptr(ahd, scbid);
+               next_scbid = ahd_inw_scbram(ahd, SCB_NEXT_COMPLETE);
+               scb = ahd_lookup_scb(ahd, scbid);
+               if (scb == NULL) {
+                       printf("%s: Warning - Complete Qfrz SCB %d invalid\n",
+                              ahd_name(ahd), scbid);
+                       continue;
+               }
+
+               ahd_complete_scb(ahd, scb);
+               scbid = next_scbid;
+       }
+       ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
 
        scbid = ahd_inw(ahd, COMPLETE_SCB_HEAD);
        while (!SCBID_IS_NULL(scbid)) {
@@ -558,150 +608,146 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
 {
        u_int seqintsrc;
 
-       while (1) {
-               seqintsrc = ahd_inb(ahd, SEQINTSRC);
-               if ((seqintsrc & CFG4DATA) != 0) {
-                       uint32_t datacnt;
-                       uint32_t sgptr;
-
-                       /*
-                        * Clear full residual flag.
-                        */
-                       sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
-                       ahd_outb(ahd, SCB_SGPTR, sgptr);
+       seqintsrc = ahd_inb(ahd, SEQINTSRC);
+       if ((seqintsrc & CFG4DATA) != 0) {
+               uint32_t datacnt;
+               uint32_t sgptr;
 
-                       /*
-                        * Load datacnt and address.
-                        */
-                       datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);
-                       if ((datacnt & AHD_DMA_LAST_SEG) != 0) {
-                               sgptr |= LAST_SEG;
-                               ahd_outb(ahd, SG_STATE, 0);
-                       } else
-                               ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
-                       ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
-                       ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
-                       ahd_outb(ahd, SG_CACHE_PRE, sgptr);
-                       ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
+               /*
+                * Clear full residual flag.
+                */
+               sgptr = ahd_inl_scbram(ahd, SCB_SGPTR) & ~SG_FULL_RESID;
+               ahd_outb(ahd, SCB_SGPTR, sgptr);
 
-                       /*
-                        * Initialize Residual Fields.
-                        */
-                       ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
-                       ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
+               /*
+                * Load datacnt and address.
+                */
+               datacnt = ahd_inl_scbram(ahd, SCB_DATACNT);
+               if ((datacnt & AHD_DMA_LAST_SEG) != 0) {
+                       sgptr |= LAST_SEG;
+                       ahd_outb(ahd, SG_STATE, 0);
+               } else
+                       ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
+               ahd_outq(ahd, HADDR, ahd_inq_scbram(ahd, SCB_DATAPTR));
+               ahd_outl(ahd, HCNT, datacnt & AHD_SG_LEN_MASK);
+               ahd_outb(ahd, SG_CACHE_PRE, sgptr);
+               ahd_outb(ahd, DFCNTRL, PRELOADEN|SCSIEN|HDMAEN);
 
-                       /*
-                        * Mark the SCB as having a FIFO in use.
-                        */
-                       ahd_outb(ahd, SCB_FIFO_USE_COUNT,
-                                ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);
+               /*
+                * Initialize Residual Fields.
+                */
+               ahd_outb(ahd, SCB_RESIDUAL_DATACNT+3, datacnt >> 24);
+               ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr & SG_PTR_MASK);
 
-                       /*
-                        * Install a "fake" handler for this FIFO.
-                        */
-                       ahd_outw(ahd, LONGJMP_ADDR, 0);
+               /*
+                * Mark the SCB as having a FIFO in use.
+                */
+               ahd_outb(ahd, SCB_FIFO_USE_COUNT,
+                        ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) + 1);
 
-                       /*
-                        * Notify the hardware that we have satisfied
-                        * this sequencer interrupt.
-                        */
-                       ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
-               } else if ((seqintsrc & SAVEPTRS) != 0) {
-                       uint32_t sgptr;
-                       uint32_t resid;
+               /*
+                * Install a "fake" handler for this FIFO.
+                */
+               ahd_outw(ahd, LONGJMP_ADDR, 0);
 
-                       if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
-                               /*
-                                * Snapshot Save Pointers.  Clear
-                                * the snapshot and continue.
-                                */
-                               ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
-                               continue;
-                       }
+               /*
+                * Notify the hardware that we have satisfied
+                * this sequencer interrupt.
+                */
+               ahd_outb(ahd, CLRSEQINTSRC, CLRCFG4DATA);
+       } else if ((seqintsrc & SAVEPTRS) != 0) {
+               uint32_t sgptr;
+               uint32_t resid;
 
+               if ((ahd_inb(ahd, LONGJMP_ADDR+1)&INVALID_ADDR) != 0) {
                        /*
-                        * Disable S/G fetch so the DMA engine
-                        * is available to future users.
+                        * Snapshot Save Pointers.  All that
+                        * is necessary to clear the snapshot
+                        * is a CLRCHN.
                         */
-                       if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
-                               ahd_outb(ahd, CCSGCTL, 0);
-                       ahd_outb(ahd, SG_STATE, 0);
+                       goto clrchn;
+               }
 
-                       /*
-                        * Flush the data FIFO.  Strickly only
-                        * necessary for Rev A parts.
-                        */
-                       ahd_outb(ahd, DFCNTRL,
-                                ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
+               /*
+                * Disable S/G fetch so the DMA engine
+                * is available to future users.
+                */
+               if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0)
+                       ahd_outb(ahd, CCSGCTL, 0);
+               ahd_outb(ahd, SG_STATE, 0);
 
-                       /*
-                        * Calculate residual.
-                        */
-                       sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
-                       resid = ahd_inl(ahd, SHCNT);
-                       resid |=
-                           ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
-                       ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
-                       if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
-                               /*
-                                * Must back up to the correct S/G element.
-                                * Typically this just means resetting our
-                                * low byte to the offset in the SG_CACHE,
-                                * but if we wrapped, we have to correct
-                                * the other bytes of the sgptr too.
-                                */
-                               if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
-                                && (sgptr & 0x80) == 0)
-                                       sgptr -= 0x100;
-                               sgptr &= ~0xFF;
-                               sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
-                                      & SG_ADDR_MASK;
-                               ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
-                               ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
-                       } else if ((resid & AHD_SG_LEN_MASK) == 0) {
-                               ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
-                                        sgptr | SG_LIST_NULL);
-                       }
-                       /*
-                        * Save Pointers.
-                        */
-                       ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
-                       ahd_outl(ahd, SCB_DATACNT, resid);
-                       ahd_outl(ahd, SCB_SGPTR, sgptr);
-                       ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
-                       ahd_outb(ahd, SEQIMODE,
-                                ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
-                       /*
-                        * If the data is to the SCSI bus, we are
-                        * done, otherwise wait for FIFOEMP.
-                        */
-                       if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
-                               break;
-               } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
-                       uint32_t sgptr;
-                       uint64_t data_addr;
-                       uint32_t data_len;
-                       u_int    dfcntrl;
+               /*
+                * Flush the data FIFO.  Strickly only
+                * necessary for Rev A parts.
+                */
+               ahd_outb(ahd, DFCNTRL, ahd_inb(ahd, DFCNTRL) | FIFOFLUSH);
 
+               /*
+                * Calculate residual.
+                */
+               sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
+               resid = ahd_inl(ahd, SHCNT);
+               resid |= ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT+3) << 24;
+               ahd_outl(ahd, SCB_RESIDUAL_DATACNT, resid);
+               if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG) == 0) {
                        /*
-                        * Disable S/G fetch so the DMA engine
-                        * is available to future users.
+                        * Must back up to the correct S/G element.
+                        * Typically this just means resetting our
+                        * low byte to the offset in the SG_CACHE,
+                        * but if we wrapped, we have to correct
+                        * the other bytes of the sgptr too.
                         */
-                       if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {
-                               ahd_outb(ahd, CCSGCTL, 0);
-                               ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
-                       }
+                       if ((ahd_inb(ahd, SG_CACHE_SHADOW) & 0x80) != 0
+                        && (sgptr & 0x80) == 0)
+                               sgptr -= 0x100;
+                       sgptr &= ~0xFF;
+                       sgptr |= ahd_inb(ahd, SG_CACHE_SHADOW)
+                              & SG_ADDR_MASK;
+                       ahd_outl(ahd, SCB_RESIDUAL_SGPTR, sgptr);
+                       ahd_outb(ahd, SCB_RESIDUAL_DATACNT + 3, 0);
+               } else if ((resid & AHD_SG_LEN_MASK) == 0) {
+                       ahd_outb(ahd, SCB_RESIDUAL_SGPTR,
+                                sgptr | SG_LIST_NULL);
+               }
+               /*
+                * Save Pointers.
+                */
+               ahd_outq(ahd, SCB_DATAPTR, ahd_inq(ahd, SHADDR));
+               ahd_outl(ahd, SCB_DATACNT, resid);
+               ahd_outl(ahd, SCB_SGPTR, sgptr);
+               ahd_outb(ahd, CLRSEQINTSRC, CLRSAVEPTRS);
+               ahd_outb(ahd, SEQIMODE,
+                        ahd_inb(ahd, SEQIMODE) | ENSAVEPTRS);
+               /*
+                * If the data is to the SCSI bus, we are
+                * done, otherwise wait for FIFOEMP.
+                */
+               if ((ahd_inb(ahd, DFCNTRL) & DIRECTION) != 0)
+                       goto clrchn;
+       } else if ((ahd_inb(ahd, SG_STATE) & LOADING_NEEDED) != 0) {
+               uint32_t sgptr;
+               uint64_t data_addr;
+               uint32_t data_len;
+               u_int    dfcntrl;
 
-                       /*
-                        * Wait for the DMA engine to notice that the
-                        * host transfer is enabled and that there is
-                        * space in the S/G FIFO for new segments before
-                        * loading more segments.
-                        */
-                       if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) == 0)
-                               continue;
-                       if ((ahd_inb(ahd, DFCNTRL) & HDMAENACK) == 0)
-                               continue;
+               /*
+                * Disable S/G fetch so the DMA engine
+                * is available to future users.  We won't
+                * be using the DMA engine to load segments.
+                */
+               if ((ahd_inb(ahd, SG_STATE) & FETCH_INPROG) != 0) {
+                       ahd_outb(ahd, CCSGCTL, 0);
+                       ahd_outb(ahd, SG_STATE, LOADING_NEEDED);
+               }
+
+               /*
+                * Wait for the DMA engine to notice that the
+                * host transfer is enabled and that there is
+                * space in the S/G FIFO for new segments before
+                * loading more segments.
+                */
+               if ((ahd_inb(ahd, DFSTATUS) & PRELOAD_AVAIL) != 0
+                && (ahd_inb(ahd, DFCNTRL) & HDMAENACK) != 0) {
 
                        /*
                         * Determine the offset of the next S/G
@@ -748,7 +794,7 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
                         * Advertise the segment to the hardware.
                         */
                        dfcntrl = ahd_inb(ahd, DFCNTRL)|PRELOADEN|HDMAEN;
-                       if ((ahd->features & AHD_NEW_DFCNTRL_OPTS)!=0) {
+                       if ((ahd->features & AHD_NEW_DFCNTRL_OPTS) != 0) {
                                /*
                                 * Use SCSIENWRDIS so that SCSIEN
                                 * is never modified by this
@@ -757,35 +803,44 @@ ahd_run_data_fifo(struct ahd_softc *ahd, struct scb *scb)
                                dfcntrl |= SCSIENWRDIS;
                        }
                        ahd_outb(ahd, DFCNTRL, dfcntrl);
-               } else if ((ahd_inb(ahd, SG_CACHE_SHADOW)
-                        & LAST_SEG_DONE) != 0) {
-
-                       /*
-                        * Transfer completed to the end of SG list
-                        * and has flushed to the host.
-                        */
-                       ahd_outb(ahd, SCB_SGPTR,
-                                ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
-                       break;
-               } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
-                       break;
                }
-               ahd_delay(200);
+       } else if ((ahd_inb(ahd, SG_CACHE_SHADOW) & LAST_SEG_DONE) != 0) {
+
+               /*
+                * Transfer completed to the end of SG list
+                * and has flushed to the host.
+                */
+               ahd_outb(ahd, SCB_SGPTR,
+                        ahd_inb_scbram(ahd, SCB_SGPTR) | SG_LIST_NULL);
+               goto clrchn;
+       } else if ((ahd_inb(ahd, DFSTATUS) & FIFOEMP) != 0) {
+clrchn:
+               /*
+                * Clear any handler for this FIFO, decrement
+                * the FIFO use count for the SCB, and release
+                * the FIFO.
+                */
+               ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
+               ahd_outb(ahd, SCB_FIFO_USE_COUNT,
+                        ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);
+               ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
        }
-       /*
-        * Clear any handler for this FIFO, decrement
-        * the FIFO use count for the SCB, and release
-        * the FIFO.
-        */
-       ahd_outb(ahd, LONGJMP_ADDR + 1, INVALID_ADDR);
-       ahd_outb(ahd, SCB_FIFO_USE_COUNT,
-                ahd_inb_scbram(ahd, SCB_FIFO_USE_COUNT) - 1);
-       ahd_outb(ahd, DFFSXFRCTL, CLRCHN);
 }
 
+/*
+ * Look for entries in the QoutFIFO that have completed.
+ * The valid_tag completion field indicates the validity
+ * of the entry - the valid value toggles each time through
+ * the queue. We use the sg_status field in the completion
+ * entry to avoid referencing the hscb if the completion
+ * occurred with no errors and no residual.  sg_status is
+ * a copy of the first byte (little endian) of the sgptr
+ * hscb field.
+ */
 void
 ahd_run_qoutfifo(struct ahd_softc *ahd)
 {
+       struct ahd_completion *completion;
        struct scb *scb;
        u_int  scb_index;
 
@@ -793,11 +848,13 @@ ahd_run_qoutfifo(struct ahd_softc *ahd)
                panic("ahd_run_qoutfifo recursion");
        ahd->flags |= AHD_RUNNING_QOUTFIFO;
        ahd_sync_qoutfifo(ahd, BUS_DMASYNC_POSTREAD);
-       while ((ahd->qoutfifo[ahd->qoutfifonext]
-            & QOUTFIFO_ENTRY_VALID_LE) == ahd->qoutfifonext_valid_tag) {
+       for (;;) {
+               completion = &ahd->qoutfifo[ahd->qoutfifonext];
 
-               scb_index = ahd_le16toh(ahd->qoutfifo[ahd->qoutfifonext]
-                                     & ~QOUTFIFO_ENTRY_VALID_LE);
+               if (completion->valid_tag != ahd->qoutfifonext_valid_tag)
+                       break;
+
+               scb_index = ahd_le16toh(completion->tag);
                scb = ahd_lookup_scb(ahd, scb_index);
                if (scb == NULL) {
                        printf("%s: WARNING no command for scb %d "
@@ -805,12 +862,15 @@ ahd_run_qoutfifo(struct ahd_softc *ahd)
                               ahd_name(ahd), scb_index,
                               ahd->qoutfifonext);
                        ahd_dump_card_state(ahd);
-               } else
-                       ahd_complete_scb(ahd, scb);
+               } else if ((completion->sg_status & SG_STATUS_VALID) != 0) {
+                       ahd_handle_scb_status(ahd, scb);
+               } else {
+                       ahd_done(ahd, scb);
+               }
 
                ahd->qoutfifonext = (ahd->qoutfifonext+1) & (AHD_QOUT_SIZE-1);
                if (ahd->qoutfifonext == 0)
-                       ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID_LE;
+                       ahd->qoutfifonext_valid_tag ^= QOUTFIFO_ENTRY_VALID;
        }
        ahd->flags &= ~AHD_RUNNING_QOUTFIFO;
 }
@@ -876,26 +936,6 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
                       ahd_name(ahd), seqintcode);
 #endif
        switch (seqintcode) {
-       case BAD_SCB_STATUS:
-       {
-               struct  scb *scb;
-               u_int   scbid;
-               int     cmds_pending;
-
-               scbid = ahd_get_scbptr(ahd);
-               scb = ahd_lookup_scb(ahd, scbid);
-               if (scb != NULL) {
-                       ahd_complete_scb(ahd, scb);
-               } else {
-                       printf("%s: WARNING no command for scb %d "
-                              "(bad status)\n", ahd_name(ahd), scbid);
-                       ahd_dump_card_state(ahd);
-               }
-               cmds_pending = ahd_inw(ahd, CMDS_PENDING);
-               if (cmds_pending > 0)
-                       ahd_outw(ahd, CMDS_PENDING, cmds_pending - 1);
-               break;
-       }
        case ENTERING_NONPACK:
        {
                struct  scb *scb;
@@ -1060,7 +1100,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
                        ahd_outb(ahd, SAVED_LUN, 0);
                        ahd_outb(ahd, SEQ_FLAGS, 0);
                        ahd_assert_atn(ahd);
-                       scb->flags &= ~(SCB_PACKETIZED);
+                       scb->flags &= ~SCB_PACKETIZED;
                        scb->flags |= SCB_ABORT|SCB_CMDPHASE_ABORT;
                        ahd_freeze_devq(ahd, scb);
                        ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);
@@ -1503,9 +1543,6 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
         && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) != 0)
                scb = NULL;
 
-       /* Make sure the sequencer is in a safe location. */
-       ahd_clear_critical_section(ahd);
-
        if ((status0 & IOERR) != 0) {
                u_int now_lvd;
 
@@ -1521,26 +1558,35 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
                ahd_setup_iocell_workaround(ahd);
                ahd_unpause(ahd);
        } else if ((status0 & OVERRUN) != 0) {
+
                printf("%s: SCSI offset overrun detected.  Resetting bus.\n",
                       ahd_name(ahd));
                ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
        } else if ((status & SCSIRSTI) != 0) {
+
                printf("%s: Someone reset channel A\n", ahd_name(ahd));
                ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE);
        } else if ((status & SCSIPERR) != 0) {
+
+               /* Make sure the sequencer is in a safe location. */
+               ahd_clear_critical_section(ahd);
+
                ahd_handle_transmission_error(ahd);
        } else if (lqostat0 != 0) {
+
                printf("%s: lqostat0 == 0x%x!\n", ahd_name(ahd), lqostat0);
                ahd_outb(ahd, CLRLQOINT0, lqostat0);
-               if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0) {
+               if ((ahd->bugs & AHD_CLRLQO_AUTOCLR_BUG) != 0)
                        ahd_outb(ahd, CLRLQOINT1, 0);
-               }
        } else if ((status & SELTO) != 0) {
                u_int  scbid;
 
                /* Stop the selection */
                ahd_outb(ahd, SCSISEQ0, 0);
 
+               /* Make sure the sequencer is in a safe location. */
+               ahd_clear_critical_section(ahd);
+
                /* No more pending messages */
                ahd_clear_msg_state(ahd);
 
@@ -1573,24 +1619,27 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
                                       scbid);
                        }
 #endif
-                       /*
-                        * Force a renegotiation with this target just in
-                        * case the cable was pulled and will later be
-                        * re-attached.  The target may forget its negotiation
-                        * settings with us should it attempt to reselect
-                        * during the interruption.  The target will not issue
-                        * a unit attention in this case, so we must always
-                        * renegotiate.
-                        */
                        ahd_scb_devinfo(ahd, &devinfo, scb);
-                       ahd_force_renegotiation(ahd, &devinfo);
                        ahd_set_transaction_status(scb, CAM_SEL_TIMEOUT);
                        ahd_freeze_devq(ahd, scb);
+
+                       /*
+                        * Cancel any pending transactions on the device
+                        * now that it seems to be missing.  This will
+                        * also revert us to async/narrow transfers until
+                        * we can renegotiate with the device.
+                        */
+                       ahd_handle_devreset(ahd, &devinfo,
+                                           CAM_LUN_WILDCARD,
+                                           CAM_SEL_TIMEOUT,
+                                           "Selection Timeout",
+                                           /*verbose_level*/1);
                }
                ahd_outb(ahd, CLRINT, CLRSCSIINT);
                ahd_iocell_first_selection(ahd);
                ahd_unpause(ahd);
        } else if ((status0 & (SELDI|SELDO)) != 0) {
+
                ahd_iocell_first_selection(ahd);
                ahd_unpause(ahd);
        } else if (status3 != 0) {
@@ -1598,6 +1647,10 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
                       ahd_name(ahd), status3);
                ahd_outb(ahd, CLRSINT3, status3);
        } else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) {
+
+               /* Make sure the sequencer is in a safe location. */
+               ahd_clear_critical_section(ahd);
+
                ahd_handle_lqiphase_error(ahd, lqistat1);
        } else if ((lqistat1 & LQICRCI_NLQ) != 0) {
                /*
@@ -1622,6 +1675,9 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
                 */
                ahd_outb(ahd, SCSISEQ0, 0);
 
+               /* Make sure the sequencer is in a safe location. */
+               ahd_clear_critical_section(ahd);
+
                /*
                 * Determine what we were up to at the time of
                 * the busfree.
@@ -1659,7 +1715,16 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
                        clear_fifo = 0;
                        packetized =  (lqostat1 & LQOBUSFREE) != 0;
                        if (!packetized
-                        && ahd_inb(ahd, LASTPHASE) == P_BUSFREE)
+                        && ahd_inb(ahd, LASTPHASE) == P_BUSFREE
+                        && (ahd_inb(ahd, SSTAT0) & SELDI) == 0
+                        && ((ahd_inb(ahd, SSTAT0) & SELDO) == 0
+                         || (ahd_inb(ahd, SCSISEQ0) & ENSELO) == 0))
+                               /*
+                                * Assume packetized if we are not
+                                * on the bus in a non-packetized
+                                * capacity and any pending selection
+                                * was a packetized selection.
+                                */
                                packetized = 1;
                        break;
                }
@@ -2310,8 +2375,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
                       "PRGMCNT == 0x%x\n",
                       ahd_lookup_phase_entry(lastphase)->phasemsg,
                       aborted,
-                      ahd_inb(ahd, PRGMCNT)
-                       | (ahd_inb(ahd, PRGMCNT+1) << 8));
+                      ahd_inw(ahd, PRGMCNT));
                ahd_dump_card_state(ahd);
        }
        /* Always restart the sequencer. */
@@ -2474,8 +2538,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd)
                u_int   i;
 
                ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
-               seqaddr = ahd_inb(ahd, CURADDR)
-                       | (ahd_inb(ahd, CURADDR+1) << 8);
+               seqaddr = ahd_inw(ahd, CURADDR);
 
                cs = ahd->critical_sections;
                for (i = 0; i < ahd->num_critical_sections; i++, cs++) {
@@ -3196,14 +3259,25 @@ ahd_update_neg_table(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
                iocell_opts[AHD_PRECOMP_SLEW_INDEX] &= ~AHD_PRECOMP_MASK;
 
                if ((ahd->features & AHD_NEW_IOCELL_OPTS) != 0
-                && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0) {
+                && (ppr_opts & MSG_EXT_PPR_DT_REQ) != 0
+                && (ppr_opts & MSG_EXT_PPR_IU_REQ) == 0) {
                        /*
                         * Slow down our CRC interval to be
-                        * compatible with devices that can't
-                        * handle a CRC at full speed.
+                        * compatible with non-packetized
+                        * U160 devices that can't handle a
+                        * CRC at full speed.
                         */
                        con_opts |= ENSLOWCRC;
                }
+
+               if ((ahd->bugs & AHD_PACED_NEGTABLE_BUG) != 0) {
+                       /*
+                        * On H2A4, revert to a slower slewrate
+                        * on non-paced transfers.
+                        */
+                       iocell_opts[AHD_PRECOMP_SLEW_INDEX] &=
+                           ~AHD_SLEWRATE_MASK;
+               }
        }
 
        ahd_outb(ahd, ANNEXCOL, AHD_ANNEXCOL_PRECOMP_SLEW);
@@ -3292,11 +3366,15 @@ ahd_update_pending_scbs(struct ahd_softc *ahd)
         * Force the sequencer to reinitialize the selection for
         * the command at the head of the execution queue if it
         * has already been setup.  The negotiation changes may
-        * effect whether we select-out with ATN.
+        * effect whether we select-out with ATN.  It is only
+        * safe to clear ENSELO when the bus is not free and no
+        * selection is in progres or completed.
         */
        saved_modes = ahd_save_modes(ahd);
        ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
-       ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
+       if ((ahd_inb(ahd, SCSISIGI) & BSYI) != 0
+        && (ahd_inb(ahd, SSTAT0) & (SELDO|SELINGO)) == 0)
+               ahd_outb(ahd, SCSISEQ0, ahd_inb(ahd, SCSISEQ0) & ~ENSELO);
        saved_scbptr = ahd_get_scbptr(ahd);
        /* Ensure that the hscbs down on the card match the new information */
        for (scb_tag = 0; scb_tag < ahd->scb_data.maxhscbs; scb_tag++) {
@@ -4909,10 +4987,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
         * Determine initial values for data_addr and data_cnt
         * for resuming the data phase.
         */
-       sgptr = (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 3) << 24)
-             | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 2) << 16)
-             | (ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR + 1) << 8)
-             | ahd_inb_scbram(ahd, SCB_RESIDUAL_SGPTR);
+       sgptr = ahd_inl_scbram(ahd, SCB_RESIDUAL_SGPTR);
        sgptr &= SG_PTR_MASK;
 
        resid = (ahd_inb_scbram(ahd, SCB_RESIDUAL_DATACNT + 2) << 16)
@@ -4930,10 +5005,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
                dataptr = ahd_le64toh(sg->addr)
                        + (ahd_le32toh(sg->len) & AHD_SG_LEN_MASK)
                        - resid;
-               ahd_outb(ahd, HADDR + 7, dataptr >> 56);
-               ahd_outb(ahd, HADDR + 6, dataptr >> 48);
-               ahd_outb(ahd, HADDR + 5, dataptr >> 40);
-               ahd_outb(ahd, HADDR + 4, dataptr >> 32);
+               ahd_outl(ahd, HADDR + 4, dataptr >> 32);
        } else {
                struct   ahd_dma_seg *sg;
 
@@ -4948,10 +5020,7 @@ ahd_reinitialize_dataptrs(struct ahd_softc *ahd)
                ahd_outb(ahd, HADDR + 4,
                         (ahd_le32toh(sg->len) & ~AHD_SG_LEN_MASK) >> 24);
        }
-       ahd_outb(ahd, HADDR + 3, dataptr >> 24);
-       ahd_outb(ahd, HADDR + 2, dataptr >> 16);
-       ahd_outb(ahd, HADDR + 1, dataptr >> 8);
-       ahd_outb(ahd, HADDR, dataptr);
+       ahd_outl(ahd, HADDR, dataptr);
        ahd_outb(ahd, HCNT + 2, resid >> 16);
        ahd_outb(ahd, HCNT + 1, resid >> 8);
        ahd_outb(ahd, HCNT, resid);
@@ -5011,13 +5080,14 @@ ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
        ahd_set_width(ahd, devinfo, MSG_EXT_WDTR_BUS_8_BIT,
                      AHD_TRANS_CUR, /*paused*/TRUE);
        ahd_set_syncrate(ahd, devinfo, /*period*/0, /*offset*/0,
-                        /*ppr_options*/0, AHD_TRANS_CUR, /*paused*/TRUE);
+                        /*ppr_options*/0, AHD_TRANS_CUR,
+                        /*paused*/TRUE);
        
-       ahd_send_async(ahd, devinfo->channel, devinfo->target,
-                      lun, AC_SENT_BDR, NULL);
+       if (status != CAM_SEL_TIMEOUT)
+               ahd_send_async(ahd, devinfo->channel, devinfo->target,
+                              CAM_LUN_WILDCARD, AC_SENT_BDR, NULL);
 
-       if (message != NULL
-        && (verbose_level <= bootverbose))
+       if (message != NULL && bootverbose)
                printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd),
                       message, devinfo->channel, devinfo->target, found);
 }
@@ -5203,13 +5273,13 @@ ahd_free(struct ahd_softc *ahd)
                /* FALLTHROUGH */
        case 4:
                ahd_dmamap_unload(ahd, ahd->shared_data_dmat,
-                                 ahd->shared_data_dmamap);
+                                 ahd->shared_data_map.dmamap);
                /* FALLTHROUGH */
        case 3:
                ahd_dmamem_free(ahd, ahd->shared_data_dmat, ahd->qoutfifo,
-                               ahd->shared_data_dmamap);
+                               ahd->shared_data_map.dmamap);
                ahd_dmamap_destroy(ahd, ahd->shared_data_dmat,
-                                  ahd->shared_data_dmamap);
+                                  ahd->shared_data_map.dmamap);
                /* FALLTHROUGH */
        case 2:
                ahd_dma_tag_destroy(ahd, ahd->shared_data_dmat);
@@ -5975,16 +6045,13 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
        newcount = MIN(scb_data->sense_left, scb_data->scbs_left);
        newcount = MIN(newcount, scb_data->sgs_left);
        newcount = MIN(newcount, (AHD_SCB_MAX_ALLOC - scb_data->numscbs));
-       scb_data->sense_left -= newcount;
-       scb_data->scbs_left -= newcount;
-       scb_data->sgs_left -= newcount;
        for (i = 0; i < newcount; i++) {
-               u_int col_tag;
-
                struct scb_platform_data *pdata;
+               u_int col_tag;
 #ifndef __linux__
                int error;
 #endif
+
                next_scb = (struct scb *)malloc(sizeof(*next_scb),
                                                M_DEVBUF, M_NOWAIT);
                if (next_scb == NULL)
@@ -6041,6 +6108,9 @@ ahd_alloc_scbs(struct ahd_softc *ahd)
                sense_data += AHD_SENSE_BUFSIZE;
                sense_busaddr += AHD_SENSE_BUFSIZE;
                scb_data->numscbs++;
+               scb_data->sense_left--;
+               scb_data->scbs_left--;
+               scb_data->sgs_left--;
        }
 }
 
@@ -6088,7 +6158,6 @@ static const char *termstat_strings[] = {
 int
 ahd_init(struct ahd_softc *ahd)
 {
-       uint8_t         *base_vaddr;
        uint8_t         *next_vaddr;
        dma_addr_t       next_baddr;
        size_t           driver_data_size;
@@ -6156,7 +6225,7 @@ ahd_init(struct ahd_softc *ahd)
         * for the target mode role, we must additionally provide space for
         * the incoming target command fifo.
         */
-       driver_data_size = AHD_SCB_MAX * sizeof(uint16_t)
+       driver_data_size = AHD_SCB_MAX * sizeof(*ahd->qoutfifo)
                         + sizeof(struct hardware_scb);
        if ((ahd->features & AHD_TARGETMODE) != 0)
                driver_data_size += AHD_TMODE_CMDS * sizeof(struct target_cmd);
@@ -6178,20 +6247,23 @@ ahd_init(struct ahd_softc *ahd)
 
        /* Allocation of driver data */
        if (ahd_dmamem_alloc(ahd, ahd->shared_data_dmat,
-                            (void **)&base_vaddr,
-                            BUS_DMA_NOWAIT, &ahd->shared_data_dmamap) != 0) {
+                            (void **)&ahd->shared_data_map.vaddr,
+                            BUS_DMA_NOWAIT,
+                            &ahd->shared_data_map.dmamap) != 0) {
                return (ENOMEM);
        }
 
        ahd->init_level++;
 
        /* And permanently map it in */
-       ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_dmamap,
-                       base_vaddr, driver_data_size, ahd_dmamap_cb,
-                       &ahd->shared_data_busaddr, /*flags*/0);
-       ahd->qoutfifo = (uint16_t *)base_vaddr;
+       ahd_dmamap_load(ahd, ahd->shared_data_dmat, ahd->shared_data_map.dmamap,
+                       ahd->shared_data_map.vaddr, driver_data_size,
+                       ahd_dmamap_cb, &ahd->shared_data_map.physaddr,
+                       /*flags*/0);
+       ahd->qoutfifo = (struct ahd_completion *)ahd->shared_data_map.vaddr;
        next_vaddr = (uint8_t *)&ahd->qoutfifo[AHD_QOUT_SIZE];
-       next_baddr = ahd->shared_data_busaddr + AHD_QOUT_SIZE*sizeof(uint16_t);
+       next_baddr = ahd->shared_data_map.physaddr
+                  + AHD_QOUT_SIZE*sizeof(struct ahd_completion);
        if ((ahd->features & AHD_TARGETMODE) != 0) {
                ahd->targetcmds = (struct target_cmd *)next_vaddr;
                next_vaddr += AHD_TMODE_CMDS * sizeof(struct target_cmd);
@@ -6212,6 +6284,7 @@ ahd_init(struct ahd_softc *ahd)
         * specially from the DMA safe memory chunk used for the QOUTFIFO.
         */
        ahd->next_queued_hscb = (struct hardware_scb *)next_vaddr;
+       ahd->next_queued_hscb_map = &ahd->shared_data_map;
        ahd->next_queued_hscb->hscb_busaddr = ahd_htole32(next_baddr);
 
        ahd->init_level++;
@@ -6517,10 +6590,10 @@ ahd_chip_init(struct ahd_softc *ahd)
 
        /* All of our queues are empty */
        ahd->qoutfifonext = 0;
-       ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID_LE;
-       ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID >> 8);
+       ahd->qoutfifonext_valid_tag = QOUTFIFO_ENTRY_VALID;
+       ahd_outb(ahd, QOUTFIFO_ENTRY_VALID_TAG, QOUTFIFO_ENTRY_VALID);
        for (i = 0; i < AHD_QOUT_SIZE; i++)
-               ahd->qoutfifo[i] = 0;
+               ahd->qoutfifo[i].valid_tag = 0;
        ahd_sync_qoutfifo(ahd, BUS_DMASYNC_PREREAD);
 
        ahd->qinfifonext = 0;
@@ -6553,24 +6626,22 @@ ahd_chip_init(struct ahd_softc *ahd)
        ahd_outw(ahd, COMPLETE_SCB_HEAD, SCB_LIST_NULL);
        ahd_outw(ahd, COMPLETE_SCB_DMAINPROG_HEAD, SCB_LIST_NULL);
        ahd_outw(ahd, COMPLETE_DMA_SCB_HEAD, SCB_LIST_NULL);
+       ahd_outw(ahd, COMPLETE_DMA_SCB_TAIL, SCB_LIST_NULL);
+       ahd_outw(ahd, COMPLETE_ON_QFREEZE_HEAD, SCB_LIST_NULL);
 
        /*
         * The Freeze Count is 0.
         */
+       ahd->qfreeze_cnt = 0;
        ahd_outw(ahd, QFREEZE_COUNT, 0);
+       ahd_outw(ahd, KERNEL_QFREEZE_COUNT, 0);
 
        /*
         * Tell the sequencer where it can find our arrays in memory.
         */
-       busaddr = ahd->shared_data_busaddr;
-       ahd_outb(ahd, SHARED_DATA_ADDR, busaddr & 0xFF);
-       ahd_outb(ahd, SHARED_DATA_ADDR + 1, (busaddr >> 8) & 0xFF);
-       ahd_outb(ahd, SHARED_DATA_ADDR + 2, (busaddr >> 16) & 0xFF);
-       ahd_outb(ahd, SHARED_DATA_ADDR + 3, (busaddr >> 24) & 0xFF);
-       ahd_outb(ahd, QOUTFIFO_NEXT_ADDR, busaddr & 0xFF);
-       ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 1, (busaddr >> 8) & 0xFF);
-       ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 2, (busaddr >> 16) & 0xFF);
-       ahd_outb(ahd, QOUTFIFO_NEXT_ADDR + 3, (busaddr >> 24) & 0xFF);
+       busaddr = ahd->shared_data_map.physaddr;
+       ahd_outl(ahd, SHARED_DATA_ADDR, busaddr);
+       ahd_outl(ahd, QOUTFIFO_NEXT_ADDR, busaddr);
 
        /*
         * Setup the allowed SCSI Sequences based on operational mode.
@@ -6619,10 +6690,7 @@ ahd_chip_init(struct ahd_softc *ahd)
         * Tell the sequencer which SCB will be the next one it receives.
         */
        busaddr = ahd_le32toh(ahd->next_queued_hscb->hscb_busaddr);
-       ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 0, busaddr & 0xFF);
-       ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 1, (busaddr >> 8) & 0xFF);
-       ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 2, (busaddr >> 16) & 0xFF);
-       ahd_outb(ahd, NEXT_QUEUED_SCB_ADDR + 3, (busaddr >> 24) & 0xFF);
+     &