]> git.pld-linux.org Git - packages/kernel.git/commitdiff
62f249c22aa58a5738af81ae3ed9e869 linux-2.4.9-aacraid-20010816.patch
authorJan Rękorajski <baggins@pld-linux.org>
Mon, 17 Sep 2001 18:33:45 +0000 (18:33 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    linux-2.4.9-aacraid-20010816.patch -> 1.1

linux-2.4.9-aacraid-20010816.patch [new file with mode: 0644]

diff --git a/linux-2.4.9-aacraid-20010816.patch b/linux-2.4.9-aacraid-20010816.patch
new file mode 100644 (file)
index 0000000..67e3242
--- /dev/null
@@ -0,0 +1,16784 @@
+diff -burN linux-2.4.9/MAINTAINERS linux/MAINTAINERS
+--- linux-2.4.9/MAINTAINERS    Thu Aug 16 13:40:30 2001
++++ linux/MAINTAINERS  Thu Aug 16 13:41:30 2001
+@@ -126,6 +126,14 @@
+ W:    http://www.uni-karlsruhe.de/~Robert.Siemer/Private/
+ S:    Maintained
++AACRAID SCSI RAID DRIVER
++P:    Adaptec OEM Raid Solutions
++M:    linux-aacraid-devel@dell.com
++L:    linux-aacraid-devel@dell.com
++L:    linux-aacraid-announce@dell.com
++W:    http://domsch.com/linux
++S:    Supported
++
+ ACPI
+ P:    Andy Grover
+ M:    andrew.grover@intel.com
+diff -burN linux-2.4.9/arch/i386/defconfig linux/arch/i386/defconfig
+--- linux-2.4.9/arch/i386/defconfig    Thu Aug 16 13:40:30 2001
++++ linux/arch/i386/defconfig  Thu Aug 16 13:41:30 2001
+@@ -286,6 +286,7 @@
+ # CONFIG_SCSI_AHA152X is not set
+ # CONFIG_SCSI_AHA1542 is not set
+ # CONFIG_SCSI_AHA1740 is not set
++# CONFIG_SCSI_AACRAID is not set
+ # CONFIG_SCSI_AIC7XXX is not set
+ # CONFIG_SCSI_AIC7XXX_OLD is not set
+ # CONFIG_SCSI_ADVANSYS is not set
+diff -burN linux-2.4.9/drivers/scsi/Config.in linux/drivers/scsi/Config.in
+--- linux-2.4.9/drivers/scsi/Config.in Thu Aug 16 13:40:11 2001
++++ linux/drivers/scsi/Config.in       Thu Aug 16 13:41:30 2001
+@@ -50,6 +50,7 @@
+ dep_tristate 'Adaptec AHA152X/2825 support' CONFIG_SCSI_AHA152X $CONFIG_SCSI
+ dep_tristate 'Adaptec AHA1542 support' CONFIG_SCSI_AHA1542 $CONFIG_SCSI
+ dep_tristate 'Adaptec AHA1740 support' CONFIG_SCSI_AHA1740 $CONFIG_SCSI
++dep_tristate 'Adaptec AACRAID support' CONFIG_SCSI_AACRAID $CONFIG_SCSI
+ source drivers/scsi/aic7xxx/Config.in
+ if [ "$CONFIG_SCSI_AIC7XXX" != "y" ]; then
+    dep_tristate 'Old Adaptec AIC7xxx support' CONFIG_SCSI_AIC7XXX_OLD $CONFIG_SCSI
+diff -burN linux-2.4.9/drivers/scsi/Makefile linux/drivers/scsi/Makefile
+--- linux-2.4.9/drivers/scsi/Makefile  Thu Aug 16 13:40:11 2001
++++ linux/drivers/scsi/Makefile        Thu Aug 16 13:41:30 2001
+@@ -70,6 +70,7 @@
+ obj-$(CONFIG_SCSI_AHA152X)    += aha152x.o
+ obj-$(CONFIG_SCSI_AHA1542)    += aha1542.o
+ obj-$(CONFIG_SCSI_AHA1740)    += aha1740.o
++obj-$(CONFIG_SCSI_AACRAID)    += aacraid.o
+ ifeq ($(CONFIG_SCSI_AIC7XXX),y)
+ obj-$(CONFIG_SCSI_AIC7XXX)    += aic7xxx/aic7xxx_drv.o
+ endif
+@@ -193,6 +194,10 @@
+ sim710_u.h: sim710_d.h
+ sim710.o : sim710_d.h
++
++aacraid.o:
++      cd aacraid; make
++
+
+ 53c700_d.h: 53c700.scr script_asm.pl
+       $(PERL) -s script_asm.pl -ncr7x0_family < 53c700.scr
+diff -burN linux-2.4.9/drivers/scsi/aacraid/ChangeLog linux/drivers/scsi/aacraid/ChangeLog
+--- linux-2.4.9/drivers/scsi/aacraid/ChangeLog Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/ChangeLog       Thu Aug 16 18:18:10 2001
+@@ -0,0 +1,30 @@
++2001-08-16  Matt Domsch <Matt_Domsch@dell.com>
++* renamed aacraid_pciid to perc_pciid for future Dell controllers
++* added rx_pciid and sa_pciid options for future Adaptec controllers
++* applied changes from Adaptec (new PCI ID, some cleanups)
++* released patch against 2.4.8
++* released patch against 2.4.9
++      
++2001-08-11  Matt Domsch <Matt_Domsch@dell.com>
++* applied pciid patch to allow passing a new PCI ID to the module at insmod
++* removed all #ifdef CONFIG_SMP and #ifdef MODULE stuff
++* released patch against 2.4.7
++* released patch against 2.4.8
++
++2001-07-21  Matt Domsch <Matt_Domsch@dell.com>
++* changed __SMP__ to CONFIG_SMP everywhere (really this time)
++* Applied read capacity patch
++* released patch against 2.4.6
++* released patch against 2.4.7
++      
++2001-07-04  Matt Domsch <Matt_Domsch@dell.com>
++* Started with linux-2.4.5-aacraid-043001.patch
++* Applied Chris Pascoe's SMP fix patch
++* Released patch against 2.4.6
++
++
++2001-04-30  Matt Domsch <Matt_Domsch@dell.com>
++* Started with linux-2.4.3-aacraid-030101.patch
++* Applied against 2.4.4.
++* Added scsi_set_pci_device() call in linit.c
++      
+diff -burN linux-2.4.9/drivers/scsi/aacraid/Makefile linux/drivers/scsi/aacraid/Makefile
+--- linux-2.4.9/drivers/scsi/aacraid/Makefile  Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/Makefile        Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,169 @@
++#
++# Makefile aacraid Raid Controller
++#
++
++###############################################################################
++### SOURCE FILES DEFINES
++###############################################################################
++
++CFILES_DRIVER=\
++      ./aachba.c \
++      ./aacid.c \
++      ./commctrl.c \
++      ./comminit.c \
++      ./commsup.c \
++      ./dpcsup.c \
++      ./linit.c \
++      ./osddi.c \
++      ./osfuncs.c \
++      ./ossup.c \
++      ./port.c \
++      ./rx.c \
++      ./sap1sup.c
++
++IFILES_DRIVER=\
++      ./include/AacGenericTypes.h \
++      ./include/aac_unix_defs.h \
++      ./include/adapter.h \
++      ./include/afacomm.h \
++      ./include/aifstruc.h \
++      ./include/build_number.h \
++      ./include/commdata.h \
++      ./include/commerr.h \
++      ./include/commfibcontext.h \
++      ./include/comprocs.h \
++      ./include/comproto.h \
++      ./include/comstruc.h \
++      ./include/comsup.h \
++      ./include/fsact.h \
++      ./include/fsafs.h  \
++      ./include/fsaioctl.h \
++      ./include/fsaport.h \
++      ./include/fsatypes.h \
++      ./include/linit.h \
++      ./include/monkerapi.h \
++      ./include/nodetype.h \
++      ./include/nvramioctl.h \
++      ./include/osheaders.h \
++      ./include/ostypes.h \
++      ./include/pcisup.h \
++      ./include/perfpack.h \
++      ./include/port.h \
++      ./include/protocol.h \
++      ./include/revision.h \
++      ./include/rxcommon.h \
++      ./include/rx.h \
++      ./include/sap1common.h \
++      ./include/sap1.h \
++      ./include/version.h
++
++ALL_SOURCE=\
++      ${CFILES_DRIVER} \
++      ${IFILES_DRIVER} 
++
++###############################################################################
++### OBJECT FILES DEFINES
++###############################################################################
++
++
++OFILES_DRIVER=\
++      linit.o \
++      osfuncs.o \
++      osddi.o \
++      aachba.o \
++      commctrl.o \
++      comminit.o \
++      commsup.o \
++      dpcsup.o \
++      ossup.o \
++      port.o \
++      rx.o \
++      sap1sup.o
++
++TARGET_OFILES= ${OFILES_DRIVER} aacid.o
++
++###############################################################################
++### GENERAL DEFINES
++###############################################################################
++
++#  Remember that we're doing a chdir one level lower, so we need an extra ../
++INCS= \
++      -I./include \
++      -I../../../include -I..
++
++WARNINGS= -w -Wall -Wno-unused -Wno-switch -Wno-missing-prototypes -Wno-implicit
++
++
++COMMON_FLAGS=\
++      -D__KERNEL__=1 -DUNIX -DCVLOCK_USE_SPINLOCK -DLINUX \
++      ${INCS} \
++      ${WARNINGS}
++
++AACFLAGS=${CFLAGS} ${COMMON_FLAGS} ${EXTRA_FLAGS}
++
++###############################################################################
++### DO GENERAL STUFF
++###############################################################################
++
++.SUFFIXES:
++.SUFFIXES: .c .o .h .a
++
++all: source ${TARGET_OFILES} aacraid.o
++
++source: ${ALL_SOURCE}
++
++clean:
++      rm *.o
++
++###############################################################################
++### DRIVER LINKS
++###############################################################################
++
++aacraid.o: source ${TARGET_OFILES}
++      ld -r -o $@ $(TARGET_OFILES)
++      cp -r aacraid.o ../
++
++###############################################################################
++### SIMPLE COMPILES
++###############################################################################
++
++linit.o: ./linit.c
++      $(CC) $(COMMON_FLAGS) $(AACFLAGS) -c -o linit.o ./linit.c
++
++aachba.o: ./aachba.c
++      $(CC) $(COMMON_FLAGS) $(AACFLAGS) -c -o aachba.o ./aachba.c
++
++osddi.o: ./osddi.c
++      $(CC) $(COMMON_FLAGS) $(AACFLAGS) -c -o osddi.o ./osddi.c
++
++osfuncs.o: ./osfuncs.c
++      $(CC) $(COMMON_FLAGS) $(AACFLAGS) -c -o osfuncs.o ./osfuncs.c
++
++commctrl.o:  ./commctrl.c
++      $(CC) $(COMMON_FLAGS) $(AACFLAGS) -c -o commctrl.o ./commctrl.c
++
++comminit.o:  ./comminit.c
++      $(CC) $(COMMON_FLAGS) $(AACFLAGS) -c -o comminit.o ./comminit.c
++
++commsup.o:  ./commsup.c
++      $(CC) $(COMMON_FLAGS) $(AACFLAGS) -c -o commsup.o ./commsup.c
++
++dpcsup.o:  ./dpcsup.c
++      $(CC) $(COMMON_FLAGS) $(AACFLAGS) -c -o dpcsup.o ./dpcsup.c
++
++aacid.o:  ./aacid.c
++      $(CC) $(COMMON_FLAGS) $(AACFLAGS) -c -o aacid.o ./aacid.c
++
++port.o:  ./port.c
++      $(CC) $(COMMON_FLAGS) $(AACFLAGS) -c -o port.o ./port.c
++
++ossup.o:  ./ossup.c
++      $(CC) $(COMMON_FLAGS) $(AACFLAGS) -c -o ossup.o ./ossup.c
++
++rx.o:  ./rx.c
++      $(CC) $(COMMON_FLAGS) $(AACFLAGS) -c -o rx.o ./rx.c
++
++sap1sup.o: ./sap1sup.c
++      $(CC) $(COMMON_FLAGS) $(AACFLAGS) -c -o sap1sup.o ./sap1sup.c
++
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/README linux/drivers/scsi/aacraid/README
+--- linux-2.4.9/drivers/scsi/aacraid/README    Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/README  Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,46 @@
++                              AACRAID Driver for Linux
++
++Introduction
++-------------------------
++The aacraid driver adds support for Adaptec (http://www.adaptec.com)
++OEM based RAID controllers.
++
++It is important to note the amount of test time the 2.4.x driver
++received. Though not a great deal has changed between 2.2 and 2.4
++for this version, it has not recevied a great deal of test time.
++
++A new driver version is in the works and that version will be
++submitted to the standard distribution kernel. The previous
++2.2 version was submitted but rejected due to the large
++amount of code reduncdancy and NTisms. This driver was
++initially ported from NT to Solaris and then to Linux.
++
++The new version is being written on Unix for Unix and
++should be much easier to read and a great deal cleaner.
++
++Supported Cards/Chipsets
++-------------------------
++      Dell Computer Corporation PERC 2 Quad Channel
++      Dell Computer Corporation PERC 2/Si
++      Dell Computer Corporation PERC 3/Si
++      Dell Computer Corporation PERC 3/Di
++      HP NetRAID-4M
++
++Not Supported Devices
++-------------------------
++      Any and All Adaptec branded raid controllers.
++
++People
++-------------------------
++      Adaptec Unix OEM Product Group
++
++Mailing List
++-------------------------
++please see http://domsch.com/linux for information
++on mailing lists. There is both a development and
++an announcment list. Due to the overwhelming amount
++of mail I receive about this driver, I can not
++answer questions individually and requests should
++be directed to the list server. Thanks.
++
++Modified by Brian Boerner February 2001
+diff -burN linux-2.4.9/drivers/scsi/aacraid/aachba.c linux/drivers/scsi/aacraid/aachba.c
+--- linux-2.4.9/drivers/scsi/aacraid/aachba.c  Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/aachba.c        Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,1897 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   aachba.c
++ *
++ * Abstract: driver...
++ *
++--*/
++
++static char *ident_aachba = "aacraid_ident aachba.c 1.0.6 2000/10/09 Adaptec, Inc.";
++
++/*------------------------------------------------------------------------------
++ *              I N C L U D E S
++ *----------------------------------------------------------------------------*/
++#include "osheaders.h"
++#include "AacGenericTypes.h"
++#include "aac_unix_defs.h"
++#include "comstruc.h"
++#include "monkerapi.h"
++#include "protocol.h"
++#include "fsafs.h"
++#include "fsact.h"
++#include "fsaioctl.h"
++
++#include "sap1common.h"
++#include "fsaport.h"
++#include "pcisup.h"
++#include "sap1.h"
++#include "nodetype.h"
++#include "comsup.h"
++#include "afacomm.h"
++#include "adapter.h"
++
++/*------------------------------------------------------------------------------
++ *              D E F I N E S
++ *----------------------------------------------------------------------------*/
++/*    SCSI Commands */
++#define       SS_TEST                 0x00    /* Test unit ready */
++#define SS_REZERO             0x01    /* Rezero unit */
++#define       SS_REQSEN               0x03    /* Request Sense */
++#define SS_REASGN             0x07    /* Reassign blocks */
++#define       SS_READ                 0x08    /* Read 6   */
++#define       SS_WRITE                0x0A    /* Write 6  */
++#define       SS_INQUIR               0x12    /* inquiry */
++#define       SS_ST_SP                0x1B    /* Start/Stop unit */
++#define       SS_LOCK                 0x1E    /* prevent/allow medium removal */
++#define SS_RESERV             0x16    /* Reserve */
++#define SS_RELES              0x17    /* Release */
++#define SS_MODESEN            0x1A    /* Mode Sense 6 */
++#define       SS_RDCAP                0x25    /* Read Capacity */
++#define       SM_READ                 0x28    /* Read 10  */
++#define       SM_WRITE                0x2A    /* Write 10 */
++#define SS_SEEK                       0x2B    /* Seek */
++
++/* values for inqd_pdt: Peripheral device type in plain English */
++#define       INQD_PDT_DA     0x00    /* Direct-access (DISK) device */
++#define       INQD_PDT_PROC   0x03    /* Processor device */
++#define       INQD_PDT_CHNGR  0x08    /* Changer (jukebox, scsi2) */
++#define       INQD_PDT_COMM   0x09    /* Communication device (scsi2) */
++#define       INQD_PDT_NOLUN2 0x1f    /* Unknown Device (scsi2) */
++#define       INQD_PDT_NOLUN  0x7f    /* Logical Unit Not Present */
++
++#define       INQD_PDT_DMASK  0x1F    /* Peripheral Device Type Mask */
++#define       INQD_PDT_QMASK  0xE0    /* Peripheral Device Qualifer Mask */
++
++#define       TARGET_LUN_TO_CONTAINER(Target, Lun)    (((Lun) << 4) | Target)
++#define CONTAINER_TO_TARGET(Container)          ((Container) & 0xf)
++#define CONTAINER_TO_LUN(Container)             ((Container) >> 4)
++
++#define MAX_FIB_DATA (sizeof(FIB) - sizeof(FIB_HEADER))
++
++#define MAX_DRIVER_SG_SEGMENT_COUNT 17
++
++// ------------------------------------------------------
++// Sense keys
++//
++#define SENKEY_NO_SENSE      0x00 //
++#define SENKEY_UNDEFINED     0x01 //
++#define SENKEY_NOT_READY     0x02 //
++#define SENKEY_MEDIUM_ERR    0x03 //
++#define SENKEY_HW_ERR        0x04 //
++#define SENKEY_ILLEGAL       0x05 //
++#define SENKEY_ATTENTION     0x06 //
++#define SENKEY_PROTECTED     0x07 //
++#define SENKEY_BLANK         0x08 //
++#define SENKEY_V_UNIQUE      0x09 //
++#define SENKEY_CPY_ABORT     0x0A //
++#define SENKEY_ABORT         0x0B //
++#define SENKEY_EQUAL         0x0C //
++#define SENKEY_VOL_OVERFLOW  0x0D //
++#define SENKEY_MISCOMP       0x0E //
++#define SENKEY_RESERVED      0x0F //
++
++// ------------------------------------------------------
++// Sense codes
++//
++#define SENCODE_NO_SENSE                        0x00
++#define SENCODE_END_OF_DATA                     0x00
++#define SENCODE_BECOMING_READY                  0x04
++#define SENCODE_INIT_CMD_REQUIRED               0x04
++#define SENCODE_PARAM_LIST_LENGTH_ERROR         0x1A
++#define SENCODE_INVALID_COMMAND                 0x20
++#define SENCODE_LBA_OUT_OF_RANGE                0x21
++#define SENCODE_INVALID_CDB_FIELD               0x24
++#define SENCODE_LUN_NOT_SUPPORTED               0x25
++#define SENCODE_INVALID_PARAM_FIELD             0x26
++#define SENCODE_PARAM_NOT_SUPPORTED             0x26
++#define SENCODE_PARAM_VALUE_INVALID             0x26
++#define SENCODE_RESET_OCCURRED                  0x29
++#define SENCODE_LUN_NOT_SELF_CONFIGURED_YET     0x3E
++#define SENCODE_INQUIRY_DATA_CHANGED            0x3F
++#define SENCODE_SAVING_PARAMS_NOT_SUPPORTED     0x39
++#define SENCODE_DIAGNOSTIC_FAILURE              0x40
++#define SENCODE_INTERNAL_TARGET_FAILURE         0x44
++#define SENCODE_INVALID_MESSAGE_ERROR           0x49
++#define SENCODE_LUN_FAILED_SELF_CONFIG          0x4c
++#define SENCODE_OVERLAPPED_COMMAND              0x4E
++
++// ------------------------------------------------------
++// Additional sense codes
++//
++#define ASENCODE_NO_SENSE                       0x00
++#define ASENCODE_END_OF_DATA                    0x05
++#define ASENCODE_BECOMING_READY                 0x01
++#define ASENCODE_INIT_CMD_REQUIRED              0x02
++#define ASENCODE_PARAM_LIST_LENGTH_ERROR        0x00
++#define ASENCODE_INVALID_COMMAND                0x00
++#define ASENCODE_LBA_OUT_OF_RANGE               0x00
++#define ASENCODE_INVALID_CDB_FIELD              0x00
++#define ASENCODE_LUN_NOT_SUPPORTED              0x00
++#define ASENCODE_INVALID_PARAM_FIELD            0x00
++#define ASENCODE_PARAM_NOT_SUPPORTED            0x01
++#define ASENCODE_PARAM_VALUE_INVALID            0x02
++#define ASENCODE_RESET_OCCURRED                 0x00
++#define ASENCODE_LUN_NOT_SELF_CONFIGURED_YET    0x00
++#define ASENCODE_INQUIRY_DATA_CHANGED           0x03
++#define ASENCODE_SAVING_PARAMS_NOT_SUPPORTED    0x00
++#define ASENCODE_DIAGNOSTIC_FAILURE             0x80
++#define ASENCODE_INTERNAL_TARGET_FAILURE        0x00
++#define ASENCODE_INVALID_MESSAGE_ERROR          0x00
++#define ASENCODE_LUN_FAILED_SELF_CONFIG         0x00
++#define ASENCODE_OVERLAPPED_COMMAND             0x00
++
++#define BYTE0( x ) ( unsigned char )( x )
++#define BYTE1( x ) ( unsigned char )( x >> 8  )
++#define BYTE2( x ) ( unsigned char )( x >> 16 )
++#define BYTE3( x ) ( unsigned char )( x >> 24 )
++
++/*------------------------------------------------------------------------------
++ *              S T R U C T S / T Y P E D E F S
++ *----------------------------------------------------------------------------*/
++/* SCSI inquiry data */
++struct inquiry_data {
++      unchar inqd_pdt;     /* Peripheral qualifier | Peripheral Device Type  */
++      unchar inqd_dtq;     /* RMB | Device Type Qualifier  */
++      unchar inqd_ver;     /* ISO version | ECMA version | ANSI-approved version */
++      unchar inqd_rdf;     /* AENC | TrmIOP | Response data format */
++      unchar inqd_len;     /* Additional length (n-4) */
++      unchar inqd_pad1[2]; /* Reserved - must be zero */
++      unchar inqd_pad2;    /* RelAdr | WBus32 | WBus16 |  Sync  | Linked |Reserved| CmdQue | SftRe */
++      unchar inqd_vid[8];  /* Vendor ID */
++      unchar inqd_pid[16]; /* Product ID */
++      unchar inqd_prl[4];  /* Product Revision Level */
++};
++
++struct sense_data {
++      unchar error_code;              // 70h (current errors), 71h(deferred errors)
++      unchar valid:1;                 // A valid bit of one indicates that the information 
++                                      // field contains valid information as defined in the
++                                      // SCSI-2 Standard.
++      
++      unchar segment_number;  // Only used for COPY, COMPARE, or COPY AND VERIFY 
++                              // commands
++      
++      unchar sense_key:4;             // Sense Key
++      unchar reserved:1;
++      unchar ILI:1;                   // Incorrect Length Indicator
++      unchar EOM:1;                   // End Of Medium - reserved for random access devices
++      unchar filemark:1;              // Filemark - reserved for random access devices
++      
++      unchar information[4];  // for direct-access devices, contains the unsigned 
++                              // logical block address or residue associated with 
++                              // the sense key 
++      unchar add_sense_len;   // number of additional sense bytes to follow this field
++      unchar cmnd_info[4];    // not used
++      unchar ASC;             // Additional Sense Code
++      unchar ASCQ;            // Additional Sense Code Qualifier
++      unchar FRUC;            // Field Replaceable Unit Code - not used
++      
++      unchar bit_ptr:3;       // indicates which byte of the CDB or parameter data
++                              // was in error
++      unchar BPV:1;           // bit pointer valid (BPV): 1- indicates that 
++                              // the bit_ptr field has valid value
++      unchar reserved2:2;
++      unchar CD:1;            // command data bit: 1- illegal parameter in CDB.
++                              //                   0- illegal parameter in data.
++      unchar SKSV:1;
++      
++      unchar field_ptr[2];    // byte of the CDB or parameter data in error
++};
++
++/*------------------------------------------------------------------------------
++ *              G L O B A L S
++ *----------------------------------------------------------------------------*/
++/*------------------------------------------------------------------------------
++ *              M O D U L E   G L O B A L S
++ *----------------------------------------------------------------------------*/
++static fsadev_t *g_fsa_dev_array[8];  // SCSI Device Instance Pointers
++static struct sense_data g_sense_data[MAXIMUM_NUM_CONTAINERS];
++
++/*------------------------------------------------------------------------------
++ *              F U N C T I O N   P R O T O T Y P E S
++ *----------------------------------------------------------------------------*/
++AAC_STATUS AacHba_OpenAdapter( PVOID AdapterArg);
++AAC_STATUS AacHba_CloseAdapter( PVOID AdapterArg);
++BOOLEAN AacHba_HandleAif( PVOID AdapterArg, PFIB_CONTEXT FibContext);
++BOOLEAN AacHba_AdapterDeviceControl ( PVOID AdapterArg, 
++      PAFA_IOCTL_CMD IoctlCmdPtr, int * ReturnStatus);
++
++void AacHba_CompleteScsi( 
++      Scsi_Cmnd *scsi_cmnd_ptr );
++
++void AacHba_CompleteScsiNoLock( 
++      Scsi_Cmnd *scsi_cmnd_ptr );
++
++static void AacHba_ReadCallback( 
++      void *Context, 
++      PFIB_CONTEXT FibContext, 
++      int FibStatus );
++
++static void AacHba_WriteCallback( 
++      void *Context, 
++      PFIB_CONTEXT FibContext, 
++      int FibStatus );
++
++int AacHba_DoScsiRead(
++      Scsi_Cmnd *scsi_cmnd_ptr,
++      int ContainerId,
++      int wait );
++
++int AacHba_DoScsiWrite(
++      Scsi_Cmnd *scsi_cmnd_ptr,
++      int ContainerId,
++      int wait );
++
++int AacHba_QueryDisk(
++      PVOID AdapterArg,               // CommonExtensionPtr
++      IN PAFA_IOCTL_CMD IoctlCmdPtr );
++
++int AacHba_ForceDeleteDisk(
++      PVOID AdapterArg,               // CommonExtensionPtr
++      IN PAFA_IOCTL_CMD IoctlCmdPtr );
++
++int AacHba_DeleteDisk(
++      PVOID AdapterArg,
++      IN PAFA_IOCTL_CMD IoctlCmdPtr );
++
++void AacHba_DetachAdapter(
++      IN PVOID AdapterArg );
++
++BOOLEAN AacCommDetachAdapter(
++      IN PAFA_COMM_ADAPTER Adapter );
++
++void AacHba_SetSenseData(
++      char * sense_buf,
++      unchar sense_key,
++      unchar sense_code,
++      unchar a_sense_code,
++      unchar incorrect_length,
++      unchar bit_pointer,
++      unsigned field_pointer,
++      unsigned long residue );
++
++static void get_sd_devname(
++      long disknum, 
++      char * buffer);
++
++// Keep these here for the time being - #REVIEW#
++int
++AfaCommAdapterDeviceControl (
++      IN PVOID AdapterArg,
++      IN PAFA_IOCTL_CMD       IoctlCmdPtr
++      );
++
++AAC_STATUS
++AfaCommRegisterNewClassDriver(
++      IN PAFA_COMM_ADAPTER    Adapter,
++      IN PAFA_NEW_CLASS_DRIVER        NewClassDriver,
++      OUT PAFA_NEW_CLASS_DRIVER_RESPONSE NewClassDriverResponse
++      );
++
++void
++SetInqDataStr (int, void *, int);
++/*------------------------------------------------------------------------------
++ *              F U N C T I O N S
++ *----------------------------------------------------------------------------*/
++
++/*------------------------------------------------------------------------------
++      AacHba_ClassDriverInit()
++
++              Setup 'core' class driver to answer ioctl's
++ *----------------------------------------------------------------------------*/
++int AacHba_ClassDriverInit(
++      PCI_MINIPORT_COMMON_EXTENSION * CommonExtensionPtr)
++/*----------------------------------------------------------------------------*/
++{
++    AFA_NEW_CLASS_DRIVER                              NewClassDriver;
++      AFA_NEW_CLASS_DRIVER_RESPONSE           NewClassDriverResponse;
++      PAFA_COMM_ADAPTER                                       Adapter;
++
++      Adapter = (AFA_COMM_ADAPTER *)CommonExtensionPtr->Adapter;
++
++      RtlZeroMemory( &NewClassDriver, sizeof( AFA_NEW_CLASS_DRIVER ) );
++      
++      // ClassDriverExtension is the first argument passed to class driver functions below
++      NewClassDriver.ClassDriverExtension = CommonExtensionPtr;
++      
++      NewClassDriver.OpenAdapter = AacHba_OpenAdapter;
++      NewClassDriver.CloseAdapter = AacHba_CloseAdapter;
++      NewClassDriver.DeviceControl = AacHba_AdapterDeviceControl;
++      NewClassDriver.HandleAif = AacHba_HandleAif;
++      AfaCommRegisterNewClassDriver( Adapter, &NewClassDriver, &NewClassDriverResponse );
++
++      return(0);
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_ProbeContainers()
++
++              Make a list of all containers in the system.
++------------------------------------------------------------------------------*/
++int AacHba_ProbeContainers (PCI_MINIPORT_COMMON_EXTENSION *CommonExtensionPtr)
++{
++      fsadev_t                                                *fsa_dev_ptr;
++      int                                                             Index, Status;
++      PMNTINFO                                                DiskInfo;
++      PMNTINFORESPONSE                                DiskInfoResponse;
++      PFIB_CONTEXT                                    FibContext;
++      AFA_COMM_ADAPTER                                *Adapter;
++      unsigned                                                instance;
++      char                            *bufp;
++      int                             size;
++
++
++      Adapter = ( AFA_COMM_ADAPTER * )CommonExtensionPtr->Adapter;
++      fsa_dev_ptr = &( CommonExtensionPtr->OsDep.fsa_dev );
++      instance = CommonExtensionPtr->OsDep.scsi_host_ptr->unique_id;
++
++      if( !( FibContext = Adapter->CommFuncs.AllocateFib( Adapter ) ) )
++      {
++              cmn_err( CE_WARN, "AacHba_ProbeContainers: AllocateFib failed" );
++              return( STATUS_UNSUCCESSFUL );
++      }
++
++    for ( Index = 0; Index < MAXIMUM_NUM_CONTAINERS; Index++ ) 
++      {
++              Adapter->CommFuncs.InitializeFib( FibContext );
++
++              DiskInfo = ( PMNTINFO )Adapter->CommFuncs.GetFibData( FibContext );
++
++              DiskInfo->Command  = VM_NameServe;
++              DiskInfo->MntCount = Index;
++              DiskInfo->MntType  = FT_FILESYS;
++              
++              Status =  Adapter->CommFuncs.SendFib(   ContainerCommand,
++                                                      FibContext,
++                                                      sizeof(MNTINFO),
++                                                      FsaNormal,
++                                                      TRUE,
++                                                      NULL,
++                                                      TRUE,
++                                                      NULL,
++                                                      NULL );
++              if ( Status ) 
++              {
++                      cmn_err( CE_WARN, "ProbeContainers: SendFIb Failed" );
++                      break;
++              }
++
++              DiskInfoResponse = ( PMNTINFORESPONSE )Adapter->CommFuncs.GetFibData( FibContext );
++              
++
++              if ( ( DiskInfoResponse->Status == ST_OK ) &&
++                      ( DiskInfoResponse->MntTable[0].VolType != CT_NONE ) ) 
++              {
++
++
++                      fsa_dev_ptr->ContainerValid[Index] = TRUE;
++                      fsa_dev_ptr->ContainerType[Index]  = DiskInfoResponse->MntTable[0].VolType;
++                      fsa_dev_ptr->ContainerSize[Index]  = DiskInfoResponse->MntTable[0].Capacity;
++
++                      if (DiskInfoResponse->MntTable[0].ContentState & FSCS_READONLY)
++                              fsa_dev_ptr->ContainerReadOnly[Index] = TRUE;
++              }
++              
++              Adapter->CommFuncs.CompleteFib( FibContext );
++
++              // If there are no more containers, then stop asking.
++              if ((Index + 1) >= DiskInfoResponse->MntRespCount)
++                      break;
++    } // end for()
++
++      Adapter->CommFuncs.FreeFib( FibContext );
++
++      g_fsa_dev_array[instance] = fsa_dev_ptr;
++      return( Status );
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_ProbeContainer()
++
++              Probe a single container.
++ *----------------------------------------------------------------------------*/
++int AacHba_ProbeContainer( 
++      PCI_MINIPORT_COMMON_EXTENSION *CommonExtensionPtr,
++      int ContainerId )
++/*----------------------------------------------------------------------------*/
++{
++      fsadev_t                                                *fsa_dev_ptr;
++    int                                                               Status;
++    PMNTINFO                                          DiskInfo;
++    PMNTINFORESPONSE                          DiskInfoResponse;
++      PFIB_CONTEXT                                    FibContext;
++      AFA_COMM_ADAPTER                                *Adapter;
++      unsigned                                                instance;
++      
++      Adapter = ( AFA_COMM_ADAPTER * )CommonExtensionPtr->Adapter;
++      fsa_dev_ptr = &( CommonExtensionPtr->OsDep.fsa_dev );
++      instance = CommonExtensionPtr->OsDep.scsi_host_ptr->unique_id;
++
++      if( !( FibContext = Adapter->CommFuncs.AllocateFib( Adapter ) ) )
++      {
++              cmn_err( CE_WARN, "AacHba_ProbeContainers: AllocateFib failed" );
++              return( STATUS_UNSUCCESSFUL );
++      }
++
++      Adapter->CommFuncs.InitializeFib( FibContext );
++
++      DiskInfo = ( PMNTINFO )Adapter->CommFuncs.GetFibData( FibContext );
++
++      DiskInfo->Command  = VM_NameServe;
++      DiskInfo->MntCount = ContainerId;
++      DiskInfo->MntType  = FT_FILESYS;
++              
++      Status =  Adapter->CommFuncs.SendFib (ContainerCommand,
++                                            FibContext,
++                                            sizeof(MNTINFO),
++                                            FsaNormal,
++                                            TRUE,
++                                            NULL,
++                                            TRUE,
++                                            NULL,
++                                            NULL );
++      if ( Status ) 
++      {
++              cmn_err( CE_WARN, "ProbeContainers: SendFIb Failed" );
++              Adapter->CommFuncs.CompleteFib( FibContext );
++              Adapter->CommFuncs.FreeFib( FibContext );
++              return( Status );
++      }
++
++      DiskInfoResponse = ( PMNTINFORESPONSE )Adapter->CommFuncs.GetFibData( FibContext );
++              
++
++      if ( ( DiskInfoResponse->Status == ST_OK ) &&
++              ( DiskInfoResponse->MntTable[0].VolType != CT_NONE ) ) 
++      {
++
++              fsa_dev_ptr->ContainerValid[ContainerId] = TRUE;
++              fsa_dev_ptr->ContainerType[ContainerId]  = DiskInfoResponse->MntTable[0].VolType;
++              fsa_dev_ptr->ContainerSize[ContainerId]  = DiskInfoResponse->MntTable[0].Capacity;
++              if (DiskInfoResponse->MntTable[0].ContentState & FSCS_READONLY)
++                      fsa_dev_ptr->ContainerReadOnly[ContainerId] = TRUE;
++      }
++              
++      Adapter->CommFuncs.CompleteFib( FibContext );
++      Adapter->CommFuncs.FreeFib( FibContext );
++
++      return( Status );
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_CompleteScsi()
++
++              Call SCSI completion routine after acquiring io_request_lock
++
++      Preconditions:
++      Postconditions:
++ *----------------------------------------------------------------------------*/
++void AacHba_CompleteScsi( 
++      Scsi_Cmnd *scsi_cmnd_ptr )
++{
++      unsigned long cpu_flags;
++
++      spin_lock_irqsave( &io_request_lock, cpu_flags );
++      scsi_cmnd_ptr->scsi_done( scsi_cmnd_ptr );
++      spin_unlock_irqrestore( &io_request_lock, cpu_flags );
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_CompleteScsiNoLock()
++
++              Call SCSI completion routine
++
++      Preconditions:
++      Postconditions:
++ *----------------------------------------------------------------------------*/
++void AacHba_CompleteScsiNoLock( 
++      Scsi_Cmnd *scsi_cmnd_ptr )
++{
++      scsi_cmnd_ptr->scsi_done( scsi_cmnd_ptr );
++}
++
++/*------------------------------------------------------------------------------
++      AacHba_DoScsiCmd()
++
++              Process SCSI command
++
++      Preconditions:
++      Postconditions:
++              Returns 0 on success, -1 on failure
++ *----------------------------------------------------------------------------*/
++int AacHba_DoScsiCmd(
++      Scsi_Cmnd *scsi_cmnd_ptr,
++      int wait )
++{
++      int                     ContainerId = 0;
++      fsadev_t        *fsa_dev_ptr;
++      PCI_MINIPORT_COMMON_EXTENSION   *CommonExtensionPtr;
++      int MiniPortIndex;
++
++      CommonExtensionPtr = ( PCI_MINIPORT_COMMON_EXTENSION * )( scsi_cmnd_ptr->host->hostdata );
++      MiniPortIndex = CommonExtensionPtr->OsDep.MiniPortIndex;
++
++      fsa_dev_ptr = g_fsa_dev_array[ scsi_cmnd_ptr->host->unique_id ];
++
++      // If the bus, target or lun is out of range, return fail
++      // Test does not apply to ID 16, the pseudo id for the controller itself.
++      if ( scsi_cmnd_ptr->target != scsi_cmnd_ptr->host->this_id ) 
++      {
++              if( ( scsi_cmnd_ptr->channel > 0 ) ||
++                      ( scsi_cmnd_ptr->target > 15 ) || 
++                      ( scsi_cmnd_ptr->lun > 7 ) )
++              {
++                      cmn_err( CE_DEBUG, "The bus, target or lun is out of range = %d, %d, %d",
++                              scsi_cmnd_ptr->channel,
++                              scsi_cmnd_ptr->target, 
++                              scsi_cmnd_ptr->lun );
++                      scsi_cmnd_ptr->result = DID_BAD_TARGET << 16;
++
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++
++                      return ( -1 );
++              }
++
++              ContainerId = TARGET_LUN_TO_CONTAINER( scsi_cmnd_ptr->target, scsi_cmnd_ptr->lun );
++
++
++              // If the target container doesn't exist, it may have been newly created
++              if( fsa_dev_ptr->ContainerValid[ContainerId] == 0 )
++              {       
++                      switch( scsi_cmnd_ptr->cmnd[0] )
++                      {
++                              case SS_INQUIR:
++                              case SS_RDCAP:
++                              case SS_TEST:
++                                      spin_unlock_irq( &io_request_lock );
++                                      AacHba_ProbeContainer( CommonExtensionPtr, ContainerId );               
++                                      spin_lock_irq( &io_request_lock );
++                              default:
++                                      break;
++                      }
++              }
++
++              // If the target container still doesn't exist, return failure
++              if( fsa_dev_ptr->ContainerValid[ContainerId] == 0 )
++              {       
++
++                      scsi_cmnd_ptr->result = DID_BAD_TARGET << 16;
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++
++                      return ( -1 );
++              }
++      }
++      else    // the command is for the controller itself
++              if( ( scsi_cmnd_ptr->cmnd[0] != SS_INQUIR )     && // only INQUIRY & TUR cmnd supported for controller 
++                      ( scsi_cmnd_ptr->cmnd[0] != SS_TEST ) )
++              {
++                      cmn_err( CE_WARN, "Only INQUIRY & TUR command supported for controller, rcvd = 0x%x", 
++                              scsi_cmnd_ptr->cmnd[0] );
++
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
++                      
++                      AacHba_SetSenseData( (char *)&g_sense_data[ ContainerId ],
++                              SENKEY_ILLEGAL, SENCODE_INVALID_COMMAND, ASENCODE_INVALID_COMMAND, 
++                              0, 0, 0, 0 );
++
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++
++                      return ( -1 );
++              }
++
++      // Handle commands here that don't really require going out to the adapter
++      switch ( scsi_cmnd_ptr->cmnd[0] ) 
++      {
++              case SS_INQUIR:
++              {
++                      struct inquiry_data *inq_data_ptr;
++              
++                      cmn_err( CE_DEBUG, "INQUIRY command, ID: %d", scsi_cmnd_ptr->target );
++                      inq_data_ptr = ( struct inquiry_data * )scsi_cmnd_ptr->request_buffer;
++                      bzero( inq_data_ptr, sizeof( struct inquiry_data ) );
++
++                      inq_data_ptr->inqd_ver = 2;             // claim compliance to SCSI-2
++
++                      inq_data_ptr->inqd_dtq = 0x80;  // set RMB bit to one indicating 
++                                                                                      // that the medium is removable
++                      inq_data_ptr->inqd_rdf = 2;             // A response data format value of
++                                                                                      // two indicates that the data shall 
++                                                                                      // be in the format specified in SCSI-2
++                      inq_data_ptr->inqd_len = 31;
++
++                      // Set the Vendor, Product, and Revision Level see: <vendor>.c i.e. aac.c
++                      SetInqDataStr(  MiniPortIndex, 
++                                                      (void *)(inq_data_ptr->inqd_vid),
++                                                      fsa_dev_ptr->ContainerType[ContainerId]);
++
++                      if ( scsi_cmnd_ptr->target == scsi_cmnd_ptr->host->this_id )
++                              inq_data_ptr->inqd_pdt = INQD_PDT_PROC; // Processor device
++                      else
++                              inq_data_ptr->inqd_pdt = INQD_PDT_DA;   // Direct/random access device
++
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++
++                      return ( 0 );
++              }
++
++              case SS_RDCAP:
++              {
++                      int capacity;
++                      char *cp;
++
++                      cmn_err( CE_DEBUG, "READ CAPACITY command" );
++                      capacity = fsa_dev_ptr->ContainerSize[ContainerId] - 1;
++                      cp = scsi_cmnd_ptr->request_buffer;
++                      cp[0] = ( capacity >> 24 ) & 0xff;
++                      cp[1] = ( capacity >> 16 ) & 0xff;
++                      cp[2] = ( capacity >>  8 ) & 0xff;
++                      cp[3] = ( capacity >>  0 ) & 0xff;
++                      cp[4] = 0;
++                      cp[5] = 0;
++                      cp[6] = 2;
++                      cp[7] = 0;
++      
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++
++                      return ( 0 );
++              }
++
++              case SS_MODESEN:
++              {
++                      char *mode_buf;
++
++                      cmn_err( CE_DEBUG, "MODE SENSE command" );
++                      mode_buf = scsi_cmnd_ptr->request_buffer;
++                      mode_buf[0] = 0;        // Mode data length (MSB)
++                      mode_buf[1] = 6;        // Mode data length (LSB)
++                      mode_buf[2] = 0;        // Medium type - default
++                      mode_buf[3] = 0;        // Device-specific param, bit 8: 0/1 = write enabled/protected
++                      mode_buf[4] = 0;        // reserved
++                      mode_buf[5] = 0;        // reserved
++                      mode_buf[6] = 0;        // Block descriptor length (MSB)
++                      mode_buf[7] = 0;        // Block descriptor length (LSB)
++      
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++
++                      return ( 0 );
++              }
++
++
++              // These commands are all No-Ops
++              case SS_TEST:
++                      cmn_err( CE_DEBUG, "TEST UNIT READY command" );
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++                      return ( 0 );
++
++              case SS_REQSEN:
++                      cmn_err( CE_DEBUG, "REQUEST SENSE command" );
++
++                      memcpy( scsi_cmnd_ptr->sense_buffer, &g_sense_data[ContainerId],
++                              sizeof( struct sense_data ) );
++                      bzero( &g_sense_data[ContainerId], sizeof( struct sense_data ) );
++
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++                      return ( 0 );
++
++              case SS_LOCK:
++                      cmn_err(CE_DEBUG, "LOCK command");
++
++                      if( scsi_cmnd_ptr->cmnd[4] )
++                              fsa_dev_ptr->ContainerLocked[ContainerId] = 1;
++                      else
++                              fsa_dev_ptr->ContainerLocked[ContainerId] = 0;
++
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++                      return ( 0 );
++
++              case SS_RESERV:
++                      cmn_err( CE_DEBUG, "RESERVE command" );
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++                      return ( 0 );
++
++              case SS_RELES:
++                      cmn_err( CE_DEBUG, "RELEASE command" );
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++                      return ( 0 );
++
++              case SS_REZERO:
++                      cmn_err( CE_DEBUG, "REZERO command" );
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++                      return ( 0 );
++
++              case SS_REASGN:
++                      cmn_err( CE_DEBUG, "REASSIGN command" );
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++                      return ( 0 );
++
++              case SS_SEEK:
++                      cmn_err( CE_DEBUG, "SEEK command" );
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++                      return ( 0 );
++
++              case SS_ST_SP:
++                      cmn_err( CE_DEBUG, "START/STOP command" );
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++                      return ( 0 );
++      }
++
++      switch ( scsi_cmnd_ptr->cmnd[0] ) 
++      {
++              case SS_READ:
++              case SM_READ:
++                      // Hack to keep track of ordinal number of the device that corresponds
++                      // to a container. Needed to convert containers to /dev/sd device names
++                      fsa_dev_ptr->ContainerDevNo[ContainerId] = 
++                              DEVICE_NR( scsi_cmnd_ptr->request.rq_dev );
++
++                      return( AacHba_DoScsiRead( scsi_cmnd_ptr, ContainerId,  wait ) );
++                      break;
++
++              case SS_WRITE:
++              case SM_WRITE:
++
++                      return( AacHba_DoScsiWrite( scsi_cmnd_ptr, ContainerId,  wait ) );
++                      break;
++      }
++      //
++      // Unhandled commands
++      //
++      cmn_err( CE_WARN, "Unhandled SCSI Command: 0x%x", scsi_cmnd_ptr->cmnd[0] );
++      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
++
++      AacHba_SetSenseData( ( char * )&g_sense_data[ ContainerId ],
++              SENKEY_ILLEGAL, SENCODE_INVALID_COMMAND, ASENCODE_INVALID_COMMAND, 
++              0, 0, 0, 0 );
++
++      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++      return ( -1 );
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_DoScsiRead()
++              
++              Handles SCSI READ requests
++
++      Preconditions:
++      Postconditions:
++              Returns 0 on success, -1 on failure
++ *----------------------------------------------------------------------------*/
++int AacHba_DoScsiRead(
++      Scsi_Cmnd *scsi_cmnd_ptr,
++      int ContainerId,
++      int wait )
++/*----------------------------------------------------------------------------*/
++{
++      u_long                          lba;
++      u_long                          count;
++      u_long                          byte_count;
++      int                                     Status;
++
++      PBLOCKREAD                      BlockReadDisk;
++      PBLOCKREADRESPONSE      BlockReadResponse;
++      uint16_t                        FibSize;
++      PCI_MINIPORT_COMMON_EXTENSION   *CommonExtension;
++      AFA_COMM_ADAPTER                                *Adapter;
++      PFIB_CONTEXT                                    cmd_fibcontext;
++
++      CommonExtension = ( PCI_MINIPORT_COMMON_EXTENSION * )( scsi_cmnd_ptr->host->hostdata );
++      Adapter         = ( AFA_COMM_ADAPTER * )CommonExtension->Adapter;
++
++      // Get block address and transfer length
++      if ( scsi_cmnd_ptr->cmnd[0] == SS_READ ) // 6 byte command
++      {
++              cmn_err( CE_DEBUG, "aachba: received a read(6) command on target %d", ContainerId );
++
++              lba = ( ( scsi_cmnd_ptr->cmnd[1] & 0x1F ) << 16 ) | 
++                      ( scsi_cmnd_ptr->cmnd[2] << 8 ) |
++                      scsi_cmnd_ptr->cmnd[3];
++              count = scsi_cmnd_ptr->cmnd[4];
++
++              if ( count == 0 )
++                      count = 256;
++      } 
++      else 
++      {               
++              cmn_err( CE_DEBUG, "aachba: received a read(10) command on target %d", ContainerId );
++              
++              lba = ( scsi_cmnd_ptr->cmnd[2] << 24 ) | ( scsi_cmnd_ptr->cmnd[3] << 16 ) | 
++                      ( scsi_cmnd_ptr->cmnd[4] << 8 ) | scsi_cmnd_ptr->cmnd[5];
++
++              count = ( scsi_cmnd_ptr->cmnd[7] << 8 ) | scsi_cmnd_ptr->cmnd[8];
++      }       
++      cmn_err( CE_DEBUG, "AacHba_DoScsiRead[cpu %d]: lba = %lu, t = %ld", smp_processor_id(), lba, jiffies );
++
++      //-------------------------------------------------------------------------
++      // Alocate and initialize a Fib
++      //  Setup BlockRead command
++      if( !( cmd_fibcontext = Adapter->CommFuncs.AllocateFib( Adapter ) ) )
++      {
++              cmn_err( CE_WARN, "AacHba_DoScsiRead: AllocateFib failed\n" );
++              scsi_cmnd_ptr->result = DID_ERROR << 16;
++              AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++              return ( -1 );
++      }
++
++    Adapter->CommFuncs.InitializeFib( cmd_fibcontext );
++
++      BlockReadDisk = ( PBLOCKREAD )Adapter->CommFuncs.GetFibData( cmd_fibcontext );
++      BlockReadDisk->Command     = VM_CtBlockRead;
++      BlockReadDisk->ContainerId = ContainerId;
++      BlockReadDisk->BlockNumber = lba;
++      BlockReadDisk->ByteCount   = count * 512;
++      BlockReadDisk->SgMap.SgCount = 1;
++
++      if( BlockReadDisk->ByteCount > ( 64 * 1024 ) )
++      {
++              cmn_err( CE_WARN, "AacHba_DoScsiRead: READ request is larger than 64K" );
++              scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
++
++              AacHba_SetSenseData( ( char * )&g_sense_data[ ContainerId ],
++                              SENKEY_ILLEGAL, SENCODE_INVALID_CDB_FIELD, ASENCODE_INVALID_CDB_FIELD, 
++                              0, 0, 7, 0 );
++
++              goto err_return;
++      }
++
++      //-------------------------------------------------------------------------
++      // Build Scatter/Gather list
++      //
++      if ( scsi_cmnd_ptr->use_sg )    // use scatter/gather list
++      {
++              struct scatterlist *scatterlist_ptr;
++              int segment;
++              
++              scatterlist_ptr = ( struct scatterlist * )scsi_cmnd_ptr->request_buffer;
++
++              byte_count = 0;
++              for( segment = 0; segment< scsi_cmnd_ptr->use_sg; segment++ ) 
++              {
++                      BlockReadDisk->SgMap.SgEntry[segment].SgAddress = 
++                              ( void * )OsVirtToPhys( scatterlist_ptr[segment].address );
++                      BlockReadDisk->SgMap.SgEntry[segment].SgByteCount = 
++                              scatterlist_ptr[segment].length;
++
++#ifdef DEBUG_SGBUFFER
++                      memset( scatterlist_ptr[segment].address, 0xa5, 
++                              scatterlist_ptr[segment].length );
++#endif
++
++                      byte_count += scatterlist_ptr[segment].length;
++                      
++                      if( BlockReadDisk->SgMap.SgEntry[segment].SgByteCount > ( 64 * 1024 ) )
++                      {
++                              cmn_err( CE_WARN, "AacHba_DoScsiRead: Segment byte count is larger than 64K" );
++                              scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
++
++                              AacHba_SetSenseData( ( char * )&g_sense_data[ ContainerId ],
++                                      SENKEY_ILLEGAL, SENCODE_INVALID_CDB_FIELD, ASENCODE_INVALID_CDB_FIELD, 
++                                      0, 0, 7, 0 );
++
++                              goto err_return;
++                      }
++                      /*
++                      cmn_err(CE_DEBUG, "SgEntry[%d].SgAddress = 0x%x, Byte count = 0x%x", 
++                                      segment,
++                                      BlockReadDisk->SgMap.SgEntry[segment].SgAddress,
++                                      BlockReadDisk->SgMap.SgEntry[segment].SgByteCount);
++                      */
++              }
++              BlockReadDisk->SgMap.SgCount = scsi_cmnd_ptr->use_sg;
++
++              if( BlockReadDisk->SgMap.SgCount > MAX_DRIVER_SG_SEGMENT_COUNT ) 
++              {
++                      cmn_err( CE_WARN, "AacHba_DoScsiRead: READ request with SgCount > %d", 
++                              MAX_DRIVER_SG_SEGMENT_COUNT );
++                      scsi_cmnd_ptr->result = DID_ERROR << 16;
++                      goto err_return;
++              }
++      }       
++      else            // one piece of contiguous phys mem
++      {
++              BlockReadDisk->SgMap.SgEntry[0].SgAddress = 
++                      ( void * )OsVirtToPhys( scsi_cmnd_ptr->request_buffer );
++              BlockReadDisk->SgMap.SgEntry[0].SgByteCount = scsi_cmnd_ptr->request_bufflen;
++
++              byte_count = scsi_cmnd_ptr->request_bufflen;
++
++              if( BlockReadDisk->SgMap.SgEntry[0].SgByteCount > ( 64 * 1024 ) )
++              {
++                      cmn_err( CE_WARN, "AacHba_DoScsiRead: Single segment byte count is larger than 64K" );
++                      cmn_err( CE_WARN, "AacHba_DoScsiRead: ByteCount: %d", BlockReadDisk->ByteCount);
++                      cmn_err( CE_WARN, "AacHba_DoScsiRead: SG ELEMENTS: %d", scsi_cmnd_ptr->use_sg);
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
++
++                      AacHba_SetSenseData( ( char * )&g_sense_data[ ContainerId ],
++                              SENKEY_ILLEGAL, SENCODE_INVALID_CDB_FIELD, ASENCODE_INVALID_CDB_FIELD, 
++                              0, 0, 7, 0 );
++
++                      goto err_return;
++              }
++      }
++
++      if( byte_count != BlockReadDisk->ByteCount )
++              cmn_err( CE_WARN, "AacHba_DoScsiRead: byte_count != BlockReadDisk->ByteCount" );
++
++      //-------------------------------------------------------------------------
++      // Now send the Fib to the adapter
++      //
++      FibSize = sizeof( BLOCKREAD ) + ( ( BlockReadDisk->SgMap.SgCount - 1 ) * sizeof( SGENTRY ) );
++
++      if( wait ) 
++      {
++              // This path shouldn't ever get executed with the current driver
++              Status = Adapter->CommFuncs.SendFib( ContainerCommand,
++                                                                                       cmd_fibcontext,
++                                                                                       FibSize,
++                                                                                       FsaNormal,
++                                                                                       TRUE,
++                                                                                       NULL,
++                                                                                       TRUE,
++                                                                                       NULL,
++                                                                                       NULL);
++
++              BlockReadResponse = ( PBLOCKREADRESPONSE )
++                      Adapter->CommFuncs.GetFibData( cmd_fibcontext );        
++
++              Adapter->CommFuncs.CompleteFib( cmd_fibcontext );
++              Adapter->CommFuncs.FreeFib( cmd_fibcontext );
++              
++              if( BlockReadResponse->Status != ST_OK )
++              {
++                      cmn_err( CE_WARN, "AacHba_DoScsiRead: BlockReadCommand failed with status: %d", 
++                              BlockReadResponse->Status );
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
++
++                      AacHba_SetSenseData( ( char * )&g_sense_data[ ContainerId ],
++                              SENKEY_HW_ERR, SENCODE_INTERNAL_TARGET_FAILURE, ASENCODE_INTERNAL_TARGET_FAILURE, 
++                              0, 0, 0, 0 );
++
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++                      return ( -1 );
++              }
++              else
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
++
++              AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++              return ( 0 );
++      } 
++      else 
++      {
++              Status = Adapter->CommFuncs.SendFib( ContainerCommand,
++                                                                                       cmd_fibcontext,
++                                                                                       FibSize,
++                                                                                       FsaNormal,
++                                                                                       FALSE,
++                                                                                       NULL,
++                                                                                       TRUE,
++                                                                                       ( PFIB_CALLBACK )AacHba_ReadCallback,
++                                                                                       ( void *)scsi_cmnd_ptr );
++
++              // Check that the command queued to the controller
++              if (Status != STATUS_PENDING) { 
++                      cmn_err( CE_WARN, "AacHba_DoScsiRead: SendFib failed with status: %d\n", 
++                                      Status);
++
++                      // For some reason, the Fib didn't queue, return QUEUE_FULL
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | QUEUE_FULL ;
++                      goto err_return;
++              }
++
++              // don't call done func here
++              return ( 0 );
++      }
++
++err_return:
++      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++
++      Adapter->CommFuncs.CompleteFib( cmd_fibcontext );
++      Adapter->CommFuncs.FreeFib( cmd_fibcontext );
++
++      return ( -1 );
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_DoScsiWrite()
++
++              Handles SCSI WRITE requests
++      
++      Preconditions:
++      Postconditions:
++              Returns 0 on success, -1 on failure
++ *----------------------------------------------------------------------------*/
++int AacHba_DoScsiWrite(
++      Scsi_Cmnd *scsi_cmnd_ptr,
++      int ContainerId,
++      int wait )
++/*----------------------------------------------------------------------------*/
++{
++      u_long                          lba;
++      u_long                          count;
++      u_long                          byte_count;
++      int                                     Status;
++
++      PBLOCKWRITE                                             BlockWriteDisk;
++      PBLOCKWRITERESPONSE                             BlockWriteResponse;
++      uint16_t                                                FibSize;
++      PCI_MINIPORT_COMMON_EXTENSION   *CommonExtension;
++      AFA_COMM_ADAPTER                                *Adapter;
++      PFIB_CONTEXT                                    cmd_fibcontext;
++
++      CommonExtension = ( PCI_MINIPORT_COMMON_EXTENSION * )( scsi_cmnd_ptr->host->hostdata );
++      Adapter         = ( AFA_COMM_ADAPTER * )CommonExtension->Adapter;
++
++      // Get block address and transfer length
++      if ( scsi_cmnd_ptr->cmnd[0] == SS_WRITE ) // 6 byte command
++      {
++              lba = ( ( scsi_cmnd_ptr->cmnd[1] & 0x1F ) << 16 ) | 
++                      ( scsi_cmnd_ptr->cmnd[2] << 8 ) |
++                      scsi_cmnd_ptr->cmnd[3];
++              count = scsi_cmnd_ptr->cmnd[4];
++
++              if ( count == 0 )
++                      count = 256;
++      } 
++      else 
++      {               
++              cmn_err( CE_DEBUG, "aachba: received a write(10) command on target %d", ContainerId );
++              
++              lba = ( scsi_cmnd_ptr->cmnd[2] << 24 ) | ( scsi_cmnd_ptr->cmnd[3] << 16 ) | 
++                      ( scsi_cmnd_ptr->cmnd[4] << 8 ) | scsi_cmnd_ptr->cmnd[5];
++
++              count = ( scsi_cmnd_ptr->cmnd[7] << 8 ) | scsi_cmnd_ptr->cmnd[8];
++
++      }       
++      cmn_err( CE_DEBUG, "AacHba_DoScsiWrite[cpu %d]: lba = %lu, t = %ld", smp_processor_id(), lba, jiffies );
++
++      //-------------------------------------------------------------------------
++      // Alocate and initialize a Fib
++      //  Setup BlockWrite command
++      if( !( cmd_fibcontext = Adapter->CommFuncs.AllocateFib( Adapter ) ) ) 
++      {
++              cmn_err( CE_WARN, "AacHba_DoScsiWrite: AllocateFib failed\n" );
++              scsi_cmnd_ptr->result = DID_ERROR << 16;
++              AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++              return ( -1 );
++      }
++
++    Adapter->CommFuncs.InitializeFib( cmd_fibcontext );
++
++      BlockWriteDisk = (PBLOCKWRITE) Adapter->CommFuncs.GetFibData( cmd_fibcontext );
++      BlockWriteDisk->Command     = VM_CtBlockWrite;
++      BlockWriteDisk->ContainerId = ContainerId;
++      BlockWriteDisk->BlockNumber = lba;
++      BlockWriteDisk->ByteCount   = count * 512;
++      BlockWriteDisk->SgMap.SgCount = 1;
++
++
++      if ( BlockWriteDisk->ByteCount > ( 64 * 1024 ) )
++        {
++                struct scatterlist *scatterlist_ptr;
++                int segment;
++                scatterlist_ptr = (struct scatterlist *)scsi_cmnd_ptr->request_buffer;
++
++                cmn_err( CE_WARN, "\n");
++                cmn_err( CE_WARN, "AacHba_DoScsiWrite: WRITE request is larger than 64K");
++                cmn_err( CE_WARN, "AacHba_DoScsiWrite: ByteCount: %d", BlockWriteDisk->ByteCount);
++/*              cmn_err( CE_WARN, "AacHba_DoScsiWrite: SG ELEMENTS: %d", scsi_cmnd_ptr->use_sg); */
++/*              cmn_err( CE_WARN, "Dump SG Element Size..."); */
++/*              for( segment = 0; segment < scsi_cmnd_ptr->use_sg; segment++ )  */
++/*              { */
++/*                      cmn_err (CE_WARN, "SG Segment %d: %d", segment, scatterlist_ptr[segment].length); */
++/*              } */
++/*              cmn_err (CE_WARN, "\n"); */
++
++              scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
++
++              AacHba_SetSenseData( ( char * )&g_sense_data[ ContainerId ],
++                              SENKEY_ILLEGAL, SENCODE_INVALID_CDB_FIELD, ASENCODE_INVALID_CDB_FIELD, 
++                              0, 0, 7, 0 );
++
++              goto err_return;
++      }
++
++      //-------------------------------------------------------------------------
++      // Build Scatter/Gather list
++      //
++      if ( scsi_cmnd_ptr->use_sg )    // use scatter/gather list
++      {
++              struct scatterlist *scatterlist_ptr;
++              int segment;
++              
++              scatterlist_ptr = ( struct scatterlist * )scsi_cmnd_ptr->request_buffer;
++
++              byte_count = 0;
++              for( segment = 0; segment< scsi_cmnd_ptr->use_sg; segment++ ) 
++              {
++                      BlockWriteDisk->SgMap.SgEntry[segment].SgAddress = 
++                              ( HOSTADDRESS )OsVirtToPhys( scatterlist_ptr[segment].address );
++                      BlockWriteDisk->SgMap.SgEntry[segment].SgByteCount = 
++                              scatterlist_ptr[segment].length;
++                      
++                      byte_count += scatterlist_ptr[segment].length;
++
++                      if ( BlockWriteDisk->SgMap.SgEntry[segment].SgByteCount > ( 64 * 1024 ) )
++                      {
++                              cmn_err( CE_WARN, "AacHba_DoScsiWrite: Segment byte count is larger than 64K" );
++                              scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
++
++                              AacHba_SetSenseData( ( char * )&g_sense_data[ ContainerId ],
++                                      SENKEY_ILLEGAL, SENCODE_INVALID_CDB_FIELD, ASENCODE_INVALID_CDB_FIELD, 
++                                      0, 0, 7, 0 );
++
++                              goto err_return;
++                      }
++
++                      /*
++                      cmn_err(CE_DEBUG, "SgEntry[%d].SgAddress = 0x%x, Byte count = 0x%x", 
++                                      segment,
++                                      BlockWriteDisk->SgMap.SgEntry[segment].SgAddress,
++                                      BlockWriteDisk->SgMap.SgEntry[segment].SgByteCount); 
++                      */
++              }
++              BlockWriteDisk->SgMap.SgCount = scsi_cmnd_ptr->use_sg;
++
++              if( BlockWriteDisk->SgMap.SgCount > MAX_DRIVER_SG_SEGMENT_COUNT ) 
++              {
++                      cmn_err( CE_WARN, "AacHba_DoScsiWrite: WRITE request with SgCount > %d", 
++                              MAX_DRIVER_SG_SEGMENT_COUNT );
++                      scsi_cmnd_ptr->result = DID_ERROR << 16;
++                      goto err_return;
++              }
++      } 
++      else            // one piece of contiguous phys mem
++      {
++              BlockWriteDisk->SgMap.SgEntry[0].SgAddress = 
++                      ( HOSTADDRESS )OsVirtToPhys( scsi_cmnd_ptr->request_buffer );
++              BlockWriteDisk->SgMap.SgEntry[0].SgByteCount = scsi_cmnd_ptr->request_bufflen;
++
++              byte_count = scsi_cmnd_ptr->request_bufflen;
++
++              if ( BlockWriteDisk->SgMap.SgEntry[0].SgByteCount > ( 64 * 1024 ) )
++              {
++                      cmn_err( CE_WARN, "AacHba_DoScsiWrite: Single segment byte count is larger than 64K" );
++
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
++                      AacHba_SetSenseData( ( char * )&g_sense_data[ ContainerId ],
++                              SENKEY_ILLEGAL, SENCODE_INVALID_CDB_FIELD, ASENCODE_INVALID_CDB_FIELD, 
++                              0, 0, 7, 0 );
++
++                      goto err_return;
++              }
++      }
++
++      if( byte_count != BlockWriteDisk->ByteCount )
++        cmn_err( CE_WARN, "AacHba_DoScsiWrite: byte_count != BlockReadDisk->ByteCount" );
++
++      //-------------------------------------------------------------------------
++      // Now send the Fib to the adapter
++      //
++      FibSize = sizeof( BLOCKWRITE ) + ( ( BlockWriteDisk->SgMap.SgCount - 1 ) * sizeof( SGENTRY ) );
++
++      if( wait ) 
++      {
++              // This path shouldn't ever get executed with the current driver
++              Status = Adapter->CommFuncs.SendFib( ContainerCommand,
++                                                                                       cmd_fibcontext,
++                                                                                       FibSize,
++                                                                                       FsaNormal,
++                                                                                       TRUE,
++                                                                                       NULL,
++                                                                                       TRUE,
++                                                                                       NULL,
++                                                                                       NULL );
++
++              BlockWriteResponse = ( PBLOCKWRITERESPONSE ) 
++                      Adapter->CommFuncs.GetFibData( cmd_fibcontext );        
++
++              Adapter->CommFuncs.CompleteFib(  cmd_fibcontext );
++              Adapter->CommFuncs.FreeFib(  cmd_fibcontext );
++
++              if( BlockWriteResponse->Status != ST_OK )
++              {
++                      cmn_err( CE_WARN, "AacHba_DoScsiWrite: BlockWriteCommand failed with status: %d\n", 
++                              BlockWriteResponse->Status );
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;;
++                      AacHba_SetSenseData( ( char * )&g_sense_data[ ContainerId ],
++                              SENKEY_HW_ERR, SENCODE_INTERNAL_TARGET_FAILURE, ASENCODE_INTERNAL_TARGET_FAILURE, 
++                              0, 0, 0, 0 );
++                      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++                      return ( -1 );
++              }
++              else
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
++
++              AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++              return ( 0 );
++      } 
++      else 
++      {
++              Status = Adapter->CommFuncs.SendFib( ContainerCommand,
++                                                                                       cmd_fibcontext,
++                                                                                       FibSize,
++                                                                                       FsaNormal,
++                                                                                       FALSE,
++                                                                                       NULL,
++                                                                                       TRUE,
++                                                                                       ( PFIB_CALLBACK )AacHba_WriteCallback,
++                                                                                       ( void * )scsi_cmnd_ptr );
++
++              // Check that the command queued to the controller
++              if (Status != STATUS_PENDING) { 
++                      cmn_err( CE_WARN, "AacHba_DoScsiWrite: SendFib failed with status: %d\n", 
++                                      Status);
++
++                      // For some reason, the Fib didn't queue, return QUEUE_FULL
++                      scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | QUEUE_FULL ;
++                      goto err_return;
++              }
++
++              // don't call done func here - it should be called by the WriteCallback
++              return ( 0 );
++      }
++
++err_return:
++      AacHba_CompleteScsiNoLock( scsi_cmnd_ptr );
++
++      Adapter->CommFuncs.CompleteFib( cmd_fibcontext );
++      Adapter->CommFuncs.FreeFib( cmd_fibcontext );
++
++      return ( -1 );
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_ReadCallback()
++ *----------------------------------------------------------------------------*/
++void AacHba_ReadCallback(  
++      VOID                    *Context,
++      PFIB_CONTEXT    FibContext,
++      int                             FibStatus )
++/*----------------------------------------------------------------------------*/
++{
++      PCI_MINIPORT_COMMON_EXTENSION   *CommonExtension;
++      AFA_COMM_ADAPTER                                *Adapter;
++      BLOCKREADRESPONSE                               *BlockReadResponse;
++      Scsi_Cmnd * scsi_cmnd_ptr;
++      u_long                                                  lba;
++      int                     ContainerId;
++
++      scsi_cmnd_ptr = ( Scsi_Cmnd * )Context;
++
++      CommonExtension = ( PCI_MINIPORT_COMMON_EXTENSION * )( scsi_cmnd_ptr->host->hostdata );
++      Adapter         = ( AFA_COMM_ADAPTER * )CommonExtension->Adapter;
++
++      ContainerId = TARGET_LUN_TO_CONTAINER( scsi_cmnd_ptr->target, scsi_cmnd_ptr->lun );
++      
++      lba = ( ( scsi_cmnd_ptr->cmnd[1] & 0x1F ) << 16 ) | 
++                      ( scsi_cmnd_ptr->cmnd[2] << 8 ) |
++                      scsi_cmnd_ptr->cmnd[3];
++      cmn_err( CE_DEBUG, "AacHba_ReadCallback[cpu %d]: lba = %ld, t = %ld", smp_processor_id(), lba, jiffies );
++
++      if( FibContext == 0 ) 
++      {
++              cmn_err( CE_WARN, "AacHba_ReadCallback: no fib context" );
++              scsi_cmnd_ptr->result = DID_ERROR << 16;
++              AacHba_CompleteScsi( scsi_cmnd_ptr );
++              return;
++      }
++
++    BlockReadResponse = ( PBLOCKREADRESPONSE )Adapter->CommFuncs.GetFibData( FibContext );
++
++      if ( BlockReadResponse->Status == ST_OK ) 
++              scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
++      else 
++      {
++              cmn_err( CE_WARN, "AacHba_ReadCallback: read failed, status = %d\n", 
++                      BlockReadResponse->Status );
++              scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
++              AacHba_SetSenseData( ( char * )&g_sense_data[ ContainerId ],
++                      SENKEY_HW_ERR, SENCODE_INTERNAL_TARGET_FAILURE, ASENCODE_INTERNAL_TARGET_FAILURE, 
++                      0, 0, 0, 0 );
++      }
++
++#ifdef DEBUG_SGBUFFER
++      if ( scsi_cmnd_ptr->use_sg )    // use scatter/gather list
++      {
++              struct scatterlist *scatterlist_ptr;
++              int i, segment, count;
++              char *ptr;
++              
++              scatterlist_ptr = ( struct scatterlist * )scsi_cmnd_ptr->request_buffer;
++
++              for( segment = 0; segment < scsi_cmnd_ptr->use_sg; segment++ ) 
++              {
++                      count = 0;
++                      ptr = scatterlist_ptr[segment].address;
++                      for( i = 0; i < scatterlist_ptr[segment].length; i++ )
++                      {
++                              if( *( ptr++ ) == 0xa5 )
++                                      count++;
++                      }
++                      if( count == scatterlist_ptr[segment].length )
++                              cmn_err( CE_WARN, "AacHba_ReadCallback: segment %d not filled", segment );
++
++              }
++      }
++#endif
++
++      Adapter->CommFuncs.CompleteFib( FibContext );
++      Adapter->CommFuncs.FreeFib( FibContext );
++
++      AacHba_CompleteScsi( scsi_cmnd_ptr );
++}
++
++/*------------------------------------------------------------------------------
++      AacHba_WriteCallback()
++ *----------------------------------------------------------------------------*/
++void AacHba_WriteCallback(  
++      VOID                    *Context,
++      PFIB_CONTEXT    FibContext,
++      int                             FibStatus )
++/*----------------------------------------------------------------------------*/
++{
++      PCI_MINIPORT_COMMON_EXTENSION   *CommonExtension;
++      AFA_COMM_ADAPTER                                *Adapter;
++      BLOCKWRITERESPONSE                              *BlockWriteResponse;
++      Scsi_Cmnd                                               *scsi_cmnd_ptr;
++      u_long                                                  lba;
++      int                     ContainerId;
++
++      scsi_cmnd_ptr = ( Scsi_Cmnd * )Context;
++
++      CommonExtension = ( PCI_MINIPORT_COMMON_EXTENSION * )( scsi_cmnd_ptr->host->hostdata );
++      Adapter         = ( AFA_COMM_ADAPTER * )CommonExtension->Adapter;
++      
++      ContainerId = TARGET_LUN_TO_CONTAINER( scsi_cmnd_ptr->target, scsi_cmnd_ptr->lun );
++
++      lba = ( ( scsi_cmnd_ptr->cmnd[1] & 0x1F ) << 16 ) | 
++                      ( scsi_cmnd_ptr->cmnd[2] << 8 ) |
++                      scsi_cmnd_ptr->cmnd[3];
++      cmn_err( CE_DEBUG, "AacHba_WriteCallback[cpu %d]: lba = %ld, t = %ld", smp_processor_id(), lba, jiffies );
++      if( FibContext == 0 ) 
++      {
++              cmn_err( CE_WARN, "AacHba_WriteCallback: no fib context" );
++              scsi_cmnd_ptr->result = DID_ERROR << 16;
++              AacHba_CompleteScsi( scsi_cmnd_ptr );
++              return;
++      }
++
++    BlockWriteResponse = (PBLOCKWRITERESPONSE) Adapter->CommFuncs.GetFibData( FibContext );
++      if (BlockWriteResponse->Status == ST_OK) 
++              scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
++      else 
++      {
++              cmn_err( CE_WARN, "AacHba_WriteCallback: write failed, status = %d\n", 
++                      BlockWriteResponse->Status );
++              scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
++              AacHba_SetSenseData( ( char * )&g_sense_data[ ContainerId ],
++                      SENKEY_HW_ERR, SENCODE_INTERNAL_TARGET_FAILURE, ASENCODE_INTERNAL_TARGET_FAILURE, 
++                      0, 0, 0, 0 );
++      }
++
++      Adapter->CommFuncs.CompleteFib( FibContext );
++      Adapter->CommFuncs.FreeFib( FibContext );
++
++      AacHba_CompleteScsi( scsi_cmnd_ptr );
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_Ioctl()
++
++              Handle IOCTL requests
++
++      Preconditions:
++      Postconditions:
++ *----------------------------------------------------------------------------*/
++int AacHba_Ioctl(
++      PCI_MINIPORT_COMMON_EXTENSION *CommonExtension,
++      int cmd,
++      void * arg )
++/*----------------------------------------------------------------------------*/
++{
++      Sa_ADAPTER_EXTENSION              *AdapterExtension;
++      AFA_IOCTL_CMD IoctlCmd;
++      int status;
++      
++      AdapterExtension = ( Sa_ADAPTER_EXTENSION * )CommonExtension->MiniPort;
++
++      cmn_err( CE_DEBUG, "AacHba_Ioctl, type = %d", cmd );
++      switch( cmd )
++      {
++        case FSACTL_SENDFIB:
++                cmn_err( CE_DEBUG, "FSACTL_SENDFIB" );
++              break;
++
++        case FSACTL_AIF_THREAD:
++                cmn_err( CE_DEBUG, "FSACTL_AIF_THREAD" );
++              break;
++
++        case FSACTL_NULL_IO_TEST:
++                cmn_err( CE_DEBUG, "FSACTL_NULL_IO_TEST" );
++              break;
++
++        case FSACTL_SIM_IO_TEST:
++                cmn_err( CE_DEBUG, "FSACTL_SIM_IO_TEST" );
++              break;
++
++        case FSACTL_GET_FIBTIMES:
++                cmn_err( CE_DEBUG, "FSACTL_GET_FIBTIMES" );
++              break;
++
++        case FSACTL_ZERO_FIBTIMES:
++                cmn_err( CE_DEBUG, "FSACTL_ZERO_FIBTIMES");
++              break;
++
++        case FSACTL_GET_VAR:
++                cmn_err( CE_DEBUG, "FSACTL_GET_VAR" );
++              break;
++
++        case FSACTL_SET_VAR:
++                cmn_err( CE_DEBUG, "FSACTL_SET_VAR" );
++              break;
++
++        case FSACTL_OPEN_ADAPTER_CONFIG:
++                cmn_err( CE_DEBUG, "FSACTL_OPEN_ADAPTER_CONFIG" );
++              break;  
++
++        case FSACTL_CLOSE_ADAPTER_CONFIG:
++                cmn_err( CE_DEBUG, "FSACTL_CLOSE_ADAPTER_CONFIG" );
++              break;
++
++        case FSACTL_QUERY_ADAPTER_CONFIG:
++                cmn_err( CE_DEBUG, "FSACTL_QUERY_ADAPTER_CONFIG" );
++              break;
++
++        case FSACTL_OPEN_GET_ADAPTER_FIB:
++                cmn_err( CE_DEBUG, "FSACTL_OPEN_GET_ADAPTER_FIB" );
++              break;
++
++        case FSACTL_GET_NEXT_ADAPTER_FIB:
++                cmn_err( CE_DEBUG, "FSACTL_GET_NEXT_ADAPTER_FIB" );
++              break;
++
++        case FSACTL_CLOSE_GET_ADAPTER_FIB:
++                cmn_err( CE_DEBUG, "FSACTL_CLOSE_GET_ADAPTER_FIB" );
++              break;
++
++        case FSACTL_MINIPORT_REV_CHECK:
++                cmn_err( CE_DEBUG, "FSACTL_MINIPORT_REV_CHECK" );
++              break;
++
++        case FSACTL_OPENCLS_COMM_PERF_DATA:
++                cmn_err( CE_DEBUG, "FSACTL_OPENCLS_COMM_PERF_DATA" );
++              break;
++      
++        case FSACTL_GET_COMM_PERF_DATA:
++                cmn_err( CE_DEBUG, "FSACTL_GET_COMM_PERF_DATA" );
++              break;
++
++        case FSACTL_QUERY_DISK:
++                cmn_err( CE_DEBUG, "FSACTL_QUERY_DISK" );
++              break;
++              
++        case FSACTL_DELETE_DISK:
++                cmn_err( CE_DEBUG, "FSACTL_DELETE_DISK" );
++              break;
++
++        default:
++                cmn_err( CE_DEBUG, "Unknown ioctl: 0x%x", cmd );
++      }
++
++      IoctlCmd.cmd = cmd;
++      IoctlCmd.arg = ( intptr_t )arg;
++      IoctlCmd.flag = 0;
++      IoctlCmd.cred_p = 0;
++      IoctlCmd.rval_p = 0;
++
++      status = AfaCommAdapterDeviceControl( CommonExtension->Adapter, &IoctlCmd );
++      cmn_err( CE_DEBUG, "AAC_Ioctl, completion status = %d", status );
++      return( status );
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_AdapterDeviceControl()
++
++      Preconditions:
++      Postconditions:
++              Returns TRUE if ioctl handled, FALSE otherwise
++              *ReturnStatus set to completion status
++ *----------------------------------------------------------------------------*/
++BOOLEAN AacHba_AdapterDeviceControl (
++      PVOID AdapterArg,               // CommonExtensionPtr
++      IN PAFA_IOCTL_CMD IoctlCmdPtr,
++      OUT int * ReturnStatus )
++/*----------------------------------------------------------------------------*/
++{
++      BOOLEAN Handled = TRUE; // start out handling it.
++      int Status = EFAULT;
++
++      switch( IoctlCmdPtr->cmd )
++      {
++              case FSACTL_QUERY_DISK:
++                      Status = AacHba_QueryDisk( AdapterArg, IoctlCmdPtr );
++                      break;
++
++              case FSACTL_DELETE_DISK:
++                      Status = AacHba_DeleteDisk( AdapterArg, IoctlCmdPtr );
++                      break;
++
++              case FSACTL_FORCE_DELETE_DISK:
++                      Status = AacHba_ForceDeleteDisk( AdapterArg, IoctlCmdPtr );
++                      break;
++
++              case 2131:
++                      if( AacHba_ProbeContainers( ( PCI_MINIPORT_COMMON_EXTENSION * )AdapterArg ) )
++                              Status = -EFAULT;
++                      break;
++
++              default:
++                      Handled = FALSE;
++                      break;
++      }
++
++      *ReturnStatus = Status;
++
++      return( Handled );
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_QueryDisk()
++
++      Postconditions:
++              Return values
++              0       = OK
++              -EFAULT = Bad address
++              -EINVAL = Bad container number
++ *----------------------------------------------------------------------------*/
++int AacHba_QueryDisk(
++      PVOID AdapterArg,               // CommonExtensionPtr
++      IN PAFA_IOCTL_CMD IoctlCmdPtr )
++/*----------------------------------------------------------------------------*/
++{
++      UNIX_QUERY_DISK QueryDisk;
++      PCI_MINIPORT_COMMON_EXTENSION   *CommonExtensionPtr;
++      fsadev_t                                                *fsa_dev_ptr;
++
++      CommonExtensionPtr = ( PCI_MINIPORT_COMMON_EXTENSION * )AdapterArg;
++      fsa_dev_ptr = &( CommonExtensionPtr->OsDep.fsa_dev );
++
++      if( copyin( IoctlCmdPtr->arg, &QueryDisk, sizeof( UNIX_QUERY_DISK ) ) )
++              return( -EFAULT );
++
++      if (QueryDisk.ContainerNumber == -1)
++              QueryDisk.ContainerNumber = TARGET_LUN_TO_CONTAINER( QueryDisk.Target, QueryDisk.Lun );
++      else 
++              if( ( QueryDisk.Bus == -1 ) && ( QueryDisk.Target == -1 ) && ( QueryDisk.Lun == -1 ) )
++              {
++                      if( QueryDisk.ContainerNumber > MAXIMUM_NUM_CONTAINERS )
++                              return( -EINVAL );
++
++                      QueryDisk.Instance = CommonExtensionPtr->OsDep.scsi_host_ptr->host_no;
++                      QueryDisk.Bus = 0;
++                      QueryDisk.Target = CONTAINER_TO_TARGET( QueryDisk.ContainerNumber );
++                      QueryDisk.Lun = CONTAINER_TO_LUN( QueryDisk.ContainerNumber );
++              }
++              else 
++                      return( -EINVAL );
++
++      QueryDisk.Valid = fsa_dev_ptr->ContainerValid[QueryDisk.ContainerNumber];
++      QueryDisk.Locked = fsa_dev_ptr->ContainerLocked[QueryDisk.ContainerNumber];
++      QueryDisk.Deleted = fsa_dev_ptr->ContainerDeleted[QueryDisk.ContainerNumber];
++
++      if( fsa_dev_ptr->ContainerDevNo[QueryDisk.ContainerNumber] == -1 )
++              QueryDisk.UnMapped = TRUE;
++      else
++              QueryDisk.UnMapped = FALSE;
++
++      get_sd_devname( fsa_dev_ptr->ContainerDevNo[QueryDisk.ContainerNumber], 
++              QueryDisk.diskDeviceName );
++
++      if( copyout( &QueryDisk, IoctlCmdPtr->arg, sizeof( UNIX_QUERY_DISK ) ) )
++              return( -EFAULT );
++
++      return( 0 );
++}
++
++
++/*------------------------------------------------------------------------------
++      get_sd_devname()
++ *----------------------------------------------------------------------------*/
++static void get_sd_devname(
++      long disknum, 
++      char * buffer)
++/*----------------------------------------------------------------------------*/
++{
++      if( disknum < 0 )
++      {
++        sprintf(buffer, "%s", "");
++              return;
++      }
++
++   if( disknum < 26 )
++        sprintf(buffer, "sd%c", 'a' + disknum);
++    else {
++        unsigned int min1;
++        unsigned int min2;
++        /*
++         * For larger numbers of disks, we need to go to a new
++         * naming scheme.
++         */
++        min1 = disknum / 26;
++        min2 = disknum % 26;
++        sprintf(buffer, "sd%c%c", 'a' + min1 - 1, 'a' + min2);
++    }
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_ForceDeleteDisk()
++
++      Postconditions:
++              Return values
++              0       = OK
++              -EFAULT = Bad address
++              -EINVAL = Bad container number
++ *----------------------------------------------------------------------------*/
++int AacHba_ForceDeleteDisk(
++      PVOID AdapterArg,               // CommonExtensionPtr
++      IN PAFA_IOCTL_CMD IoctlCmdPtr )
++/*----------------------------------------------------------------------------*/
++{
++      DELETE_DISK      DeleteDisk;
++      PCI_MINIPORT_COMMON_EXTENSION   *CommonExtensionPtr;
++      fsadev_t                                                *fsa_dev_ptr;
++
++      CommonExtensionPtr = ( PCI_MINIPORT_COMMON_EXTENSION * )AdapterArg;
++      fsa_dev_ptr = &( CommonExtensionPtr->OsDep.fsa_dev );
++
++      if ( copyin( IoctlCmdPtr->arg,  &DeleteDisk, sizeof( DELETE_DISK ) ) )
++              return( -EFAULT );
++
++      if ( DeleteDisk.ContainerNumber > MAXIMUM_NUM_CONTAINERS ) 
++              return( -EINVAL );
++      
++      // Mark this container as being deleted.
++      fsa_dev_ptr->ContainerDeleted[DeleteDisk.ContainerNumber] = TRUE;
++
++      // Mark the container as no longer valid
++      fsa_dev_ptr->ContainerValid[DeleteDisk.ContainerNumber] = 0;
++
++      return( 0 );
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_DeleteDisk()
++
++      Postconditions:
++              Return values
++              0       = OK
++              -EFAULT = Bad address
++              -EINVAL = Bad container number
++              -EBUSY  = Device locked
++ *----------------------------------------------------------------------------*/
++int AacHba_DeleteDisk(
++      PVOID AdapterArg,
++      IN PAFA_IOCTL_CMD IoctlCmdPtr )
++/*----------------------------------------------------------------------------*/
++{
++      DELETE_DISK DeleteDisk;
++      PCI_MINIPORT_COMMON_EXTENSION   *CommonExtensionPtr;
++      fsadev_t                                                *fsa_dev_ptr;
++
++      CommonExtensionPtr = ( PCI_MINIPORT_COMMON_EXTENSION * )AdapterArg;
++      fsa_dev_ptr = &( CommonExtensionPtr->OsDep.fsa_dev );
++
++      if( copyin( IoctlCmdPtr->arg, &DeleteDisk, sizeof( DELETE_DISK ) ) ) 
++              return( -EFAULT );
++
++      if( DeleteDisk.ContainerNumber > MAXIMUM_NUM_CONTAINERS )
++              return( -EINVAL );
++      
++      // If the container is locked, it can not be deleted by the API.
++      if( fsa_dev_ptr->ContainerLocked[DeleteDisk.ContainerNumber] )
++              return( -EBUSY );
++      else 
++      {       
++              // Mark the container as no longer being valid.
++              fsa_dev_ptr->ContainerValid[DeleteDisk.ContainerNumber] = 0;
++              fsa_dev_ptr->ContainerDevNo[DeleteDisk.ContainerNumber] = -1;
++              return(0);
++      }       
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_OpenAdapter()
++ *----------------------------------------------------------------------------*/
++AAC_STATUS AacHba_OpenAdapter(
++      IN PVOID AdapterArg )
++/*----------------------------------------------------------------------------*/
++{
++      return( STATUS_SUCCESS );
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_CloseAdapter()
++ *----------------------------------------------------------------------------*/
++AAC_STATUS AacHba_CloseAdapter(
++      IN PVOID AdapterArg )
++/*----------------------------------------------------------------------------*/
++{
++      return( STATUS_SUCCESS );
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_DetachAdapter()
++ *----------------------------------------------------------------------------*/
++void AacHba_DetachAdapter(
++      IN PVOID AdapterArg )
++/*----------------------------------------------------------------------------*/
++{
++      AacCommDetachAdapter( AdapterArg );
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_AbortScsiCommand()
++ *----------------------------------------------------------------------------*/
++void AacHba_AbortScsiCommand(
++      Scsi_Cmnd *scsi_cmnd_ptr )
++/*----------------------------------------------------------------------------*/
++{
++      u_short interrupt_status;
++      PCI_MINIPORT_COMMON_EXTENSION *CommonExtensionPtr;
++
++      CommonExtensionPtr = ( PCI_MINIPORT_COMMON_EXTENSION * )( scsi_cmnd_ptr->host->hostdata );
++      interrupt_status = Sa_READ_USHORT( ( PSa_ADAPTER_EXTENSION )( CommonExtensionPtr->MiniPort ),
++              DoorbellReg_p );
++      cmn_err( CE_WARN, "interrupt_status = %d", interrupt_status );
++      
++      if( interrupt_status & DOORBELL_1) {    // Adapter -> Host Normal Command Ready
++              cmn_err( CE_WARN, "DOORBELL_1: Adapter -> Host Normal Command Ready" );
++      } 
++
++      if( interrupt_status & DOORBELL_2) {    // Adapter -> Host Normal Response Ready
++              cmn_err( CE_WARN, "DOORBELL_2: Adapter -> Host Normal Response Ready" );
++      }
++
++      if ( interrupt_status & DOORBELL_3) {   // Adapter -> Host Normal Command Not Full
++              cmn_err( CE_WARN, "DOORBELL_3: Adapter -> Host Normal Command Not Full" );
++      }
++
++      if ( interrupt_status & DOORBELL_4) {   // Adapter -> Host Normal Response Not Full
++              cmn_err( CE_WARN, "DOORBELL_4: Adapter -> Host Normal Response Not Full" );
++      }
++
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_HandleAif()
++ *----------------------------------------------------------------------------*/
++BOOLEAN AacHba_HandleAif(
++      IN PVOID AdapterArg,
++      IN PFIB_CONTEXT FibContext )
++/*----------------------------------------------------------------------------*/
++{
++      return( FALSE );
++}
++
++
++/*------------------------------------------------------------------------------
++      AacHba_SetSenseData()
++              Fill in the sense data.
++      Preconditions:
++      Postconditions:
++ *----------------------------------------------------------------------------*/
++void AacHba_SetSenseData(
++      char * sense_buf,
++      unchar sense_key,
++      unchar sense_code,
++      unchar a_sense_code,
++      unchar incorrect_length,
++      unchar bit_pointer,
++      unsigned field_pointer,
++      unsigned long residue )
++/*----------------------------------------------------------------------------*/
++{
++      sense_buf[0] = 0xF0;                    // Sense data valid, err code 70h (current error)
++      sense_buf[1] = 0;                                                               // Segment number, always zero
++
++      if( incorrect_length )
++      {
++              sense_buf[2] = sense_key | 0x20;                // Set the ILI bit | sense key
++              sense_buf[3] = BYTE3(residue);
++              sense_buf[4] = BYTE2(residue);
++              sense_buf[5] = BYTE1(residue);
++              sense_buf[6] = BYTE0(residue);
++      }
++      else
++              sense_buf[2] = sense_key;                               // Sense key
++
++      if( sense_key == SENKEY_ILLEGAL )
++              sense_buf[7] = 10;                                              // Additional sense length
++      else
++              sense_buf[7] = 6;                                               // Additional sense length
++
++      sense_buf[12] = sense_code;                             // Additional sense code
++      sense_buf[13] = a_sense_code;                           // Additional sense code qualifier
++      if( sense_key == SENKEY_ILLEGAL )
++      {
++              sense_buf[15] = 0;
++
++              if( sense_code == SENCODE_INVALID_PARAM_FIELD )
++                      sense_buf[15] = 0x80;                           // Std sense key specific field
++                                                                                              // Illegal parameter is in the parameter block
++
++              if( sense_code == SENCODE_INVALID_CDB_FIELD )
++                      sense_buf[15] = 0xc0;                           // Std sense key specific field
++                                                                                              // Illegal parameter is in the CDB block
++              sense_buf[15] |= bit_pointer;
++              sense_buf[16] = field_pointer >> 8;     // MSB
++              sense_buf[17] = field_pointer;          // LSB
++      }
++}
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/aacid.c linux/drivers/scsi/aacraid/aacid.c
+--- linux-2.4.9/drivers/scsi/aacraid/aacid.c   Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/aacid.c Thu Aug 16 18:10:23 2001
+@@ -0,0 +1,157 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *  aac.c
++ *
++ * Abstract: Data structures for controller specific info.
++ *
++--*/
++
++static char *ident_aacid = "aacraid_ident aacid.c 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#include "osheaders.h"
++
++#include "AacGenericTypes.h"
++
++#include "aac_unix_defs.h"
++
++#include "fsatypes.h"
++#include "comstruc.h"
++#include "fsaport.h"
++#include "pcisup.h"
++
++#include "version.h"
++
++
++/* Function Prototypes */
++void InqStrCopy(char *a, char *b); /* ossup.c */
++
++/* Device name used to register and unregister
++   the device in linit.c */
++char devicestr[]="aac";
++
++char *container_types[] = {
++        "None",
++        "Volume",
++        "Mirror",
++        "Stripe",
++        "RAID5",
++        "SSRW",
++        "SSRO",
++        "Morph",
++        "Legacy",
++        "RAID4",
++        "RAID10",             
++        "RAID00",             
++        "V-MIRRORS",          
++        "PSEUDO R4",          
++      "RAID50",
++        "Unknown"
++};
++
++/* Local Structure to set SCSI inquiry data strings */
++typedef struct _INQSTR {
++  char vid[8];         /* Vendor ID */
++  char pid[16];        /* Product ID */
++  char prl[4];         /* Product Revision Level */
++} INQSTR, *INQSTRP;
++
++FSA_MINIPORT MiniPorts[];
++
++/* Function: SetInqDataStr
++ *
++ * Arguments: [1] pointer to void [1] int
++ *
++ * Purpose: Sets SCSI inquiry data strings for vendor, product
++ * and revision level. Allows strings to be set in platform dependant
++ * files instead of in OS dependant driver source.
++ */
++void
++SetInqDataStr (
++  int MiniPortIndex,
++  void *dataPtr,
++  int tindex)
++{
++  INQSTRP InqStrPtr;
++   char *findit;
++   FSA_MINIPORT   *mp;
++
++   mp = &MiniPorts[MiniPortIndex];
++   
++    InqStrPtr = (INQSTRP)(dataPtr); /* cast dataPtr to type INQSTRP */
++
++    InqStrCopy (mp->Vendor, InqStrPtr->vid); 
++    InqStrCopy (mp->Model,  InqStrPtr->pid); /* last six chars reserved for vol type */
++
++    findit = InqStrPtr->pid;
++
++    for ( ; *findit != ' '; findit++); /* walk till we find a space then incr by 1 */
++        findit++;
++      
++    if (tindex < (sizeof(container_types)/sizeof(char *))){
++      InqStrCopy (container_types[tindex], findit);
++    }
++   InqStrCopy ("0001", InqStrPtr->prl);
++}
++
++int
++SaInitDevice(
++      IN PPCI_MINIPORT_COMMON_EXTENSION CommonExtension,
++      IN ULONG AdapterNumber,
++      IN ULONG PciBus,
++      IN ULONG PciSlot
++);
++
++int
++RxInitDevice(
++      IN PPCI_MINIPORT_COMMON_EXTENSION CommonExtension,
++      IN ULONG AdapterNumber,
++      IN ULONG PciBus,
++      IN ULONG PciSlot
++);
++
++
++/*
++ * Because of the way Linux names scsi devices, the order in this table has
++ * become important.  Check for on-board Raid first, add-in cards second.
++ */
++
++FSA_MINIPORT MiniPorts[] = {
++      { 0x0000, 0x0000, 0x0000, 0x0000, "afa", RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* Dell unknown - uses perc_pciid */
++      { 0x0000, 0x0000, 0x0000, 0x0000, "aac", RxInitDevice, "aacraid", "ADAPTEC  ", "AACRAID         " }, /* unknown - uses rx_pciid */
++      { 0x0000, 0x0000, 0x0000, 0x0000, "aac", SaInitDevice, "aacraid", "ADAPTEC  ", "AACRAID         " }, /* unknown - uses sa_pciid */
++      { 0x1028, 0x0001, 0x1028, 0x0001, "afa", RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* PERC 2/Si */
++      { 0x1028, 0x0002, 0x1028, 0x0002, "afa", RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* PERC 3/Di */
++      { 0x1028, 0x0003, 0x1028, 0x0003, "afa", RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* PERC 3/Si */
++      { 0x1028, 0x0004, 0x1028, 0x00d0, "afa", RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* PERC 3/Si */
++      { 0x1028, 0x0002, 0x1028, 0x00d1, "afa", RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* PERC 3/Di */
++      { 0x1028, 0x0002, 0x1028, 0x00d9, "afa", RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* PERC 3/Di */
++      { 0x1028, 0x000a, 0x1028, 0x0106, "afa", RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* PERC 3/Di */
++      { 0x1011, 0x0046, 0x9005, 0x1364, "afa", SaInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* Dell PERC2 "Quad Channel" */
++      { 0x1011, 0x0046, 0x9005, 0x0365, "aac", SaInitDevice, "aacraid",  "ADAPTEC ", "Adaptec 5400S   " }, /* Adaptec 5400S */
++      { 0x1011, 0x0046, 0x103c, 0x10c2, "hpn", SaInitDevice, "hpnraid",  "HP      ", "NetRAID-4M      " }  /* HP NetRAID-4M */
++};
++
++
++#define NUM_MINIPORTS (sizeof(MiniPorts) / sizeof(FSA_MINIPORT))
++
++int NumMiniPorts = NUM_MINIPORTS;
++
++char DescriptionString[] =    "AACxxx Raid Controller" FSA_VERSION_STRING ;
+diff -burN linux-2.4.9/drivers/scsi/aacraid/commctrl.c linux/drivers/scsi/aacraid/commctrl.c
+--- linux-2.4.9/drivers/scsi/aacraid/commctrl.c        Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/commctrl.c      Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,1098 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *  commctrl.c
++ *
++ * Abstract: Contains all routines for control of the AFA comm layer
++ *
++--*/
++
++static char *ident_commctrl = "aacraid_ident commctrl.c 1.0.7 2000/10/11 Adaptec, Inc.";
++
++#include "comprocs.h"
++#include "osheaders.h"
++#include "ostypes.h"
++
++
++
++
++
++typedef BOOLEAN BOOL;
++#define inline /* _inline */
++
++#include <revision.h>
++AAC_STATUS
++FsaCtlCheckRevision(
++      IN PAFA_COMM_ADAPTER    Adapter,
++      IN PAFA_IOCTL_CMD               IoctlCmdPtr
++      )
++/*++
++
++Routine Description:
++
++      This routine validates the revision of the caller with the current revision
++      of the filesystem.
++
++Arguments:
++
++      Adapter - Supplies which adapter is being processed.
++
++    Irp - Supplies the Irp being processed.
++
++      IrpContext - Supplies the IrpContext.
++
++Return Value:
++
++      AAC_STATUS
++
++--*/
++
++{
++      RevCheck APIRevCheck;
++      RevCheckResp APIRevCheckResp;
++      RevComponent APICallingComponent;
++      ULONG APIBuildNumber;
++
++      if (COPYIN( (caddr_t) IoctlCmdPtr->arg, (caddr_t) &APIRevCheck, sizeof(RevCheck), IoctlCmdPtr->flag )) {
++              return (EFAULT);
++      }
++
++      APICallingComponent = APIRevCheck.callingComponent;
++      APIBuildNumber = APIRevCheck.callingRevision.buildNumber;
++
++      APIRevCheckResp.possiblyCompatible = RevCheckCompatibility( RevMiniportDriver , APICallingComponent, APIBuildNumber );
++
++      APIRevCheckResp.adapterSWRevision.external.ul = RevGetExternalRev();
++      APIRevCheckResp.adapterSWRevision.buildNumber = RevGetBuildNumber();
++
++      if (COPYOUT( (caddr_t) &APIRevCheckResp, (caddr_t) IoctlCmdPtr->arg, sizeof(RevCheckResp), IoctlCmdPtr->flag )) {
++              return (EFAULT);
++      }
++
++      return (0);
++}
++
++
++int
++AfaCommAdapterDeviceControl(
++      IN PVOID AdapterArg,
++      IN PAFA_IOCTL_CMD IoctlCmdPtr
++      )
++{
++      PAFA_COMM_ADAPTER Adapter = (PAFA_COMM_ADAPTER) AdapterArg;
++    int Status = ENOTTY;
++//    PIO_STACK_LOCATION IrpSp;
++      PAFA_CLASS_DRIVER ClassDriver;
++
++      //
++      // First loop through all of the class drivers to give them a chance to handle
++      // the Device control first.
++      //
++
++      ClassDriver = Adapter->ClassDriverList;
++
++      while (ClassDriver) {
++
++              if (ClassDriver->DeviceControl) {
++
++                      if (ClassDriver->DeviceControl( ClassDriver->ClassDriverExtension, IoctlCmdPtr, &Status ) ) {
++
++                              return (Status);
++
++                      }
++              }
++
++              ClassDriver = ClassDriver->Next;
++      }
++
++    switch (IoctlCmdPtr->cmd) {
++
++
++        case FSACTL_SENDFIB:
++
++              Status = AfaCommCtlSendFib( Adapter, IoctlCmdPtr );
++              break;
++
++        case FSACTL_AIF_THREAD:
++
++              Status = AfaCommCtlAifThread( Adapter, IoctlCmdPtr );   
++              break;
++
++
++        case FSACTL_OPEN_GET_ADAPTER_FIB:
++
++              Status = FsaCtlOpenGetAdapterFib( Adapter, IoctlCmdPtr );
++              break;
++
++        case FSACTL_GET_NEXT_ADAPTER_FIB:
++
++              Status = FsaCtlGetNextAdapterFib( Adapter, IoctlCmdPtr );
++              break;
++
++        case FSACTL_CLOSE_GET_ADAPTER_FIB:
++
++              Status = FsaCtlCloseGetAdapterFib( Adapter, IoctlCmdPtr );
++              break;
++
++        case FSACTL_MINIPORT_REV_CHECK:
++        
++              Status = FsaCtlCheckRevision( Adapter , IoctlCmdPtr );
++              break;
++
++
++      default:
++        
++              Status = ENOTTY;
++              break;  
++
++      }
++
++
++      return (Status);
++}
++
++AAC_STATUS
++AfaCommRegisterNewClassDriver(
++      IN PAFA_COMM_ADAPTER    Adapter,
++      IN PAFA_NEW_CLASS_DRIVER        NewClassDriver,
++      OUT PAFA_NEW_CLASS_DRIVER_RESPONSE NewClassDriverResponse
++      )
++/*++
++
++Routine Description:
++
++      This routine registers a new class driver for the comm layer.
++
++      It will return a pointer to the communication functions for the class driver
++      to use.
++
++Arguments:
++
++      Adapter - Supplies which adapter is being processed.
++
++    Irp - Supplies the Irp being processed.
++
++Return Value:
++
++      STATUS_SUCCESS           - Everything OK.
++
++--*/
++{
++      AAC_STATUS Status;
++      PAFA_CLASS_DRIVER ClassDriver;
++
++
++      ClassDriver = (PAFA_CLASS_DRIVER) OsAllocMemory( sizeof(AFA_CLASS_DRIVER), OS_ALLOC_MEM_SLEEP );
++
++      if (ClassDriver == NULL) {
++
++              Status = STATUS_INSUFFICIENT_RESOURCES;
++
++              return Status;
++      }
++
++      //
++      // If the class driver has sent in user Vars, then copy them into the global
++      // area.
++      //
++
++      if (NewClassDriver->NumUserVars) {
++
++              PFSA_USER_VAR   NewUserVars;
++
++              NewUserVars = OsAllocMemory( (FsaCommData.NumUserVars +
++                                                                 NewClassDriver->NumUserVars) * sizeof(FSA_USER_VAR), OS_ALLOC_MEM_SLEEP );
++
++              //
++              // First copy the existing into the new area.
++              //
++
++              RtlCopyMemory( NewUserVars, FsaCommData.UserVars, FsaCommData.NumUserVars * sizeof(FSA_USER_VAR) );
++
++              //
++              // Next copy the new vars passed in from class driver.
++              //
++
++              RtlCopyMemory( (NewUserVars + FsaCommData.NumUserVars),
++                                         NewClassDriver->UserVars,
++                                         NewClassDriver->NumUserVars * sizeof(FSA_USER_VAR) );
++
++              //
++              // Free up the old user vars.
++              //
++
++              OsFreeMemory( FsaCommData.UserVars, FsaCommData.NumUserVars * sizeof(FSA_USER_VAR) );
++
++              //
++              // Point the global to the new area.
++              //
++
++              FsaCommData.UserVars = NewUserVars;
++
++              //
++              // Update the total count.
++              //
++
++              FsaCommData.NumUserVars += NewClassDriver->NumUserVars;
++
++      }
++
++      ClassDriver->OpenAdapter = NewClassDriver->OpenAdapter;
++      ClassDriver->CloseAdapter = NewClassDriver->CloseAdapter;
++      ClassDriver->DeviceControl = NewClassDriver->DeviceControl;
++      ClassDriver->HandleAif = NewClassDriver->HandleAif;
++      ClassDriver->ClassDriverExtension = NewClassDriver->ClassDriverExtension;
++
++      ClassDriver->Next = Adapter->ClassDriverList;
++      Adapter->ClassDriverList = ClassDriver;
++
++      //
++      // Now return the information needed by the class driver to communicate to us.
++      //
++
++      NewClassDriverResponse->CommFuncs = &Adapter->CommFuncs;
++      NewClassDriverResponse->CommPortExtension = Adapter;
++      NewClassDriverResponse->MiniPortExtension = Adapter->AdapterExtension;
++      NewClassDriverResponse->SpinLockCookie = Adapter->SpinLockCookie;
++      NewClassDriverResponse->Dip = Adapter->Dip;
++
++      return (STATUS_SUCCESS);
++
++
++}
++
++int
++AfaCommCtlSendFib(
++      IN PAFA_COMM_ADAPTER    Adapter,
++      IN PAFA_IOCTL_CMD               IoctlCmdPtr
++)
++/*++
++
++Routine Description:
++
++      This routine sends a fib to the adapter on behalf of a user level
++      program.
++
++Arguments:
++
++      Adapter - Supplies which adapter is being processed.
++
++      IoctlCmdPtr - Pointer to the arguments to the IOCTL call
++
++Return Value:
++
++      STATUS_INVALID_PARAMETER - If the AdapterFibContext was not a valid pointer.
++
++      STATUS_INSUFFICIENT_RESOURCES - If a memory allocation failed.
++
++      STATUS_SUCCESS           - Everything OK.
++
++--*/
++{
++    PFIB KFib;
++//    PMDL DmaMdl = NULL;
++      PCOMM_FIB_CONTEXT FibContext;
++      PSGMAP_CONTEXT SgMapContext;
++      SGMAP_CONTEXT _SgMapContext;
++    QUEUE_TYPES WhichQueue;
++    PVOID UsersAddress;
++      AAC_STATUS Status;
++
++      FibContext = AllocateFib( Adapter );
++
++    KFib = FibContext->Fib;
++
++      //
++      // First copy in the header so that we can check the size field.
++      //
++
++      if (COPYIN( (caddr_t) IoctlCmdPtr->arg, (caddr_t) KFib, sizeof(FIB_HEADER), IoctlCmdPtr->flag )) {
++              FreeFib( FibContext );
++              Status = EFAULT;
++              return (Status);
++      }
++
++      //
++      //      Since we copy based on the fib header size, make sure that we
++      //      will not overrun the buffer when we copy the memory. Return
++      //      an error if we would.
++      //
++
++      if (KFib->Header.Size > sizeof(FIB) - sizeof(FIB_HEADER)) {
++              FreeFib( FibContext );
++              Status = EINVAL;
++              return Status;
++
++      }
++
++      if (COPYIN( (caddr_t) IoctlCmdPtr->arg, (caddr_t) KFib, KFib->Header.Size + sizeof(FIB_HEADER), IoctlCmdPtr->flag )) {
++              FreeFib( FibContext );
++              Status = EFAULT;
++              return (Status);
++      }
++
++    WhichQueue = AdapNormCmdQueue;
++
++
++      if (KFib->Header.Command == TakeABreakPt) {
++
++              InterruptAdapter(Adapter);
++
++              //
++              // Since we didn't really send a fib, zero out the state to allow 
++              // cleanup code not to assert.
++              //
++
++              KFib->Header.XferState = 0;
++
++
++      } else {
++      
++              if (SendFib(KFib->Header.Command, FibContext, KFib->Header.Size , FsaNormal,
++                                      TRUE, NULL, TRUE, NULL, NULL) != FSA_SUCCESS) {
++              FsaCommPrint("User SendFib failed!.\n");
++
++
++                      FreeFib( FibContext );
++                      return (ENXIO);
++              }
++
++          if (CompleteFib(FibContext) != FSA_SUCCESS) {
++              FsaCommPrint("User Complete FIB failed.\n");
++
++                      FreeFib( FibContext );
++                      return (ENXIO);
++              }
++
++
++    }
++
++
++      //
++      //      Make sure that the size returned by the adapter (which includes
++      //      the header) is less than or equal to the size of a fib, so we
++      //      don't corrupt application data. Then copy that size to the user
++      //      buffer. (Don't try to add the header information again, since it
++      //      was already included by the adapter.)
++      //
++    ASSERT(KFib->Header.Size <= sizeof(FIB));
++
++      if (COPYOUT( (caddr_t) KFib, (caddr_t) IoctlCmdPtr->arg, KFib->Header.Size, IoctlCmdPtr->flag )) {
++              FreeFib( FibContext );
++              Status = EFAULT;
++              return (Status);
++      }
++
++      FreeFib( FibContext );
++
++    return (0);
++
++}
++
++int
++AfaCommCtlAifThread(
++      IN PAFA_COMM_ADAPTER    Adapter,
++      IN PAFA_IOCTL_CMD               IoctlCmdPtr
++)
++/*++
++
++Routine Description:
++
++      This routine will act as the AIF thread for this adapter.
++
++Arguments:
++
++      Adapter - Supplies which adapter is being processed.
++
++      IoctlCmdPtr - Pointer to the arguments to the IOCTL call
++
++Return Value:
++
++      STATUS_INVALID_PARAMETER - If the AdapterFibContext was not a valid pointer.
++
++      STATUS_INSUFFICIENT_RESOURCES - If a memory allocation failed.
++
++      STATUS_SUCCESS           - Everything OK.
++
++--*/
++{
++      return (NormCommandThread(Adapter));
++}
++
++
++
++#ifdef GATHER_FIB_TIMES
++AAC_STATUS
++AfaCommGetFibTimes(
++      IN PAFA_COMM_ADAPTER    Adapter,
++      IN PIRP                                 Irp
++      )
++/*++
++
++Routine Description:
++
++      This routine returns the gathered fibtimes to the user.
++
++Arguments:
++
++      Adapter - Supplies which adapter is being processed.
++
++    Irp - Supplies the Irp being processed.
++
++Return Value:
++
++      STATUS_INVALID_PARAMETER - If the AdapterFibContext was not a valid pointer.
++
++      STATUS_INSUFFICIENT_RESOURCES - If a memory allocation failed.
++
++      STATUS_SUCCESS           - Everything OK.
++
++--*/
++{
++      PALL_FIB_TIMES AllFibTimes;
++      PLARGE_INTEGER FreqPtr;
++    PIO_STACK_LOCATION IrpSp;
++
++    //
++    //  Get a pointer to the current Irp stack location
++    //
++
++    IrpSp = IoGetCurrentIrpStackLocation( Irp );
++
++      FreqPtr = (PLARGE_INTEGER)IrpSp->Parameters.FileSystemControl.Type3InputBuffer;
++
++      *FreqPtr = Adapter->FibTimesFrequency;
++
++      AllFibTimes = (PALL_FIB_TIMES)((PUCHAR)FreqPtr + sizeof(LARGE_INTEGER));
++
++      RtlCopyMemory(AllFibTimes, Adapter->FibTimes, sizeof(ALL_FIB_TIMES));
++
++      Irp->IoStatus.Information = 0;
++
++      return (STATUS_SUCCESS);
++
++}
++
++AAC_STATUS
++AfaCommZeroFibTimes(
++      IN PAFA_COMM_ADAPTER    Adapter,
++      IN PIRP                                 Irp
++      )
++/*++
++
++Routine Description:
++
++      This routine zero's the FibTimes structure within the adapter structure.
++
++Arguments:
++
++      Adapter - Supplies which adapter is being processed.
++
++    Irp - Supplies the Irp being processed.
++
++Return Value:
++
++      STATUS_INVALID_PARAMETER - If the AdapterFibContext was not a valid pointer.
++
++      STATUS_INSUFFICIENT_RESOURCES - If a memory allocation failed.
++
++      STATUS_SUCCESS           - Everything OK.
++
++--*/
++{
++      PFIB_TIMES FibTimesPtr;
++      int i;
++    PIO_STACK_LOCATION IrpSp;
++
++    //
++    //  Get a pointer to the current Irp stack location
++    //
++
++    IrpSp = IoGetCurrentIrpStackLocation( Irp );
++
++      //
++      // Initialize the Fib timing data structures
++      //
++      RtlZeroMemory(Adapter->FibTimes, sizeof(ALL_FIB_TIMES));
++
++      for (i = 0; i < MAX_FSACOMMAND_NUM; i++) {
++
++              FibTimesPtr = &Adapter->FibTimes->FileSys[i];
++
++              FibTimesPtr->Minimum.LowPart = 0xffffffff;
++              FibTimesPtr->Minimum.HighPart = 0x7fffffff;
++              FibTimesPtr->AdapterMinimum.LowPart = 0xffffffff;
++              FibTimesPtr->AdapterMinimum.HighPart = 0x7fffffff;
++      }
++      for (i = 0; i < MAX_RW_FIB_TIMES; i++) {
++
++              FibTimesPtr = &Adapter->FibTimes->Read[i];
++
++              FibTimesPtr->Minimum.LowPart = 0xffffffff;
++              FibTimesPtr->Minimum.HighPart = 0x7fffffff;
++              FibTimesPtr->AdapterMinimum.LowPart = 0xffffffff;
++              FibTimesPtr->AdapterMinimum.HighPart = 0x7fffffff;
++      }
++      for (i = 0; i < MAX_RW_FIB_TIMES; i++) {
++
++              FibTimesPtr = &Adapter->FibTimes->Write[i];
++
++              FibTimesPtr->Minimum.LowPart = 0xffffffff;
++              FibTimesPtr->Minimum.HighPart = 0x7fffffff;
++              FibTimesPtr->AdapterMinimum.LowPart = 0xffffffff;
++              FibTimesPtr->AdapterMinimum.HighPart = 0x7fffffff;
++      }
++
++      FibTimesPtr = &Adapter->FibTimes->Other;
++
++      FibTimesPtr->Minimum.LowPart = 0xffffffff;
++      FibTimesPtr->Minimum.HighPart = 0x7fffffff;
++      FibTimesPtr->AdapterMinimum.LowPart = 0xffffffff;
++      FibTimesPtr->AdapterMinimum.HighPart = 0x7fffffff;
++
++      Irp->IoStatus.Information = 0;
++
++      return (STATUS_SUCCESS);
++
++}
++#endif        // GATHER_FIB_TIMES
++
++#ifndef unix_aif
++int
++FsaCtlOpenGetAdapterFib(
++      IN PAFA_COMM_ADAPTER    Adapter,
++      IN PAFA_IOCTL_CMD               IoctlCmdPtr
++      )
++/*++
++
++Routine Description:
++
++    This routine will get the next Fib, if available, from the AdapterFibContext
++      passed in from the user.
++
++Arguments:
++
++      Adapter - Supplies which adapter is being processed.
++
++    Irp - Supplies the Irp being processed.
++
++Return Value:
++
++      STATUS_INVALID_PARAMETER - If the AdapterFibContext was not a valid pointer.
++
++      STATUS_INSUFFICIENT_RESOURCES - If a memory allocation failed.
++
++      STATUS_SUCCESS           - Everything OK.
++
++--*/
++{
++      PGET_ADAPTER_FIB_CONTEXT AdapterFibContext;
++//    HANDLE Event;
++//    PKEVENT eventObject = (PKEVENT) NULL;
++      int Status;
++
++      //
++      // The context must be allocated from NonPagedPool because we need to use MmIsAddressValid.
++      //
++
++      AdapterFibContext = OsAllocMemory(sizeof(GET_ADAPTER_FIB_CONTEXT), OS_ALLOC_MEM_SLEEP);
++
++      if (AdapterFibContext == NULL) {
++
++              Status = ENOMEM;
++
++      } else {
++
++              AdapterFibContext->NodeTypeCode = FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT;
++              AdapterFibContext->NodeByteSize = sizeof(GET_ADAPTER_FIB_CONTEXT);
++
++
++              //
++              // Initialize the conditional variable use to wait for the next AIF.
++              //
++
++              OsCv_init( &AdapterFibContext->UserEvent);
++
++              //
++              // Set WaitingForFib to FALSE to indicate we are not in a WaitForSingleObject
++              //
++
++              AdapterFibContext->WaitingForFib = FALSE;
++
++              //
++              // Initialize the FibList and set the count of fibs on the list to 0.
++              //
++
++              AdapterFibContext->FibCount = 0;
++              InitializeListHead(&AdapterFibContext->FibList);
++
++              //
++              // Overload FileObject with a time stamp.
++              //
++              AdapterFibContext->FileObject = (void *)OsGetSeconds();
++
++              //
++              // Now add this context onto the adapter's AdapterFibContext list.
++              //
++
++              OsCvLockAcquire(Adapter->AdapterFibMutex);
++
++              InsertTailList(&Adapter->AdapterFibContextList, &AdapterFibContext->NextContext);
++
++              OsCvLockRelease(Adapter->AdapterFibMutex);
++
++              if (COPYOUT( &AdapterFibContext, (caddr_t) IoctlCmdPtr->arg, sizeof(PGET_ADAPTER_FIB_CONTEXT), 
++                                               IoctlCmdPtr->flag )) {
++
++                      Status = EFAULT;
++                      
++              } else {
++              
++                      Status = 0;
++
++              }       
++
++      }
++
++      return (Status);
++}
++
++int
++FsaCtlGetNextAdapterFib(
++      IN PAFA_COMM_ADAPTER    Adapter,
++      IN PAFA_IOCTL_CMD               IoctlCmdPtr
++      )
++/*++
++
++Routine Description:
++
++    This routine will get the next Fib, if available, from the AdapterFibContext
++      passed in from the user.
++
++Arguments:
++
++      Adapter - Supplies which adapter is being processed.
++
++    Irp - Supplies the Irp being processed.
++
++Return Value:
++
++      STATUS_INVALID_PARAMETER - If the AdapterFibContext was not a valid pointer.
++
++      STATUS_NO_MORE_ENTRIES - There are no more Fibs for this AdapterFibContext.
++
++      STATUS_SUCCESS           - Everything OK.
++
++--*/
++{
++      GET_ADAPTER_FIB_IOCTL AdapterFibIoctl;
++      PGET_ADAPTER_FIB_CONTEXT AdapterFibContext, aifcp;
++      PFIB Fib;
++      int Status;
++      PLIST_ENTRY Entry;
++      int found;
++
++      if (COPYIN( (caddr_t) IoctlCmdPtr->arg, (caddr_t) &AdapterFibIoctl,
++                                      sizeof(GET_ADAPTER_FIB_IOCTL), IoctlCmdPtr->flag )) {
++              return (EFAULT);
++      }
++
++      //
++      // Extract the AdapterFibContext from the Input parameters.
++      //
++
++      AdapterFibContext = (PGET_ADAPTER_FIB_CONTEXT) AdapterFibIoctl.AdapterFibContext;
++
++      //
++      // Verify that the HANDLE passed in was a valid AdapterFibContext
++      //
++      // Search the list of AdapterFibContext addresses on the adapter to be sure
++      // this is a valid address
++
++      found = 0;
++      Entry = Adapter->AdapterFibContextList.Flink;
++
++      while ( Entry != &Adapter->AdapterFibContextList ) {
++                      aifcp = CONTAINING_RECORD ( Entry, GET_ADAPTER_FIB_CONTEXT, NextContext );
++                      if ( AdapterFibContext == aifcp ) {   // We found a winner
++                                      found = 1;
++                                      break;
++                      }
++                      Entry = Entry->Flink;
++      }
++
++      if ( found == 0 ) {
++                      return ( EINVAL );;
++      }
++
++      if ( (AdapterFibContext->NodeTypeCode != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||
++               (AdapterFibContext->NodeByteSize != sizeof(GET_ADAPTER_FIB_CONTEXT)) ) {
++
++              return ( EINVAL );
++
++      }
++
++      Status = STATUS_SUCCESS;
++
++      OsCvLockAcquire(Adapter->AdapterFibMutex);
++
++      //
++      // If there are no fibs to send back, then either wait or return EAGAIN
++      //
++return_fib:
++
++      if (!IsListEmpty(&AdapterFibContext->FibList)) {
++
++              PLIST_ENTRY Entry;
++
++              //
++              // Pull the next fib from the FibList
++              //
++              Entry = RemoveHeadList(&AdapterFibContext->FibList);
++
++              Fib = CONTAINING_RECORD( Entry, FIB, Header.FibLinks );
++
++              AdapterFibContext->FibCount--;
++
++              if (COPYOUT( Fib, AdapterFibIoctl.AifFib, sizeof(FIB), IoctlCmdPtr->flag )) {
++
++                      OsCvLockRelease( Adapter->AdapterFibMutex );
++                      OsFreeMemory( Fib, sizeof(Fib) );
++                      return (EFAULT);
++
++              }       
++
++              //
++              // Free the space occupied by this copy of the fib.
++              //
++
++              OsFreeMemory(Fib, sizeof(FIB));
++
++        Status = 0;
++
++              //
++              // Overload FileObject with a time stamp
++              // 
++              AdapterFibContext->FileObject = ( void * )OsGetSeconds();
++
++      } else {
++
++              if (AdapterFibIoctl.Wait) {
++                      
++                      if (OsCv_wait_sig( &AdapterFibContext->UserEvent, Adapter->AdapterFibMutex ) == 0) {
++
++                              Status = EINTR;
++
++                      } else {
++                      
++                              goto return_fib;
++                              
++                      }
++              } else {
++                                      
++                      Status = EAGAIN;
++
++              }       
++
++      }
++      OsCvLockRelease( Adapter->AdapterFibMutex );
++
++      return (Status);
++}
++
++int
++FsaCtlCloseGetAdapterFib(
++      IN PAFA_COMM_ADAPTER    Adapter,
++      IN PAFA_IOCTL_CMD               IoctlCmdPtr
++      )
++/*++
++
++Routine Description:
++
++    This routine will close down the AdapterFibContext passed in from the user.
++
++Arguments:
++
++      Adapter - Supplies which adapter is being processed.
++
++    Irp - Supplies the Irp being processed.
++
++Return Value:
++
++      STATUS_INVALID_PARAMETER - If the AdapterFibContext was not a valid pointer.
++
++      STATUS_SUCCESS           - Everything OK.
++
++--*/
++{
++      PGET_ADAPTER_FIB_CONTEXT AdapterFibContext, aifcp;
++      AAC_STATUS Status;
++
++      PLIST_ENTRY Entry;
++      int found;
++
++      //
++      // Extract the AdapterFibContext from the Input parameters
++      //
++
++      AdapterFibContext = (PGET_ADAPTER_FIB_CONTEXT) IoctlCmdPtr->arg;
++
++      if (AdapterFibContext == 0) {
++              cmn_err(CE_WARN, "FsaCtlCloseGetAdapterFib: AdapterFibContext is NULL");
++              return(EINVAL);
++      }
++
++      //
++      // Verify that the HANDLE passed in was a valid AdapterFibContext
++      //
++      // Search the list of AdapterFibContext addresses on the adapter to be sure
++      // this is a valid address
++
++      found = 0;
++      Entry = Adapter->AdapterFibContextList.Flink;
++
++      while ( Entry != &Adapter->AdapterFibContextList ) {
++                      aifcp = CONTAINING_RECORD ( Entry, GET_ADAPTER_FIB_CONTEXT, NextContext );
++                      if ( AdapterFibContext == aifcp ) {   // We found a winner
++                                      found = 1;
++                                      break;
++                      }
++                      Entry = Entry->Flink;
++      }
++
++      if ( found == 0 ) {
++              return ( 0 ); // Already Gone
++      }
++
++      if ( (AdapterFibContext->NodeTypeCode != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||
++               (AdapterFibContext->NodeByteSize != sizeof(GET_ADAPTER_FIB_CONTEXT)) ) {
++
++              return (EINVAL);
++
++      }
++
++      OsCvLockAcquire(Adapter->AdapterFibMutex);
++
++      Status = FsaCloseAdapterFibContext(Adapter, AdapterFibContext);
++
++      OsCvLockRelease(Adapter->AdapterFibMutex);
++
++      return (Status);
++}
++
++int
++FsaCloseAdapterFibContext(
++      IN PAFA_COMM_ADAPTER                    Adapter,
++      IN PGET_ADAPTER_FIB_CONTEXT             AdapterFibContext
++      )
++{
++      int Status;
++      PFIB Fib;
++
++      //
++      // First free any FIBs that have not been consumed yet.
++      //
++
++      while (!IsListEmpty(&AdapterFibContext->FibList)) {
++
++              PLIST_ENTRY Entry;
++
++              //
++              // Pull the next fib from the FibList
++              //
++
++              Entry = RemoveHeadList(&AdapterFibContext->FibList);
++
++              Fib = CONTAINING_RECORD( Entry, FIB, Header.FibLinks );
++
++              AdapterFibContext->FibCount--;
++
++              //
++              // Free the space occupied by this copy of the fib.
++              //
++
++              OsFreeMemory(Fib, sizeof(FIB));
++      }
++
++      //
++      // Remove the Context from the AdapterFibContext List
++      //
++
++      RemoveEntryList(&AdapterFibContext->NextContext);
++
++      OsCv_destroy( &AdapterFibContext->UserEvent );
++
++      //
++      // Invalidate context
++      //
++
++      AdapterFibContext->NodeTypeCode = 0;
++
++      //
++      // Free the space occupied by the Context
++      //
++
++      OsFreeMemory(AdapterFibContext, sizeof(GET_ADAPTER_FIB_CONTEXT));
++
++      Status = STATUS_SUCCESS;
++
++    return Status;
++}
++#endif 
++
++AAC_STATUS
++AfaCommOpenAdapter(
++      IN PVOID Arg
++      )
++/*++
++
++Routine Description:
++
++      The routine will get called by the miniport each time a user issues a CreateFile on the DeviceObject
++      for the adapter.
++
++      The main purpose of this routine is to set up any data structures that may be needed
++      to handle any requests made on this DeviceObject.
++
++Arguments:
++
++      Adapter - Pointer to which adapter miniport was opened.
++
++
++Return Value:
++
++      STATUS_SUCCESS
++
++--*/
++
++{
++      PAFA_COMM_ADAPTER       Adapter = (PAFA_COMM_ADAPTER) Arg;
++      AAC_STATUS Status = STATUS_SUCCESS;
++      PAFA_CLASS_DRIVER ClassDriver;
++
++      ClassDriver = Adapter->ClassDriverList;
++
++      while (ClassDriver) {
++
++              if (ClassDriver->OpenAdapter) {
++
++                      Status = ClassDriver->OpenAdapter( ClassDriver->ClassDriverExtension );
++
++                      if (Status != STATUS_SUCCESS)
++                              break;
++              }
++
++              ClassDriver = ClassDriver->Next;
++      }
++
++      return ( Status );
++}
++
++AAC_STATUS
++AfaCommCloseAdapter(
++      IN PVOID Arg
++      )
++/*++
++
++Routine Description:
++
++      This routine will get called by the miniport each time a user issues a CloseHandle on the DeviceObject
++      for the adapter.
++
++      The main purpose of this routine is to cleanup any data structures that have been set up
++      while this FileObject has been opened.
++
++      This routine loops through all of the AdapterFibContext structures to determine if any need
++      to be deleted for this FileObject.
++
++Arguments:
++
++      Adapter - Pointer to adapter miniport
++
++      Irp - Pointer to Irp that caused this close
++
++Return Value:
++
++      Status value returned from File system driver AdapterClose
++
++--*/
++{
++      PAFA_COMM_ADAPTER       Adapter = (PAFA_COMM_ADAPTER) Arg;
++      PLIST_ENTRY Entry, NextEntry;
++      PGET_ADAPTER_FIB_CONTEXT AdapterFibContext;
++      AAC_STATUS Status = STATUS_SUCCESS;
++      PAFA_CLASS_DRIVER ClassDriver;
++
++      OsCvLockAcquire(Adapter->AdapterFibMutex);
++
++      Entry = Adapter->AdapterFibContextList.Flink;
++
++      //
++      // Loop through all of the AdapterFibContext, looking for any that
++      // were created with the FileObject that is being closed.
++      //
++      while (Entry != &Adapter->AdapterFibContextList) {
++
++              //
++              // Extract the AdapterFibContext
++              //
++              AdapterFibContext = CONTAINING_RECORD( Entry, GET_ADAPTER_FIB_CONTEXT, NextContext );
++
++              // 
++              // Save the next entry because CloseAdapterFibContext will delete the AdapterFibContext
++              //
++              NextEntry = Entry->Flink;
++
++              Entry = NextEntry;
++
++      }
++
++#ifdef unix_config_file
++      //
++      // If this FileObject had the adapter open for configuration, then release it.
++      //
++      if ( Adapter->AdapterConfigFileObject == IrpSp->FileObject ) {
++
++              Adapter->AdapterConfigFileObject = NULL;
++
++      }
++#endif
++
++      OsCvLockRelease(Adapter->AdapterFibMutex);
++
++      ClassDriver = Adapter->ClassDriverList;
++
++      while (ClassDriver) {
++
++              if (ClassDriver->CloseAdapter) {
++
++                      Status = ClassDriver->CloseAdapter( ClassDriver->ClassDriverExtension );
++
++                      if (Status != STATUS_SUCCESS)
++                              break;
++              }
++
++              ClassDriver = ClassDriver->Next;
++      }
++
++      return ( Status );
++
++}
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/comminit.c linux/drivers/scsi/aacraid/comminit.c
+--- linux-2.4.9/drivers/scsi/aacraid/comminit.c        Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/comminit.c      Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,986 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *  comminit.c
++ *
++ * Abstract: This supports the initialization of the host adapter commuication interface.
++ *    This is a platform dependent module for the pci cyclone board.
++ *
++ --*/
++
++static char *ident_comminit = "aacraid_ident comminit.c 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#include "comprocs.h"
++
++#define BugCheckFileId                   (FSAFS_BUG_CHECK_COMMINIT)
++
++VOID
++AfaCommBugcheckHandler(
++              IN PVOID Buffer,
++              IN ULONG Length
++              );
++
++VOID
++ThrottlePeriodEndDpcRtn(
++      IN PKDPC Dpc,
++      IN PVOID DeferredContext,
++      IN PVOID SystemArgument1,
++      IN PVOID SystemArgument2);
++
++FSA_COMM_DATA FsaCommData;
++
++AAC_STATUS
++HardInterruptModeration1Changed(
++      IN PVOID AdapterContext,
++      IN ULONG NewValue
++      )
++{
++      PAFA_COMM_ADAPTER Adapter = AdapterContext;
++
++      //
++      // If we are using interrupt moderation, then disable the interrupt
++      // until we need to use it.
++      //
++      if (FsaCommData.HardInterruptModeration1)
++              DisableInterrupt( Adapter, AdapNormCmdNotFull, FALSE );
++      else
++              EnableInterrupt( Adapter, AdapNormCmdNotFull, FALSE );
++
++      return (STATUS_SUCCESS);
++}
++
++AAC_STATUS
++FsaFibTimeoutChanged(
++      IN PVOID AdapterContext,
++      IN ULONG NewValue
++      )
++{
++      //
++      // scale the new timeout from seconds to 100 nsec units
++      //
++//    FsaCommData.AdapterTimeout = RtlConvertLongToLargeInteger(-10*1000*1000*NewValue);
++
++      return (STATUS_SUCCESS);
++}
++
++#ifdef GATHER_FIB_TIMES
++extern int GatherFibTimes;
++#endif
++
++FSA_USER_VAR FsaCommUserVars[] = {
++#ifdef FIB_CHECKSUMS
++    { "do_fib_checksums", (PULONG)&FsaCommData.do_fib_checksums, NULL },
++#endif
++#ifdef GATHER_FIB_TIMES
++      { "GatherFibTimes", (PULONG)&GatherFibTimes, NULL },
++#endif
++      { "EnableAdapterTimeouts", (PULONG)&FsaCommData.EnableAdapterTimeouts, NULL},
++      { "EnableInterruptModeration", (PULONG)&FsaCommData.EnableInterruptModeration, NULL },
++      { "FsaDataFibsSent", (PULONG) &FsaCommData.FibsSent, NULL },
++      { "FsaDataFibRecved", (PULONG) &FsaCommData.FibRecved, NULL },
++      { "HardInterruptModeration", (PULONG)&FsaCommData.HardInterruptModeration, NULL},
++      { "HardInterruptModeration1", (PULONG)&FsaCommData.HardInterruptModeration1, HardInterruptModeration1Changed},
++      { "EnableFibTimeoutBreak", (PULONG)&FsaCommData.EnableFibTimeoutBreak, NULL},
++      { "PeakFibsConsumed", (PULONG)&FsaCommData.PeakFibsConsumed, NULL },
++      { "ZeroFibsConsumed", (PULONG)&FsaCommData.ZeroFibsConsumed, NULL },
++      { "FibTimeoutSeconds", (PULONG) &FsaCommData.FibTimeoutSeconds, FsaFibTimeoutChanged },
++};
++
++#define NUM_COMM_USER_VARS    (sizeof(FsaCommUserVars) / sizeof(FSA_USER_VAR) )
++
++\f
++AAC_STATUS
++AacCommDriverEntry(
++    )
++
++/*++
++
++Routine Description:
++
++    This is the initialization routine for the FileArray Comm layer device driver.
++
++Arguments:
++
++    DriverObject - Pointer to driver object created by the system.
++
++Return Value:
++
++    AAC_STATUS - The function value is the final status from the initialization
++        operation.
++
++--*/
++
++{
++    AAC_STATUS Status;
++      PVOID BugCheckBuffer;
++
++      RtlZeroMemory( &FsaCommData, sizeof(FSA_COMM_DATA) );
++
++
++    //
++    // Load the global timeout value for the adapter timeout
++    // Also init the global that enables or disables adapter timeouts
++    //
++
++//    FsaCommData.AdapterTimeout = RtlConvertLongToLargeInteger(-10*1000*1000*180);
++
++      FsaCommData.FibTimeoutSeconds = 180;
++
++      FsaCommData.EnableAdapterTimeouts = TRUE; 
++
++//    FsaCommData.QueueFreeTimeout = RtlConvertLongToLargeInteger(QUEUE_ENTRY_FREE_TIMEOUT);
++
++#ifdef unix_fib_timeout
++      FsaCommData.FibTimeoutIncrement = (180 * 1000 * 1000 * 10) / KeQueryTimeIncrement();
++#endif
++
++      FsaCommData.EnableInterruptModeration = FALSE;
++
++      //
++      // Preload UserVars with all variables from the comm layer.  The class layers will
++      // include theirs when they register.
++      //
++
++      FsaCommData.UserVars = OsAllocMemory(NUM_COMM_USER_VARS * sizeof(FSA_USER_VAR), OS_ALLOC_MEM_SLEEP );
++      FsaCommData.NumUserVars = NUM_COMM_USER_VARS;
++
++      RtlCopyMemory( FsaCommData.UserVars, &FsaCommUserVars, NUM_COMM_USER_VARS * sizeof(FSA_USER_VAR) );
++
++
++#ifdef AACDISK
++      //
++      // Call the disk driver to initialize itself.
++      //
++
++      AacDiskDriverEntry();
++
++#endif
++
++
++
++      return (STATUS_SUCCESS);
++}
++
++
++VOID
++DetachNTQueue(
++      IN PAFA_COMM_ADAPTER Adapter,
++    IN OUT PCOMM_QUE Queue,
++    IN QUEUE_TYPES WhichQueue
++    )
++/*++
++
++Routine Description:
++
++      This routine will release all of the resources used by a given queue.
++
++Arguments:
++
++      Adapter - Which adapter the queue belongs to
++      Queue - Pointer to the queue itself
++      WhichQueue - Identifies which of the host queues this is.
++
++Return Value:
++
++      NONE.
++
++--*/
++{
++    switch (WhichQueue) {
++
++        case HostNormCmdQueue:
++
++                      Os_remove_softintr( Queue->ConsumerRoutine );
++                      OsSpinLockDestroy( Queue->QueueLock );
++                      OsCv_destroy( &Queue->CommandReady );
++                              
++            break;
++
++        case HostHighCmdQueue:
++
++                      Os_remove_softintr( Queue->ConsumerRoutine );
++                      OsSpinLockDestroy( Queue->QueueLock );
++                      OsCv_destroy( &Queue->CommandReady );
++                              
++            break;
++
++        case HostNormRespQueue:
++
++                      Os_remove_softintr( Queue->ConsumerRoutine );
++                      OsSpinLockDestroy( Queue->QueueLock );
++            break;
++
++        case HostHighRespQueue:
++
++                      Os_remove_softintr( Queue->ConsumerRoutine );
++                      OsSpinLockDestroy( Queue->QueueLock );
++            break;
++
++        case AdapNormCmdQueue:
++        case AdapHighCmdQueue:
++        case AdapNormRespQueue:
++        case AdapHighRespQueue:
++                      OsCv_destroy( &Queue->QueueFull );
++            break;
++    }
++}
++    
++VOID
++InitializeNTQueue(
++      IN PAFA_COMM_ADAPTER Adapter,
++    IN OUT PCOMM_QUE Queue,
++    IN QUEUE_TYPES WhichQueue
++    )
++/*++
++
++Routine Description:
++
++    Will initialize all entries in the queue that is NT specific.
++
++Arguments:
++
++Return Value:
++
++    Nothing there is nothing to allocate so nothing should fail
++
++--*/
++{
++    
++      Queue->NumOutstandingIos = 0;
++
++      //
++      // Store a pointer to the adapter structure.
++      //
++
++      Queue->Adapter = Adapter;
++
++      InitializeListHead( &Queue->OutstandingIoQueue );
++          
++    switch (WhichQueue) {
++
++        case HostNormCmdQueue:
++
++                      OsCv_init( &Queue->CommandReady);
++                      OsSpinLockInit( Queue->QueueLock, Adapter->SpinLockCookie);
++                      if (ddi_add_softintr( Adapter->Dip, DDI_SOFTINT_HIGH, &Queue->ConsumerRoutine, NULL,
++                                                                NULL, (PUNIX_INTR_HANDLER)HostCommandNormDpc,
++                                                                (caddr_t)Queue ) != DDI_SUCCESS) {
++
++                              cmn_err(CE_CONT, "OS_addr_intr failed\n");                                      
++                      }                                       
++
++            InitializeListHead(&Queue->CommandQueue);
++
++            break;
++
++        case HostHighCmdQueue:
++
++                      OsCv_init( &Queue->CommandReady);
++                      OsSpinLockInit( Queue->QueueLock, Adapter->SpinLockCookie);
++                      if (ddi_add_softintr( Adapter->Dip, DDI_SOFTINT_HIGH, &Queue->ConsumerRoutine, NULL,
++                                                                NULL, (PUNIX_INTR_HANDLER)HostCommandHighDpc,
++                                                                (caddr_t) Queue ) != DDI_SUCCESS) {
++
++                              cmn_err(CE_CONT, "OS_addr_intr failed\n");                                      
++                      }                                       
++
++            InitializeListHead(&Queue->CommandQueue);
++            break;
++
++        case HostNormRespQueue:
++
++                      OsSpinLockInit( Queue->QueueLock, Adapter->SpinLockCookie);
++                      if (ddi_add_softintr( Adapter->Dip, DDI_SOFTINT_HIGH, &Queue->ConsumerRoutine, NULL,
++                                                                NULL, (PUNIX_INTR_HANDLER)HostResponseNormalDpc, 
++                                                                (caddr_t) Queue ) != DDI_SUCCESS) {
++
++                              cmn_err(CE_CONT, "OS_addr_intr failed\n");                                      
++                      }                                       
++            break;
++
++        case HostHighRespQueue:
++
++
++                      OsSpinLockInit( Queue->QueueLock, Adapter->SpinLockCookie);
++                      if (ddi_add_softintr( Adapter->Dip, DDI_SOFTINT_HIGH, &Queue->ConsumerRoutine, NULL,
++                                                                NULL, (PUNIX_INTR_HANDLER)HostResponseHighDpc, 
++                                                                (caddr_t) Queue ) != DDI_SUCCESS) {
++
++                              cmn_err(CE_CONT, "OS_addr_intr failed\n");                                      
++                      }                                       
++            break;
++
++        case AdapNormCmdQueue:
++        case AdapHighCmdQueue:
++        case AdapNormRespQueue:
++        case AdapHighRespQueue:
++
++                      OsCv_init( &Queue->QueueFull);
++            break;
++    }
++}
++
++BOOLEAN
++StartFsaCommandThreads(PAFA_COMM_ADAPTER Adapter)
++/*++
++
++Routine Description:
++
++    Create and start the command receiver threads.
++
++Arguments:
++
++
++Return Value:
++
++    Nothing
++
++--*/
++
++{
++    return(TRUE);
++}
++
++
++
++/*++
++
++Routine Description:
++
++      This routine gets called to detach all resources that have been allocated for 
++      this adapter.
++
++Arguments:
++
++      Adapter - Pointer to the adapter structure to detach.
++
++Return Value:
++
++    TRUE - All resources have been properly released.
++    FALSE - An error occured while trying to release resources.
++--*/
++BOOLEAN
++AacCommDetachAdapter (IN PAFA_COMM_ADAPTER    Adapter)
++{
++      PAFA_CLASS_DRIVER ClassDriver;
++      //
++      // First remove this adapter from the list of adapters.
++      //
++
++      if (FsaCommData.AdapterList == Adapter) {
++              
++              FsaCommData.AdapterList = Adapter->NextAdapter;
++
++      } else {
++
++              PAFA_COMM_ADAPTER CurrentAdapter, NextAdapter;
++      
++              CurrentAdapter = FsaCommData.AdapterList;
++              NextAdapter = CurrentAdapter->NextAdapter;
++
++              while (NextAdapter) {
++                              
++                      if (NextAdapter == Adapter) {
++
++                              CurrentAdapter->NextAdapter = NextAdapter->NextAdapter;
++                              break;
++                       
++                      }
++                      
++                      CurrentAdapter = NextAdapter;
++                      NextAdapter = CurrentAdapter->NextAdapter;
++              }
++      }                       
++              
++      //
++      // First send a shutdown to the adapter.
++      //
++
++      AfaCommShutdown( Adapter );
++
++      //
++      // Destroy the FibContextZone for this adapter.  This will free up all
++      // of the fib space used by this adapter.
++      //
++      
++      FsaFreeFibContextZone( Adapter );
++
++      //
++      // Destroy the mutex used for synch'ing adapter fibs.
++      //
++
++      OsCvLockDestroy( Adapter->AdapterFibMutex );
++
++      //
++      // Detach all of the host queues.
++      //
++
++    DetachNTQueue( Adapter, &Adapter->CommRegion->AdapHighRespQue, AdapHighRespQueue );
++    DetachNTQueue( Adapter, &Adapter->CommRegion->AdapNormRespQue, AdapNormRespQueue );
++    DetachNTQueue( Adapter, &Adapter->CommRegion->HostHighRespQue, HostHighRespQueue );
++    DetachNTQueue( Adapter, &Adapter->CommRegion->HostNormRespQue, HostNormRespQueue );
++    DetachNTQueue( Adapter, &Adapter->CommRegion->AdapHighCmdQue, AdapHighCmdQueue );
++    DetachNTQueue( Adapter, &Adapter->CommRegion->AdapNormCmdQue, AdapNormCmdQueue );
++    DetachNTQueue( Adapter, &Adapter->CommRegion->HostHighCmdQue, HostHighCmdQueue );
++      DetachNTQueue( Adapter, &Adapter->CommRegion->HostNormCmdQue, HostNormCmdQueue );
++
++      //
++      // Destroy the mutex used to protect the FibContextZone
++      //
++
++      OsSpinLockDestroy( Adapter->FibContextZoneSpinLock );
++
++      //
++      // Call the miniport to free the space allocated for the shared comm queues
++      // between the host and the adapter.
++      //
++
++      FsaFreeAdapterCommArea( Adapter );
++
++      //
++      // Free the memory used by the comm region for this adapter
++      //
++
++      OsFreeMemory( Adapter->CommRegion, sizeof(COMM_REGION) );
++
++      //
++      // Free the memory used by the adapter structure.
++      //
++      ClassDriver = Adapter->ClassDriverList;
++      Adapter->ClassDriverList = Adapter->ClassDriverList->Next;
++      OsFreeMemory( ClassDriver, sizeof(AFA_CLASS_DRIVER) );
++      
++      OsFreeMemory( Adapter, sizeof(AFA_COMM_ADAPTER) );
++
++      return (TRUE);
++}
++
++PVOID
++AfaCommInitNewAdapter (IN PFSA_NEW_ADAPTER NewAdapter)
++{
++      PVOID BugCheckBuffer;
++      PAFA_COMM_ADAPTER Adapter;
++      MAPFIB_CONTEXT MapFibContext;
++      LARGE_INTEGER Time;
++      char ErrorBuffer[60];
++
++      Adapter = (PAFA_COMM_ADAPTER) OsAllocMemory( sizeof(AFA_COMM_ADAPTER) , OS_ALLOC_MEM_SLEEP );
++
++      if (Adapter == NULL)
++              return (NULL);
++
++      RtlZeroMemory(Adapter, sizeof(AFA_COMM_ADAPTER));
++
++
++      //
++      // Save the current adapter number and increment the total number.
++      //
++
++      Adapter->AdapterNumber = FsaCommData.TotalAdapters++;
++
++
++      //
++      // Fill in the pointer back to the device specific structures.
++      // The device specific driver has also passed a pointer for us to 
++      // fill in with the Adapter object that we have created.
++      //
++
++      Adapter->AdapterExtension = NewAdapter->AdapterExtension;
++      Adapter->AdapterFuncs = NewAdapter->AdapterFuncs;
++      Adapter->InterruptsBelowDpc = NewAdapter->AdapterInterruptsBelowDpc;
++      Adapter->AdapterUserVars = NewAdapter->AdapterUserVars;
++      Adapter->AdapterUserVarsSize = NewAdapter->AdapterUserVarsSize;
++
++      Adapter->Dip = NewAdapter->Dip;
++
++      //
++      // Fill in Our address into the function dispatch table
++      //
++
++      NewAdapter->AdapterFuncs->InterruptHost = AfaCommInterruptHost;
++      NewAdapter->AdapterFuncs->OpenAdapter = AfaCommOpenAdapter;
++      NewAdapter->AdapterFuncs->CloseAdapter = AfaCommCloseAdapter;
++      NewAdapter->AdapterFuncs->DeviceControl = AfaCommAdapterDeviceControl;
++
++      //
++      // Ok now init the communication subsystem
++      //
++
++      Adapter->CommRegion = (PCOMM_REGION) OsAllocMemory(sizeof(COMM_REGION), OS_ALLOC_MEM_SLEEP);
++      if (Adapter->CommRegion == NULL) {
++              cmn_err(CE_WARN, "Error could not allocate comm region.\n");
++              return (NULL);
++      }
++      RtlZeroMemory(Adapter->CommRegion, sizeof(COMM_REGION));
++
++      //
++      // Get a pointer to the iblock_cookie
++      //
++
++      ddi_get_soft_iblock_cookie( Adapter->Dip, DDI_SOFTINT_HIGH, &Adapter->SpinLockCookie );
++
++      if (!CommInit(Adapter)) {
++              FsaCommPrint("Failed to init the commuication subsystem.\n");
++              return(NULL);
++      }
++
++
++      //
++      // Initialize the list of AdapterFibContext's.
++      //
++
++      InitializeListHead(&Adapter->AdapterFibContextList);
++
++      //
++      // Initialize the fast mutex used for synchronization of the adapter fibs
++      //
++
++      Adapter->AdapterFibMutex = OsCvLockAlloc();
++      OsCvLockInit(Adapter->AdapterFibMutex, NULL);
++
++    //
++    // Allocate and start the FSA command threads. These threads will handle
++    // command requests from the adapter. They will wait on an event then pull
++    // all CDBs off the thread's queue. Each CDB will be given to a worker thread
++    // upto a defined limit. When that limit is reached wait a event will be waited
++    // on till a worker thread is finished.
++    //
++
++    if (!StartFsaCommandThreads(Adapter)) {
++          FsaCommPrint("Fsainit could not initilize the command receiver threads.\n");
++              return (NULL);
++    }
++
++#ifdef unix_crash_dump
++      //
++      // Allocate and map a fib for use by the synch path, which is used for crash
++      // dumps.
++      //
++      // Allocate an entire page so that alignment is correct.
++      //
++
++      Adapter->SyncFib = OsAllocMemory( PAGE_SIZE, OS_ALLOC_MEM_SLEEP );
++      MapFibContext.Fib = Adapter->SyncFib;
++      MapFibContext.Size = sizeof(FIB);
++      MapFib( Adapter, &MapFibContext );
++      Adapter->SyncFibPhysicalAddress = MapFibContext.LogicalFibAddress.LowPart;
++#endif
++
++      Adapter->CommFuncs.SizeOfAfaCommFuncs = sizeof(AFACOMM_FUNCS);
++
++      Adapter->CommFuncs.AllocateFib = AllocateFib;
++
++      Adapter->CommFuncs.FreeFib = FreeFib;
++      Adapter->CommFuncs.FreeFibFromDpc = FreeFibFromDpc;
++      Adapter->CommFuncs.DeallocateFib = DeallocateFib;
++
++      Adapter->CommFuncs.InitializeFib = InitializeFib;
++      Adapter->CommFuncs.GetFibData = FsaGetFibData;
++      Adapter->CommFuncs.SendFib = SendFib;
++      Adapter->CommFuncs.CompleteFib = CompleteFib;
++      Adapter->CommFuncs.CompleteAdapterFib = CompleteAdapterFib;
++
++      Adapter->CommFuncs.SendSynchFib = SendSynchFib;
++
++      Adapter->CommFuncs.FreeDmaResources = Adapter->AdapterFuncs->FreeDmaResources;
++      Adapter->CommFuncs.BuildSgMap = Adapter->AdapterFuncs->BuildSgMap;
++
++      //
++      // Add this adapter in to our Adapter List.
++      //
++
++      Adapter->NextAdapter = FsaCommData.AdapterList;
++      FsaCommData.AdapterList = Adapter;
++
++      NewAdapter->Adapter = Adapter;
++
++//    AfaDiskInitNewAdapter( Adapter->AdapterNumber, Adapter );
++
++      return (Adapter);
++}
++
++AAC_STATUS
++CommInitialize(
++      PAFA_COMM_ADAPTER Adapter
++      )
++{
++    //
++    //  Now allocate and initialize the zone structures used as our pool
++    //  of FIB context records.  The size of the zone is based on the
++    //  system memory size.  We also initialize the mutex used to protect
++    //  the zone.
++    //
++      Adapter->FibContextZoneSpinLock = OsSpinLockAlloc();
++      OsSpinLockInit( Adapter->FibContextZoneSpinLock, Adapter->SpinLockCookie );
++
++      Adapter->FibContextZoneExtendSize = 64;
++
++      return (STATUS_SUCCESS);
++}
++
++
++    
++/*++
++
++Routine Description:
++
++    Initializes the data structures that are required for the FSA commuication
++    interface to operate.
++
++Arguments:
++
++    None - all global or allocated data.
++
++Return Value:
++
++    TRUE - if we were able to init the commuication interface.
++    FALSE - If there were errors initing. This is a fatal error.
++--*/
++BOOLEAN
++CommInit(PAFA_COMM_ADAPTER Adapter)
++{
++    
++    ULONG SizeOfHeaders = (sizeof(QUEUE_INDEX) * NUMBER_OF_COMM_QUEUES) * 2;
++    ULONG SizeOfQueues = sizeof(QUEUE_ENTRY) * TOTAL_QUEUE_ENTRIES;
++    PQUEUE_INDEX Headers;
++    PQUEUE_ENTRY Queues;
++      ULONG TotalSize;
++      PCOMM_REGION CommRegion = Adapter->CommRegion;
++
++       CommInitialize( Adapter );
++
++      FsaCommPrint("CommInit: Queue entry size is 0x%x, Queue index size is 0x%x, Number of total entries is 0x%x, # queues = 0x%x.\n",
++                        sizeof(QUEUE_ENTRY), sizeof(QUEUE_INDEX), TOTAL_QUEUE_ENTRIES, NUMBER_OF_COMM_QUEUES);
++      //
++      //
++      // Allocate the physically contigous space for the commuication queue
++      // headers. 
++      //
++
++      TotalSize = SizeOfHeaders + SizeOfQueues;
++
++      if (!FsaAllocateAdapterCommArea(Adapter, (PVOID *)&Headers, TotalSize, QUEUE_ALIGNMENT))
++              return (FALSE);
++
++      Queues = (PQUEUE_ENTRY)((PUCHAR)Headers + SizeOfHeaders);
++
++      if (ddi_add_softintr( Adapter->Dip, DDI_SOFTINT_HIGH, &CommRegion->QueueNotFullDpc, NULL,
++                                                NULL, (PUNIX_INTR_HANDLER)CommonNotFullDpc,
++                                                (caddr_t)CommRegion ) != DDI_SUCCESS) {
++
++        cmn_err(CE_CONT, "Os_addr_intr failed\n");                                    
++      }                                       
++
++
++    // Adapter to Host normal priority Command queue
++
++
++    CommRegion->HostNormCmdQue.Headers.ProducerIndex = Headers++;
++    CommRegion->HostNormCmdQue.Headers.ConsumerIndex = Headers++;
++    *CommRegion->HostNormCmdQue.Headers.ProducerIndex = HOST_NORM_CMD_ENTRIES;
++    *CommRegion->HostNormCmdQue.Headers.ConsumerIndex = HOST_NORM_CMD_ENTRIES;
++
++    CommRegion->HostNormCmdQue.SavedIrql = 0;
++    CommRegion->HostNormCmdQue.BaseAddress = Queues;
++    CommRegion->HostNormCmdQue.QueueEntries = HOST_NORM_CMD_ENTRIES;
++
++      CommRegion->HostNormCmdQue.QueueLock = OsSpinLockAlloc();
++      if (CommRegion->HostNormCmdQue.QueueLock == NULL) {
++              return (FALSE);
++      }
++    InitializeNTQueue(Adapter, &CommRegion->HostNormCmdQue, HostNormCmdQueue);
++
++    
++    Queues += HOST_NORM_CMD_ENTRIES;
++
++    // Adapter to Host high priority command queue
++    
++    CommRegion->HostHighCmdQue.Headers.ProducerIndex = Headers++;
++    CommRegion->HostHighCmdQue.Headers.ConsumerIndex = Headers++;
++    *CommRegion->HostHighCmdQue.Headers.ProducerIndex = HOST_HIGH_CMD_ENTRIES;
++    *CommRegion->HostHighCmdQue.Headers.ConsumerIndex = HOST_HIGH_CMD_ENTRIES;
++
++    CommRegion->HostHighCmdQue.SavedIrql = 0;
++    CommRegion->HostHighCmdQue.BaseAddress = Queues;
++    CommRegion->HostHighCmdQue.QueueEntries = HOST_HIGH_CMD_ENTRIES;
++//    CommRegion->HostHighCmdQue.QueueLock = (PKSPIN_LOCK) ExAllocatePool(NonPagedPool, sizeof(KSPIN_LOCK));
++      CommRegion->HostHighCmdQue.QueueLock = OsSpinLockAlloc();
++      if (CommRegion->HostHighCmdQue.QueueLock == NULL) {
++              return (FALSE);
++      }
++    InitializeNTQueue(Adapter, &CommRegion->HostHighCmdQue, HostHighCmdQueue);
++    
++    Queues += HOST_HIGH_CMD_ENTRIES;
++
++    // Host to adapter normal priority command queue
++    
++    CommRegion->AdapNormCmdQue.Headers.ProducerIndex = Headers++;
++    CommRegion->AdapNormCmdQue.Headers.ConsumerIndex = Headers++;
++    *CommRegion->AdapNormCmdQue.Headers.ProducerIndex = ADAP_NORM_CMD_ENTRIES;
++    *CommRegion->AdapNormCmdQue.Headers.ConsumerIndex = ADAP_NORM_CMD_ENTRIES;
++
++    CommRegion->AdapNormCmdQue.SavedIrql = 0;    
++    CommRegion->AdapNormCmdQue.BaseAddress = Queues;
++    CommRegion->AdapNormCmdQue.QueueEntries = ADAP_NORM_CMD_ENTRIES;
++    InitializeNTQueue(Adapter, &CommRegion->AdapNormCmdQue, AdapNormCmdQueue);
++    
++    Queues += ADAP_NORM_CMD_ENTRIES;
++
++    // host to adapter high priority command queue
++    
++    CommRegion->AdapHighCmdQue.Headers.ProducerIndex = Headers++;
++    CommRegion->AdapHighCmdQue.Headers.ConsumerIndex = Headers++;
++    *CommRegion->AdapHighCmdQue.Headers.ProducerIndex = ADAP_HIGH_CMD_ENTRIES;
++    *CommRegion->AdapHighCmdQue.Headers.ConsumerIndex = ADAP_HIGH_CMD_ENTRIES;
++
++    CommRegion->AdapHighCmdQue.SavedIrql = 0;    
++    CommRegion->AdapHighCmdQue.BaseAddress = Queues;
++    CommRegion->AdapHighCmdQue.QueueEntries = ADAP_HIGH_CMD_ENTRIES;
++    InitializeNTQueue(Adapter, &CommRegion->AdapHighCmdQue, AdapHighCmdQueue);
++    
++    Queues += ADAP_HIGH_CMD_ENTRIES;
++
++    // adapter to host normal priority response queue
++    
++    CommRegion->HostNormRespQue.Headers.ProducerIndex = Headers++;
++    CommRegion->HostNormRespQue.Headers.ConsumerIndex = Headers++;
++    *CommRegion->HostNormRespQue.Headers.ProducerIndex = HOST_NORM_RESP_ENTRIES;
++    *CommRegion->HostNormRespQue.Headers.ConsumerIndex = HOST_NORM_RESP_ENTRIES;
++
++    CommRegion->HostNormRespQue.SavedIrql = 0;    
++    CommRegion->HostNormRespQue.BaseAddress = Queues;
++    CommRegion->HostNormRespQue.QueueEntries = HOST_NORM_RESP_ENTRIES;
++//    CommRegion->HostNormRespQue.QueueLock = (PKSPIN_LOCK) ExAllocatePool(NonPagedPool, sizeof(KSPIN_LOCK));
++      CommRegion->HostNormRespQue.QueueLock = OsSpinLockAlloc();
++      if (CommRegion->HostNormRespQue.QueueLock == NULL) {
++              return (FALSE);
++      }
++    InitializeNTQueue(Adapter, &CommRegion->HostNormRespQue, HostNormRespQueue);
++    
++    Queues += HOST_NORM_RESP_ENTRIES;
++
++    // adapter to host high priority response queue
++    
++    CommRegion->HostHighRespQue.Headers.ProducerIndex = Headers++;
++    CommRegion->HostHighRespQue.Headers.ConsumerIndex = Headers++;
++    *CommRegion->HostHighRespQue.Headers.ProducerIndex = HOST_HIGH_RESP_ENTRIES;
++    *CommRegion->HostHighRespQue.Headers.ConsumerIndex = HOST_HIGH_RESP_ENTRIES;
++
++    CommRegion->HostHighRespQue.SavedIrql = 0;    
++    CommRegion->HostHighRespQue.BaseAddress = Queues;
++    CommRegion->HostHighRespQue.QueueEntries = HOST_HIGH_RESP_ENTRIES;
++//    CommRegion->HostHighRespQue.QueueLock = (PKSPIN_LOCK) ExAllocatePool(NonPagedPool, sizeof(KSPIN_LOCK));
++      CommRegion->HostHighRespQue.QueueLock = OsSpinLockAlloc();
++      if (CommRegion->HostHighRespQue.QueueLock == NULL) {
++              return (FALSE);
++      }
++    InitializeNTQueue(Adapter, &CommRegion->HostHighRespQue, HostHighRespQueue);
++    
++    Queues += HOST_HIGH_RESP_ENTRIES;
++
++    // host to adapter normal priority response queue
++    
++    CommRegion->AdapNormRespQue.Headers.ProducerIndex = Headers++;
++    CommRegion->AdapNormRespQue.Headers.ConsumerIndex = Headers++;
++    *CommRegion->AdapNormRespQue.Headers.ProducerIndex = ADAP_NORM_RESP_ENTRIES;
++    *CommRegion->AdapNormRespQue.Headers.ConsumerIndex = ADAP_NORM_RESP_ENTRIES;
++
++    CommRegion->AdapNormRespQue.SavedIrql = 0;    
++    CommRegion->AdapNormRespQue.BaseAddress = Queues;
++    CommRegion->AdapNormRespQue.QueueEntries = ADAP_NORM_RESP_ENTRIES;
++    InitializeNTQueue(Adapter, &CommRegion->AdapNormRespQue, AdapNormRespQueue);
++    
++    Queues += ADAP_NORM_RESP_ENTRIES;
++
++    // host to adapter high priority response queue
++    
++    CommRegion->AdapHighRespQue.Headers.ProducerIndex = Headers++;
++    CommRegion->AdapHighRespQue.Headers.ConsumerIndex = Headers++;
++    *CommRegion->AdapHighRespQue.Headers.ProducerIndex = ADAP_HIGH_RESP_ENTRIES;
++    *CommRegion->AdapHighRespQue.Headers.ConsumerIndex = ADAP_HIGH_RESP_ENTRIES;
++
++    CommRegion->AdapHighRespQue.SavedIrql = 0;    
++    CommRegion->AdapHighRespQue.BaseAddress = Queues;
++    CommRegion->AdapHighRespQue.QueueEntries = ADAP_HIGH_RESP_ENTRIES;
++    InitializeNTQueue(Adapter, &CommRegion->AdapHighRespQue, AdapHighRespQueue);
++
++      CommRegion->AdapNormCmdQue.QueueLock = CommRegion->HostNormRespQue.QueueLock;
++      CommRegion->AdapHighCmdQue.QueueLock = CommRegion->HostHighRespQue.QueueLock;
++      CommRegion->AdapNormRespQue.QueueLock = CommRegion->HostNormCmdQue.QueueLock;
++      CommRegion->AdapHighRespQue.QueueLock = CommRegion->HostHighCmdQue.QueueLock;
++
++    return(TRUE);
++}
++
++AAC_STATUS
++AfaCommShutdown(
++      PAFA_COMM_ADAPTER Adapter
++      )
++/*++
++
++Routine Description:
++
++      This routine will send a shutdown request to each adapter.
++
++Arguments:
++
++      Adapter - which adapter to send the shutdown to.
++
++Return Value:
++
++    NT Status success.
++
++--*/
++
++{
++      PFIB_CONTEXT FibContext;
++      PCLOSECOMMAND CloseCommand;
++      AAC_STATUS Status;
++
++      FibContext = AllocateFib( Adapter );
++
++      InitializeFib( FibContext );
++
++      CloseCommand = (PCLOSECOMMAND) FsaGetFibData( FibContext );
++
++      CloseCommand->Command = VM_CloseAll;
++      CloseCommand->ContainerId = 0xffffffff;
++
++      Status = SendFib( ContainerCommand, FibContext, sizeof(CLOSECOMMAND), FsaNormal, TRUE, NULL, TRUE, NULL, NULL );
++
++      if (Status != STATUS_SUCCESS) {
++
++              FreeFib( FibContext );
++
++              goto ret;
++
++      }
++
++      CompleteFib( FibContext );
++
++      FreeFib( FibContext );
++
++
++      Status = STATUS_SUCCESS;
++
++ret:
++
++      return (Status);
++
++}
++
++VOID
++AfaCommBugcheckHandler(
++              IN PVOID Buffer,
++              IN ULONG Length
++              )
++/*++
++
++Routine Description:
++
++      This routine will shutdown the adapter if there is a bugcheck and
++      copy the shutdown data from the adapter response into the buffer
++      so it will show up in the host dump file.
++p
++Arguments:
++
++      Buffer - This buffer will be written to the host dump by nt for us.
++
++      Length - The size of the buffer.
++
++Return Value:
++
++      N/A
++
++--*/
++{
++      PAFA_COMM_ADAPTER Adapter = FsaCommData.AdapterList;
++
++      while (Adapter) {
++
++              NotifyAdapter(Adapter, HostShutdown);
++
++              Adapter = Adapter->NextAdapter;
++
++      }
++
++}     
++
++VOID
++FsaCommLogEvent(
++      PFIB_CONTEXT FibContext, 
++      PDEVICE_OBJECT DeviceObject,
++      AAC_STATUS FsaStatus,
++      AAC_STATUS AacStatus,
++      ULONG LocationCode,
++      USHORT Category,
++      PUCHAR String,
++      BOOLEAN DumpFib
++)
++{
++}
++
++AfaCommProbeDisks(
++      PAFA_COMM_ADAPTER       Adapter
++      )
++{
++    PMNTINFO DiskInfo;
++    PMNTINFORESPONSE DiskInfoResponse;
++      AAC_STATUS Status;
++      PCOMM_FIB_CONTEXT FibContext;
++    
++      FibContext = AllocateFib( Adapter );
++
++      InitializeFib( FibContext );
++
++      DiskInfo = (PMNTINFO) FibContext->Fib->data;
++      DiskInfo->Command = VM_NameServe;
++      DiskInfo->MntCount = 0;
++      DiskInfo->MntType = FT_FILESYS;
++
++    Status = SendFib(ContainerCommand,
++                           FibContext,
++                       sizeof(MNTINFO),
++                       FsaNormal,
++                       TRUE,
++                       NULL,
++                       TRUE,
++                       NULL,
++                       NULL);
++
++      DiskInfoResponse = (PMNTINFORESPONSE) FibContext->Fib->data;
++
++      if (DiskInfoResponse->MntRespCount) {
++
++              cmn_err(CE_CONT, "container found on adapter, size = 0x%x blocks\n", 
++                              DiskInfoResponse->MntTable[0].Capacity);
++                              
++      } else {
++      
++              cmn_err(CE_CONT, "no containers found on adapter\n");
++              
++      }
++                                      
++      CompleteFib( FibContext );
++      
++      FreeFib( FibContext );                           
++}
++
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/commsup.c linux/drivers/scsi/aacraid/commsup.c
+--- linux-2.4.9/drivers/scsi/aacraid/commsup.c Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/commsup.c       Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,2185 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *  commsup.c
++ *
++ * Abstract: Contain all routines that are required for FSA host/adapter
++ *    commuication.
++ *
++ *
++ --*/
++
++static char *ident_commsup = "aacraid_ident commsup.c 1.0.7 2000/10/11 Adaptec, Inc.";
++
++#include "comprocs.h"
++
++#define BugCheckFileId                   (FSAFS_BUG_CHECK_COMMSUP)
++
++int CommPrinting;
++
++void
++ThrottleExceptionHandler(
++      IN PCOMM_REGION CommRegion,
++      AAC_STATUS              Status
++      );
++
++void ThrottlePeriodEndDpcRtn(
++    IN PKDPC Dpc,
++    IN PVOID DeferredContext,
++    IN PVOID SystemArgument1,
++    IN PVOID SystemArgument2
++    );
++
++
++/*++
++
++Routine Description:
++
++      This routine will free all resources used by a given FibContextSegment.
++
++Arguments:
++
++      Adapter - The adapter that this COMM_FIB_CONTEXT will communicate with.
++      ZoneSegment - The segment to release resources from.
++
++Return Value:
++
++      TRUE - All resources were properly freed.
++      FALSE - An Error occured while freeing resources.
++
++--*/
++BOOLEAN
++FsaFreeFibContextSegment (PAFA_COMM_ADAPTER Adapter,
++                                                PFIB_CONTEXT_ZONE_SEGMENT     ZoneSegment)
++{
++      PCOMM_FIB_CONTEXT FibContext;
++      int i;
++      
++      // Account for the ZONE_SEGMENT_HEADER before the first actual FibContext.
++
++      for (i = 0, FibContext = (PCOMM_FIB_CONTEXT)((PUCHAR)ZoneSegment->FibContextSegment + sizeof(ZONE_SEGMENT_HEADER));
++               i < ZoneSegment->ExtendSize; i++, FibContext++) {
++
++              OsCvLockDestroy( FibContext->FsaEventMutex );
++              OsCv_destroy( &FibContext->FsaEvent );
++
++      }
++
++      UnmapAndFreeFibSpace( Adapter, &ZoneSegment->MapFibContext );
++
++      OsFreeMemory( ZoneSegment->FibContextSegment, ZoneSegment->FibContextSegmentSize );
++
++      OsFreeMemory( ZoneSegment, sizeof( FIB_CONTEXT_ZONE_SEGMENT ) );
++
++      return (TRUE);
++}
++
++BOOLEAN
++FsaFreeFibContextZone(
++      PAFA_COMM_ADAPTER Adapter
++      )
++/*++
++
++Routine Description:
++
++      This routine will walk through the FibContextSegmentList and free up all
++      resources used by the FibContextZone.
++
++Arguments:
++
++      Adapter - The adapter that this COMM_FIB_CONTEXT will communicate with.
++
++Return Value:
++
++      TRUE - All resources were properly freed.
++      FALSE - An Error occured while freeing resources.
++
++--*/
++
++{
++      PFIB_CONTEXT_ZONE_SEGMENT ZoneSegment, NextZoneSegment;
++
++      ZoneSegment = Adapter->FibContextSegmentList;
++
++      while (ZoneSegment) {
++
++              NextZoneSegment = ZoneSegment->Next;
++
++              FsaFreeFibContextSegment( Adapter, ZoneSegment );
++
++              ZoneSegment = NextZoneSegment;
++      }
++
++      return (TRUE);
++}
++
++      
++
++BOOLEAN
++FsaExtendFibContextZone (IN PAFA_COMM_ADAPTER Adapter)
++{
++    int ExtendSize;
++    KIRQL SavedIrql;
++      ULONG ZoneSegmentAllocSize, FibAllocSize;
++      PVOID FibContextSegment;
++      PCOMM_FIB_CONTEXT FibContext;
++      PFIB Fib;
++      PVOID FibPhysicalAddress;
++      int i;
++      PFIB_CONTEXT_ZONE_SEGMENT ZoneSegment;
++      
++      //
++      // Allocate space to describe this zone segment.
++      //
++
++      cmn_err (CE_DEBUG, "Entered FsaExtendFibContextZone");
++      ZoneSegment = OsAllocMemory( sizeof( FIB_CONTEXT_ZONE_SEGMENT ), OS_ALLOC_MEM_SLEEP );
++      if (ZoneSegment == NULL) {
++              return (FALSE);
++      }
++
++      ExtendSize = Adapter->FibContextZoneExtendSize;
++      ZoneSegmentAllocSize = (ExtendSize * sizeof(COMM_FIB_CONTEXT)) + sizeof(ZONE_SEGMENT_HEADER);
++
++      FibContextSegment = OsAllocMemory( ZoneSegmentAllocSize, OS_ALLOC_MEM_SLEEP );
++
++      if (FibContextSegment == NULL) {
++              OsFreeMemory(ZoneSegment);
++              return (FALSE);
++      }       
++
++      RtlZeroMemory( FibContextSegment, ZoneSegmentAllocSize );
++
++      ZoneSegment->FibContextSegment = FibContextSegment;
++      ZoneSegment->FibContextSegmentSize = ZoneSegmentAllocSize;
++      ZoneSegment->ExtendSize = ExtendSize;
++
++      FibAllocSize = ExtendSize * sizeof(FIB);
++
++
++      ZoneSegment->MapFibContext.Size = FibAllocSize;
++
++      AllocateAndMapFibSpace( Adapter, &ZoneSegment->MapFibContext );
++
++      Fib = ZoneSegment->MapFibContext.FibVirtualAddress;
++      FibPhysicalAddress = ZoneSegment->MapFibContext.FibPhysicalAddress;
++
++      RtlZeroMemory( Fib, FibAllocSize );
++
++      // Account for the ZONE_SEGMENT_HEADER before the first actual FibContext.
++
++      for (i = 0, FibContext = (PCOMM_FIB_CONTEXT)((PUCHAR)FibContextSegment + sizeof(ZONE_SEGMENT_HEADER));
++               i < ExtendSize; i++, FibContext++) {
++
++              FibContext->Adapter = Adapter;
++
++              FibContext->Fib = Fib;
++              FibContext->FibData = (PVOID) FibContext->Fib->data;
++
++              OsCv_init( &FibContext->FsaEvent);
++              FibContext->FsaEventMutex = OsCvLockAlloc();
++              OsCvLockInit( FibContext->FsaEventMutex, Adapter->SpinLockCookie );
++
++              Fib->Header.XferState = 0xffffffff;
++              Fib->Header.SenderSize = sizeof(FIB);
++
++              FibContext->LogicalFibAddress.LowPart = (ULONG) FibPhysicalAddress;
++
++              Fib = (PFIB)((PUCHAR)Fib + sizeof(FIB));
++              FibPhysicalAddress = (PVOID)((PUCHAR)FibPhysicalAddress + sizeof(FIB));
++      }
++
++      //
++      // If FibContextZone.TotalSegmentSize is non-zero, then a zone has already been
++      // initialized, we just need to extend it.
++      //
++
++      if (Adapter->FibContextZone.TotalSegmentSize) {
++
++              OsSpinLockAcquire( Adapter->FibContextZoneSpinLock );
++
++              ExExtendZone( &Adapter->FibContextZone,
++                                        FibContextSegment,
++                                        ZoneSegmentAllocSize );
++
++              OsSpinLockRelease( Adapter->FibContextZoneSpinLock );
++
++      } else {
++
++          if (ExInitializeZone( &Adapter->FibContextZone,
++                                                        sizeof(COMM_FIB_CONTEXT),
++                            FibContextSegment,
++                                ZoneSegmentAllocSize ) != STATUS_SUCCESS)
++                      FsaBugCheck(0,0,0);
++
++      }
++
++      //
++      // Add this segment to the adapter's list of segments
++      //
++
++      ZoneSegment->Next = Adapter->FibContextSegmentList;
++      Adapter->FibContextSegmentList = ZoneSegment;
++
++      return (TRUE);
++}
++
++
++
++/*++
++
++Routine Description:
++
++    This routine creates a new COMM_FIB_CONTEXT record
++
++Arguments:
++
++      Adapter - The adapter that this COMM_FIB_CONTEXT will communicate with.
++
++Return Value:
++
++    PCOMM_FIB_CONTEXT - returns a pointer to the newly allocate COMM_FIB_CONTEXT Record
++
++--*/
++PFIB_CONTEXT
++AllocateFib (IN PVOID AdapterArg)
++{
++      PAFA_COMM_ADAPTER Adapter = (PAFA_COMM_ADAPTER) AdapterArg;
++    KIRQL SavedIrql;
++    PCOMM_FIB_CONTEXT FibContext;
++      int FullZoneLoopCounter = 0;
++        
++
++        //
++      // Acquire the zone spin lock, and check to see if the zone is full.
++      // If it is, then release the spin lock and allocate more fibs for the 
++      // zone.  The ExtendFibZone routine will re-acquire the spin lock to add
++      // the new fibs onto the zone.
++        //
++
++    OsSpinLockAcquire( Adapter->FibContextZoneSpinLock );
++
++    while (ExIsFullZone( &Adapter->FibContextZone )) {
++
++              if (++FullZoneLoopCounter >  10)
++                      FsaBugCheck(0,0,0);
++
++              OsSpinLockRelease( Adapter->FibContextZoneSpinLock );
++
++                // bmb debug
++                cmn_err (CE_DEBUG, "Extending FibContextZone");
++              if (FsaExtendFibContextZone(Adapter) == FALSE) {
++                      return (NULL);
++              }
++
++                OsSpinLockAcquire( Adapter->FibContextZoneSpinLock );
++
++      }
++
++    //
++      //  At this point we now know that the zone has at least one more
++    //  IRP context record available.  So allocate from the zone and
++    //  then release the mutex.
++    //
++
++    FibContext = (PCOMM_FIB_CONTEXT) ExAllocateFromZone( &Adapter->FibContextZone );
++
++      OsSpinLockRelease( Adapter->FibContextZoneSpinLock );
++
++    //
++    //  Set the proper node type code and node byte size
++    //
++
++    FibContext->NodeTypeCode = FSAFS_NTC_FIB_CONTEXT;
++    FibContext->NodeByteSize = sizeof( COMM_FIB_CONTEXT );
++
++      // 
++      // Null out fields that depend on being zero at the start of each I/O
++      //
++
++      FibContext->Fib->Header.XferState = 0;
++      FibContext->FibCallback = NULL;
++      FibContext->FibCallbackContext = NULL;
++
++
++    //
++    //  return and tell the caller
++    //
++
++    return ((PFIB_CONTEXT) FibContext);
++}
++
++
++/*++
++
++Routine Description:
++
++    This routine deallocates and removes the specified COMM_FIB_CONTEXT record
++    from the Fsafs in memory data structures.  It should only be called
++    by FsaCompleteRequest.
++
++Arguments:
++
++      FibContext - Supplies the COMM_FIB_CONTEXT to remove
++
++Return Value:
++
++    None
++
++--*/
++VOID
++FreeFib (IN PFIB_CONTEXT Context)
++{
++    KIRQL SavedIrql;
++      PCOMM_FIB_CONTEXT FibContext = Context;
++
++    ASSERT(FibContext->NodeTypeCode == FSAFS_NTC_FIB_CONTEXT);
++
++    OsSpinLockAcquire( FibContext->Adapter->FibContextZoneSpinLock );
++
++      if (FibContext->Flags & FIB_CONTEXT_FLAG_TIMED_OUT) {
++
++              FsaCommData.TimedOutFibs++;
++
++              FibContext->Next = FibContext->Adapter->FibContextTimedOutList;
++              FibContext->Adapter->FibContextTimedOutList = FibContext;
++
++      } else {
++
++          ASSERT(FibContext->Fib->Header.XferState == 0);
++
++              if (FibContext->Fib->Header.XferState != 0) {
++                              cmn_err(CE_WARN, "FreeFib, XferState != 0, FibContext = 0x%x, XferState = 0x%x\n", 
++                                       FibContext, FibContext->Fib->Header.XferState);
++              }
++
++          ExFreeToZone( &FibContext->Adapter->FibContextZone, FibContext );
++
++      }       
++
++      OsSpinLockRelease( FibContext->Adapter->FibContextZoneSpinLock );
++
++    //
++    //  return and tell the caller
++    //
++
++    return;
++}
++
++
++/*++
++
++Routine Description:
++
++    This routine deallocates and removes the specified COMM_FIB_CONTEXT record
++    from the Fsafs in memory data structures.  It should only be called
++    from the dpc routines to from dpc to free an FibContext from an async or
++      no response io
++
++Arguments:
++
++    FibContext - Supplies the COMM_FIB_CONTEXT to remove
++
++Return Value:
++
++    None
++
++--*/
++VOID
++FreeFibFromDpc (IN PFIB_CONTEXT Context)
++{
++    PCOMM_FIB_CONTEXT FibContext = (PCOMM_FIB_CONTEXT) Context;
++
++    ASSERT(FibContext->NodeTypeCode == FSAFS_NTC_FIB_CONTEXT);
++
++    OsSpinLockAcquire(FibContext->Adapter->FibContextZoneSpinLock);
++
++      if (FibContext->Flags & FIB_CONTEXT_FLAG_TIMED_OUT) {
++
++              FsaCommData.TimedOutFibs++;
++
++              FibContext->Next = FibContext->Adapter->FibContextTimedOutList;
++              FibContext->Adapter->FibContextTimedOutList = FibContext;
++
++      } else {
++
++          ASSERT(FibContext->Fib->Header.XferState == 0);
++
++              if (FibContext->Fib->Header.XferState != 0) {
++                              cmn_err(CE_WARN, "FreeFibFromDpc, XferState != 0, FibContext = 0x%x, XferState = 0x%x\n", 
++                                       FibContext, FibContext->Fib->Header.XferState);
++              }
++
++
++          ExFreeToZone( &FibContext->Adapter->FibContextZone, FibContext );
++
++      }
++              
++      OsSpinLockRelease(FibContext->Adapter->FibContextZoneSpinLock);
++
++    //
++    //  return and tell the caller
++    //
++
++    return;
++}
++
++
++/*++
++
++Routine Description:
++
++    Will initialize a FIB of the requested size.
++    
++Arguments:
++
++    Fib is a pointer to a location which will receive the address of the allocated
++        FIB.
++
++    Size is the size of the Fib to allocate.
++
++Return Value:
++
++    NT_SUCCESS if a Fib was returned to the caller.
++    NT_ERROR if event was an invalid event. 
++
++--*/
++AAC_STATUS
++InitializeFib (IN PFIB_CONTEXT Context)
++{
++    PCOMM_FIB_CONTEXT FibContext = (PCOMM_FIB_CONTEXT) Context;
++      PFIB Fib = FibContext->Fib;
++
++    Fib->Header.StructType = TFib;
++    Fib->Header.Size = sizeof(FIB);
++//    if (Fib->Header.XferState & AllocatedFromPool)
++//        Fib->Header.XferState = HostOwned | FibInitialized | FibEmpty | AllocatedFromPool;
++//    else
++        Fib->Header.XferState = HostOwned | FibInitialized | FibEmpty | FastResponseCapable;
++    Fib->Header.SenderFibAddress = 0;
++    Fib->Header.ReceiverFibAddress = 0;
++    Fib->Header.SenderSize = sizeof(FIB);
++
++    return(STATUS_SUCCESS);
++}
++    
++
++/*++
++
++Routine Description:
++
++    Will allocate and initialize a FIB of the requested size and return a
++    pointer to the structure. The size allocated may be larger than the size
++    requested due to allocation performace optimizations.
++    
++Arguments:
++
++    Fib is a pointer to a location which will receive the address of the allocated
++        FIB.
++
++    Size is the size of the Fib to allocate.
++
++    JustInitialize is a boolean which indicates a Fib has been allocated most likly in an
++        imbedded structure the FS always allocates. So just initiaize it and return.
++    
++Return Value:
++
++    NT_SUCCESS if a Fib was returned to the caller.
++    NT_ERROR if event was an invalid event. 
++
++--*/
++AAC_STATUS
++AllocatePoolFib (OUT PFIB *Fib, IN USHORT Size)
++{}
++    
++
++/*++
++
++Routine Description:
++
++    Will deallocate and return to the free pool the FIB pointed to by the
++    caller. Upon return accessing locations pointed to by the FIB parameter
++    could cause system access faults.
++
++Arguments:
++
++    Fib is a pointer to the FIB that caller wishes to deallocate.
++    
++Return Value:
++
++    NT_SUCCESS if a Fib was returned to the caller.
++    NT_ERROR if event was an invalid event. 
++
++--*/
++AAC_STATUS
++DeallocateFib (PFIB_CONTEXT Context)
++{
++    PCOMM_FIB_CONTEXT FibContext = (PCOMM_FIB_CONTEXT) Context;
++      PFIB Fib = FibContext->Fib;
++
++    if ( Fib->Header.StructType != TFib ) {
++        FsaCommPrint("Error CompleteFib called with a non Fib structure.\n");
++        return(STATUS_UNSUCCESSFUL);
++    }
++
++
++    Fib->Header.XferState = 0;        
++        
++    return(STATUS_SUCCESS);
++
++}
++
++
++AAC_STATUS
++GetResponse(
++    IN PCOMM_QUE ResponseQueue,
++    OUT PFIB Fib
++    )
++/*++
++
++Routine Description:
++
++    Gets a QE off the requested response queue and gets the response FIB into
++    host memory. The FIB may already be in host memory depending on the bus
++    interface, or may require the host to DMA it over from the adapter. The routine
++    will return the FIB to the caller.
++
++Arguments:
++
++    ResponseQueue - Is the queue the caller wishes to have the response gotten from.
++    Fib - Is the Fib which was the response from the adapter
++
++Return Value:
++
++    NT_SUCCESS if a Fib was returned to the caller.
++    NT_ERROR if there was no Fib to return to the caller.
++    bkpfix - add in all the other possible errors ect
++
++--*/
++{
++return(STATUS_UNSUCCESSFUL);
++}
++
++//
++// Commuication primitives define and support the queuing method we use to
++// support host to adapter commuication. All queue accesses happen through
++// these routines and are the only routines which have a knowledge of the
++// how these queues are implemented.
++//
++
++
++/*++
++
++Routine Description:
++
++    With a priority the routine returns a queue entry if the queue has free entries. If the queue
++    is full(no free entries) than no entry is returned and the function returns FALSE otherwise TRUE is
++    returned.
++
++Arguments:
++
++    Priority is an enumerated type which determines which priority level
++        command queue the QE is going to be queued on.
++
++    Entry is a pointer to the address of where to return the address of
++        the queue entry from the requested command queue.
++
++    Index is a pointer to the address of where to store the index of the new
++        queue entry returned.
++
++      DontInterrupt - We set this true if the queue state is such that we don't
++              need to interrupt the adapter for this queue entry.
++
++Return Value:
++
++    TRUE - If a queue entry is returned
++    FALSE - If there are no free queue entries on the requested command queue.
++
++--*/
++BOOLEAN
++GetEntry (IN PAFA_COMM_ADAPTER Adapter, IN QUEUE_TYPES WhichQueue,
++                OUT PQUEUE_ENTRY *Entry, OUT PQUEUE_INDEX Index,
++                OUT ULONG *DontInterrupt)
++{
++    ULONG QueueOffset;
++      BOOLEAN status;
++      PCOMM_REGION CommRegion;
++
++      CommRegion = Adapter->CommRegion;
++
++    //
++    // All of the queues wrap when they reach the end, so we check to see if they
++    // have reached the end and if they have we just set the index back to zero.
++    // This is a wrap. You could or off the high bits in all updates but this is
++    // a bit faster I think.
++    //
++
++    if (WhichQueue == AdapHighCmdQueue) {
++        *Index = *(CommRegion->AdapHighCmdQue.Headers.ProducerIndex);
++
++              if (*Index - 2 == *(CommRegion->AdapHighCmdQue.Headers.ConsumerIndex))
++                      *DontInterrupt = TRUE; 
++
++        if (*Index >= ADAP_HIGH_CMD_ENTRIES)
++            *Index = 0;
++
++        if (*Index + 1 == *(CommRegion->AdapHighCmdQue.Headers.ConsumerIndex)) { // Queue is full
++                      status = FALSE;
++                      cmn_err(CE_WARN, "Adapter High Command Queue full, %d outstanding",
++                                      CommRegion->AdapHighCmdQue.NumOutstandingIos);
++              } else {
++              QueueOffset = sizeof(QUEUE_ENTRY) * (*Index);
++              *Entry = QueueOffset + CommRegion->AdapHighCmdQue.BaseAddress;
++
++                      status = TRUE;
++              }
++    } else if (WhichQueue == AdapNormCmdQueue) {
++
++        *Index = *(CommRegion->AdapNormCmdQue.Headers.ProducerIndex);
++
++              if (*Index - 2 == *(CommRegion->AdapNormCmdQue.Headers.ConsumerIndex))
++                      *DontInterrupt = TRUE; 
++
++              //
++              // If we are at the end of the QUEUE then wrap back to 
++              // the beginning.
++        //
++
++        if (*Index >= ADAP_NORM_CMD_ENTRIES) 
++            *Index = 0; // Wrap to front of the Producer Queue.
++
++              //
++        // The IEEE spec says that it the producer is one behind the consumer then
++        // the queue is full.
++        //       
++
++              ASSERT(*(CommRegion->AdapNormCmdQue.Headers.ConsumerIndex) != 0);
++
++        if (*Index + 1 == *(CommRegion->AdapNormCmdQue.Headers.ConsumerIndex)) { // Queue is full
++                      cmn_err(CE_WARN, "Adapter Norm Command Queue full, %d outstanding",
++                                      CommRegion->AdapNormCmdQue.NumOutstandingIos);
++                      status = FALSE;
++              } else {        
++              //
++                      // The success case just falls through and returns the a valid queue entry.
++                      //
++
++#ifdef commdebug
++              FsaCommPrint("queue entry = %x.\n",CommRegion->AdapNormCmdQue.BaseAddress + *Index);
++              FsaCommPrint("GetEntry: Index = %d, QueueOffset = %x, Entry = %x, *Entry = %x.\n",
++                           *Index, QueueOffset, Entry, *Entry);
++#endif
++              *Entry = CommRegion->AdapNormCmdQue.BaseAddress + *Index;
++
++                      status = TRUE;
++              }
++    } else if (WhichQueue == AdapHighRespQueue) {
++
++        *Index = *(CommRegion->AdapHighRespQue.Headers.ProducerIndex);
++
++              if (*Index - 2 == *(CommRegion->AdapHighRespQue.Headers.ConsumerIndex))
++                      *DontInterrupt = TRUE; 
++
++        if (*Index >= ADAP_HIGH_RESP_ENTRIES)
++            *Index = 0;
++
++        if (*Index + 1 == *(CommRegion->AdapHighRespQue.Headers.ConsumerIndex)) { // Queue is full
++                      status = FALSE;
++                      cmn_err(CE_WARN, "Adapter High Resp Queue full, %d outstanding",
++                                      CommRegion->AdapHighRespQue.NumOutstandingIos);
++              } else {                                                        
++              *Entry = CommRegion->AdapHighRespQue.BaseAddress + *Index;
++              status = TRUE;
++              } 
++    } else if (WhichQueue == AdapNormRespQueue) {
++
++        *Index = *(CommRegion->AdapNormRespQue.Headers.ProducerIndex);
++
++              if (*Index - 2 == *(CommRegion->AdapNormRespQue.Headers.ConsumerIndex))
++                      *DontInterrupt = TRUE; 
++
++              //
++              // If we are at the end of the QUEUE then wrap back to 
++              // the beginning.
++        //
++
++        if (*Index >= ADAP_NORM_RESP_ENTRIES) 
++            *Index = 0; // Wrap to front of the Producer Queue.
++
++              //
++        // The IEEE spec says that it the producer is one behind the consumer then
++        // the queue is full.
++        //       
++
++        if (*Index + 1 == *(CommRegion->AdapNormRespQue.Headers.ConsumerIndex)) { // Queue is full
++                      status = FALSE; 
++                      cmn_err(CE_WARN, "Adapter Norm Resp Queue full, %d outstanding",
++                                      CommRegion->AdapNormRespQue.NumOutstandingIos);
++              } else {        
++              //
++                      // The success case just falls through and returns the a valid queue entry.
++                      //
++
++              *Entry = CommRegion->AdapNormRespQue.BaseAddress + *Index;
++
++#ifdef commdebug
++              FsaCommPrint("queue entry = %x.\n",CommRegion->AdapNormRespQue.BaseAddress + *Index);
++              FsaCommPrint("GetEntry: Index = %d, Entry = %x, *Entry = %x.\n",*Index, Entry, *Entry);
++#endif
++                      status = TRUE;
++              }     
++    } else {
++              cmn_err(CE_PANIC, "GetEntry: invalid queue %d", WhichQueue);
++      }
++
++
++      return (status);
++}
++   
++
++
++#ifdef API_THROTTLE
++
++void ThrottleCheck(
++      IN PAFA_COMM_ADAPTER Adapter,
++      IN PFIB Fib
++      )
++/*++
++
++Routine Description:
++
++    This routine implements data I/O throttling. Throttling occurs when
++      a CLI FIB is detected. To ensure the CLI responds quickly (the user
++      is waiting for the response), this mechanism restricts the queue
++      depth of data IOs at the adapter for a period of time (called the
++      Throttle Period, default 5 seconds).
++
++    The mechanism uses a counted semaphore to place threads into a wait
++      state should there be too many data I/Os outstanding.
++
++      At the start of a throttle period (indicated by the first CLI FIB)
++      a timer is started. When the timer expires, new requests can go to
++      the adapter freely. Throttled requests gradually drain to the
++      adapter as each outstanding throttle I/O completes.
++
++    To avoid hurting regular I/O performance, we use a flag in the FIB
++      header to mark FIBs involved in throttling. This means we only need
++      take the extra spinlock in the response DPC routine for FIBs who
++      were subject to throttling. If no throttling is occurring, the cost
++      to the regular code paths is a handful of instructions.
++
++Arguments:
++
++      Adapter - Pointer to per-adapter context. This is used to locate the
++                        throttle information for this adapter.
++      
++      Fib             - Pointer to the header for the fib being sent.
++
++Return Value:
++
++      None.
++
++--*/
++{
++      PCOMM_REGION CommRegion = Adapter->CommRegion;
++      AAC_STATUS       Status;
++
++      //
++      // This routine is called under protection of the queue spinlock.
++      // As such we are allowed to check and change the counts for the
++      // throttle.
++      // Check the FIB. If its not a data operation, send it on without
++      // throttle check. If it is a data operation, check for throttle.
++      //
++
++      CommRegion->TotalFibs++;                                                        // Keep statistics
++
++      if ((Fib->Header.XferState & ApiFib) != 0) {
++
++              CommRegion->ApiFibs++;                                                  // Keep statistics
++
++              //
++              // Its an API fib. If the throttle is not already active,
++              // make it so. This will prevent new data Fibs being sent
++              // if they exceed the throttle check.
++              //
++
++              if (!CommRegion->ThrottleActive) {
++                      BOOLEAN          InQue;
++
++                      CommRegion->ThrottleActive = TRUE;                      // This causes new data I/Os to be throttled
++
++                      //
++                      // Schedule a timer for the throttle active period. When
++                      // it expires, we'll be called back at routine ThrottleDpcRoutine
++                      // above. This will signify the throttle active period ended
++                      // and any waiting threads will be signalled to restart.
++                      //
++
++                      FsaCommPrint("Throttle Period Start - CommRegion: %x\n", CommRegion);
++                      CommRegion->ThrottleTimerSets++;
++                      InQue = KeSetTimer( &CommRegion->ThrottleTimer,
++                                                              CommRegion->ThrottleTimeout,
++                                                              &CommRegion->ThrottleDpc);
++                      ASSERT(InQue == FALSE);
++              }
++
++              return;
++      }
++
++      //
++      // Its a non-API fib, so subject to throttle checks.
++      // The following are exempt from throttling:
++      //              o FIBs marked as "throttle exempt" by upper layers.
++      //              o I/Os issued from a raised IRQL. We can't suspend
++      //                a thread when at raised IRQL so throttling is exempt.
++      //
++
++      if (CommRegion->AdapNormCmdQue.SavedIrql != PASSIVE_LEVEL) {
++
++              CommRegion->NonPassiveFibs++;
++              FsaCommPrint("ThrottleCheck: Non-Passive level FIB bypasses throttle: %x\n", Fib);
++              return;
++
++      }
++
++      if (CommRegion->ThrottleActive) {
++
++              //
++              // Throttle is active.
++              // Check if the FIB is a read or write. If so, and its to the
++              // file system information area, let it through without throttling.
++              //
++
++              if (Fib->Header.Command == ContainerCommand) {
++                      PBLOCKREAD BlockDisk = (PBLOCKREAD) &Fib->data;
++
++                      //
++                      // *** Note *** We are using read and write command formats
++                      // interchangably here. This is ok for this purpose as the
++                      // command is in the same place for both. Read and write command
++                      // formats are different at higher offsets though.
++                      //
++
++                      if ( ((BlockDisk->Command == VM_CtBlockRead) ||
++                                (BlockDisk->Command == VM_CtBlockWrite)) &&
++                                (BlockDisk->BlockNumber <= FILESYSTEM_INFO_MAX_BLKNO)) {
++
++                              CommRegion->FSInfoFibs++;                                                       // Keep statistics
++                              return;
++
++                      }
++
++              }
++
++              //
++              // Throttle the FIB.
++              // Mark it as throttle active so that it can signal a waiter
++              // when it completes.
++
++              CommRegion->ThrottledFibs++;
++              Fib->Header.Flags |= ThrottledFib;
++              
++              //
++              // Release the spinlock so we can wait the thread if necessary.
++              // Since we specify a timeout, check the caller is at passive level.
++              //
++
++              OsSpinLockRelease((CommRegion->AdapNormCmdQue.QueueLock), CommRegion->AdapNormCmdQue.SavedIrql);
++
++              FsaCommPrint("ThrottleCheck - Thread Suspension - FIB: %x\n", Fib);
++
++              Status = KeWaitForSingleObject(&CommRegion->ThrottleReleaseSema,
++                                                                              Executive,                                                      // Don't allow user APCs to wake us
++                                                                              KernelMode,                                                     // Wait in kernel mode
++                                                                              FALSE,                                                          // Not alertable
++                                                                              &CommRegion->ThrottleWaitTimeout);      // Timeout after this time
++
++              //
++              // Check the signal status. If we've timed out, clear the throttle
++              // flag on the FIB to avoid us signalling the semaphore on completion.
++              // We never acquired the semaphore.
++              //
++              if (Status == STATUS_TIMEOUT) {
++
++                      CommRegion->ThrottleTimedoutFibs++;
++                      FsaCommPrint("ThrottledFib Timed Out - FIB: %x\n", Fib);
++                      Fib->Header.Flags &= ~ThrottledFib;                                             // Clear the throttledfib flag
++
++              } else {
++
++                      ASSERT(Status == STATUS_SUCCESS);                                               // No other return is possible
++
++              }
++
++              //
++              // We've been woken up and can now send the FIB to the adapter.
++              // Acquire the spinlock again so we can get a queue entry. This
++              // returns to GetQueueEntry.
++              //
++
++              FsaCommPrint("ThrottleCheck - Thread Resume - FIB: %x\n", Fib);
++              KeAcquireSpinLock((CommRegion->AdapNormCmdQue.QueueLock), &(CommRegion->AdapNormCmdQue.SavedIrql));
++              CommRegion->ThrottleOutstandingFibs++;          // There's another throttle controlled FIB going.
++              return;
++
++      }
++}
++
++#endif //#ifdef API_THROTTLE
++
++int GetQueueEntryTimeouts = 0;
++
++
++/*++
++
++Routine Description:
++
++    Gets the next free QE off the requested priorty adapter command queue and
++    associates the Fib with the QE. The QE represented by index is ready to
++     insert on the queue when this routine returns success.
++
++Arguments:
++
++    Index is the returned value which represents the QE which is ready to
++        insert on the adapter's command queue.
++
++    Priority is an enumerated type which determines which priority level
++        command queue the QE is going to be queued on.
++
++    Fib is a pointer to the FIB the caller wishes to have associated with the
++        QE.
++
++    Wait is a boolean which determines if the routine will wait if there are
++        no free QEs on the requested priority command queue.
++
++    FibContext is where the driver stores all system resources required to execute the
++        command requested from the calling thread. This includes mapping resources for
++        the FIB and the 'users' buffer.
++
++      DontInterrupt - We set this true if the queue state is such that we don't
++              need to interrupt the adapter for this queue entry.
++
++Return Value:
++
++    NT_SUCCESS if a Fib was returned to the caller.
++    NT_ERROR if event was an invalid event. 
++
++--*/
++AAC_STATUS
++GetQueueEntry (IN PAFA_COMM_ADAPTER Adapter, OUT PQUEUE_INDEX Index,
++                         IN QUEUE_TYPES WhichQueue, IN PFIB Fib, IN BOOLEAN Wait,
++                         IN PCOMM_FIB_CONTEXT FibContext, OUT ULONG *DontInterrupt)
++{
++    PQUEUE_ENTRY QueueEntry = NULL;
++    BOOLEAN MapAddress = FALSE;
++      int timeouts = 0;
++      AAC_STATUS Status;
++      PCOMM_REGION CommRegion;
++
++      CommRegion = Adapter->CommRegion;
++
++    //
++    // Get the spinlock for the queue we are putting a command on
++    //
++
++    if (WhichQueue == AdapHighCmdQueue) 
++        OsSpinLockAcquire(CommRegion->AdapHighCmdQue.QueueLock);
++    else if (WhichQueue == AdapNormCmdQueue)
++        OsSpinLockAcquire(CommRegion->AdapNormCmdQue.QueueLock);
++    else if (WhichQueue == AdapHighRespQueue)
++        OsSpinLockAcquire(CommRegion->AdapHighRespQue.QueueLock);
++    else if (WhichQueue == AdapNormRespQueue)
++        OsSpinLockAcquire(CommRegion->AdapNormRespQue.QueueLock);
++    else {
++        FsaCommPrint("Invalid queue priority passed to GetQueueEntry.\n");
++        return(FSA_INVALID_QUEUE);
++    }
++    
++    //
++    // Get the pointers to a queue entry on the queue the caller wishes to queue
++    // a command request on. If there are no entries then wait if that is what the
++    // caller requested. 
++    //
++
++    if (WhichQueue == AdapHighCmdQueue) {
++        // if no entries wait for some if caller wants to
++        while ( !GetEntry(Adapter, AdapHighCmdQueue, &QueueEntry, Index, DontInterrupt) ) { 
++                      cmn_err(CE_PANIC, "GetEntries failed (1)\n");
++              }
++
++        //
++        // Setup queue entry with a command, status and Fib mapped
++        //
++
++        QueueEntry->Size = Fib->Header.Size;
++        MapAddress = TRUE;
++      
++    } else if (WhichQueue == AdapNormCmdQueue) {
++        // if no entries wait for some if caller wants to
++        while ( !GetEntry(Adapter, AdapNormCmdQueue, &QueueEntry, Index, DontInterrupt) ) { 
++                      cmn_err(CE_PANIC, "GetEntries failed (2)\n");
++              }
++ 
++        //
++        // Setup queue entry with command, status and Fib mapped
++        //
++
++        QueueEntry->Size = Fib->Header.Size;
++        MapAddress = TRUE;
++        
++     } else if (WhichQueue == AdapHighRespQueue) {
++
++        while ( !GetEntry(Adapter, AdapHighRespQueue, &QueueEntry, Index, DontInterrupt) ) { // if no entries wait for some if caller wants to
++              }
++
++        //
++        // Setup queue entry with command, status and Fib mapped
++        //
++
++        QueueEntry->Size = Fib->Header.Size;
++        QueueEntry->FibAddress = Fib->Header.SenderFibAddress;                        // Restore adapters pointer to the FIB
++              Fib->Header.ReceiverFibAddress = Fib->Header.SenderFibAddress;          // Let the adapter now where to find its data
++        MapAddress = FALSE;
++        
++     } else if (WhichQueue == AdapNormRespQueue) {
++        while ( !GetEntry(Adapter, AdapNormRespQueue, &QueueEntry, Index, DontInterrupt) ) { // if no entries wait for some if caller wants to
++              }
++
++              //
++              // Setup queue entry with command, status, adapter's pointer to the Fib it sent
++              //
++      
++        QueueEntry->Size = Fib->Header.Size;
++        QueueEntry->FibAddress = Fib->Header.SenderFibAddress;                        // Restore adapters pointer to the FIB
++              Fib->Header.ReceiverFibAddress = Fib->Header.SenderFibAddress;          // Let the adapter now where to find its data
++        MapAddress = FALSE;
++     }
++                
++    //
++    // If MapFib is true than we need to map the Fib and put pointers in the queue entry.
++    //
++
++    if (MapAddress) {
++              QueueEntry->FibAddress = (ULONG)(FibContext->LogicalFibAddress.LowPart);
++    }
++    
++    //
++    // Return
++    //
++#ifdef commdebug    
++    FsaCommPrint("Queue Entry contents:.\n");
++    FsaCommPrint("  Command =               %d.\n", QueueEntry->Command);
++    FsaCommPrint("  Status  =               %x.\n", QueueEntry->Status);
++    FsaCommPrint("  Rec Fib address low =   %x.\n", QueueEntry->FibAddressLow);        
++    FsaCommPrint("  Fib size in bytes =     %d.\n", QueueEntry->Size);
++#endif
++
++    return(FSA_SUCCESS);
++}
++
++
++/*++
++
++Routine Description:
++
++    Gets the next free QE off the requested priorty adapter command queue and
++      associates the Fib with the QE. The QE represented by index is ready to
++    insert on the queue when this routine returns success.
++
++Arguments:
++
++    Index is the returned value which represents the QE which is ready to
++        insert on the adapter's command queue.
++
++    WhichQueue tells us which queue the caller wishes to have the entry put.
++        
++Return Value:
++
++    NT_SUCCESS if a Fib was returned to the caller.
++    NT_ERROR if event was an invalid event. 
++
++--*/
++AAC_STATUS
++InsertQueueEntry(
++                 IN PAFA_COMM_ADAPTER Adapter,
++                 IN QUEUE_INDEX Index,
++                 IN QUEUE_TYPES WhichQueue,
++                 IN ULONG DontInterrupt
++                 )
++{
++      PCOMM_REGION CommRegion;
++    
++      CommRegion = Adapter->CommRegion;
++
++    //
++    // We have already verified the queue in getentry, but we still have to make
++    // sure we don't wrap here too.
++    //
++
++    if (WhichQueue == AdapHighCmdQueue) {
++
++        *(CommRegion->AdapHighCmdQue.Headers.ProducerIndex) = Index + 1;
++            
++        OsSpinLockRelease(CommRegion->AdapHighCmdQue.QueueLock);
++
++              if (!DontInterrupt)
++              NotifyAdapter(Adapter, AdapHighCmdQue);
++        
++    } else if (WhichQueue == AdapNormCmdQueue) {
++
++#ifdef commdebug
++        FsaCommPrint("InsertQueueEntry: Inerting with an index of %d.\n",Index);
++#endif
++        *(CommRegion->AdapNormCmdQue.Headers.ProducerIndex) = Index + 1;
++      
++        OsSpinLockRelease(CommRegion->AdapNormCmdQue.QueueLock);
++
++              if (!DontInterrupt)
++              NotifyAdapter(Adapter, AdapNormCmdQue);
++
++    } else if (WhichQueue == AdapHighRespQueue) {
++
++        *(CommRegion->AdapHighRespQue.Headers.ProducerIndex) = Index + 1;
++
++        OsSpinLockRelease(CommRegion->AdapHighRespQue.QueueLock);
++
++              if (!DontInterrupt)
++              NotifyAdapter(Adapter, AdapHighRespQue);
++
++    } else if (WhichQueue == AdapNormRespQueue) {
++
++          *(CommRegion->AdapNormRespQue.Headers.ProducerIndex) = Index + 1;
++          
++          OsSpinLockRelease(CommRegion->AdapNormRespQue.QueueLock);
++
++          if (!DontInterrupt)
++                  NotifyAdapter(Adapter, AdapNormRespQue);
++
++    } else {        
++        FsaCommPrint("Invalid queue priority passed to InsertQueueEntry.\n");
++        return(FSA_INVALID_QUEUE_PRIORITY);
++    }
++
++    return(FSA_SUCCESS);                
++}
++
++extern int GatherFibTimes;
++
++BOOLEAN
++SendSynchFib(
++      PVOID                   Arg,
++      FIB_COMMAND     Command,
++      PVOID                   Data,
++      USHORT                  Size,
++      PVOID                   Response,
++      USHORT                  *ResponseSize
++      )
++/*++
++
++Routine Description:
++
++      This routine will send a synchronous FIB to the adapter and wait for its
++      completion.
++
++Arguments:
++
++      DeviceExtension - Pointer to adapter extension structure.
++
++
++Return Value:
++
++      BOOLEAN
++
++--*/
++{
++      PAFA_COMM_ADAPTER Adapter = Arg;
++      FIB *Fib;
++      ULONG returnStatus;
++
++      Fib = Adapter->SyncFib;
++
++    Fib->Header.StructType = TFib;
++    Fib->Header.Size = sizeof(FIB);
++    Fib->Header.XferState = HostOwned | FibInitialized | FibEmpty;
++    Fib->Header.ReceiverFibAddress = 0;
++    Fib->Header.SenderSize = sizeof(FIB);
++    Fib->Header.SenderFibAddress = (ULONG)Fib;
++    Fib->Header.Command = Command;
++
++      //
++      // Copy the Data portion into the Fib.
++      //
++
++      RtlCopyMemory( Fib->data, Data, Size );
++
++
++    Fib->Header.XferState |= (SentFromHost | NormalPriority);
++    
++      //
++    // Set the size of the Fib we want to send to the adapter
++      //
++
++    Fib->Header.Size = sizeof(FIB_HEADER) + Size;
++
++      if (!Adapter->AdapterFuncs->SendSynchFib( Adapter->AdapterExtension,
++                                                                                        Adapter->SyncFibPhysicalAddress )) {
++
++                      return (FALSE);
++
++      }
++
++      //
++      // Copy the response back to the caller's buffer.
++      //
++
++      RtlCopyMemory( Response, Fib->data, Fib->Header.Size - sizeof(FIB_HEADER) );
++
++      *ResponseSize = Fib->Header.Size - sizeof(FIB_HEADER);
++
++      //
++      // Indicate success
++      //
++
++      return (TRUE);
++}
++
++//
++// Define the highest level of host to adapter communication routines. These
++// routines will support host to adapter FS commuication. These routines have
++// no knowledge of the commuication method used. This level sends and receives
++// FIBs. This level has no knowledge of how these FIBs get passed back and forth.
++//
++
++
++
++/*++
++
++Routine Description:
++
++    Sends the requested FIB to the adapter and optionally will wait for a
++     response FIB. If the caller does not wish to wait for a response than
++    an event to wait on must be supplied. This event will be set when a
++    response FIB is received from the adapter.
++
++Arguments:
++
++    Fib is a pointer to the FIB the caller wishes to send to the adapter.
++    
++    Size - Size of the data portion of the Fib.
++    
++    Priority is an enumerated type which determines which priority level
++        the caller wishes to send this command at. 
++
++    Wait is a boolean which determines if the routine will wait for the
++        completion Fib to be returned(TRUE), or return when the Fib has been
++        successfully received by the adapter(FALSE).
++
++    WaitOn is only vaild when Wait is FALSE. The Event will be set when the response
++        FIB has been returned by the adapter.
++
++    ReturnFib is an optional pointer to a FIB that if present the response FIB will
++        copied to.     
++        
++Return Value:
++
++    NT_SUCCESS if a Fib was returned to the caller.
++    NT_ERROR if event was an invalid event. 
++
++      --*/
++AAC_STATUS
++SendFib (IN FIB_COMMAND Command,
++         IN PFIB_CONTEXT Context,
++         IN ULONG Size, 
++         IN COMM_PRIORITIES Priority,
++         IN BOOLEAN Wait,
++         IN PVOID WaitOn,
++         IN BOOLEAN ResponseExpected,
++         IN PFIB_CALLBACK FibCallback,
++         IN PVOID FibCallbackContext)
++{
++              PCOMM_FIB_CONTEXT FibContext = (PCOMM_FIB_CONTEXT) Context;
++              QUEUE_INDEX Index;
++              QUEUE_TYPES WhichQueue;
++              LARGE_INTEGER Timeout;
++              AAC_STATUS Status;
++              PAFA_COMM_ADAPTER Adapter = FibContext->Adapter;
++              ULONG DontInterrupt = FALSE;
++              PFIB Fib = FibContext->Fib;
++              IN PCOMM_QUE OurQueue;
++
++              Timeout = FsaCommData.AdapterTimeout;
++
++              if (!(Fib->Header.XferState & HostOwned)) {
++                              FsaCommPrint("SendFib was called with a xfer state not set to HostOwned!\n");
++                              FsaCommLogEvent(FibContext,
++                                                              FsaCommData.DeviceObject, 
++                                                              FSAFS_FIB_INVALID, 
++                                                              STATUS_UNSUCCESSFUL, 
++                                                              BugCheckFileId | __LINE__,
++                                                              FACILITY_FSAFS_ERROR_CODE,
++                                                              NULL,
++                                                              TRUE);                  
++
++                              return(STATUS_UNSUCCESSFUL);
++
++              }
++    
++              //
++              // There are 5 cases with the wait and reponse requested flags. The only invalid cases
++              // are if the caller requests to wait and  does not request a response and if the
++              // caller does not want a response and the Fib is not allocated from pool. If a response
++              // is not requesed the Fib will just be deallocaed by the DPC routine when the response
++              // comes back from the adapter. No further processing will be done besides deleting the
++              // Fib. We will have a debug mode where the adapter can notify the host it had a problem
++              // and the host can log that fact.
++
++              if (Wait && !ResponseExpected) {
++
++                              FsaCommLogEvent(FibContext,
++                                                FsaCommData.DeviceObject, 
++                                                FSAFS_FIB_INVALID, 
++                                                STATUS_UNSUCCESSFUL, 
++                                                BugCheckFileId | __LINE__,
++                                                FACILITY_FSAFS_ERROR_CODE,
++                                                NULL,
++                                                TRUE);                        
++
++                              return(STATUS_UNSUCCESSFUL);
++
++              } else if (!Wait && ResponseExpected) {
++                              Fib->Header.XferState |= (Async | ResponseExpected);
++                              FIB_COUNTER_INCREMENT(FsaCommData.AsyncSent);
++              } else if (!Wait && !ResponseExpected) {
++                              Fib->Header.XferState |= NoResponseExpected;
++                              FIB_COUNTER_INCREMENT(FsaCommData.NoResponseSent);
++              } else if (Wait && ResponseExpected) {
++                  Fib->Header.XferState |= ResponseExpected;
++                  FIB_COUNTER_INCREMENT(FsaCommData.NormalSent);
++              } 
++
++              Fib->Header.SenderData = (ULONG)FibContext; // so we can complete the io in the dpc routine
++
++              //
++              // Set FIB state to indicate where it came from and if we want a response from the
++              // adapter. Also load the command from the caller.
++              //
++
++              Fib->Header.SenderFibAddress = (ULONG)Fib;
++              Fib->Header.Command = Command;
++              Fib->Header.XferState |= SentFromHost;
++              FibContext->Fib->Header.Flags = 0;                              // Zero the flags field - its internal only...
++    
++              //
++              // Set the size of the Fib we want to send to the adapter
++              //
++
++              Fib->Header.Size = sizeof(FIB_HEADER) + Size;
++              if (Fib->Header.Size > Fib->Header.SenderSize) {
++                              return(STATUS_BUFFER_OVERFLOW);
++              }                
++
++              //
++              // Get a queue entry connect the FIB to it and send an notify the adapter a command is ready.
++              //
++            
++              if (Priority == FsaHigh) {
++                              Fib->Header.XferState |= HighPriority;
++                              WhichQueue = AdapHighCmdQueue;
++                              OurQueue = &Adapter->CommRegion->AdapHighCmdQue;
++              } else {
++                              Fib->Header.XferState |= NormalPriority;
++                              WhichQueue = AdapNormCmdQueue;
++                              OurQueue = &Adapter->CommRegion->AdapNormCmdQue;
++              }
++
++              if (Wait) {
++                              OsCvLockAcquire( FibContext->FsaEventMutex );
++              }
++
++              if ( GetQueueEntry( Adapter, &Index, WhichQueue, Fib, TRUE, FibContext, &DontInterrupt) != FSA_SUCCESS )
++                              return(STATUS_UNSUCCESSFUL);
++
++              // bmb debug
++
++              cmn_err (CE_DEBUG,"SendFib: inserting a queue entry at index %d.\n",Index);
++              cmn_err (CE_DEBUG,"Fib contents:.\n");
++              cmn_err (CE_DEBUG,"  Command =               %d.\n", Fib->Header.Command);
++              cmn_err (CE_DEBUG,"  XferState  =            %x.\n", Fib->Header.XferState );
++
++              //
++              // Fill in the Callback and CallbackContext if we are not going to wait.
++              //
++
++              if (!Wait) {
++
++                              FibContext->FibCallback = FibCallback;
++                              FibContext->FibCallbackContext = FibCallbackContext;
++
++              }
++
++              FIB_COUNTER_INCREMENT(FsaCommData.FibsSent);
++
++              InsertTailList( &OurQueue->OutstandingIoQueue, &FibContext->QueueEntry );
++              OurQueue->NumOutstandingIos++;
++
++              FibContext->FibComplete = 0;
++
++
++
++              if ( InsertQueueEntry( Adapter, Index, WhichQueue, (DontInterrupt & FsaCommData.EnableInterruptModeration)) != FSA_SUCCESS )
++                        return(STATUS_UNSUCCESSFUL);
++
++              //
++              // If the caller wanted us to wait for response wait now. 
++              // If Timeouts are enabled than set the timeout otherwise wait forever.
++              //
++    
++              if (Wait) {
++                        while (FibContext->FibComplete == 0) {
++                                OsCv_wait( &FibContext->FsaEvent, FibContext->FsaEventMutex );
++                        }     
++                        
++                        OsCvLockRelease( FibContext->FsaEventMutex );
++                                      
++                        if ( (FibContext->Flags & FIB_CONTEXT_FLAG_TIMED_OUT) ) {
++                                return(STATUS_IO_TIMEOUT);
++                        } else {
++                                return(STATUS_SUCCESS);
++                        }
++              }
++
++              //
++              // If the user does not want a response than return success otherwise return pending
++              // 
++
++              ASSERT( FibCallback );
++
++              if (ResponseExpected)
++                              return(STATUS_PENDING);
++              else
++                              return(STATUS_SUCCESS);
++}
++
++BOOLEAN
++GetConsumerEntry(
++      IN PAFA_COMM_ADAPTER Adapter,
++    PCOMM_QUE OurQueue,
++    OUT PQUEUE_ENTRY *Entry
++    )
++/*++
++
++Routine Description:
++
++    Will return a pointer to the entry on the top of the queue requested that we are a consumer
++    of, and return the address of the queue entry. It does not change the state of the queue. 
++
++Arguments:
++
++    OurQueue - is the queue the queue entry should be removed from.
++
++    Entry - is a pointer where the address  of the queue entry should be returned.    
++    
++Return Value:
++
++    TRUE if there was a queue entry on the response queue for the host to consume.
++    FALSE if there were no queue entries to consume.
++    
++--*/
++
++{
++    QUEUE_INDEX Index;
++      BOOLEAN status;
++
++    if (*OurQueue->Headers.ProducerIndex == *OurQueue->Headers.ConsumerIndex) {
++              status = FALSE;
++      } else {
++
++          //
++          // The consumer index must be wrapped if we have reached the end of
++          // the queue. 
++          // Else we just use the entry pointed to by the header index
++          //
++          
++          if (*OurQueue->Headers.ConsumerIndex >= OurQueue->QueueEntries) 
++                      Index = 0;              
++          else
++              Index = *OurQueue->Headers.ConsumerIndex;
++          
++          *Entry = OurQueue->BaseAddress + Index;
++
++#ifdef commdebug
++          FsaCommPrint("Got a QE at Index %d, QE Addrss of %x.\n",Index,*Entry);
++#endif
++              status = TRUE;
++      }
++
++    return(status);
++}
++
++BOOLEAN
++ConsumerEntryAvailable(
++      IN PAFA_COMM_ADAPTER Adapter,
++    PCOMM_QUE OurQueue
++      )
++{
++    return (*OurQueue->Headers.ProducerIndex != *OurQueue->Headers.ConsumerIndex);
++}
++
++VOID
++FreeConsumerEntry(
++      IN PAFA_COMM_ADAPTER Adapter,
++    PCOMM_QUE OurQueue,
++    QUEUE_TYPES WhichQueue
++    )
++/*++
++
++Routine Description:
++
++    Frees up the current top of the queue we are a consumer of. If the queue was full
++    notify the producer that the queue is no longer full.
++
++Arguments:
++
++    OurQueue - is the queue we will free the current consumer entry on.
++
++Return Value:
++
++    TRUE if there was a queue entry on the response queue for the host to consume.
++    FALSE if there were no queue entries to consume.
++    
++--*/
++
++{
++    BOOLEAN WasFull = FALSE;
++    HOST_2_ADAP_EVENT Notify;
++
++    if (*OurQueue->Headers.ProducerIndex+1 == *OurQueue->Headers.ConsumerIndex)
++        WasFull = TRUE;
++        
++    if (*OurQueue->Headers.ConsumerIndex >= OurQueue->QueueEntries)
++        *OurQueue->Headers.ConsumerIndex = 1;
++    else
++        *OurQueue->Headers.ConsumerIndex += 1;
++        
++    if (WasFull) {
++        switch (WhichQueue) {
++
++            case HostNormCmdQueue:
++                Notify = HostNormCmdNotFull;
++                break;
++            case HostHighCmdQueue:
++                Notify = HostHighCmdNotFull;
++                break;
++
++            case HostNormRespQueue:
++                Notify = HostNormRespNotFull;
++                break;
++
++            case HostHighRespQueue:
++                Notify = HostHighRespNotFull;
++                break;
++
++        }
++        NotifyAdapter(Adapter, Notify);
++    }
++
++}        
++
++AAC_STATUS
++CompleteAdapterFib(
++      IN PFIB_CONTEXT Context,
++    IN USHORT Size
++    )
++/*++
++
++Routine Description:
++
++    Will do all necessary work to complete a FIB that was sent from the adapter.
++
++Arguments:
++
++    Fib is a pointer to the FIB that caller wishes to complete processing on. 
++
++    Size - Size of the completion Packet(Opitional). If not present than the current
++           largest size in the Fib will be used
++    
++      Adapter - Pointer to which adapter sent this FIB
++
++Return Value:
++
++    NT_SUCCESS if a Fib was returned to the caller.
++    NT_ERROR if event was an invalid event. 
++
++--*/
++{
++      PCOMM_FIB_CONTEXT FibContext = Context;
++    PFIB Fib = FibContext->Fib;
++      PAFA_COMM_ADAPTER Adapter = FibContext->Adapter;
++    ULONG DontInterrupt = FALSE;
++
++    if (Fib->Header.XferState == 0)
++        return(STATUS_SUCCESS);
++
++    //
++    // If we plan to do anything check the structure type first.
++    // 
++
++    if ( Fib->Header.StructType != TFib ) {
++        FsaCommPrint("Error CompleteFib called with a non Fib structure.\n");
++        return(STATUS_UNSUCCESSFUL);
++    }
++
++    //
++    // This block handles the case where the adapter had sent us a command and we
++    // have finished processing the command. We call completeFib when we are done
++    // processing the command and want to send a response back to the adapter. This
++    // will send the completed cdb to the adapter.
++    //
++
++    if (Fib->Header.XferState & SentFromAdapter) {
++        Fib->Header.XferState |= HostProcessed;
++        if (Fib->Header.XferState & HighPriority) {
++            QUEUE_INDEX Index;
++            
++            if (Size) {
++                Size += sizeof(FIB_HEADER);
++                if (Size > Fib->Header.SenderSize) 
++                    return(STATUS_BUFFER_OVERFLOW);
++                Fib->Header.Size = Size;
++            }
++
++            if (GetQueueEntry(Adapter, &Index, AdapHighRespQueue, Fib, TRUE, NULL, &DontInterrupt) != STATUS_SUCCESS) {
++                FsaCommPrint("CompleteFib got an error geting a queue entry for a response.\n");
++                return(FSA_FATAL);
++            }
++            if (InsertQueueEntry(Adapter, 
++                                              Index, 
++                                              AdapHighRespQueue, 
++                                              (DontInterrupt & (BOOLEAN)FsaCommData.EnableInterruptModeration)) != STATUS_SUCCESS) {
++                FsaCommPrint("CompleteFib failed while inserting entry on the queue.\n");
++            }
++        } else if (Fib->Header.XferState & NormalPriority) {
++            QUEUE_INDEX Index;
++
++            if (Size) {
++                Size += sizeof(FIB_HEADER);
++                if (Size > Fib->Header.SenderSize) 
++                    return(STATUS_BUFFER_OVERFLOW);
++                Fib->Header.Size = Size;
++            }
++            
++            if (GetQueueEntry(Adapter, &Index, AdapNormRespQueue, Fib, TRUE, NULL, &DontInterrupt) != STATUS_SUCCESS) {
++                FsaCommPrint("CompleteFib got an error geting a queue entry for a response.\n");
++                return(FSA_FATAL);
++            }
++            if (InsertQueueEntry(Adapter, 
++                                              Index, 
++                                              AdapNormRespQueue, 
++                                              (DontInterrupt & (BOOLEAN)FsaCommData.EnableInterruptModeration)) != STATUS_SUCCESS) {
++                FsaCommPrint("CompleteFib failed while inserting entry on the queue.\n");
++            }
++              }
++    } else {
++        cmn_err(CE_WARN, "CompleteFib: Unknown xferstate detected.\n");
++              FsaBugCheck(0,0,0);
++    }   
++    return(STATUS_SUCCESS);
++}
++
++AAC_STATUS
++CompleteFib(
++      IN PFIB_CONTEXT Context
++    )
++/*++
++
++Routine Description:
++
++    Will do all necessary work to complete a FIB. If the caller wishes to
++    reuse the FIB after post processing has been completed Reinitialize
++    should be called set to TRUE, otherwise the FIB will be returned to the
++    free FIB pool. If Reinitialize is set to TRUE then the FIB header is
++    reinitialzied and is ready for reuse on return from this routine.
++
++Arguments:
++
++    Fib is a pointer to the FIB that caller wishes to complete processing on. 
++
++    Size - Size of the completion Packet(Opitional). If not present than the current
++           largest size in the Fib will be used
++    
++    Reinitialize is a boolean which determines if the routine will ready the
++        completed FIB for reuse(TRUE) or not(FALSE).
++
++Return Value:
++
++    NT_SUCCESS if a Fib was returned to the caller.
++    NT_ERROR if event was an invalid event. 
++
++--*/
++{
++    PCOMM_FIB_CONTEXT FibContext = (PCOMM_FIB_CONTEXT) Context;
++      PAFA_COMM_ADAPTER Adapter = FibContext->Adapter;
++      PFIB Fib = FibContext->Fib;
++
++    //
++    // Check for a fib which has already been completed
++    //
++
++//    ASSERT(Fib->Header.XferState & AdapterProcessed);
++    if (Fib->Header.XferState == 0)
++        return(STATUS_SUCCESS);
++
++    //
++    // If we plan to do anything check the structure type first.
++    // 
++
++    if ( Fib->Header.StructType != TFib ) {
++        FsaCommPrint("Error CompleteFib called with a non Fib structure.\n");
++        return(STATUS_UNSUCCESSFUL);
++    }
++
++#if 0
++//#if FSA_ADAPTER_METER
++      //
++      // Meter the completion
++      //
++      fsaMeterEnd(                                            // meter the end of an operation
++              &(Adapter->FibMeter),                   // .. the meter
++              IrpContext->FibMeterType,               // .. type of operation
++              &(IrpContext->FibStartTime),    // .. ptr to operation start timestamp
++              FibGetMeterSize(Fib,                    // .. number of bytes in operation
++                              IrpContext->FibMeterType, 
++                              IrpContext->FibSubCommand));
++#endif // FSA_ADAPTER_METER
++      
++    //
++    // This block completes a cdb which orginated on the host and we just need
++    // to deallocate the cdb or reinit it. At this point the command is complete
++    // that we had sent to the adapter and this cdb could be reused.
++    //
++      
++    if ( (Fib->Header.XferState & SentFromHost) &&
++         (Fib->Header.XferState & AdapterProcessed)) {
++        
++        ASSERT(FibContext->LogicalFibAddress.LowPart != 0);
++
++        return( DeallocateFib(FibContext) ); 
++      
++    //
++    // This handles the case when the host has aborted the I/O to the
++    // adapter because the adapter is not responding
++    //
++
++    } else if (Fib->Header.XferState & SentFromHost) {
++
++        ASSERT(FibContext->LogicalFibAddress.LowPart != 0);
++
++
++        return( DeallocateFib(FibContext) ); 
++
++    } else if (Fib->Header.XferState & HostOwned) {
++
++        return(DeallocateFib(FibContext));
++
++    } else {
++        cmn_err(CE_WARN, "CompleteFib: Unknown xferstate detected.\n");
++              FsaBugCheck(0,0,0);
++    }   
++    return(STATUS_SUCCESS);
++}
++
++VOID
++HandleDriverAif(
++    IN PAFA_COMM_ADAPTER Adapter,
++      IN PCOMM_FIB_CONTEXT FibContext
++    )
++/*++
++
++Routine Description:
++
++      This routine handles a driver notify fib from the adapter and dispatches it to 
++      the appropriate routine for handling.
++
++Arguments:
++
++      Adapter - Which adapter this fib is from
++      FibContext - Pointer to FibContext from adapter.
++    
++Return Value:
++
++    Nothing.
++    
++--*/
++{
++      PFIB Fib = FibContext->Fib;
++      PAFA_CLASS_DRIVER ClassDriver;
++      BOOLEAN Handled = FALSE;
++
++
++      //
++      // First loop through all of the class drivers to give them a chance to handle
++      // the Fib.
++      //
++
++      ClassDriver = Adapter->ClassDriverList;
++
++      while (ClassDriver) {
++
++              if (ClassDriver->HandleAif) {
++
++                      if (ClassDriver->HandleAif( ClassDriver->ClassDriverExtension, FibContext ) ) {
++
++                              Handled = TRUE;
++                              break;
++
++                      }
++              }
++
++              ClassDriver = ClassDriver->Next;
++      }
++
++      if (!Handled) {
++
++              //
++              // Set the status of this FIB to be Invalid parameter.
++              //
++
++//            *(FSASTATUS *)Fib->data = ST_INVAL;
++              *(FSASTATUS *)Fib->data = ST_OK;
++
++
++              CompleteAdapterFib(FibContext, sizeof(FSASTATUS));
++
++      }
++}
++
++int
++NormCommandThread(
++    IN PAFA_COMM_ADAPTER Adapter
++    )
++/*++
++
++Routine Description:
++
++    Waits on the commandready event in it's queue. When the event gets set it will
++    pull FIBs off it's queue. It will continue to pull FIBs off till the queue is empty.
++    When the queue is empty it will wait for more FIBs.
++
++Arguments:
++
++    Context is used. All data os global
++    
++Return Value:
++    Nothing.
++    
++--*/
++{
++    PFIB Fib, NewFib;
++      COMM_FIB_CONTEXT FibContext; // for error logging
++    KIRQL SavedIrql;
++      PCOMM_REGION CommRegion = Adapter->CommRegion;
++      PLIST_ENTRY Entry;
++      PGET_ADAPTER_FIB_CONTEXT AdapterFibContext;
++
++      //
++      // We can only have one thread per adapter for AIF's.
++      //
++
++      if (Adapter->AifThreadStarted) {
++              return (EINVAL);
++      }
++
++// cmn_err(CE_DEBUG, "AIF thread started");
++
++      //
++      // Let the DPC know it has a place to send the AIF's to.
++      //
++
++      Adapter->AifThreadStarted = TRUE;
++
++      RtlZeroMemory(&FibContext, sizeof(COMM_FIB_CONTEXT));
++
++      OsSpinLockAcquire(CommRegion->HostNormCmdQue.QueueLock);
++
++    while (TRUE) {
++
++              //
++              // NOTE : the QueueLock is held at the top of each loop.
++              //
++
++              ASSERT(OsSpinLockOwned(CommRegion->HostNormCmdQue.QueueLock));
++
++              while (!IsListEmpty(&(CommRegion->HostNormCmdQue.CommandQueue))) {
++                      PLIST_ENTRY Entry;
++                      PAIFCOMMANDTOHOST AifCommandToHost;
++
++                      Entry = RemoveHeadList(&(CommRegion->HostNormCmdQue.CommandQueue));
++
++                      OsSpinLockRelease(CommRegion->HostNormCmdQue.QueueLock);
++
++                      Fib = CONTAINING_RECORD( Entry, FIB, Header.FibLinks );
++                                              
++                      //
++                      // We will process the FIB here or pass it to a worker thread that is TBD. We Really
++                      // can't do anything at this point since we don't have anything defined for this thread to
++                      // do.
++                      //
++                      
++                      // cmn_err(CE_DEBUG, "Got Fib from the adapter with a NORMAL priority, command 0x%x.\n", Fib->Header.Command);
++
++                      RtlZeroMemory( &FibContext, sizeof(COMM_FIB_CONTEXT) );
++
++
++                  FibContext.NodeTypeCode = FSAFS_NTC_FIB_CONTEXT;
++                  FibContext.NodeByteSize = sizeof( COMM_FIB_CONTEXT );
++                      FibContext.Fib = Fib;
++                      FibContext.FibData = Fib->data;
++                      FibContext.Adapter = Adapter;
++
++                      
++                      //
++                      // We only handle AifRequest fibs from the adapter.
++                      //
++
++                      ASSERT(Fib->Header.Command == AifRequest);
++
++
++                      AifCommandToHost = (PAIFCOMMANDTOHOST) Fib->data;
++
++                      if (AifCommandToHost->command == AifCmdDriverNotify) {
++
++
++
++                              HandleDriverAif( Adapter, &FibContext );
++
++                      } else {
++                                      AAC_UINT32 time_now, time_last;
++                                      time_now = (AAC_UINT32)OsGetSeconds();
++                      
++
++                              OsCvLockAcquire(Adapter->AdapterFibMutex);
++
++                              Entry = Adapter->AdapterFibContextList.Flink;
++
++                              //
++                              // For each Context that is on the AdapterFibContextList, make a copy of the
++                              // fib, and then set the event to wake up the thread that is waiting for it.
++                              //
++
++                              while (Entry != &Adapter->AdapterFibContextList) {
++
++                                      //
++                                      // Extract the AdapterFibContext
++                                      //
++
++                                      AdapterFibContext = CONTAINING_RECORD( Entry, GET_ADAPTER_FIB_CONTEXT, NextContext );
++
++                                      //
++                                      // Check if the queue is getting backlogged
++                                      //
++                                      if ( AdapterFibContext->FibCount > 20 ) {
++                                              time_last = (AAC_UINT32)(AdapterFibContext->FileObject);
++
++                                              //
++                                              // has it been > 2 minutes since the last read off the queue?
++                                              //
++                                              if ((time_now - time_last) > 120) {
++                                                      Entry = Entry->Flink;
++                                                      // cmn_err (CE_WARN, "aifd: Flushing orphaned AdapterFibContext: idle %d seconds, %d fibs",
++                                                      //               time_now - time_last,
++                                                      //               AdapterFibContext->FibCount);
++                                                      FsaCloseAdapterFibContext ( Adapter, AdapterFibContext );
++                                                      continue;
++                                              }
++                                      }
++                                                                      
++//  Warning: sleep possible while holding spinlock
++                                      NewFib = OsAllocMemory(sizeof(FIB), OS_ALLOC_MEM_SLEEP);
++
++                                      if (NewFib) {
++
++                                              //
++                                              // Make the copy of the FIB
++                                              //
++
++                                              RtlCopyMemory(NewFib, Fib, sizeof(FIB));
++
++                                              //
++                                              // Put the FIB onto the AdapterFibContext's FibList
++                                              //
++
++                                              InsertTailList(&AdapterFibContext->FibList, &NewFib->Header.FibLinks);
++                                              AdapterFibContext->FibCount++;
++
++                                              // 
++                                              // Set the event to wake up the thread that will waiting.
++                                              //
++
++                                              OsCv_signal(&AdapterFibContext->UserEvent);
++
++                                      } else {
++
++                                              cmn_err (CE_WARN, "aifd: didn't allocate NewFib");
++
++                                      }
++
++                                      Entry = Entry->Flink;
++                              }
++
++                              //
++                              // Set the status of this FIB
++                              //
++
++                              *(FSASTATUS *)Fib->data = ST_OK;
++                              
++                              CompleteAdapterFib( &FibContext, sizeof(FSASTATUS) );
++
++                              OsCvLockRelease(Adapter->AdapterFibMutex);
++
++                      }
++
++                      OsSpinLockAcquire(CommRegion->HostNormCmdQue.QueueLock);
++
++              }
++
++              //
++              // There are no more AIF's,  call cv_wait_sig to wait for more
++              // to process.
++              //
++
++              // cmn_err(CE_DEBUG, "no more AIF's going to sleep\n");
++
++              if (OsCv_wait_sig( &(CommRegion->HostNormCmdQue.CommandReady), 
++                                               CommRegion->HostNormCmdQue.QueueLock ) == 0) {
++
++                      OsSpinLockRelease(CommRegion->HostNormCmdQue.QueueLock);
++
++                      Adapter->AifThreadStarted = FALSE;
++
++                      // cmn_err(CE_DEBUG, "AifThread awoken by a signal\n");
++                      
++                      return (EINTR);
++                      
++              }                                
++
++              // cmn_err(CE_DEBUG, "Aif thread awake, going to look for more AIF's\n");
++
++      }
++}
++    
++
++PVOID
++FsaGetFibData(
++      IN PFIB_CONTEXT Context
++      )
++{
++    PCOMM_FIB_CONTEXT FibContext = (PCOMM_FIB_CONTEXT) Context;
++
++      return ((PVOID)FibContext->Fib->data);
++}         
++                              
++
++#ifdef API_THROTTLE
++
++void ThrottlePeriodEndDpcRtn(
++    IN PKDPC Dpc,
++    IN PVOID DeferredContext,
++    IN PVOID SystemArgument1,
++    IN PVOID SystemArgument2
++    )
++/*++
++
++Routine Description:
++
++    This routine is called as a DPC when a throttle period expires. It
++      restarts all threads suspended due to the throttling flow control.
++      
++      The throttling counted semaphore is signalled for all waiting threads
++      and the indicator of throttling active is cleared.
++
++Arguments:
++
++    Dpc                               - Pointer to Dpc structure. Not used.
++      DefferedContext - Pointer to per-adapter context. This is used to locate the
++                                        throttle information for this adapter.
++    SystemArgument1   - Not used
++      SystemArgument2 - Not used
++      
++Return Value:
++
++      None.
++
++--*/
++{
++      PCOMM_REGION CommRegion;
++      PAFA_COMM_ADAPTER Adapter = (PAFA_COMM_ADAPTER) DeferredContext;
++
++      CommRegion = Adapter->CommRegion;
++
++      //
++      // Acquire the spinlock protecting the throttle status.
++      //
++      OsSpinLockAcquire(CommRegion->AdapNormCmdQue.QueueLock);
++
++      FsaCommPrint("ThrottlePeriodEndDpc\n");
++
++      //
++      // Check that the timer has fired as many times as it was set !
++      //
++
++      CommRegion->ThrottleTimerFires++;
++      ASSERT(CommRegion->ThrottleTimerFires == CommRegion->ThrottleTimerSets);
++
++      //
++      // The throttle period is now over. Restart all threads waiting
++      // on the throttle being released.
++      // Clear the throttle active indicator. This will allow new FIBs
++      // to be sent to the adapter once we release the spinlock on exiting
++      // the DPC. This means all restarted threads will be runnable
++      // threads by then.
++      //
++
++      ASSERT(CommRegion->ThrottleActive == TRUE);             // The throttle had better be on !
++      CommRegion->ThrottleActive = FALSE;                             // This allows new data FIBs to go to the adapter on dpc exit
++
++      OsSpinLockRelease(CommRegion->AdapNormCmdQue.QueueLock);
++}
++
++#endif // #ifdef API_THROTTLE
++
++/*
++ * Overrides for Emacs so that we almost follow Linus's tabbing style.
++ * Emacs will notice this stuff at the end of the file and automatically
++ * adjust the settings for this buffer only.  This must remain at the end
++ * of the file.
++ * ---------------------------------------------------------------------------
++ * Local variables:
++ * c-indent-level: 4
++ * c-brace-imaginary-offset: 0
++ * c-brace-offset: -4
++ * c-argdecl-indent: 4
++ * c-label-offset: -4
++ * c-continued-statement-offset: 4
++ * c-continued-brace-offset: 0
++ * indent-tabs-mode: nil
++ * tab-width: 8
++ * End:
++ */
+diff -burN linux-2.4.9/drivers/scsi/aacraid/dpcsup.c linux/drivers/scsi/aacraid/dpcsup.c
+--- linux-2.4.9/drivers/scsi/aacraid/dpcsup.c  Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/dpcsup.c        Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,443 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *  dpcsup.c
++ *
++ * Abstract: All DPC processing routines for the cyclone board occur here.
++ *
++ *
++ --*/
++
++static char *ident_dpcsup = "aacraid_ident dpcsup.c 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#include "comprocs.h"
++
++
++//
++//  The Bug check file id for this module
++//
++
++#define BugCheckFileId                   (FSAFS_BUG_CHECK_DPCSUP)
++
++#define Dbg                              (DEBUG_TRACE_DPCSUP)
++
++u_int
++CommonNotFullDpc(
++      IN PCOMM_REGION CommRegion
++    )
++/*++
++
++Routine Description:
++
++    This DPC routine will be queued when the adapter interrupts us to let us know the queue is
++    no longer full. The Isr will pass the queue that we will set the not full event.
++
++Arguments:
++
++    Dpc - Pointer to this routine.
++
++    Dummy - is a pointer to the comm region which is global so we don't need it anyway
++
++    Queue is a pointer to the queue structure we will operate on.
++
++    MoreData2 are DPC parameters we don't need for this function. Maybe we can add some accounting
++        stuff in here.
++
++Return Value:
++    Nothing.
++
++--*/
++{
++
++#ifdef unix_queue_full
++    KeSetEvent(&Queue->QueueFull, 0, FALSE);
++#endif
++
++}
++
++int GatherFibTimes = 0;
++
++// XXX - hack this in until I figure out which header file should contain it. <smb>
++extern ULONG
++FibGetMeterSize(
++    PFIB pFib,
++      ULONG MeterType,
++      char SubCommand
++      );
++
++
++/*++
++
++Routine Description:
++
++    This DPC routine will be queued when the adapter interrupts us to let us know there
++    is a response on our normal priority queue. We will pull off all QE there are and wake
++    up all the waiters before exiting. We will take a spinlock out on the queue before operating
++    on it.
++
++Arguments:
++
++    Dpc - Pointer to this routine.
++
++    OurQueue is a pointer to the queue structure we will operate on.
++
++    MoreData1&2 are DPC parameters we don't need for this function. Maybe we can add some accounting
++        stuff in here.
++
++Return Value:
++    Nothing.
++
++--*/
++u_int
++HostResponseNormalDpc (IN PCOMM_QUE OurQueue)
++{
++    PAFA_COMM_ADAPTER Adapter = OurQueue->Adapter;
++    PQUEUE_ENTRY QueueEntry;
++    PFIB Fib;
++      PCOMM_FIB_CONTEXT FibContext;
++    int Consumed = 0;
++      KIRQL OldIrql;
++
++      LARGE_INTEGER ResponseAllocSize;
++
++#ifdef commdebug
++    FsaCommPrint("entering the host normal reponse dpc routine.\n");
++#endif
++
++      OsSpinLockAcquire( OurQueue->QueueLock );       
++
++    //
++    // Keep pulling response QEs off the response queue and waking
++    // up the waiters until there are no more QEs. We then return
++    // back to the system. If no response was requesed we just
++    // deallocate the Fib here and continue.
++    //
++
++ loop:
++    while ( GetConsumerEntry( Adapter, OurQueue, &QueueEntry) ) {
++
++              int IsFastResponse;
++
++              IsFastResponse = (int) (QueueEntry->FibAddress & 0x01);
++              Fib = (PFIB) (QueueEntry->FibAddress & ~0x01);
++
++              FreeConsumerEntry(Adapter, OurQueue, HostNormRespQueue);
++
++              FibContext = (PCOMM_FIB_CONTEXT)Fib->Header.SenderData;
++
++              ASSERT(FibContext->Fib == Fib);
++
++              //
++              // Remove this FibContext from the Outstanding I/O queue.
++              // But only if it has not already been timed out.
++              //
++              // If the fib has been timed out already, then just continue.
++              // The caller has already been notified that the fib timed out.
++              //
++
++              if (!(FibContext->Flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
++
++                      RemoveEntryList( &FibContext->QueueEntry );
++                      Adapter->CommRegion->AdapNormCmdQue.NumOutstandingIos--;
++
++              } else {
++
++                      FsaCommLogEvent(FibContext,
++                                                      FsaCommData.DeviceObject, 
++                                                      FSAFS_TIMED_OUT_FIB_COMPLETED,
++                                                      STATUS_UNSUCCESSFUL, 
++                                                      BugCheckFileId | __LINE__,
++                                                      FACILITY_FSAFS_ERROR_CODE,
++                                                      NULL,
++                                                      TRUE);                  
++
++                      continue;
++
++              }
++
++              OsSpinLockRelease( OurQueue->QueueLock );
++
++              if (IsFastResponse) {
++
++                      //
++                      // doctor the fib
++                      //
++
++                      *(FSASTATUS *)Fib->data = ST_OK;
++
++                      Fib->Header.XferState |= AdapterProcessed;
++
++              }
++
++              ASSERT((Fib->Header.XferState & (AdapterProcessed | HostOwned | SentFromHost)) == (AdapterProcessed | HostOwned | SentFromHost));
++
++              FIB_COUNTER_INCREMENT(FsaCommData.FibRecved);
++
++              ASSERT(FsaCommData.FibsSent >= FsaCommData.FibRecved);
++
++
++              if (Fib->Header.Command == NuFileSystem) {
++
++                      FSASTATUS *pStatus = (FSASTATUS *)Fib->data;
++
++                      if (*pStatus & 0xffff0000) {
++
++                              ULONG Hint = *pStatus;
++
++                              *pStatus = ST_OK;
++
++/*
++                              DbgPrint("Replacing hint in fid (drive = %d, f1 = 0x%x, f2 = 0x%x, hint = 0x%x, new_hint = 0x%x)\n", 
++                                               IrpContext->NonPaged->FileId.fid_driveno,
++                                               IrpContext->NonPaged->FileId.fid_f1,
++                                               IrpContext->NonPaged->FileId.fid_f2,
++                                               IrpContext->NonPaged->FileId.fid_hint,
++                                               Hint);
++*/
++
++                      }
++
++              }
++
++              if (Fib->Header.XferState & (NoResponseExpected | Async) ) {
++
++                      ASSERT(FibContext->FibCallback);
++
++              if (Fib->Header.XferState & NoResponseExpected)
++                              FIB_COUNTER_INCREMENT(FsaCommData.NoResponseRecved);
++                      else 
++                              FIB_COUNTER_INCREMENT(FsaCommData.AsyncRecved);
++
++                      //
++                      // NOTE:  we can not touch the FibContext after this call, because it may have been
++                      // deallocated.
++                      //
++
++                      FibContext->FibCallback(FibContext->FibCallbackContext, FibContext, STATUS_SUCCESS);
++
++              } else {
++
++                      OsCvLockAcquire( FibContext->FsaEventMutex);
++
++                      FibContext->FibComplete = 1;
++
++                      OsCv_signal( &FibContext->FsaEvent );
++
++                      OsCvLockRelease( FibContext->FsaEventMutex );
++
++                      FIB_COUNTER_INCREMENT(FsaCommData.NormalRecved);
++                      
++              }
++
++
++              Consumed++;
++
++              OsSpinLockAcquire( OurQueue->QueueLock );
++              
++    }
++
++      if (Consumed > FsaCommData.PeakFibsConsumed)
++              FsaCommData.PeakFibsConsumed = Consumed;
++
++      if (Consumed == 0) 
++              FsaCommData.ZeroFibsConsumed++;
++
++      if (FsaCommData.HardInterruptModeration) {
++
++              //
++              // Re-Enable the interrupt from the adapter, then recheck to see if anything has 
++              // been put on the queue.  This removes the race condition that exists between the
++              // last time we checked the queue, and when we re-enabled the interrupt.
++              //
++              // If there is something on the queue, then go handle it.
++              //
++
++              EnableInterrupt( Adapter, HostNormRespQue, FALSE );
++
++              if (ConsumerEntryAvailable( Adapter, OurQueue ) ) {
++
++                      DisableInterrupt( Adapter, HostNormRespQue, FALSE );
++
++                      goto loop;
++
++              }
++      }
++
++#ifdef commdebug
++    FsaCommPrint("Exiting host normal reponse dpc routine after consuming %d QE(s).\n",Consumed);
++#endif
++
++      OsSpinLockRelease( OurQueue->QueueLock );
++
++}
++
++/*++
++
++Routine Description:
++
++    This DPC routine wiol be queued when the adapter interrupts us to let us know there
++    is a response on our high priority queue. We will pull off all QE there are and wake
++    up all the waiters before exiting. We will take a spinlock out on the queue before operating
++    on it.
++
++Arguments:
++
++    Dpc - Pointer to this routine.
++
++    OurQueue is a pointer to the queue structure we will operate on.
++
++    MoreData1&2 are DPC parameters we don't need for this function. Maybe we can add some accounting
++        stuff in here.
++
++Return Value:
++    Nothing.
++
++--*/
++u_int
++HostResponseHighDpc (IN PCOMM_QUE OurQueue)
++{}
++
++
++/*++
++
++Routine Description:
++
++    This DPC routine will be queued when the adapter interrupts us to let us know there
++    is a command on our high priority queue. We will pull off all QE there are and wake
++    up all the waiters before exiting. We will take a spinlock out on the queue before operating
++    on it.
++
++Arguments:
++
++    Dpc - Pointer to this routine.
++
++    OurQueue is a pointer to the queue structure we will operate on.
++
++    MoreData1&2 are DPC parameters we don't need for this function. Maybe we can add some accounting
++        stuff in here.
++
++Return Value:
++    Nothing.
++
++--*/
++u_int
++HostCommandHighDpc (IN PCOMM_QUE OurQueue)
++{}
++
++
++/*++
++
++Routine Description:
++
++    This DPC routine will be queued when the adapter interrupts us to let us know there
++    is a command on our normal priority queue. We will pull off all QE there are and wake
++    up all the waiters before exiting. We will take a spinlock out on the queue before operating
++    on it.
++
++Arguments:
++
++    Dpc - Pointer to this routine.
++
++    OurQueue is a pointer to the queue structure we will operate on.
++
++    MoreData1&2 are DPC parameters we don't need for this function. Maybe we can add some accounting
++        stuff in here.
++
++Return Value:
++    Nothing.
++
++--*/
++u_int
++HostCommandNormDpc (IN PCOMM_QUE OurQueue)
++{
++    PAFA_COMM_ADAPTER Adapter = OurQueue->Adapter;
++    PQUEUE_ENTRY QueueEntry;
++
++      OsSpinLockAcquire( OurQueue->QueueLock );
++
++    //
++    // Keep pulling response QEs off the response queue and waking
++    // up the waiters until there are no more QEs. We then return
++    // back to the system.
++    //
++
++    while ( GetConsumerEntry( Adapter, OurQueue, &QueueEntry) ) {
++
++              PFIB Fib;
++
++              Fib = (PFIB)QueueEntry->FibAddress;
++
++
++              if (Adapter->AifThreadStarted) {
++
++
++//                    cmn_err(CE_CONT, "^Received AIF, putting onto command queue\n");
++
++
++              InsertTailList(&OurQueue->CommandQueue, &Fib->Header.FibLinks);
++              FreeConsumerEntry(Adapter, OurQueue, HostNormCmdQueue);
++              OsCv_signal(&OurQueue->CommandReady);
++
++
++
++              } else {
++
++
++
++                      COMM_FIB_CONTEXT FibContext;
++
++              
++
++              FreeConsumerEntry(Adapter, OurQueue, HostNormCmdQueue);
++
++
++
++                      OsSpinLockRelease( OurQueue->QueueLock );
++
++
++
++//                    cmn_err(CE_CONT, "^Received AIF, thread not started\n");
++
++
++                      RtlZeroMemory( &FibContext, sizeof(COMM_FIB_CONTEXT) );
++
++                  FibContext.NodeTypeCode = FSAFS_NTC_FIB_CONTEXT;
++                  FibContext.NodeByteSize = sizeof( COMM_FIB_CONTEXT );
++                      FibContext.Fib = Fib;
++                      FibContext.FibData = Fib->data;
++                      FibContext.Adapter = Adapter;
++
++                      //
++                      // Set the status of this FIB
++                      //
++
++                      *(FSASTATUS *)Fib->data = ST_OK;
++                              
++                      CompleteAdapterFib( &FibContext, sizeof(FSASTATUS) );
++
++
++
++                      OsSpinLockAcquire( OurQueue->QueueLock );
++              }               
++    }
++
++      OsSpinLockRelease( OurQueue->QueueLock );
++
++}
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/AacGenericTypes.h linux/drivers/scsi/aacraid/include/AacGenericTypes.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/AacGenericTypes.h Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/AacGenericTypes.h       Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,57 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *
++ *  AacGenericTypes.h
++ *
++ * Abstract:
++ *
++ *     The module defines the generic data types that all of the other header files
++ *     depend upon.
++ --*/
++
++#ifndef _AAC_GENERIC_TYPES
++#define _AAC_GENERIC_TYPES
++
++static char *ident_AacGeneric = "aacraid_ident AacGenericTypes.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++typedef       char                    AAC_INT8, *PAAC_INT8;
++typedef short                 AAC_INT16, *PAAC_INT16;
++typedef int                   AAC_INT32, *PAAC_INT32;
++typedef long long             AAC_INT64, *PAAC_INT64;
++
++typedef unsigned char AAC_UINT8, *PAAC_UINT8;
++typedef unsigned short        AAC_UINT16, *PAAC_UINT16;
++typedef unsigned int  AAC_UINT32, *PAAC_UINT32;
++typedef unsigned long long    AAC_UINT64, *PAAC_UINT64;
++
++typedef void                  AAC_VOID, *PAAC_VOID;
++
++//
++// this compiler uses 32 bit enum data types
++//
++
++#define       AAC_32BIT_ENUMS 1
++#define FAILURE 1
++#define INTR_UNCLAIMED 1
++#define INTR_CLAIMED 0
++
++#endif // _AAC_GENERIC_TYPES
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/aac_unix_defs.h linux/drivers/scsi/aacraid/include/aac_unix_defs.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/aac_unix_defs.h   Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/aac_unix_defs.h Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,300 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *
++ *  aac_unix_defs.h
++ *
++ * Abstract:
++ *
++ *     Macro definition and typedefs
++ *
++ --*/
++
++#ifndef _AAC_UNIX_DEFS
++#define _AAC_UNIX_DEFS
++
++static char *ident_aac_unix = "aacraid_ident aac_unix_defs.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#define       AAC_MAX_ADAPTERS        64
++
++#ifndef       TRUE
++#define TRUE  1
++#define FALSE 0
++#endif
++
++#define PAGE_SIZE     4096
++
++typedef       void    VOID;
++typedef VOID  *PVOID;
++
++typedef char          CHAR, *PCHAR;
++typedef unsigned char         UCHAR, *PUCHAR;
++typedef short         SHORT, *PSHORT;
++typedef short         CSHORT, *PCSHORT;
++typedef unsigned short        USHORT, *PUSHORT;
++typedef unsigned long         ULONG, *PULONG;
++typedef long          LONG, *PLONG;
++
++typedef unsigned long BOOLEAN;
++
++typedef unsigned long AAC_STATUS, *PNT_STATUS;
++
++typedef struct {
++      unsigned long   LowPart;
++      unsigned long   HighPart;
++} LARGE_INTEGER;
++
++typedef LARGE_INTEGER PHYSICAL_ADDRESS;
++
++
++typedef struct _AFA_IOCTL_CMD {
++      int             cmd;
++      intptr_t        arg;
++      int             flag;
++      cred_t          *cred_p;
++      int             *rval_p;
++} AFA_IOCTL_CMD, *PAFA_IOCTL_CMD;
++
++
++//
++//  Singly linked list structure. Can be used as either a list head, or
++//  as link words.
++//
++
++typedef struct _SINGLE_LIST_ENTRY {
++    struct _SINGLE_LIST_ENTRY *Next;
++} SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY;
++
++
++//
++// Calculate the address of the base of the structure given its type, and an
++// address of a field within the structure.
++//
++
++#define CONTAINING_RECORD(address, type, field) ((type *)( \
++                                                  (PCHAR)(address) - \
++                                                  (PCHAR)(&((type *)0)->field)))
++
++typedef       PVOID   PMDL;
++typedef PVOID PDEVICE_OBJECT;
++typedef PVOID PADAPTER_OBJECT;
++typedef ULONG KIRQL;
++typedef PVOID HANDLE;
++typedef PVOID KDPC, *PKDPC;
++typedef PVOID PFILE_OBJECT;
++typedef PVOID PIRP;
++typedef PVOID PDRIVER_OBJECT;
++typedef ULONG KTIMER;
++
++
++#define       STATUS_SUCCESS          0x00000000
++#define STATUS_PENDING                0x40000001
++#define STATUS_IO_TIMEOUT                     0xc0000001
++#define STATUS_UNSUCCESSFUL                   0xc0000002
++#define STATUS_INSUFFICIENT_RESOURCES 0xc0000005
++#define STATUS_BUFFER_OVERFLOW                0xc0000003
++
++
++#define OUT
++
++
++
++typedef u_int
++(*PUNIX_INTR_HANDLER)(caddr_t Arg);
++
++//
++// Zone Allocation
++//
++
++typedef struct _ZONE_SEGMENT_HEADER {
++    SINGLE_LIST_ENTRY SegmentList;
++    PVOID Reserved;
++} ZONE_SEGMENT_HEADER, *PZONE_SEGMENT_HEADER;
++
++typedef struct _ZONE_HEADER {
++    SINGLE_LIST_ENTRY FreeList;
++    SINGLE_LIST_ENTRY SegmentList;
++    ULONG BlockSize;
++    ULONG TotalSegmentSize;
++} ZONE_HEADER, *PZONE_HEADER;
++
++
++//++
++//
++// PVOID
++// ExAllocateFromZone(
++//     IN PZONE_HEADER Zone
++//     )
++//
++// Routine Description:
++//
++//     This routine removes an entry from the zone and returns a pointer to it.
++//
++// Arguments:
++//
++//     Zone - Pointer to the zone header controlling the storage from which the
++//         entry is to be allocated.
++//
++// Return Value:
++//
++//     The function value is a pointer to the storage allocated from the zone.
++//
++//--
++
++#define ExAllocateFromZone(Zone) \
++    (PVOID)((Zone)->FreeList.Next); \
++    if ( (Zone)->FreeList.Next ) (Zone)->FreeList.Next = (Zone)->FreeList.Next->Next
++
++//++
++//
++// PVOID
++// ExFreeToZone(
++//     IN PZONE_HEADER Zone,
++//     IN PVOID Block
++//     )
++//
++// Routine Description:
++//
++//     This routine places the specified block of storage back onto the free
++//     list in the specified zone.
++//
++// Arguments:
++//
++//     Zone - Pointer to the zone header controlling the storage to which the
++//         entry is to be inserted.
++//
++//     Block - Pointer to the block of storage to be freed back to the zone.
++//
++// Return Value:
++//
++//     Pointer to previous block of storage that was at the head of the free
++//         list.  NULL implies the zone went from no available free blocks to
++//         at least one free block.
++//
++//--
++
++#define ExFreeToZone(Zone,Block)                                    \
++    ( ((PSINGLE_LIST_ENTRY)(Block))->Next = (Zone)->FreeList.Next,  \
++      (Zone)->FreeList.Next = ((PSINGLE_LIST_ENTRY)(Block)),        \
++      ((PSINGLE_LIST_ENTRY)(Block))->Next                           \
++    )
++
++//++
++//
++// BOOLEAN
++// ExIsFullZone(
++//     IN PZONE_HEADER Zone
++//     )
++//
++// Routine Description:
++//
++//     This routine determines if the specified zone is full or not.  A zone
++//     is considered full if the free list is empty.
++//
++// Arguments:
++//
++//     Zone - Pointer to the zone header to be tested.
++//
++// Return Value:
++//
++//     TRUE if the zone is full and FALSE otherwise.
++//
++//--
++
++#define ExIsFullZone(Zone) \
++    ( (Zone)->FreeList.Next == (PSINGLE_LIST_ENTRY)NULL )
++
++
++#define RtlCopyMemory( Destination, Source, Size )    bcopy( (Source), (Destination), (Size) )
++#define RtlZeroMemory( Destination, Size )                    bzero( (Destination), (Size) )
++
++//
++//  Doubly-linked list manipulation routines.  Implemented as macros
++//  but logically these are procedures.
++//
++
++//
++//  VOID
++//  InitializeListHead(
++//      PLIST_ENTRY ListHead
++//      );
++//
++
++#define InitializeListHead(ListHead) (\
++    (ListHead)->Flink = (ListHead)->Blink = (ListHead))
++
++//
++//  BOOLEAN
++//  IsListEmpty(
++//      PLIST_ENTRY ListHead
++//      );
++//
++
++#define IsListEmpty(ListHead) \
++    ((ListHead)->Flink == (ListHead))
++
++//
++//  PLIST_ENTRY
++//  RemoveHeadList(
++//      PLIST_ENTRY ListHead
++//      );
++//
++
++#define RemoveHeadList(ListHead) \
++    (ListHead)->Flink;\
++    {RemoveEntryList((ListHead)->Flink)}
++
++
++//
++//  VOID
++//  RemoveEntryList(
++//      PLIST_ENTRY Entry
++//      );
++//
++
++#define RemoveEntryList(Entry) {\
++    PLIST_ENTRY _EX_Blink;\
++    PLIST_ENTRY _EX_Flink;\
++    _EX_Flink = (Entry)->Flink;\
++    _EX_Blink = (Entry)->Blink;\
++    _EX_Blink->Flink = _EX_Flink;\
++    _EX_Flink->Blink = _EX_Blink;\
++    }
++
++//
++//  VOID
++//  InsertTailList(
++//      PLIST_ENTRY ListHead,
++//      PLIST_ENTRY Entry
++//      );
++//
++
++#define InsertTailList(ListHead,Entry) {\
++    PLIST_ENTRY _EX_Blink;\
++    PLIST_ENTRY _EX_ListHead;\
++    _EX_ListHead = (ListHead);\
++    _EX_Blink = _EX_ListHead->Blink;\
++    (Entry)->Flink = _EX_ListHead;\
++    (Entry)->Blink = _EX_Blink;\
++    _EX_Blink->Flink = (Entry);\
++    _EX_ListHead->Blink = (Entry);\
++    }
++
++#endif /* AAC_UNIX_DEFS */
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/adapter.h linux/drivers/scsi/aacraid/include/adapter.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/adapter.h Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/adapter.h       Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,164 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *
++ *   Adapter.h
++ *
++ * Abstract:
++ *   The module contains the definitions for a comm layer view of the adapter.
++ *
++ *
++ *
++ --*/
++
++#ifndef _ADAPTER_
++#define _ADAPTER_
++
++static char *ident_adapter = "aacraid_ident adapter.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++typedef struct _GET_ADAPTER_FIB_CONTEXT {
++
++      NODE_TYPE_CODE          NodeTypeCode;   // used for verification of structure   
++      NODE_BYTE_SIZE          NodeByteSize;
++      PFILE_OBJECT            FileObject;     // used for cleanup
++      LIST_ENTRY              NextContext;    // used to link context's into a linked list
++      OS_CV_T                 UserEvent;      // this is used to wait for the next fib to arrive.
++      BOOLEAN                 WaitingForFib;  // Set to true when thread is in WaitForSingleObject
++      ULONG                   FibCount;       // total number of FIBs on FibList
++      LIST_ENTRY              FibList;
++} GET_ADAPTER_FIB_CONTEXT;
++typedef GET_ADAPTER_FIB_CONTEXT *PGET_ADAPTER_FIB_CONTEXT;
++
++
++typedef struct _FIB_CONTEXT_ZONE_SEGMENT {
++
++      struct _FIB_CONTEXT_ZONE_SEGMENT        *Next;
++      ULONG                                   FibContextSegmentSize;
++      PVOID                                   FibContextSegment;
++      ULONG                                   ExtendSize;
++      MAPFIB_CONTEXT                          MapFibContext;
++
++} FIB_CONTEXT_ZONE_SEGMENT;
++typedef FIB_CONTEXT_ZONE_SEGMENT *PFIB_CONTEXT_ZONE_SEGMENT;
++
++typedef struct _AFA_COMM_ADAPTER {
++
++      struct _AFA_COMM_ADAPTER        *NextAdapter;
++
++    //
++    //  The following fields are used to allocate FIB context structures
++    //  using the zone allocator, and other fixed sized structures from a
++    //  small cache.  The mutex protects access to the zone/lists
++    //
++
++    ZONE_HEADER               FibContextZone;
++      OS_SPINLOCK                     *FibContextZoneSpinLock;
++      int                             FibContextZoneExtendSize;
++
++      PFIB_CONTEXT_ZONE_SEGMENT       FibContextSegmentList;
++
++      PVOID                           FibContextTimedOutList;
++
++      PFIB                            SyncFib;
++      ULONG                           SyncFibPhysicalAddress;
++
++      PCOMM_REGION            CommRegion;
++
++      OS_SPINLOCK_COOKIE      SpinLockCookie;
++
++      //
++      // The user API will use an IOCTL to register itself to receive FIBs
++      // from the adapter.  The following list is used to keep track of all
++      // the threads that have requested these FIBs.  The mutex is used to 
++      // synchronize access to all data associated with the adapter fibs.
++      //
++      LIST_ENTRY                      AdapterFibContextList;
++      OS_CVLOCK                       *AdapterFibMutex;
++
++      //
++      // The following holds which FileObject is allow to send configuration
++      // commands to the adapter that would modify the configuration.
++      //
++      // This is controlled by the FSACTL_OPEN_ADAPTER_CONFIG and FSACTL_CLOSE_ADAPTER_CONFIG
++      // ioctls.
++      //
++      PFILE_OBJECT            AdapterConfigFileObject;
++
++      //
++      // The following is really here because of the simulator
++      //
++      BOOLEAN                         InterruptsBelowDpc;
++
++      //
++      // The following is the device specific extension.
++      //
++      PVOID                   AdapterExtension;       
++      PFSAPORT_FUNCS          AdapterFuncs;
++      void                    *Dip;
++
++      //
++      // The following are user variables that are specific to the mini port.
++      //
++      PFSA_USER_VAR           AdapterUserVars;
++      ULONG                   AdapterUserVarsSize;
++
++      //
++      // The following is the number of the individual adapter..i.e. \Device\Afa0
++      //
++      LONG                    AdapterNumber;
++
++      AFACOMM_FUNCS           CommFuncs;
++
++      PAFA_CLASS_DRIVER       ClassDriverList;
++
++      BOOLEAN                 AifThreadStarted;
++
++} AFA_COMM_ADAPTER;
++
++typedef AFA_COMM_ADAPTER *PAFA_COMM_ADAPTER;
++
++
++#define FsaAllocateAdapterCommArea(Adapter, BaseAddress, Size, Alignment) \
++      Adapter->AdapterFuncs->AllocateAdapterCommArea(Adapter->AdapterExtension, BaseAddress, Size, Alignment)
++
++#define FsaFreeAdapterCommArea(Adapter) \
++      Adapter->AdapterFuncs->FreeAdapterCommArea(Adapter->AdapterExtension)
++
++
++#define AllocateAndMapFibSpace(Adapter, MapFibContext) \
++      Adapter->AdapterFuncs->AllocateAndMapFibSpace(Adapter->AdapterExtension, MapFibContext)
++
++#define UnmapAndFreeFibSpace(Adapter, MapFibContext) \
++      Adapter->AdapterFuncs->UnmapAndFreeFibSpace(Adapter->AdapterExtension, MapFibContext)
++
++#define InterruptAdapter(Adapter) \
++      Adapter->AdapterFuncs->InterruptAdapter(Adapter->AdapterExtension)
++
++#define NotifyAdapter(Adapter, AdapterEvent) \
++      Adapter->AdapterFuncs->NotifyAdapter(Adapter->AdapterExtension, AdapterEvent)
++
++#define EnableInterrupt(Adapter, AdapterEvent, AtDeviceIrq) \
++      Adapter->AdapterFuncs->EnableInterrupt(Adapter->AdapterExtension, AdapterEvent, AtDeviceIrq)
++
++#define DisableInterrupt(Adapter, AdapterEvent, AtDeviceIrq) \
++      Adapter->AdapterFuncs->DisableInterrupt(Adapter->AdapterExtension, AdapterEvent, AtDeviceIrq)
++
++
++#endif // _ADAPTER_
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/afacomm.h linux/drivers/scsi/aacraid/include/afacomm.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/afacomm.h Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/afacomm.h       Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,191 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   AfaComm.h
++ *
++ * Abstract:
++ *   This module defines all of the external interfaces to the AFA comm layer.
++ *
++ *
++ *
++ --*/
++#ifndef _AFACOMM_
++#define _AFACOMM_
++
++static char *ident_afacomm = "aacraid_ident afacomm.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#include "fsaport.h"
++
++typedef void  *PFIB_CONTEXT;
++
++typedef VOID
++(*PFIB_CALLBACK)(
++      PVOID           FibCallbackContext,
++      PFIB_CONTEXT    FibContext,
++      AAC_STATUS      Status
++      );
++
++
++typedef PFIB_CONTEXT
++(*PAFA_COMM_ALLOCATE_FIB) (
++      IN PVOID AdapterExtension
++    );
++
++typedef VOID
++(*PAFA_COMM_FREE_FIB) (
++    IN PFIB_CONTEXT FibContext
++    );
++
++
++typedef AAC_STATUS
++(*PAFA_COMM_DEALLOCATE_FIB) (
++    IN PFIB_CONTEXT FibContext
++    );
++
++
++typedef VOID
++(*PAFA_COMM_FREE_FIB_FROM_DPC) (
++    IN PFIB_CONTEXT FibContext
++    );
++
++typedef AAC_STATUS
++(*PAFA_COMM_INITIALIZE_FIB) (
++      IN PFIB_CONTEXT FibContext
++    );
++
++typedef PVOID
++(*PAFA_COMM_GET_FIB_DATA) (
++      IN PFIB_CONTEXT FibContext
++      );
++
++typedef AAC_STATUS
++(*PAFA_COMM_SEND_FIB) (
++    IN FIB_COMMAND Command, 
++      IN PFIB_CONTEXT FibContext,
++    IN ULONG Size,
++    IN COMM_PRIORITIES Priority,
++    IN BOOLEAN Wait,
++    IN PVOID WaitOn,
++    IN BOOLEAN ResponseExpected,
++      IN PFIB_CALLBACK FibCallback,
++      IN PVOID FibCallbackContext
++    );
++
++typedef AAC_STATUS
++(*PAFA_COMM_COMPLETE_FIB) (
++      IN PFIB_CONTEXT FibContext
++    );
++
++typedef AAC_STATUS
++(*PAFA_COMM_COMPLETE_ADAPTER_FIB) (
++      IN PFIB_CONTEXT FibContext,
++      IN USHORT Size
++    );
++
++typedef BOOLEAN
++(*PAFA_COMM_SEND_SYNCH_FIB) (
++      PVOID                   AdapterExtension,
++      FIB_COMMAND     Command,
++      PVOID                   Data,
++      USHORT                  Size,
++      PVOID                   Response,
++      USHORT                  *ResponseSize
++      );
++
++
++typedef struct _AFACOMM_FUNCS {
++      ULONG                                   SizeOfAfaCommFuncs;
++      PAFA_COMM_ALLOCATE_FIB                  AllocateFib;
++      PAFA_COMM_FREE_FIB                      FreeFib;
++      PAFA_COMM_FREE_FIB_FROM_DPC             FreeFibFromDpc;
++      PAFA_COMM_DEALLOCATE_FIB                DeallocateFib;
++      PAFA_COMM_INITIALIZE_FIB                InitializeFib;
++      PAFA_COMM_GET_FIB_DATA                  GetFibData;
++      PAFA_COMM_SEND_FIB                      SendFib;
++      PAFA_COMM_COMPLETE_FIB                  CompleteFib;
++      PAFA_COMM_COMPLETE_ADAPTER_FIB          CompleteAdapterFib;
++      PAFA_COMM_SEND_SYNCH_FIB                SendSynchFib;
++      PFSA_FREE_DMA_RESOURCES                 FreeDmaResources;
++      PFSA_BUILD_SGMAP                        BuildSgMap;
++      PFSA_ADAPTER_ADDR_TO_SYSTEM_ADDR        AdapterAddressToSystemAddress;
++} AFACOMM_FUNCS;
++typedef AFACOMM_FUNCS *PAFACOMM_FUNCS;
++
++
++typedef AAC_STATUS
++(*PAFA_CLASS_OPEN_ADAPTER) (
++      IN PVOID Adapter
++      );
++
++
++typedef AAC_STATUS
++(*PAFA_CLASS_CLOSE_ADAPTER) (
++      IN PVOID Adapter
++      );
++
++
++typedef BOOLEAN
++(*PAFA_CLASS_DEV_CONTROL) (
++      IN PVOID Adapter,
++      IN PAFA_IOCTL_CMD       IoctlCmdPtr,
++      OUT int * Status
++      );
++
++typedef BOOLEAN
++(*PAFA_CLASS_HANDLE_AIF) (
++      IN PVOID Adapter,
++      IN PFIB_CONTEXT FibContext
++      );
++
++
++typedef struct _AFA_NEW_CLASS_DRIVER {
++      PVOID                           ClassDriverExtension;
++      PAFA_CLASS_OPEN_ADAPTER         OpenAdapter;
++        PAFA_CLASS_CLOSE_ADAPTER      CloseAdapter;
++        PAFA_CLASS_DEV_CONTROL                DeviceControl;
++      PAFA_CLASS_HANDLE_AIF           HandleAif;
++      PFSA_USER_VAR                   UserVars;
++      ULONG                           NumUserVars;
++} AFA_NEW_CLASS_DRIVER;
++typedef AFA_NEW_CLASS_DRIVER *PAFA_NEW_CLASS_DRIVER;
++
++
++typedef struct _AFA_NEW_CLASS_DRIVER_RESPONSE {
++      PAFACOMM_FUNCS          CommFuncs;
++      PVOID                   CommPortExtension;
++      PVOID                   MiniPortExtension;
++      OS_SPINLOCK_COOKIE      SpinLockCookie;
++      void                    *Dip;
++} AFA_NEW_CLASS_DRIVER_RESPONSE;
++typedef AFA_NEW_CLASS_DRIVER_RESPONSE *PAFA_NEW_CLASS_DRIVER_RESPONSE;
++
++
++typedef struct _AFA_CLASS_DRIVER {
++      struct _AFA_CLASS_DRIVER        *Next;
++      PVOID                           ClassDriverExtension;
++      PAFA_CLASS_OPEN_ADAPTER         OpenAdapter;
++      PAFA_CLASS_CLOSE_ADAPTER        CloseAdapter;
++      PAFA_CLASS_DEV_CONTROL          DeviceControl;
++      PAFA_CLASS_HANDLE_AIF           HandleAif;
++} AFA_CLASS_DRIVER;
++typedef AFA_CLASS_DRIVER *PAFA_CLASS_DRIVER;
++
++
++#endif // _AFACOMM_
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/aifstruc.h linux/drivers/scsi/aacraid/include/aifstruc.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/aifstruc.h        Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/aifstruc.h      Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,319 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   Aifstruc.h
++ *
++ * Abstract:
++ *   Define all shared data types relating to
++ *   the set of features utilizing Adapter
++ *   Initiated Fibs.
++ *
++ *
++ *
++ --*/
++#ifndef _AIFSTRUC_H
++#define _AIFSTRUC_H
++
++static char *ident_aifstruc = "aacraid_ident aifstruc.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#include <protocol.h>
++
++//
++//    Progress report structure definitions
++//
++typedef enum {
++      AifJobStsSuccess = 1,
++      AifJobStsFinished,
++      AifJobStsAborted,
++      AifJobStsFailed,
++      AifJobStsLastReportMarker = 100, // All before mean last report
++      AifJobStsSuspended,
++      AifJobStsRunning
++} _E_AifJobStatus;
++
++#ifdef AAC_32BIT_ENUMS
++typedef       _E_AifJobStatus AifJobStatus;
++#else
++typedef       AAC_UINT32              AifJobStatus;
++#endif
++
++
++typedef enum {
++      AifJobScsiMin = 1,              // Minimum value for Scsi operation
++      AifJobScsiZero,                 // SCSI device clear operation
++      AifJobScsiVerify,               // SCSI device Verify operation NO REPAIR
++      AifJobScsiExercise,             // SCSI device Exercise operation
++      AifJobScsiVerifyRepair, // SCSI device Verify operation WITH repair
++      // Add new SCSI task types above this line
++      AifJobScsiMax = 99,             // Max Scsi value
++      AifJobCtrMin,                   // Min Ctr op value
++      AifJobCtrZero,                  // Container clear operation
++      AifJobCtrCopy,                  // Container copy operation
++      AifJobCtrCreateMirror,  // Container Create Mirror operation
++      AifJobCtrMergeMirror,   // Container Merge Mirror operation
++      AifJobCtrScrubMirror,   // Container Scrub Mirror operation
++      AifJobCtrRebuildRaid5,  // Container Rebuild Raid5 operation
++      AifJobCtrScrubRaid5,    // Container Scrub Raid5 operation
++      AifJobCtrMorph,                 // Container morph operation
++      AifJobCtrPartCopy,              // Container Partition copy operation
++      AifJobCtrRebuildMirror, // Container Rebuild Mirror operation
++      AifJobCtrCrazyCache,            // crazy cache
++      // Add new container task types above this line
++      AifJobCtrMax = 199,             // Max Ctr type operation
++      AifJobFsMin,                    // Min Fs type operation
++      AifJobFsCreate,                 // File System Create operation
++      AifJobFsVerify,                 // File System Verify operation
++      AifJobFsExtend,                 // File System Extend operation
++      // Add new file system task types above this line
++      AifJobFsMax = 299,              // Max Fs type operation
++      // Add new API task types here
++      AifJobApiFormatNTFS,    // Format a drive to NTFS
++      AifJobApiFormatFAT,             // Format a drive to FAT
++      AifJobApiUpdateSnapshot, // update the read/write half of a snapshot
++      AifJobApiFormatFAT32,   // Format a drive to FAT32
++      AifJobApiMax = 399,             // Max API type operation
++      AifJobCtlContinuousCtrVerify,   // Controller operation
++      AifJobCtlMax = 499              // Max Controller type operation
++
++} _E_AifJobType;
++
++#ifdef AAC_32BIT_ENUMS
++typedef       _E_AifJobType   AifJobType;
++#else
++typedef       AAC_UINT32              AifJobType;
++#endif
++
++union SrcContainer {
++      AAC_UINT32 from;
++      AAC_UINT32 master;
++      AAC_UINT32 container;
++};
++
++union DstContainer {
++      AAC_UINT32 to;
++      AAC_UINT32 slave;
++      AAC_UINT32 container;
++};
++
++
++struct AifContainers {
++      union SrcContainer src;
++      union DstContainer dst;
++};
++
++union AifJobClient {
++      
++      struct AifContainers container; // For Container nd file system progress ops;
++      AAC_INT32 scsi_dh;                      // For SCSI progress ops
++};
++
++struct AifJobDesc {
++      AAC_UINT32 jobID;                       // DO NOT FILL IN! Will be filled in by AIF
++      AifJobType type;                // Operation that is being performed
++      union AifJobClient client; // Details
++};
++
++struct AifJobProgressReport {
++      struct AifJobDesc jd;
++      AifJobStatus status;
++      AAC_UINT32 finalTick;
++      AAC_UINT32 currentTick;
++      AAC_UINT32 jobSpecificData1;
++      AAC_UINT32 jobSpecificData2;
++};
++
++//
++//    Notification of events structure definition starts here
++//
++typedef enum {
++      // General application notifies start here
++      AifEnGeneric = 1,                       // Generic notification
++      AifEnTaskComplete,                      // Task has completed
++      AifEnConfigChange,                      // Adapter configuration change occurred
++      AifEnContainerChange,           // Adapter specific container configuration change
++      AifEnDeviceFailure,                     // SCSI device failed
++      AifEnMirrorFailover,            // Mirror failover started
++      AifEnContainerEvent,            // Significant container event
++      AifEnFileSystemChange,          // File system changed
++      AifEnConfigPause,                       // Container pause event
++      AifEnConfigResume,                      // Container resume event
++      AifEnFailoverChange,            // Failover space assignment changed
++      AifEnRAID5RebuildDone,          // RAID5 rebuild finished
++      AifEnEnclosureManagement,       // Enclosure management event
++      AifEnBatteryEvent,                      // Significant NV battery event
++      AifEnAddContainer,                      // A new container was created.
++      AifEnDeleteContainer,           // A container was deleted.
++      AifEnSMARTEvent,            // SMART Event
++      AifEnBatteryNeedsRecond,        // The battery needs reconditioning
++      AifEnClusterEvent,                      // Some cluster event
++      AifEnDiskSetEvent,                      // A disk set event occured.
++      // Add general application notifies above this comment
++      AifDriverNotifyStart=199,       // Notifies for host driver go here
++      // Host driver notifications start here
++      AifDenMorphComplete,            // A morph operation completed
++      AifDenVolumeExtendComplete      // A volume expand operation completed
++      // Add host driver notifications above this comment
++} _E_AifEventNotifyType;
++
++#ifdef AAC_32BIT_ENUMS
++typedef _E_AifEventNotifyType AifEventNotifyType;
++#else
++typedef       AAC_UINT32                              AifEventNotifyType;
++#endif
++
++struct AifEnsGeneric {
++      AAC_INT8 text[132];                             // Generic text
++};
++
++struct AifEnsDeviceFailure {
++      AAC_INT32 deviceHandle; // SCSI device handle
++};
++
++struct AifEnsMirrorFailover {
++      AAC_UINT32 container;           // Container with failed element
++      AAC_UINT32 failedSlice;         // Old slice which failed
++      AAC_UINT32 creatingSlice;       // New slice used for auto-create
++};
++
++struct AifEnsContainerChange {
++      AAC_UINT32 container[2];                // container that changed, -1 if no container
++};
++
++struct AifEnsContainerEvent {
++      AAC_UINT32 container;           // container number 
++      AAC_UINT32 eventType;           // event type
++};
++
++struct AifEnsEnclosureEvent {
++      AAC_UINT32 empID;                               // enclosure management processor number 
++      AAC_UINT32 unitID;                      // unitId, fan id, power supply id, slot id, tempsensor id. 
++      AAC_UINT32 eventType;           // event type
++};
++
++
++struct AifEnsBatteryEvent {
++      NVBATT_TRANSITION transition_type;      // e.g. from low to ok
++      NVBATTSTATUS current_state;                     // current battery state
++      NVBATTSTATUS prior_state;                       // previous battery state
++};
++
++struct AifEnsDiskSetEvent {
++      AAC_UINT32      eventType;
++      AAC_UINT32      DsNum[2];
++      AAC_UINT32      CreatorId[2];
++};
++
++
++
++typedef enum _CLUSTER_AIF_EVENT {
++      CLUSTER_NULL_EVENT = 0,
++      CLUSTER_PARTNER_NAME_EVENT,             // change in partner hostname or adaptername from NULL to non-NULL
++                                                                      // (partner's agent may be up)
++      CLUSTER_PARTNER_NULL_NAME_EVENT // change in partner hostname or adaptername from non-null to NULL
++                                                                      // (partner has rebooted)
++} _E_CLUSTER_AIF_EVENT;
++
++#ifdef AAC_32BIT_ENUMS
++typedef       _E_CLUSTER_AIF_EVENT    CLUSTER_AIF_EVENT;
++#else
++typedef       AAC_UINT32                              CLUSTER_AIF_EVENT;
++#endif
++
++struct AifEnsClusterEvent {
++      CLUSTER_AIF_EVENT   eventType;
++};
++
++struct AifEventNotify {
++      AifEventNotifyType      type;
++      union {
++              struct AifEnsGeneric            EG;
++              struct AifEnsDeviceFailure      EDF;
++              struct AifEnsMirrorFailover EMF;
++              struct AifEnsContainerChange ECC;
++              struct AifEnsContainerEvent ECE;
++              struct AifEnsEnclosureEvent EEE;
++              struct AifEnsBatteryEvent       EBE;
++              struct AifEnsDiskSetEvent       EDS;
++#ifdef BRIDGE
++              struct AifEnsSMARTEvent ES;
++#endif
++              struct AifEnsClusterEvent ECLE;
++      } data;
++};
++
++//
++//    Generic API structure
++//
++#define AIF_API_REPORT_MAX_SIZE 64
++typedef AAC_INT8 AifApiReport[AIF_API_REPORT_MAX_SIZE];
++
++
++
++//
++//    For FIB communication, we need all of the following things
++//    to send back to the user.
++//
++typedef enum {
++      AifCmdEventNotify = 1,  // Notify of event
++      AifCmdJobProgress,              // Progress report
++      AifCmdAPIReport,                // Report from other user of API
++      AifCmdDriverNotify,             // Notify host driver of event
++      AifReqJobList = 100,    // Gets back complete job list
++      AifReqJobsForCtr,               // Gets back jobs for specific container
++      AifReqJobsForScsi,              // Gets back jobs for specific SCSI device
++      AifReqJobReport,                // Gets back a specific job report or list of them
++      AifReqTerminateJob,             // Terminates job
++      AifReqSuspendJob,               // Suspends a job
++      AifReqResumeJob,                // Resumes a job
++      AifReqSendAPIReport,    // API generic report requests
++      AifReqAPIJobStart,              // Start a job from the API
++      AifReqAPIJobUpdate,             // Update a job report from the API
++      AifReqAPIJobFinish              // Finish a job from the API
++} _E_AIFCOMMAND;
++
++#ifdef AAC_32BIT_ENUMS
++typedef _E_AIFCOMMAND AIFCOMMAND;
++#else
++typedef       AAC_UINT32              AIFCOMMAND;
++#endif
++
++
++
++//
++//    Adapter Initiated FIB command structures. Start with the adapter
++//    initiated FIBs that really come from the adapter, and get responded
++//    to by the host.
++//
++typedef struct _AIFCOMMANDTOHOST {
++      AIFCOMMAND command;                     // Tell host what type of notify this is
++      AAC_UINT32 seqNumber;   // To allow ordering of reports (if necessary)
++      union {
++              // First define data going to the adapter
++              struct AifEventNotify EN;       // Event notify structure
++              struct AifJobProgressReport PR[1]; // Progress report
++              AifApiReport AR;
++      } data;
++} AIFCOMMANDTOHOST, *PAIFCOMMANDTOHOST;
++
++
++#endif // _AIFSTRUC_H
++
++
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/build_number.h linux/drivers/scsi/aacraid/include/build_number.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/build_number.h    Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/build_number.h  Thu Aug 16 18:16:55 2001
+@@ -0,0 +1,39 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   build_number.h
++ *
++ * Abstract:
++ *   DThis module contains the single location where the build number
++ *   is kept.
++ *
++ *
++ *
++ --*/
++#ifndef _BUILD_NUMBER_H 
++#define _BUILD_NUMBER_H 
++
++static char *ident_build_num = "aacraid_ident build_number.h 1.0.7 2001/08/10 Adaptec, Inc.";
++
++#define REV_BUILD_NUMBER 5125 
++
++
++#endif  // _BUILD_NUMBER_H 
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/commdata.h linux/drivers/scsi/aacraid/include/commdata.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/commdata.h        Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/commdata.h      Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,112 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   commdata.h
++ *
++ * Abstract: Define the communication layer of the adapter
++ *
++ *
++ *
++ --*/
++#ifndef _COMMDATA_
++#define _COMMDATA_
++
++static char *ident_commdata = "aacraid_ident commdata.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++typedef struct _FSA_COMM_DATA {
++  
++  //
++  //  A pointer to the Driver and Device object we were initialized with
++  //
++  
++  PDRIVER_OBJECT DriverObject;
++  PDEVICE_OBJECT DeviceObject;
++  
++  //
++  // A list of all adapters we have configured.
++  // 
++  
++  PAFA_COMM_ADAPTER AdapterList;
++  ULONG                 TotalAdapters;
++  
++  //
++  // Adapter timeout support. This is the default timeout to wait for the
++  // adapter to respond(setup in initfs.c), and a boolean to indicate if
++  // we should timeout requests to the adapter or not.
++  //
++
++  LARGE_INTEGER QueueFreeTimeout;
++  LARGE_INTEGER AdapterTimeout;
++  BOOLEAN EnableAdapterTimeouts;
++
++  ULONG       FibTimeoutIncrement;
++  
++  ULONG FibsSent;
++  ULONG FibRecved;
++  ULONG NoResponseSent;
++  ULONG NoResponseRecved;
++  ULONG AsyncSent;
++  ULONG AsyncRecved;
++  ULONG NormalSent;
++  ULONG NormalRecved;
++  
++  ULONG TimedOutFibs;
++  
++  KDPC                TimeoutDPC;
++  KTIMER      TimeoutTimer;
++  
++  // 
++  // If this value is set to 1 then interrupt moderation will occur 
++  // in the base commuication support.
++  //
++
++  ULONG EnableInterruptModeration;
++
++  int HardInterruptModeration;
++  int HardInterruptModeration1;
++  int PeakFibsConsumed;
++  int ZeroFibsConsumed;
++  int EnableFibTimeoutBreak;
++  ULONG FibTimeoutSeconds;
++  
++  //
++  // The following holds all of the available user settable variables.
++  // This includes all for the comm layer as well as any from the class
++  // drivers as well.
++  //
++  
++  FSA_USER_VAR        *UserVars;
++  ULONG                       NumUserVars;
++  
++  
++  ULONG           MeterFlag;
++  
++#ifdef FIB_CHECKSUMS
++  int do_fib_checksums;
++#endif
++  
++} FSA_COMM_DATA;
++typedef FSA_COMM_DATA *PFSA_COMM_DATA;
++
++extern FSA_COMM_DATA FsaCommData;
++
++
++#endif // _COMMDATA_
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/commerr.h linux/drivers/scsi/aacraid/include/commerr.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/commerr.h Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/commerr.h       Thu Aug 16 18:16:55 2001
+@@ -0,0 +1,125 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   commerr.h
++ *
++ * Abstract: This file defines all errors that are unique to the Adaptec Fsa Filesystem
++ *
++ *
++ *
++ --*/
++
++#ifndef _FSAERR_
++#define _FSAERR_
++
++static char *ident_commerr = "aacraid_ident commerr.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++//
++//  Note: comments in the .mc file must use both ";" and "//".
++//
++//  Status values are 32 bit values layed out as follows:
++//
++//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
++//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
++//  +---+-+-------------------------+-------------------------------+
++//  |Sev|C|       Facility          |               Code            |
++//  +---+-+-------------------------+-------------------------------+
++//
++//  where
++//
++//      Sev - is the severity code
++//
++//          00 - Success
++//          01 - Informational
++//          10 - Warning
++//          11 - Error
++//
++//      C - is the Customer code flag
++//
++//      Facility - is the facility code
++//
++//      Code - is the facility's status code
++//
++
++
++//
++// %1 is reserved by the IO Manager. If IoAllocateErrorLogEntry is
++// called with a device, the name of the device will be inserted into
++// the message at %1. Otherwise, the place of %1 will be left empty.
++// In either case, the insertion strings from the driver's error log
++// entry starts at %2. In other words, the first insertion string goes
++// to %2, the second to %3 and so on.
++//
++
++//
++//  Values are 32 bit values layed out as follows:
++//
++//   3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
++//   1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
++//  +---+-+-+-----------------------+-------------------------------+
++//  |Sev|C|R|     Facility          |               Code            |
++//  +---+-+-+-----------------------+-------------------------------+
++//
++//  where
++//
++//      Sev - is the severity code
++//
++//          00 - Success
++//          01 - Informational
++//          10 - Warning
++//          11 - Error
++//
++//      C - is the Customer code flag
++//
++//      R - is a reserved bit
++//
++//      Facility - is the facility code
++//
++//      Code - is the facility's status code
++//
++//
++// Define the facility codes
++//
++
++
++#define FACILITY_FSAFS_ERROR_CODE        0x7
++
++
++
++//
++// MessageId: FSAFS_FIB_INVALID
++//
++// MessageText:
++//
++//  A communication packet was detected to be formatted poorly. Please Contact Adaptec support.
++//
++#define FSAFS_FIB_INVALID                ((AAC_STATUS)0xE0070009L)
++
++
++//
++// MessageId: FSAFS_TIMED_OUT_FIB_COMPLETED
++//
++// MessageText:
++//
++//  A Fib previously timed out by host has been completed by the adapter. (\\.\Afa%2)
++//
++#define FSAFS_TIMED_OUT_FIB_COMPLETED    ((AAC_STATUS)0xA007000EL)
++
++#endif /* _FSAERR_ */
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/commfibcontext.h linux/drivers/scsi/aacraid/include/commfibcontext.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/commfibcontext.h  Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/commfibcontext.h        Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,98 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   commfibcontext.h
++ *
++ * Abstract: defines the _COMM_FIB_CONTEXT strcuture
++ *
++ *
++ *
++ --*/
++#ifndef _COMM_FIB_CONTEXT_
++#define _COMM_FIB_CONTEXT_
++
++static char *ident_commfib = "aacraid_ident commfibcontext.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++typedef struct _COMM_FIB_CONTEXT {
++
++      PVOID           Next;   // this is used by the zone allocation
++
++    //
++    //  Type and size of this record (must be FSA_NTC_FIB_CONTEXT)
++    //
++    //  NOTE:  THIS STRUCTURE MUST REMAIN 64-bit ALIGNED IN SIZE, SINCE
++    //         IT IS ZONE ALLOCATED, AND REPINNED_BCBS_ARRAY_SIZE AFFECTS
++    //         ITS SIZE.
++    //
++
++    NODE_TYPE_CODE NodeTypeCode;
++    NODE_BYTE_SIZE NodeByteSize;
++
++      //
++      //      The Adapter that this I/O is destined for.
++      //
++
++      PAFA_COMM_ADAPTER Adapter;
++
++    PHYSICAL_ADDRESS LogicalFibAddress;
++
++    //
++    // This is the event the sendfib routine will wait on if the
++    // caller did not pass one and this is synch io.
++    //
++
++  OS_CV_T     FsaEvent;
++      OS_CVLOCK       *FsaEventMutex;
++
++      ULONG   FibComplete;    // gets set to 1 when fib is complete
++    
++      PFIB_CALLBACK FibCallback;
++      PVOID FibCallbackContext;
++
++      ULONG   Flags;
++
++
++#ifdef GATHER_FIB_TIMES
++      LARGE_INTEGER   FibTimeStamp;
++      PFIB_TIMES              FibTimesPtr;
++#endif
++
++      //
++      // The following is used to put this fib context onto the Outstanding I/O queue.
++      //
++              
++      LIST_ENTRY      QueueEntry;     
++
++      //
++      // The following is used to timeout a fib to the adapter.
++      //
++
++      LARGE_INTEGER   TimeoutValue;
++
++      PVOID   FibData;
++
++    PFIB Fib;
++
++} COMM_FIB_CONTEXT;
++typedef COMM_FIB_CONTEXT *PCOMM_FIB_CONTEXT;
++
++#define FIB_CONTEXT_FLAG_TIMED_OUT            (0x00000001)
++
++#endif /* _COMM_FIB_CONTEXT_ */
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/comprocs.h linux/drivers/scsi/aacraid/include/comprocs.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/comprocs.h        Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/comprocs.h      Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,93 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   comprocs.h
++ *
++ * Abstract: This module defines all of the globally used procedures in the Afa comm layer
++ *
++ *
++ *
++ --*/
++#ifndef _COMPROCS_
++#define _COMPROCS_
++
++static char *ident_comproc = "aacraid_ident comprocs.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#include "osheaders.h"
++
++#include "AacGenericTypes.h"
++
++#include "aac_unix_defs.h"
++
++#include "nodetype.h"
++
++// #define GATHER_FIB_TIMES
++
++#include "fsatypes.h"
++
++#include "perfpack.h"
++
++#include "comstruc.h"
++
++//#include "unix_protocol.h"
++
++#include "fsact.h"
++
++#include "protocol.h"
++
++#include "fsaioctl.h"
++
++#undef GATHER_FIB_TIMES
++
++#include "aifstruc.h"
++
++#include "fsaport.h"
++#include "comsup.h"
++#include "afacomm.h"
++#include "adapter.h"
++
++#include "commfibcontext.h"
++#include "comproto.h"
++#include "commdata.h"
++#include "commerr.h"
++
++
++
++
++//
++// The following macro is used when sending and receiving FIBs.  It is only used for
++// debugging.
++
++#if DBG
++#define       FIB_COUNTER_INCREMENT(Counter)          InterlockedIncrement(&(Counter))
++#else
++#define       FIB_COUNTER_INCREMENT(Counter)          
++#endif
++
++
++
++int
++AfaCommAdapterDeviceControl (
++      IN PVOID AdapterArg,
++      IN PAFA_IOCTL_CMD       IoctlCmdPtr
++      );
++
++
++#endif // _COMPROCS_
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/comproto.h linux/drivers/scsi/aacraid/include/comproto.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/comproto.h        Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/comproto.h      Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,170 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   comproto.h
++ *
++ * Abstract: Global routines for the commuication interface that are device
++ *           independant.
++ *
++ *
++ *
++ --*/
++#ifndef _COMM_PROTO
++#define _COMM_PROTO
++
++static char *ident_comproto = "aacraid_ident comproto.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++//
++// define the routines we need so we can commuicate with the
++// fsa adapter
++//
++
++//
++// The following 4 dpc routines will support commuication from the adapter to the
++// host. There is one DPC routine to deal with each type of queue that supports
++// commuication from the adapter. (adapter to host resposes, adapter to host commands)
++// These routines will simply pull off the QE and set an event. In the case of a
++// adapter to host command they will also put the FIB on a queue to be processed by
++// a FS thread running at passive level.
++//
++
++// Handle queue not full notification to the file system thread waiting for a queue entry
++
++u_int
++CommonNotFullDpc(
++      IN PCOMM_REGION CommRegion
++    );
++
++// Adapter to host normal priority responses
++
++u_int
++HostResponseNormalDpc(
++    IN PCOMM_QUE OurQueue
++    );
++
++// Adapter to host high priority responses
++u_int
++HostResponseHighDpc(
++    IN PCOMM_QUE OurQueue
++    );
++
++// Adapter to host high priority commands
++u_int
++HostCommandHighDpc(
++    IN PCOMM_QUE OurQueue
++    );
++    
++
++// Adapter to host normal priority commands
++u_int
++HostCommandNormDpc(
++    IN PCOMM_QUE OurQueue
++    );
++
++
++
++BOOLEAN
++SendSynchFib(
++      PVOID                   Arg,
++      FIB_COMMAND     Command,
++      PVOID                   Data,
++      USHORT                  Size,
++      PVOID                   Response,
++      USHORT                  *ResponseSize
++      );
++
++PFIB_CONTEXT
++AllocateFib (
++      IN PVOID Adapter
++    );
++
++VOID
++FreeFib (
++    IN PFIB_CONTEXT FibContext
++    );
++
++VOID
++FreeFibFromDpc(
++    IN PFIB_CONTEXT FibContext
++    );
++
++AAC_STATUS
++DeallocateFib(
++    IN PFIB_CONTEXT FibContext
++    );
++
++
++
++AAC_STATUS
++SendFib(
++    IN FIB_COMMAND Command, 
++      IN PFIB_CONTEXT FibContext,
++    IN ULONG Size,
++    IN COMM_PRIORITIES Priority,
++    IN BOOLEAN Wait,
++    IN PVOID WaitOn,
++    IN BOOLEAN ResponseExpected,
++      IN PFIB_CALLBACK FibCallback,
++      IN PVOID FibCallbackContext
++    );
++
++AAC_STATUS
++CompleteFib(
++      IN PFIB_CONTEXT FibContext
++    );
++
++AAC_STATUS
++CompleteAdapterFib(
++      IN PFIB_CONTEXT FibContext,
++    IN USHORT Size
++    );
++
++AAC_STATUS
++InitializeFib(
++      IN PFIB_CONTEXT FibContext
++    );
++
++
++PVOID
++FsaGetFibData(
++      IN PFIB_CONTEXT FibContext
++      );
++
++
++
++AAC_STATUS
++AfaCommOpenAdapter (
++      IN PVOID AdapterArg
++      );
++
++AAC_STATUS
++AfaCommCloseAdapter (
++      IN PVOID AdapterArg
++      );
++
++
++VOID
++AfaCommInterruptHost(
++      PVOID   Adapter,
++      ADAPTER_EVENT   AdapterEvent
++      );
++
++
++#endif // _COMM_PROTO
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/comstruc.h linux/drivers/scsi/aacraid/include/comstruc.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/comstruc.h        Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/comstruc.h      Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,435 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   comstruc.h
++ *
++ * Abstract: This module defines the data structures that make up the communication
++ *           region for the FSA filesystem. This region is how the host based code
++ *           communicates both control and data to the adapter based code.
++ *
++ *
++ *
++ --*/
++#ifndef _COMM_STRUCT
++#define _COMM_STRUCT
++
++static char *ident_comstruc = "aacraid_ident comstruc.h 1.0.7 2000/10/11 Adaptec, Inc.";
++
++//
++// Define all the constants needed for the communication interface
++//
++
++// Define how many queue entries each queue will have and the total number of
++// entries for the entire communication interface. Also define how many queues
++// we support.
++
++#define NUMBER_OF_COMM_QUEUES  8   // 4 command; 4 response
++#define HOST_HIGH_CMD_ENTRIES  4
++#define HOST_NORM_CMD_ENTRIES  8
++#define ADAP_HIGH_CMD_ENTRIES  4
++#define ADAP_NORM_CMD_ENTRIES  512
++#define HOST_HIGH_RESP_ENTRIES 4
++#define HOST_NORM_RESP_ENTRIES 512
++#define ADAP_HIGH_RESP_ENTRIES 4
++#define ADAP_NORM_RESP_ENTRIES 8
++
++#define TOTAL_QUEUE_ENTRIES  \
++    (HOST_NORM_CMD_ENTRIES + HOST_HIGH_CMD_ENTRIES + ADAP_NORM_CMD_ENTRIES + ADAP_HIGH_CMD_ENTRIES + \
++          HOST_NORM_RESP_ENTRIES + HOST_HIGH_RESP_ENTRIES + ADAP_NORM_RESP_ENTRIES + ADAP_HIGH_RESP_ENTRIES)
++
++
++
++
++// Set the queues on a 16 byte alignment
++#define QUEUE_ALIGNMENT               16
++
++
++//
++// The queue headers define the Communication Region queues. These
++// are physically contiguous and accessible by both the adapter and the
++// host. Even though all queue headers are in the same contiguous block they will be
++// represented as individual units in the data structures.
++//
++
++typedef AAC_UINT32 QUEUE_INDEX;
++
++typedef QUEUE_INDEX *PQUEUE_INDEX;
++
++typedef struct _QUEUE_ENTRY {
++
++    AAC_UINT32 Size;                     // Size in bytes of the Fib which this QE points to
++    AAC_UINT32 FibAddress;                    // Receiver addressable address of the FIB (low 32 address bits)
++
++} QUEUE_ENTRY;
++
++typedef QUEUE_ENTRY *PQUEUE_ENTRY;
++
++
++
++// The adapter assumes the ProducerIndex and ConsumerIndex are grouped
++// adjacently and in that order.
++//
++typedef struct _QUEUE_HEADERS {
++
++    PHYSICAL_ADDRESS LogicalHeaderAddress;  // Address to hand the adapter to access to this queue head
++    PQUEUE_INDEX ProducerIndex;              // The producer index for this queue (host address)
++    PQUEUE_INDEX ConsumerIndex;              // The consumer index for this queue (host address)
++
++} QUEUE_HEADERS;
++typedef QUEUE_HEADERS *PQUEUE_HEADERS;
++
++//
++// Define all the events which the adapter would like to notify
++// the host of.
++//
++typedef enum _ADAPTER_EVENT {
++    HostNormCmdQue = 1,         // Change in host normal priority command queue
++    HostHighCmdQue,             // Change in host high priority command queue
++    HostNormRespQue,            // Change in host normal priority response queue
++    HostHighRespQue,            // Change in host high priority response queue
++    AdapNormRespNotFull,
++    AdapHighRespNotFull,
++    AdapNormCmdNotFull,
++    AdapHighCmdNotFull,
++      SynchCommandComplete,
++    AdapInternalError = 0xfe    // The adapter detected an internal error shutting down
++
++} _E_ADAPTER_EVENT;
++
++#ifdef AAC_32BIT_ENUMS
++typedef _E_ADAPTER_EVENT      ADAPTER_EVENT;
++#else
++typedef AAC_UINT32                    ADAPTER_EVENT;
++#endif
++
++//
++// Define all the events the host wishes to notify the
++// adapter of.
++//
++typedef enum _HOST_2_ADAP_EVENT {
++    AdapNormCmdQue = 1,
++    AdapHighCmdQue,
++    AdapNormRespQue,
++    AdapHighRespQue,
++    HostShutdown,
++    HostPowerFail,
++    FatalCommError,
++    HostNormRespNotFull,
++    HostHighRespNotFull,
++    HostNormCmdNotFull,
++    HostHighCmdNotFull,
++      FastIo,
++      AdapPrintfDone
++} _E_HOST_2_ADAP_EVENT;
++
++#ifdef AAC_32BIT_ENUMS
++typedef _E_HOST_2_ADAP_EVENT  HOST_2_ADAP_EVENT;
++#else
++typedef       AAC_UINT32                              HOST_2_ADAP_EVENT;
++#endif
++
++//
++// Define all the queues that the adapter and host use to communicate
++//
++
++typedef enum _QUEUE_TYPES {
++        HostNormCmdQueue = 1,       // Adapter to host normal priority command traffic
++        HostHighCmdQueue,           // Adapter to host high priority command traffic
++        AdapNormRespQueue,          // Host to adapter normal priority response traffic
++        AdapHighRespQueue,          // Host to adapter high priority response traffic
++        AdapNormCmdQueue,           // Host to adapter normal priority command traffic
++        AdapHighCmdQueue,           // Host to adapter high priority command traffic
++        HostNormRespQueue,          // Adapter to host normal priority response traffic
++        HostHighRespQueue           // Adapter to host high priority response traffic
++} _E_QUEUE_TYPES;
++
++#ifdef AAC_32BIT_ENUMS
++typedef _E_QUEUE_TYPES                QUEUE_TYPES;
++#else
++typedef       AAC_UINT32                      QUEUE_TYPES;
++#endif
++
++
++//
++// Assign type values to the FSA communication data structures
++//
++
++typedef enum _STRUCT_TYPES {
++    TFib = 1,
++    TQe,
++      TCtPerf
++} _E_STRUCT_TYPES;
++
++#ifdef AAC_32BIT_ENUMS
++typedef       _E_STRUCT_TYPES STRUCT_TYPES;
++#else
++typedef       AAC_UINT32              STRUCT_TYPES;
++#endif
++
++//
++// Define the priority levels the FSA communication routines support.
++//
++
++typedef enum _COMM_PRIORITIES {
++    FsaNormal = 1,
++    FsaHigh
++} _E_COMM_PRIORITIES;
++
++#ifdef AAC_32BIT_ENUMS
++typedef _E_COMM_PRIORITIES    COMM_PRIORITIES;
++#else
++typedef       AAC_UINT32                      COMM_PRIORITIES;
++#endif
++
++
++
++//
++// Define the LIST_ENTRY structure.  This structure is used on the NT side to link
++// the FIBs together in a linked list.  Since this structure gets compiled on the adapter
++// as well, we need to define this structure for the adapter's use.  If '_NT_DEF_'
++// is defined, then this header is being included from the NT side, and therefore LIST_ENTRY
++// is already defined.
++#if !defined(_NTDEF_) && !defined(_WINNT_)
++typedef struct _LIST_ENTRY {
++   struct _LIST_ENTRY *Flink;
++   struct _LIST_ENTRY *Blink;
++} LIST_ENTRY;
++typedef LIST_ENTRY *PLIST_ENTRY;
++#endif
++
++
++//
++// Define the FIB. The FIB is the where all the requested data and
++// command information are put to the application on the FSA adapter.
++//
++
++typedef struct _FIB_HEADER {
++    AAC_UINT32 XferState;                    // Current transfer state for this CCB
++    AAC_UINT16 Command;                     // Routing information for the destination
++    AAC_UINT8 StructType;                   // Type FIB
++      AAC_UINT8 Flags;                                                  // Flags for FIB
++    AAC_UINT16 Size;                        // Size of this FIB in bytes
++    AAC_UINT16 SenderSize;                  // Size of the FIB in the sender (for response sizing)
++    AAC_UINT32 SenderFibAddress;              // Host defined data in the FIB
++    AAC_UINT32 ReceiverFibAddress;            // Logical address of this FIB for the adapter
++    AAC_UINT32 SenderData;                    // Place holder for the sender to store data
++#ifndef __midl
++      union {
++              struct {
++                  AAC_UINT32 _ReceiverTimeStart;      // Timestamp for receipt of fib
++                  AAC_UINT32 _ReceiverTimeDone;       // Timestamp for completion of fib
++              } _s;
++              LIST_ENTRY _FibLinks;                   // Used to link Adapter Initiated Fibs on the host
++      } _u;
++#else                         // The MIDL compiler does not support unions without a discriminant.
++      struct {                // Since nothing during the midl compile actually looks into this
++              struct {        // structure, this shoudl be ok.
++                      AAC_UINT32 _ReceiverTimeStart;  // Timestamp for receipt of fib
++                  AAC_UINT32 _ReceiverTimeDone;       // Timestamp for completion of fib
++              } _s;
++      } _u;
++#endif
++} FIB_HEADER;
++
++
++#define FibLinks                      _u._FibLinks
++
++
++#define FIB_DATA_SIZE_IN_BYTES (512 - sizeof(FIB_HEADER))
++
++
++typedef struct _FIB {
++
++#ifdef BRIDGE //rma
++      DLQUE link;
++#endif
++    FIB_HEADER Header;
++
++    AAC_UINT8 data[FIB_DATA_SIZE_IN_BYTES];           // Command specific data
++
++} FIB;
++typedef FIB *PFIB;
++
++
++
++//
++// FIB commands
++//
++
++typedef enum _FIB_COMMANDS {
++    TestCommandResponse =                     1,
++    TestAdapterCommand =                      2,
++
++      // Lowlevel and comm commands
++
++    LastTestCommand =                                 100,
++    ReinitHostNormCommandQueue =      101,
++    ReinitHostHighCommandQueue =      102,
++    ReinitHostHighRespQueue =                 103,
++    ReinitHostNormRespQueue =                 104,
++    ReinitAdapNormCommandQueue =      105,
++    ReinitAdapHighCommandQueue =      107,
++    ReinitAdapHighRespQueue =                 108,
++    ReinitAdapNormRespQueue =                 109,
++    InterfaceShutdown =                       110,
++    DmaCommandFib =                           120,
++    StartProfile =                                    121,
++    TermProfile =                                     122,
++    SpeedTest =                                       123,
++    TakeABreakPt =                                    124,
++    RequestPerfData =                         125,
++    SetInterruptDefTimer=           126,
++    SetInterruptDefCount=           127,
++    GetInterruptDefStatus=          128,
++    LastCommCommand =                                 129,
++
++      // Filesystem commands
++
++    NuFileSystem =                                    300,
++    UFS =                                                     301,
++    HostFileSystem =                          302,
++    LastFileSystemCommand =           303,
++
++      // Container Commands
++
++    ContainerCommand =                                500,
++      ContainerCommand64 =                    501,
++
++      // Cluster Commands
++
++    ClusterCommand =                          550,
++
++      // Scsi Port commands (scsi passthrough)
++
++    ScsiPortCommand =                                 600,
++
++      // misc house keeping and generic adapter initiated commands
++
++    AifRequest =                                      700,
++    CheckRevision =                                   701,
++    FsaHostShutdown =                                 702,
++    RequestAdapterInfo =                      703,
++    IsAdapterPaused =                         704,
++    SendHostTime =                                    705,
++    LastMiscCommand =                         706
++
++} _E_FIB_COMMANDS;
++
++
++
++typedef AAC_UINT16 FIB_COMMAND;
++
++//
++// Commands that will target the failover level on the FSA adapter
++//
++
++typedef enum _FIB_XFER_STATE {
++    HostOwned                                 = (1<<0),
++    AdapterOwned                      = (1<<1),
++    FibInitialized                    = (1<<2),
++    FibEmpty                          = (1<<3),
++    AllocatedFromPool                 = (1<<4),
++    SentFromHost                      = (1<<5),
++    SentFromAdapter           = (1<<6),
++    ResponseExpected          = (1<<7),
++    NoResponseExpected                = (1<<8),
++    AdapterProcessed          = (1<<9),
++    HostProcessed                     = (1<<10),
++    HighPriority                      = (1<<11),
++    NormalPriority                    = (1<<12),
++    Async                                     = (1<<13),
++    AsyncIo                                   = (1<<13),      // rpbfix: remove with new regime
++    PageFileIo                                = (1<<14),      // rpbfix: remove with new regime
++    ShutdownRequest                   = (1<<15),
++    LazyWrite                         = (1<<16),      // rpbfix: remove with new regime
++    AdapterMicroFib                   = (1<<17),
++    BIOSFibPath                               = (1<<18),
++    FastResponseCapable               = (1<<19),
++      ApiFib                                  = (1<<20)       // Its an API Fib.
++
++} _E_FIB_XFER_STATE;
++
++
++typedef enum _FSA_ERRORS {
++    FSA_NORMAL                  = 0,
++    FSA_SUCCESS                 = 0,
++    FSA_PENDING                 = 0x01,
++    FSA_FATAL                   = 0x02,
++    FSA_INVALID_QUEUE           = 0x03,
++    FSA_NOENTRIES               = 0x04,
++    FSA_SENDFAILED              = 0x05,
++    FSA_INVALID_QUEUE_PRIORITY  = 0x06,
++    FSA_FIB_ALLOCATION_FAILED   = 0x07,
++    FSA_FIB_DEALLOCATION_FAILED = 0x08
++
++} _E_FSA_ERRORS;
++
++
++//
++// The following defines needs to be updated any time there is an incompatible change made
++// to the ADAPTER_INIT_STRUCT structure.
++//
++#define ADAPTER_INIT_STRUCT_REVISION          3
++
++typedef struct _ADAPTER_INIT_STRUCT {
++      AAC_UINT32              InitStructRevision;
++      AAC_UINT32              MiniPortRevision;
++      AAC_UINT32              FilesystemRevision;
++      PAAC_VOID               CommHeaderAddress;
++      PAAC_VOID               FastIoCommAreaAddress;
++      PAAC_VOID               AdapterFibsPhysicalAddress;
++      PAAC_VOID               AdapterFibsVirtualAddress;
++      AAC_UINT32              AdapterFibsSize;
++      AAC_UINT32              AdapterFibAlign;
++      PAAC_VOID               PrintfBufferAddress;
++      AAC_UINT32              PrintfBufferSize;
++      AAC_UINT32              HostPhysMemPages;               // number of 4k pages of host physical memory
++      AAC_UINT32              HostElapsedSeconds;             // number of seconds since 1970.
++} ADAPTER_INIT_STRUCT;
++typedef ADAPTER_INIT_STRUCT *PADAPTER_INIT_STRUCT;
++
++#ifdef AAC_32BIT_ENUMS
++typedef _E_FSA_ERRORS FSA_ERRORS;
++#else
++typedef       AAC_UINT32              FSA_ERRORS;
++#endif
++
++typedef enum _LOG_LEVEL {
++      LOG_INIT                                = 10,
++      LOG_INFORMATIONAL               = 20,
++      LOG_WARNING                             = 30,
++      LOG_LOW_ERROR                   = 40,
++      LOG_MEDIUM_ERROR                = 50,
++      LOG_HIGH_ERROR                  = 60,
++      LOG_PANIC                               = 70,
++      LOG_DEBUG                               = 80,
++      LOG_WINDBG_PRINT                = 90
++} _E_LOG_LEVEL;
++
++#ifdef AAC_32BIT_ENUMS
++typedef _E_LOG_LEVEL  LOG_LEVEL;
++#else
++typedef       AAC_UINT32              LOG_LEVEL;
++#endif
++
++
++#endif //_COMM_STRUCT
++
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/comsup.h linux/drivers/scsi/aacraid/include/comsup.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/comsup.h  Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/comsup.h        Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,132 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   comsup.h
++ *
++ * Abstract: This module defines the data structures that make up the 
++ *           commuication region for the FSA filesystem. This region is
++ *           how the host based code commuicates both control and data
++ *           to the adapter based code. 
++ *
++ *
++ *
++ --*/
++#ifndef _COMM_SUP_DEF
++#define _COMM_SUP_DEF
++
++static char *ident_comsup = "aacraid_ident comsup.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++//
++// The adapter interface specs all queues to be located in the same physically
++// contigous block. The host structure that defines the commuication queues will
++// assume they are each a seperate physically contigous memory region that will
++// support them all being one big contigous block.
++// There is a command and response queue for each level and direction of
++// commuication. These regions are accessed by both the host and adapter.
++//
++typedef struct _COMM_QUE {
++
++    PHYSICAL_ADDRESS LogicalAddress;    // This is the address we give the adapter
++    
++    PQUEUE_ENTRY      BaseAddress;        // This is the system virtual address 
++    QUEUE_HEADERS     Headers;            // A pointer to the producer and consumer queue headers for this queue
++    ULONG                     QueueEntries;       // Number of queue entries on this queue
++    OS_CV_T                   QueueFull;          // Event to wait on if the queue is full
++    OS_CV_T                   CommandReady;       // Indicates there is a Command ready from the adapter on this queue.
++                                        // This is only valid for adapter to host command queues.                                        
++    OS_SPINLOCK               *QueueLock;         // Spinlock for this queue must take this lock before accessing the lock
++    KIRQL                     SavedIrql;          // Previous IRQL when the spin lock is taken
++    ddi_softintr_t    ConsumerRoutine;    // The DPC routine which will consume entries off this queue
++                                        // Only queues which the host will be the consumer will this field be valid
++    LIST_ENTRY                CommandQueue;       // A queue of FIBs which need to be prcessed by the FS thread. This is
++                                        // only valid for command queues which receive entries from the adapter.
++      LIST_ENTRY              OutstandingIoQueue;     // A queue of outstanding fib's to the adapter.
++      ULONG                   NumOutstandingIos;      // Number of entries on outstanding queue.
++
++      PVOID                   Adapter;                        // Back pointer to adapter structure
++
++} COMM_QUE;
++typedef COMM_QUE *PCOMM_QUE;
++
++
++typedef struct _COMM_REGION {
++
++    COMM_QUE HostNormCmdQue;          // Command queue for normal priority commands from the host
++    COMM_QUE HostNormRespQue;           // A response for normal priority adapter responses
++    
++    COMM_QUE HostHighCmdQue;            // Command queue for high priority commands from the host
++    COMM_QUE HostHighRespQue;           // A response for normal priority adapter responses
++    
++    COMM_QUE AdapNormCmdQue;            // Command queue for normal priority command from the adapter
++    COMM_QUE AdapNormRespQue;           // A response for normal priority host responses
++
++    COMM_QUE AdapHighCmdQue;            // Command queue for high priority command from the adapter
++    COMM_QUE AdapHighRespQue;           // A response for high priority host responses
++
++    //
++    // The 2 threads below are the threads which handle command traffic from the
++    // the adapter. There is one for normal priority and one for high priority queues.
++    // These threads will wait on the commandready event for it's queue.
++    //
++
++    HANDLE NormCommandThread;
++    HANDLE HighCommandThread;
++
++    //
++    // This dpc routine will handle the setting the of not full event when the adapter
++    // lets us know the queue is not longer full via interrupt
++    //
++
++    KDPC QueueNotFullDpc;
++
++#ifdef API_THROTTLE
++      //
++      // Support for data I/O throttling to improve CLI performance
++      // while the system is under load.
++      // This is the throttling mechanism built into the COMM layer.
++      // Look in commsup.c, dpcsup.c and comminit.c for use.
++      //
++
++      int                             ThrottleLimit;                          // Max queue depth of data ops allowed during throttle
++      int                             ThrottleOutstandingFibs;        // Number of data FIBs outstanding to adapter
++      LARGE_INTEGER   ThrottleTimeout;                        // Duration of a a throttle period
++      LARGE_INTEGER   ThrottleWaitTimeout;            // Timeout for a suspended threads to wait
++      BOOLEAN                 ThrottleActive;                         // Is there a current throttle active period ?
++      KTIMER                  ThrottleTimer;                          // Throttle timer to end a throttle period.
++      KDPC                    ThrottleDpc;                            // Throttle timer timeout DPC routine.
++      KSEMAPHORE              ThrottleReleaseSema;            // Semaphore callers of SendFib wait on during a throttle.
++
++      unsigned int    ThrottleExceptionsCount;        // Number of times throttle exception handler executed (0!)
++      unsigned int    ThrottleTimerFires;                     // Debug info - #times throttle timer Dpc has fired
++      unsigned int    ThrottleTimerSets;                      // Debug info - #times throttle timer was set
++
++      unsigned int    ThrottledFibs;
++      unsigned int    ThrottleTimedoutFibs;
++      unsigned int    ApiFibs;
++      unsigned int    NonPassiveFibs;
++      unsigned int    TotalFibs;
++      unsigned int    FSInfoFibs;
++
++#endif // #ifdef API_THROTTLE
++
++} COMM_REGION;
++typedef COMM_REGION *PCOMM_REGION;
++
++#endif // _COMM_SUP
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/fsact.h linux/drivers/scsi/aacraid/include/fsact.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/fsact.h   Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/fsact.h Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,165 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   fsact.h
++ *
++ * Abstract:  Common container structures that are required to be
++ *            known on both the host and adapter.
++ *
++ *
++ --*/
++#ifndef _FSACT_H_
++#define       _FSACT_H_
++
++static char *ident_fsact = "aacraid_ident fsact.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++//#include <comstruc.h>
++//#include <fsatypes.h>
++#include <protocol.h> // definitions for FSASTATUS
++
++
++/*
++ * Object-Server / Volume-Manager Dispatch Classes
++ */
++typedef enum _VM_COMMANDS {
++   VM_Null = 0,
++   VM_NameServe,
++   VM_ContainerConfig,
++   VM_Ioctl,
++   VM_FilesystemIoctl,
++   VM_CloseAll,
++   VM_CtBlockRead,            // see protocol.h for BlockRead command layout
++   VM_CtBlockWrite,           // see protocol.h for BlockWrite command layout
++   VM_SliceBlockRead, // raw access to configured "storage objects"
++   VM_SliceBlockWrite,
++   VM_DriveBlockRead, // raw access to physical devices
++   VM_DriveBlockWrite,
++   VM_EnclosureMgt,           // enclosure management
++   VM_Unused,                 // used to be diskset management
++   VM_CtBlockVerify,  // see protocol.h for BlockVerify command layout
++   VM_CtPerf,                 // performance test
++   VM_CtBlockRead64,  // see protocol.h for BlockRead64 command layout
++   VM_CtBlockWrite64, // see protocol.h for BlockWrite64 command layout
++   VM_CtBlockVerify64,        // see protocol.h for BlockVerify64 command layout   
++   MAX_VMCOMMAND_NUM  // used for sizing stats array - leave last
++} _E_VMCOMMAND;
++
++#ifdef AAC_32BIT_ENUMS
++typedef _E_VMCOMMAND  VMCOMMAND;
++#else
++typedef       AAC_UINT32              VMCOMMAND;
++#endif
++
++
++
++//
++// Descriptive information (eg, vital stats)
++// that a content manager might report.  The
++// FileArray filesystem component is one example
++// of a content manager.  Raw mode might be
++// another.
++//
++
++struct FileSysInfo {
++/*
++      a) DOS usage - THINK ABOUT WHERE THIS MIGHT GO -- THXXX
++      b) FSA usage (implemented by ObjType and ContentState fields)
++      c) Block size
++      d) Frag size
++      e) Max file system extension size - (fsMaxExtendSize * fsSpaceUnits)
++      f) I-node density - (computed from other fields)
++*/
++      AAC_UINT32  fsTotalSize;        // consumed by fs, incl. metadata
++      AAC_UINT32  fsBlockSize;
++      AAC_UINT32  fsFragSize;
++      AAC_UINT32  fsMaxExtendSize;
++      AAC_UINT32  fsSpaceUnits;
++      AAC_UINT32  fsMaxNumFiles;
++      AAC_UINT32  fsNumFreeFiles;
++      AAC_UINT32  fsInodeDensity;
++};    // valid iff ObjType == FT_FILESYS && !(ContentState & FSCS_NOTCLEAN)
++
++union ContentManagerInfo {
++      struct FileSysInfo FileSys;     // valid iff ObjType == FT_FILESYS && !(ContentState & FSCS_NOTCLEAN)
++};
++
++//
++// Query for "mountable" objects, ie, objects that are typically
++// associated with a drive letter on the client (host) side.
++//
++
++typedef struct _MNTOBJ {
++
++   AAC_UINT32    ObjectId;
++   FSASTRING  FileSystemName;   // if applicable
++   ContainerCreationInfo   CreateInfo; // if applicable
++   AAC_UINT32    Capacity;
++   FSAVOLTYPE VolType;          // substrate structure
++   FTYPE      ObjType;          // FT_FILESYS, FT_DATABASE, etc.
++   AAC_UINT32     ContentState;     // unready for mounting, readonly, etc.
++
++   union ContentManagerInfo
++              ObjExtension;     // Info specific to content manager (eg, filesystem)
++
++   AAC_UINT32    AlterEgoId;       // != ObjectId <==> snapshot or broken mirror exists
++
++} MNTOBJ;
++
++
++#define FSCS_READONLY 0x0002  // possible result of broken mirror
++
++
++
++typedef struct _MNTINFO {
++
++   VMCOMMAND  Command;
++   FTYPE      MntType;
++   AAC_UINT32     MntCount;
++
++} MNTINFO;
++typedef MNTINFO *PMNTINFO;
++
++typedef struct _MNTINFORESPONSE {
++
++   FSASTATUS Status;
++   FTYPE     MntType;           // should be same as that requested
++   AAC_UINT32    MntRespCount;
++   MNTOBJ    MntTable[1];
++
++} MNTINFORESPONSE;
++typedef MNTINFORESPONSE *PMNTINFORESPONSE;
++
++
++//
++// The following command is sent to shut down each container.
++//
++
++typedef struct _CLOSECOMMAND {
++
++   VMCOMMAND  Command;
++   AAC_UINT32   ContainerId;
++
++} CLOSECOMMAND;
++typedef CLOSECOMMAND *PCLOSECOMMAND;
++
++
++#endif /* _FSACT_H_ */
++
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/fsafs.h linux/drivers/scsi/aacraid/include/fsafs.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/fsafs.h   Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/fsafs.h Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,78 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   fsafs.h
++ *
++ * Abstract: Common file system structures that are required to be
++ *           known on both the host and adapter
++ *
++ *
++ *
++ --*/
++
++#ifndef _FSAFS_H_
++#define       _FSAFS_H_ 1
++
++static char *ident_fsafs = "aacraid_ident fsafs.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#include <fsatypes.h>   // core types, shared by client and server, eg, u_long
++
++/*
++ *  Maximum number of filesystems.
++ */
++#define NFILESYS   24
++
++/*
++ * File identifier.
++ * These are unique and self validating within a filesystem
++ * on a single machine and can persist across reboots.
++ * The hint field may be volatile and is not guaranteed to persist
++ * across reboots but is used to speed up the FID to file object translation
++ * if possible. The opaque f1 and f2 fields are guaranteed to uniquely identify
++ * the file object (assuming a filesystem context, i.e. driveno).
++ */
++typedef struct {
++                              AAC_UINT32  hint; // last used hint for fast reclaim
++                              AAC_UINT32  f1;   // opaque
++                              AAC_UINT32  f2;   // opaque
++                      } fileid_t;             /* intra-filesystem file ID type */
++
++      
++/*
++ * Generic file handle
++ */
++struct fhandle {
++      fsid_t   fh_fsid;       /* File system id of mount point */
++      fileid_t fh_fid;        /* File sys specific file id */
++};
++typedef struct fhandle fhandle_t;
++
++#define       FIDSIZE         sizeof(fhandle_t)
++
++typedef struct {
++      union {
++              AAC_INT8        fid_data[FIDSIZE];
++              struct  fhandle fsafid;
++      } fidu;
++} FSAFID;                                     /* FSA File ID type */
++
++                                                              
++#endif /* _FSAFS_H_ */
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/fsaioctl.h linux/drivers/scsi/aacraid/include/fsaioctl.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/fsaioctl.h        Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/fsaioctl.h      Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,159 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   fsaioctl.h
++ *
++ * Abstract: Defines the interface structures between user mode applications
++ *           and the fsa driver.  This structures are used in 
++ *           DeviceIoControl() calls.
++ *
++ *
++ *
++ --*/
++#ifndef _FSAIOCTL_H_
++#define _FSAIOCTL_H_
++
++static char *ident_fsaioctl = "aacraid_ident fsaioctl.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#ifndef IOTRACEUSER
++
++#ifndef CTL_CODE
++
++
++#define FILE_DEVICE_CONTROLLER          0x00000004
++
++//
++// Macro definition for defining IOCTL and FSCTL function control codes.  Note
++// that function codes 0-2047 are reserved for Microsoft Corporation, and
++// 2048-4095 are reserved for customers.
++//
++
++#define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
++    ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
++)
++
++//
++// Define the method codes for how buffers are passed for I/O and FS controls
++//
++
++#define METHOD_BUFFERED                 0
++
++
++#define METHOD_NEITHER                  3
++
++//
++// Define the access check value for any access
++//
++//
++// The FILE_READ_ACCESS and FILE_WRITE_ACCESS constants are also defined in
++// ntioapi.h as FILE_READ_DATA and FILE_WRITE_DATA. The values for these
++// constants *MUST* always be in sync.
++//
++#define FILE_ANY_ACCESS                 0
++
++
++
++#endif
++
++
++
++typedef struct _UNIX_QUERY_DISK {
++      AAC_INT32       ContainerNumber;
++      AAC_INT32       Bus;
++      AAC_INT32       Target;
++      AAC_INT32       Lun;
++      AAC_BOOLEAN     Valid;
++      AAC_BOOLEAN     Locked;
++      AAC_BOOLEAN     Deleted;
++      AAC_INT32       Instance;
++      AAC_INT8        diskDeviceName[10];
++      AAC_BOOLEAN UnMapped;
++} UNIX_QUERY_DISK;
++typedef UNIX_QUERY_DISK *PUNIX_QUERY_DISK;
++
++
++typedef struct _DELETE_DISK {
++      AAC_UINT32      NtDiskNumber;
++      AAC_UINT32      ContainerNumber;
++} DELETE_DISK;
++typedef DELETE_DISK *PDELETE_DISK;
++
++
++#endif /*IOTRACEUSER*/
++
++#define FSACTL_NULL_IO_TEST             0x43    // CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2048, METHOD_NEITHER, FILE_ANY_ACCESS)
++#define FSACTL_SIM_IO_TEST              0x53    // CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2049, METHOD_NEITHER, FILE_ANY_ACCESS)
++
++
++#define FSACTL_SENDFIB                  CTL_CODE(FILE_DEVICE_CONTROLLER, 2050, METHOD_BUFFERED, FILE_ANY_ACCESS)
++
++
++#define FSACTL_GET_VAR                                        0x93
++#define FSACTL_SET_VAR                                        0xa3
++#define FSACTL_GET_FIBTIMES                           0xb3
++#define FSACTL_ZERO_FIBTIMES                  0xc3
++
++
++#define FSACTL_DELETE_DISK                            0x163
++#define FSACTL_QUERY_DISK                             0x173
++
++
++// AfaComm perfmon ioctls
++#define FSACTL_GET_COMM_PERF_DATA             CTL_CODE(FILE_DEVICE_CONTROLLER, 2084, METHOD_BUFFERED, FILE_ANY_ACCESS)
++
++
++#define FSACTL_OPENCLS_COMM_PERF_DATA CTL_CODE(FILE_DEVICE_CONTROLLER, 2085, METHOD_BUFFERED, FILE_ANY_ACCESS)
++
++
++typedef struct _GET_ADAPTER_FIB_IOCTL {
++      char    *AdapterFibContext;
++      int             Wait;
++      char    *AifFib;
++} GET_ADAPTER_FIB_IOCTL, *PGET_ADAPTER_FIB_IOCTL;
++
++//
++// filesystem ioctls
++//
++#define FSACTL_OPEN_GET_ADAPTER_FIB           CTL_CODE(FILE_DEVICE_CONTROLLER, 2100, METHOD_BUFFERED, FILE_ANY_ACCESS)
++
++#define FSACTL_GET_NEXT_ADAPTER_FIB           CTL_CODE(FILE_DEVICE_CONTROLLER, 2101, METHOD_BUFFERED, FILE_ANY_ACCESS)
++
++#define FSACTL_CLOSE_GET_ADAPTER_FIB  CTL_CODE(FILE_DEVICE_CONTROLLER, 2102, METHOD_BUFFERED, FILE_ANY_ACCESS)
++
++#define FSACTL_OPEN_ADAPTER_CONFIG            CTL_CODE(FILE_DEVICE_CONTROLLER, 2103, METHOD_NEITHER, FILE_ANY_ACCESS)
++
++#define FSACTL_CLOSE_ADAPTER_CONFIG           CTL_CODE(FILE_DEVICE_CONTROLLER, 2104, METHOD_NEITHER, FILE_ANY_ACCESS)
++
++
++#define FSACTL_MINIPORT_REV_CHECK             CTL_CODE(FILE_DEVICE_CONTROLLER, 2107, METHOD_BUFFERED, FILE_ANY_ACCESS)
++
++
++#define FSACTL_QUERY_ADAPTER_CONFIG           CTL_CODE(FILE_DEVICE_CONTROLLER, 2113, METHOD_BUFFERED, FILE_ANY_ACCESS)
++
++
++#define FSACTL_FORCE_DELETE_DISK              CTL_CODE(FILE_DEVICE_CONTROLLER, 2120, METHOD_NEITHER, FILE_ANY_ACCESS)
++
++
++#define FSACTL_AIF_THREAD                             CTL_CODE(FILE_DEVICE_CONTROLLER, 2127, METHOD_NEITHER, FILE_ANY_ACCESS)
++
++
++#endif // _FSAIOCTL_H_
++
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/fsaport.h linux/drivers/scsi/aacraid/include/fsaport.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/fsaport.h Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/fsaport.h       Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,223 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   fsaport.h
++ *
++ * Abstract: This module defines all of the globally used procedures in the FSA
++ *           file system.
++ *
++ *
++ *
++ --*/
++#ifndef _FSAPORT_
++#define _FSAPORT_
++
++static char *ident_fsaport = "aacraid_ident fsaport.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++//
++// The scatter/gather map context is the information we 
++// we need to keep the map and transfer data to and from the
++// adapter.
++//
++
++typedef struct _SGMAP_CONTEXT {
++      
++      caddr_t         BaseAddress;
++    PVOID             MapRegBase;
++    ULONG             NumberMapRegs;
++      PSGMAP          SgMapPtr;
++      ULONG           ByteCount;              // Used to check the Mdl length.
++      BOOLEAN         WriteToDevice;
++
++      struct buf      *bp;
++
++
++} SGMAP_CONTEXT;
++typedef SGMAP_CONTEXT *PSGMAP_CONTEXT;
++
++typedef struct _MAPFIB_CONTEXT {
++      PMDL            Mdl;    
++    PVOID             MapRegBase;
++    ULONG             NumberMapRegs;
++      PVOID           FibVirtualAddress;
++      ULONG           Size;
++      PVOID       FibPhysicalAddress;
++
++
++} MAPFIB_CONTEXT;
++typedef MAPFIB_CONTEXT *PMAPFIB_CONTEXT;
++
++typedef BOOLEAN
++(*PFSA_ALLOCATE_ADAPTER_COMM_AREA)(
++      PVOID AdapterExtension,
++      IN OUT PVOID    *BaseAddress,
++      IN ULONG                Size,
++      IN ULONG                Alignment
++      );
++
++typedef BOOLEAN
++(*PFSA_FREE_ADAPTER_COMM_AREA)(
++      PVOID   AdapterExtension
++      );
++
++typedef VOID
++(*PFSA_FREE_DMA_RESOURCES)(    
++      IN PVOID AdapterExtension,
++    IN PSGMAP_CONTEXT SgMapContext
++    );
++
++typedef BOOLEAN
++(*PFSA_ALLOCATE_AND_MAP_FIB_SPACE)(
++      IN PVOID AdapterExtension, 
++      IN PMAPFIB_CONTEXT MapFibContext
++    );
++
++typedef BOOLEAN
++(*PFSA_UNMAP_AND_FREE_FIB_SPACE)(
++      IN PVOID AdapterExtension, 
++      IN PMAPFIB_CONTEXT MapFibContext
++    );
++
++typedef VOID
++(*PFSA_INTERRUPT_ADAPTER)(
++      IN PVOID AdapterExtension
++      );
++
++typedef VOID
++(*PFSA_NOTIFY_ADAPTER)(
++      IN PVOID AdapterExtension,
++    IN HOST_2_ADAP_EVENT AdapterEvent
++    );
++
++typedef VOID
++(*PFSA_RESET_DEVICE)(
++      PVOID AdapterExtension
++      );
++
++typedef AAC_STATUS
++(*PFSA_BUILD_SGMAP)(  
++      IN PVOID AdapterExtension,
++      IN PSGMAP_CONTEXT SgMapContext
++      );
++
++typedef PVOID
++(*PFSA_ADAPTER_ADDR_TO_SYSTEM_ADDR)(  
++      IN PVOID AdapterExtension,
++      IN PVOID AdapterAddress
++      );
++
++typedef VOID
++(*PFSA_INTERRUPT_HOST)(
++      PVOID                   Adapter,
++      ADAPTER_EVENT   AdapterEvent
++      );
++
++typedef VOID
++(*PFSA_ENABLE_INTERRUPT)(
++      PVOID                   Adapter,
++      ADAPTER_EVENT   AdapterEvent,
++      BOOLEAN                 AtDeviceIrq
++      );
++
++
++typedef VOID
++(*PFSA_DISABLE_INTERRUPT)(
++      PVOID                   Adapter,
++      ADAPTER_EVENT   AdapterEvent,
++      BOOLEAN                 AtDeviceIrq
++      );
++
++typedef AAC_STATUS
++(*PFSA_OPEN_ADAPTER) (
++      IN PVOID Adapter
++      );
++
++typedef int
++(*PFSA_DEVICE_CONTROL) (
++      IN PVOID Adapter,
++      IN PAFA_IOCTL_CMD IoctlCmdPtr
++      );
++
++typedef AAC_STATUS
++(*PFSA_CLOSE_ADAPTER) (
++      IN PVOID Adapter
++      );
++
++typedef BOOLEAN
++(*PFSA_SEND_SYNCH_FIB) (
++      IN PVOID Adapter,
++      IN ULONG FibPhysicalAddress
++      );
++
++typedef struct _FSAPORT_FUNCS {
++      ULONG                                                           SizeOfFsaPortFuncs;
++
++      PFSA_ALLOCATE_ADAPTER_COMM_AREA         AllocateAdapterCommArea;
++      PFSA_FREE_ADAPTER_COMM_AREA                     FreeAdapterCommArea;
++      PFSA_FREE_DMA_RESOURCES                         FreeDmaResources;
++      PFSA_ALLOCATE_AND_MAP_FIB_SPACE         AllocateAndMapFibSpace;
++      PFSA_UNMAP_AND_FREE_FIB_SPACE           UnmapAndFreeFibSpace;
++      PFSA_INTERRUPT_ADAPTER                          InterruptAdapter;
++      PFSA_NOTIFY_ADAPTER                                     NotifyAdapter;
++      PFSA_ENABLE_INTERRUPT                           EnableInterrupt;
++      PFSA_DISABLE_INTERRUPT                          DisableInterrupt;
++      PFSA_RESET_DEVICE                                       ResetDevice;
++      PFSA_BUILD_SGMAP                                        BuildSgMap;
++      PFSA_ADAPTER_ADDR_TO_SYSTEM_ADDR        AdapterAddressToSystemAddress;
++
++      PFSA_INTERRUPT_HOST                                     InterruptHost;
++      PFSA_OPEN_ADAPTER                                       OpenAdapter;
++      PFSA_DEVICE_CONTROL                                     DeviceControl;
++      PFSA_CLOSE_ADAPTER                                      CloseAdapter;
++
++      PFSA_SEND_SYNCH_FIB                                     SendSynchFib;
++
++} FSAPORT_FUNCS;
++typedef FSAPORT_FUNCS *PFSAPORT_FUNCS;
++
++typedef AAC_STATUS
++(*PFSA_SETVAR_CALLBACK) (
++      IN PVOID Adapter,
++      IN ULONG NewValue
++      );
++
++typedef struct _FSA_USER_VAR {
++      char                                    Name[32];
++      ULONG                                   *Address;
++      PFSA_SETVAR_CALLBACK    SetVarCallback;
++} FSA_USER_VAR;
++
++typedef FSA_USER_VAR *PFSA_USER_VAR;
++
++typedef struct _FSA_NEW_ADAPTER {
++      PVOID                           AdapterExtension;
++      PFSAPORT_FUNCS          AdapterFuncs;
++      PVOID                           Adapter;
++      BOOLEAN                         AdapterInterruptsBelowDpc;
++      PFSA_USER_VAR           AdapterUserVars;
++      ULONG                           AdapterUserVarsSize;
++      void                            *Dip;
++} FSA_NEW_ADAPTER;
++typedef FSA_NEW_ADAPTER *PFSA_NEW_ADAPTER;
++
++#define       FSAFS_GET_NEXT_ADAPTER                  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2048, METHOD_NEITHER, FILE_ANY_ACCESS)
++#define       FSAFS_INIT_NEW_ADAPTER                  CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 2049, METHOD_NEITHER, FILE_ANY_ACCESS)
++
++#endif
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/fsatypes.h linux/drivers/scsi/aacraid/include/fsatypes.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/fsatypes.h        Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/fsatypes.h      Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,214 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   fsatypes.h
++ *
++ * Abstract: Define all shared data types here, ie, those
++ *           types shared among several components, such
++ *           as host (driver + apps), adapter, and BIOS.
++ *
++ *
++ --*/
++#ifndef _FSATYPES_H
++#define _FSATYPES_H
++
++static char *ident_fsatype = "aacraid_ident fsatypes.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++typedef       AAC_UINT32              AAC_BOOLEAN;
++
++//
++// Define a 64-bit address structure for use on
++// a 32-bit processor architecture.
++//
++typedef struct {
++      AAC_UINT32              lo32;
++      AAC_UINT32              hi32;
++} AAC_UINT64S, *PAAC_UINT64S;
++
++
++
++//
++// Container Types
++//
++typedef struct {
++   AAC_UINT32 data[2];  // RMA FIX, make this a real serial number when we
++                          // know what it looks like.  Note, BIOS sees this
++                          // definition and it must be coded in such a way
++                          // that it appears to be 64 bits.  ints are 16 bits
++                          // in BIOS land; fortunately, longs are 32 bits.
++} SerialNumberT;
++
++
++
++//
++//    ***********************
++//    DON'T CHANGE THE ORDER, ctdevsw use this order to map the drivers
++//    ***********************
++//    drivers for CT_NONE to CT_PASSTHRU
++//
++typedef enum _FSAVOLTYPE {
++      CT_NONE = 0,                            
++      CT_VOLUME,                                      
++      CT_MIRROR,
++      CT_STRIPE,
++      CT_RAID5,
++      CT_SSRW,
++      CT_SSRO,
++      CT_MORPH,
++      CT_PASSTHRU,
++      CT_RAID4,
++      CT_RAID10,                                      // stripe of mirror
++      CT_RAID00,                                      // stripe of stripe
++      CT_VOLUME_OF_MIRRORS,           // volume of mirror
++      CT_PSEUDO_RAID3,                        // really raid4
++
++      CT_LAST_VOLUME_TYPE
++
++} _E_FSAVOLTYPE;
++
++#ifdef AAC_32BIT_ENUMS
++typedef       _E_FSAVOLTYPE   FSAVOLTYPE;
++#else
++typedef       AAC_UINT32              FSAVOLTYPE;
++#endif
++
++
++//
++// Types of objects addressable in some fashion by the client.
++// This is a superset of those objects handled just by the filesystem
++// and includes "raw" objects that an administrator would use to
++// configure containers and filesystems.
++//
++typedef enum _FTYPE {
++    FT_REG = 1,     // regular file
++    FT_DIR,         // directory
++    FT_BLK,         // "block" device - reserved
++    FT_CHR,         // "character special" device - reserved
++    FT_LNK,         // symbolic link
++    FT_SOCK,        // socket
++    FT_FIFO,        // fifo
++    FT_FILESYS,     // ADAPTEC's "FSA"(tm) filesystem
++    FT_DRIVE,       // physical disk - addressable in scsi by bus/target/lun
++    FT_SLICE,       // virtual disk - raw volume - slice
++    FT_PARTITION,   // FSA partition - carved out of a slice - building block for containers
++    FT_VOLUME,      // Container - Volume Set
++    FT_STRIPE,      // Container - Stripe Set
++    FT_MIRROR,      // Container - Mirror Set
++    FT_RAID5,       // Container - Raid 5 Set
++    FT_DATABASE     // Storage object with "foreign" content manager
++} _E_FTYPE;
++
++#ifdef AAC_32BIT_ENUMS
++typedef       _E_FTYPE        FTYPE;
++#else
++typedef       AAC_UINT32      FTYPE;
++#endif
++
++
++
++//
++// Host side memory scatter gather list
++// Used by the adapter for read, write, and readdirplus operations
++//
++typedef  PAAC_UINT8 HOSTADDRESS;
++
++typedef struct _SGENTRY {
++      HOSTADDRESS             SgAddress;              /* 32-bit Base address. */
++      AAC_UINT32                      SgByteCount;    /* Length. */
++} SGENTRY;
++typedef SGENTRY *PSGENTRY;
++
++
++
++//
++// SGMAP
++//
++// This is the SGMAP structure for all commands that use
++// 32-bit addressing.
++//
++// Note that the upper 16 bits of SgCount are used as flags.
++// Only the lower 16 bits of SgCount are actually used as the
++// SG element count.
++//
++typedef struct _SGMAP {
++      AAC_UINT32              SgCount;
++      SGENTRY                 SgEntry[1];
++} SGMAP;
++typedef SGMAP *PSGMAP;
++
++
++
++//
++// SGMAP64
++//
++// This is the SGMAP structure for 64-bit container commands.
++//
++typedef struct _SGMAP64 {
++      AAC_UINT8       SgCount;
++      AAC_UINT8       SgSectorsPerPage;
++      AAC_UINT16      SgByteOffset; // For the first page 
++      AAC_UINT64S     SgEntry[1];     // Must be last entry
++} SGMAP64;
++typedef SGMAP64 *PSGMAP64;
++
++
++
++
++//
++// attempt at common time structure across host and adapter
++//
++typedef struct __TIME_T {
++
++      AAC_UINT32      tv_sec;         /* seconds (maybe, depends upon host) */
++      AAC_UINT32      tv_usec;        /* and nanoseconds (maybe, depends upon host)*/
++
++} TIME_T;
++typedef TIME_T *PTIME_T;
++
++#ifndef _TIME_T
++#define timespec __TIME_T
++#define ts_sec        tv_sec
++#define ts_nsec       tv_usec
++#endif
++
++
++
++
++typedef struct _ContainerCreationInfo
++{
++
++      AAC_UINT8               ViaBuildNumber;         // e.g., 588
++      AAC_UINT8               MicroSecond;            // e.g., 588
++      AAC_UINT8               Via;                            // e.g.,        1 = FSU,
++                                                                              //                      2 = API,
++      AAC_UINT8               YearsSince1900;         // e.g., 1997 = 97
++      AAC_UINT32              Date;                   //
++                                                                              // unsigned     Month           :4;             // 1 - 12
++                                                                              // unsigned     Day                     :6;             // 1 - 32
++                                                                              // unsigned     Hour            :6;             // 0 - 23
++                                                                              // unsigned     Minute          :6;             // 0 - 60
++                                                                              // unsigned     Second          :6;             // 0 - 60
++      SerialNumberT   ViaAdapterSerialNumber; // e.g., 0x1DEADB0BFAFAF001
++} ContainerCreationInfo;
++
++
++#endif // _FSATYPES_H
++
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/linit.h linux/drivers/scsi/aacraid/include/linit.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/linit.h   Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/linit.h Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,107 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   linit.h
++ *
++ * Abstract: Header file for Linux Driver for Adaptec RAID Array Controller
++ *
++ --*/
++/*------------------------------------------------------------------------------
++ *              I N C L U D E S
++ *----------------------------------------------------------------------------*/
++
++#ifndef _LINIT_H_
++#define _LINIT_H_
++
++static char *ident_linith = "aacraid_ident linit.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#include <linux/config.h>
++
++/*------------------------------------------------------------------------------
++ *              D E F I N E S
++ *----------------------------------------------------------------------------*/
++/* Define the AAC SCSI Host Template structure. */
++#define AAC_HOST_TEMPLATE_ENTRY       \
++  { name:           "AAC",                   /* Driver Name            */ \
++    proc_info:      AAC_ProcDirectoryInfo,   /* ProcFS Info Func       */ \
++    detect:         AAC_DetectHostAdapter,   /* Detect Host Adapter    */ \
++    release:        AAC_ReleaseHostAdapter,  /* Release Host Adapter   */ \
++    info:           AAC_DriverInfo,          /* Driver Info Function   */ \
++    ioctl:          AAC_Ioctl,               /* ioctl Interface        */ \
++    command:        AAC_Command,             /* unqueued command       */ \
++    queuecommand:   AAC_QueueCommand,        /* Queue Command Function */ \
++    abort:          AAC_AbortCommand,        /* Abort Command Function */ \
++    reset:          AAC_ResetCommand,        /* Reset Command Function */ \
++    bios_param:     AAC_BIOSDiskParameters,  /* BIOS Disk Parameters   */ \
++    can_queue:      1,                       /* Default initial value  */ \
++    this_id:        0,                       /* Default initial value  */ \
++    sg_tablesize:   0,                       /* Default initial value  */ \
++    max_sectors:    128,                     /* max xfer size of 64k   */ \
++    cmd_per_lun:    0,                       /* Default initial value  */ \
++    present:        0,                       /* Default initial value  */ \
++    unchecked_isa_dma: 0,                    /* Default Initial Value  */ \
++    use_new_eh_code:         0,                  /* Default initial value      */ \
++    eh_abort_handler:        AAC_AbortCommand,   /* New Abort Command func     */ \
++    eh_strategy_handler:     NULL,               /* New Strategy Error Handler */ \
++    eh_device_reset_handler: NULL,               /* New Device Reset Handler   */ \
++    eh_bus_reset_handler:    NULL,               /* New Bus Reset Handler      */ \
++    eh_host_reset_handler:   NULL,               /* New Host reset Handler     */ \
++    use_clustering: ENABLE_CLUSTERING        /* Disable Clustering      */ \
++  }
++
++
++/*------------------------------------------------------------------------------
++ *              T Y P E D E F S / S T R U C T S
++ *----------------------------------------------------------------------------*/
++typedef struct AAC_BIOS_DiskParameters
++{
++      int heads;
++      int sectors;
++      int cylinders;
++} AAC_BIOS_DiskParameters_T;
++
++
++/*------------------------------------------------------------------------------
++ *              P R O G R A M   G L O B A L S
++ *----------------------------------------------------------------------------*/
++
++const char *AAC_DriverInfo( struct Scsi_Host * );
++
++
++/*------------------------------------------------------------------------------
++ *              F U N C T I O N   P R O T O T Y P E S
++ *----------------------------------------------------------------------------*/
++/* Define prototypes for the AAC Driver Interface Functions. */
++int AAC_DetectHostAdapter( Scsi_Host_Template * );
++int AAC_ReleaseHostAdapter( struct Scsi_Host * );
++int AAC_QueueCommand( Scsi_Cmnd *, void ( *CompletionRoutine )( Scsi_Cmnd * ) );
++int AAC_Command( Scsi_Cmnd * );
++int AAC_ResetCommand( Scsi_Cmnd *, unsigned int );
++int AAC_BIOSDiskParameters( Disk *, kdev_t, int * );
++int AAC_ProcDirectoryInfo( char *, char **, off_t, int, int, int );
++int AAC_Ioctl( Scsi_Device *, int, void * );
++
++
++void AAC_SelectQueueDepths(   struct Scsi_Host *, Scsi_Device * );
++
++
++int AAC_AbortCommand( Scsi_Cmnd *scsi_cmnd_ptr );
++
++#endif /* _LINIT_H_ */
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/monkerapi.h linux/drivers/scsi/aacraid/include/monkerapi.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/monkerapi.h       Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/monkerapi.h     Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,98 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   monkerapi.h
++ *
++ * Abstract: This module contains the definitions used by the Host Adapter
++ *      Communications interface.
++ *      This is the interface used for by host programs and the Adapter 
++ *      to communicate via synchronous commands via a shared set of registers
++ *      on a platform (typically doorbells and mailboxes).
++ *
++ --*/
++//**********************************************************************
++//
++//    Monitor / Kernel API
++//
++//    03/24/1998 Bob Peret    Initial creation
++//
++//**********************************************************************
++
++#ifndef MONKER_H
++#define MONKER_H
++
++static char *ident_monk = "aacraid_ident monkerapi.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#define       BREAKPOINT_REQUEST                                      0x00000004
++#define       INIT_STRUCT_BASE_ADDRESS                        0x00000005
++
++
++#define       SEND_SYNCHRONOUS_FIB                            0x0000000c
++
++
++
++//
++//    Adapter Status Register
++//
++//  Phase Staus mailbox is 32bits:
++//    <31:16> = Phase Status
++//    <15:0>  = Phase
++//
++//  The adapter reports is present state through the phase.  Only
++//  a single phase should be ever be set.  Each phase can have multiple
++//    phase status bits to provide more detailed information about the 
++//    state of the board.  Care should be taken to ensure that any phase status 
++//  bits that are set when changing the phase are also valid for the new phase
++//  or be cleared out.  Adapter software (monitor, iflash, kernel) is responsible
++//  for properly maintining the phase status mailbox when it is running.
++
++//                                                                                    
++// MONKER_API Phases                                                  
++//
++// Phases are bit oriented.  It is NOT valid 
++// to have multiple bits set                                          
++//                                    
++
++
++#define       SELF_TEST_FAILED                                        0x00000004
++
++
++#define       KERNEL_UP_AND_RUNNING                           0x00000080
++#define       KERNEL_PANIC                                            0x00000100
++
++
++
++//
++// Doorbell bit defines
++//
++
++
++#define DoorBellPrintfDone                            (1<<5)  // Host -> Adapter
++
++
++#define DoorBellAdapterNormCmdReady           (1<<1)  // Adapter -> Host
++#define DoorBellAdapterNormRespReady  (1<<2)  // Adapter -> Host
++#define DoorBellAdapterNormCmdNotFull (1<<3)  // Adapter -> Host
++#define DoorBellAdapterNormRespNotFull        (1<<4)  // Adapter -> Host
++#define DoorBellPrintfReady                           (1<<5)  // Adapter -> Host
++
++
++#endif // MONKER_H
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/nodetype.h linux/drivers/scsi/aacraid/include/nodetype.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/nodetype.h        Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/nodetype.h      Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,67 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   nodetype.h
++ *
++ * Abstract:     This module defines all of the node type codes used in this development
++ *  shell.  Every major data structure in the file system is assigned a node
++ *  type code that is.  This code is the first CSHORT in the structure and is
++ *  followed by a CSHORT containing the size, in bytes, of the structure.
++ *
++ --*/
++#ifndef _NODETYPE_
++#define _NODETYPE_
++
++static char *ident_node = "aacraid_ident nodetype.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++typedef CSHORT NODE_TYPE_CODE;
++
++
++#define FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT ((NODE_TYPE_CODE)0x030b)
++#define FSAFS_NTC_FIB_CONTEXT            ((NODE_TYPE_CODE)0x030c)
++
++
++typedef CSHORT NODE_BYTE_SIZE;
++
++
++//
++//  The following definitions are used to generate meaningful blue bugcheck
++//  screens.  On a bugcheck the file system can output 4 ulongs of useful
++//  information.  The first ulong will have encoded in it a source file id
++//  (in the high word) and the line number of the bugcheck (in the low word).
++//  The other values can be whatever the caller of the bugcheck routine deems
++//  necessary.
++//
++//  Each individual file that calls bugcheck needs to have defined at the
++//  start of the file a constant called BugCheckFileId with one of the
++//  FSAFS_BUG_CHECK_ values defined below and then use FsaBugCheck to bugcheck
++//  the system.
++//
++
++
++#define FSAFS_BUG_CHECK_COMMSUP           (0X001e0000)
++#define FSAFS_BUG_CHECK_DPCSUP            (0X001f0000)
++
++
++#define FsaBugCheck(A,B,C) { cmn_err( CE_PANIC, "aacdisk: module %x, line %x, 0x%x, 0x%x, 0x%x ", BugCheckFileId, __LINE__, A, B, C); }
++
++
++#endif // _NODETYPE_
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/nvramioctl.h linux/drivers/scsi/aacraid/include/nvramioctl.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/nvramioctl.h      Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/nvramioctl.h    Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,112 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   nvramioctl.h
++ *
++ * Abstract: This file defines the data structures related to querying
++ *    and controlling the FSA NVRAM/WriteCache subsystem via the NVRAMIOCTL FIB.
++ *
++ --*/
++#ifndef _NVRAMIOCTL_H_
++#define _NVRAMIOCTL_H_ 1
++
++static char *ident_nvram = "aacraid_ident nvramioctl.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++/*
++ * NVRAM/Write Cache subsystem states
++ */
++typedef enum _NVSTATUS {
++      NVSTATUS_DISABLED = 0,  // present, clean, not being used
++      NVSTATUS_ENABLED,               // present, possibly dirty, ready for use
++      NVSTATUS_ERROR,                 // present, dirty, contains dirty data
++                                                      // for bad/missing device
++      NVSTATUS_BATTERY,               // present, bad or low battery, may contain dirty data
++                                                      // for bad/missing device
++      NVSTATUS_UNKNOWN                // present?????
++} _E_NVSTATUS;
++
++#ifdef AAC_32BIT_ENUMS
++typedef _E_NVSTATUS   NVSTATUS;
++#else
++typedef AAC_UINT32    NVSTATUS;
++#endif
++
++/*
++ * NVRAM/Write Cache subsystem battery component states
++ *
++ */
++//NB: this enum should be identical to battery_status in nvram.h
++//      or else collapsed into one enum someday
++typedef enum _NVBATTSTATUS {
++      NVBATTSTATUS_NONE = 0,  // battery has no power or is not present
++      NVBATTSTATUS_LOW,               // battery is low on power
++      NVBATTSTATUS_OK,                        // battery is okay - normal operation possible only in this state
++      NVBATTSTATUS_RECONDITIONING     // no battery present - reconditioning in process
++} _E_NVBATTSTATUS;
++
++#ifdef AAC_32BIT_ENUMS
++typedef       _E_NVBATTSTATUS NVBATTSTATUS;
++#else
++typedef AAC_UINT32            NVBATTSTATUS;
++#endif
++
++/*
++ * battery transition type
++ */
++typedef enum _NVBATT_TRANSITION {
++      NVBATT_TRANSITION_NONE = 0,     // battery now has no power or is not present
++      NVBATT_TRANSITION_LOW,          // battery is now low on power
++      NVBATT_TRANSITION_OK            // battery is now okay - normal operation possible only in this state
++} _E_NVBATT_TRANSITION;
++
++#ifdef AAC_32BIT_ENUMS
++typedef _E_NVBATT_TRANSITION  NVBATT_TRANSITION;
++#else
++typedef       AAC_UINT32                              NVBATT_TRANSITION;
++#endif
++
++/*
++ * NVRAM Info structure returned for NVRAM_GetInfo call
++ */
++typedef struct _NVRAMDEVINFO {
++      AAC_UINT32              NV_Enabled;             /* write caching enabled */
++      AAC_UINT32              NV_Error;               /* device in error state */
++      AAC_UINT32              NV_NDirty;              /* count of dirty NVRAM buffers */
++      AAC_UINT32              NV_NActive;             /* count of NVRAM buffers being written */
++} NVRAMDEVINFO, *PNVRAMDEVINFO;
++
++typedef struct _NVRAMINFO {
++      NVSTATUS                NV_Status;                              /* nvram subsystem status */
++      NVBATTSTATUS    NV_BattStatus;                  /* battery status */
++      AAC_UINT32              NV_Size;                                /* size of WriteCache NVRAM in bytes */
++      AAC_UINT32              NV_BufSize;                             /* size of NVRAM buffers in bytes */
++      AAC_UINT32              NV_NBufs;                               /* number of NVRAM buffers */
++      AAC_UINT32              NV_NDirty;                              /* count of dirty NVRAM buffers */
++      AAC_UINT32              NV_NClean;                              /* count of clean NVRAM buffers */
++      AAC_UINT32              NV_NActive;                             /* count of NVRAM buffers being written */
++      AAC_UINT32              NV_NBrokered;                   /* count of brokered NVRAM buffers */
++      NVRAMDEVINFO    NV_DevInfo[NFILESYS];   /* per device info */
++      AAC_UINT32              NV_BattNeedsReconditioning;     /* boolean */
++      AAC_UINT32              NV_TotalSize;                   /* total size of all non-volatile memories in bytes */
++} NVRAMINFO, *PNVRAMINFO;
++
++#endif /* !_NVRAMIOCTL_H_ */
++
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/osheaders.h linux/drivers/scsi/aacraid/include/osheaders.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/osheaders.h       Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/osheaders.h     Thu Aug 16 18:12:22 2001
+@@ -0,0 +1,127 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   osheaders.h
++ *
++ * Abstract: Holds all of the header file includes for a particular O/S flavor.
++ *
++ --*/
++#ifndef _OSHEADERS_H_
++#define _OSHEADERS_H_
++
++static char *ident_oshead = "aacraid_ident osheaders.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/blk.h>
++#include <linux/blkdev.h>
++#include <linux/delay.h>
++#include <linux/ioport.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/stat.h>
++#include <linux/pci.h>
++#include <linux/interrupt.h>
++#include <asm/dma.h>
++#include <asm/io.h>
++#include <linux/spinlock.h>
++#include <asm/system.h>
++#include <asm/bitops.h>
++#include <asm/uaccess.h>
++#include <linux/wait.h>
++#include <linux/slab.h>
++#include <linux/tqueue.h>
++#include "ostypes.h"
++#include "scsi.h"
++#include "hosts.h"
++
++#ifndef intptr_t
++#define intptr_t void *
++#endif
++
++#ifndef cred_t
++#define cred_t void
++#endif
++
++#ifndef paddr32_t
++#define paddr32_t unsigned
++#endif
++
++#ifndef bzero 
++#define bzero(b,len) memset(b,0,len)
++#endif
++
++#ifndef bcopy
++#define bcopy(src,dst,len) memcpy(dst,src,len )
++#endif
++
++#ifndef DEVICE_NR
++#define DEVICE_NR(device) ( ( ( MAJOR( device ) & 7 ) << 4 ) + ( MINOR( device ) >> 4 ) )
++#endif
++
++typedef unsigned uint_t;
++
++typedef enum
++{
++      CE_PANIC = 0,
++      CE_WARN,
++      CE_NOTE, 
++      CE_CONT, 
++      CE_DEBUG,
++      CE_DEBUG2,
++      CE_TAIL
++} CE_ENUM_T;
++
++#define CMN_ERR_LEVEL CE_NOTE
++
++#ifndef IN
++#define IN
++#endif
++
++// usage of READ & WRITE as a typedefs in protocol.h
++// conflicts with <linux/fs.h> definition.
++#ifdef READ
++#undef READ
++#endif
++
++#ifdef WRITE
++#undef WRITE
++#endif
++
++typedef struct aac_options
++{
++      int message_level;
++      int reverse_scan; 
++} aac_options_t;
++
++#endif // _OSHEADERS_H_
++
++
++
++
++
++
++
++
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/ostypes.h linux/drivers/scsi/aacraid/include/ostypes.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/ostypes.h Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/ostypes.h       Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,149 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   ostypes.h
++ *
++ * Abstract: Holds all of the O/S specific types.
++ *
++ --*/
++/*------------------------------------------------------------------------------
++ *              D E F I N E S
++ *----------------------------------------------------------------------------*/
++#ifndef _OSTYPES_H_
++#define _OSTYPES_H_
++
++static char *ident_ostypes = "aacraid_ident ostypes.h 1.0.7 2000/10/11 Adaptec, Inc.";
++
++#include <linux/types.h>
++
++#define MAXIMUM_NUM_CONTAINERS        64              // 4 Luns * 16 Targets
++#define MAXIMUM_NUM_ADAPTERS  8
++
++#define OS_ALLOC_MEM_SLEEP            GFP_KERNEL
++
++#define Os_remove_softintr OsSoftInterruptRemove
++#define OsPrintf printk
++#define FsaCommPrint
++
++// the return values for copy_from_user & copy_to_user is the 
++// number of bytes not transferred. Thus if an internal error 
++// occurs, the return value is greater than zero.
++#define COPYIN(SRC,DST,COUNT,FLAGS)  copy_from_user(DST,SRC,COUNT)
++#define COPYOUT(SRC,DST,COUNT,FLAGS) copy_to_user(DST,SRC,COUNT)
++
++#define copyin(SRC,DST,COUNT) copy_from_user(DST,SRC,COUNT)
++#define copyout(SRC,DST,COUNT) copy_to_user(DST,SRC,COUNT)
++
++/*------------------------------------------------------------------------------
++ *              S T R U C T S / T Y P E D E F S
++ *----------------------------------------------------------------------------*/
++typedef struct OS_MUTEX
++{
++      unsigned long lock_var;
++      wait_queue_head_t wq;
++      unsigned owner;
++} OS_MUTEX;
++
++typedef       struct OS_SPINLOCK
++{
++      spinlock_t      spin_lock;
++      unsigned cpu_lock_count[NR_CPUS];
++      unsigned long cpu_flags[NR_CPUS];
++      long lockout_count;
++} OS_SPINLOCK;
++
++#ifdef CVLOCK_USE_SPINLOCK
++      typedef OS_SPINLOCK OS_CVLOCK;
++#else
++      typedef OS_MUTEX OS_CVLOCK;
++#endif
++
++typedef size_t                OS_SIZE_T;
++
++typedef       struct OS_CV_T
++{
++      unsigned long lock_var;
++      unsigned long type;
++      wait_queue_head_t wq;   
++} OS_CV_T;
++
++struct fsa_scsi_hba {
++      void                            *CommonExtension;
++      unsigned long           ContainerSize[MAXIMUM_NUM_CONTAINERS];
++      unsigned long           ContainerType[MAXIMUM_NUM_CONTAINERS];
++      unsigned char           ContainerValid[MAXIMUM_NUM_CONTAINERS];
++      unsigned char           ContainerReadOnly[MAXIMUM_NUM_CONTAINERS];
++      unsigned char           ContainerLocked[MAXIMUM_NUM_CONTAINERS];
++      unsigned char           ContainerDeleted[MAXIMUM_NUM_CONTAINERS];
++      long                            ContainerDevNo[MAXIMUM_NUM_CONTAINERS];
++};
++
++typedef struct fsa_scsi_hba fsadev_t;
++
++typedef struct OsKI
++{
++      struct Scsi_Host *scsi_host_ptr;
++      void * dip;     // #REVISIT#
++      fsadev_t fsa_dev;
++      int thread_pid;
++  int    MiniPortIndex;
++} OsKI_t;
++
++#define dev_info_t    fsadev_t
++
++typedef int   OS_SPINLOCK_COOKIE;
++
++typedef unsigned int  OS_STATUS;
++
++typedef struct tq_struct OS_SOFTINTR;
++
++typedef       OS_SOFTINTR     *ddi_softintr_t;
++
++
++
++//-----------------------------------------------------------------------------
++// Conditional variable functions
++
++void OsCv_init ( 
++      OS_CV_T *cv_ptr );
++
++
++//-----------------------------------------------------------------------------
++// Printing functions
++void printk_err(int flag, char *fmt, ...);
++
++#define cmn_err printk_err
++
++
++//
++// just ignore these solaris ddi functions in the code
++//
++#define DDI_SUCCESS                                           0
++
++#define ddi_add_softintr(A,B,C,D,E,F,G)               OsSoftInterruptAdd(C,F,G)
++
++//#REVIEW#
++#define ddi_remove_softintr(A)                                0
++#define ddi_get_soft_iblock_cookie(A, B, C)   0
++
++#define ASSERT(expr) ((void) 0)
++#define drv_usecwait udelay
++
++#endif // _OSTYPES_H_
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/pcisup.h linux/drivers/scsi/aacraid/include/pcisup.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/pcisup.h  Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/pcisup.h        Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,97 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   pcisup.h
++ *
++ * Abstract: This module defines functions that are defined in PciSup.c
++ *
++ --*/
++#ifndef _PCISUP_
++#define _PCISUP_
++
++static char *ident_pcisup = "aacraid_ident pcisup.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++      
++/*
++ * define which interrupt handler needs to be installed
++ */
++
++#define SaISR 1
++#define RxISR 2
++
++typedef struct _PCI_MINIPORT_COMMON_EXTENSION {
++      ULONG                                   AdapterNumber;                  // Which FSA# this miniport is
++      
++      ULONG                                   PciBusNumber;                   // Which PCI bus we are located on
++      ULONG                                   PciSlotNumber;                  // Whiat PCI slot we are in
++      
++      PVOID                                   Adapter;                                // Back pointer to Fsa adapter object
++      ULONG                                   AdapterIndex;                   // Index into PlxAdapterTypes array
++      PDEVICE_OBJECT                  DeviceObject;                   // Pointer to our device object
++      
++      FSAPORT_FUNCS                   AdapterFuncs;
++      ULONG                                   FilesystemRevision;     // Main driver's revision number
++      
++      
++      PADAPTER_INIT_STRUCT    InitStruct;                             // Holds initialization info to communicate with adapter
++      PVOID                                   PhysicalInitStruct;     // Holds physical address of the init struct
++      
++      
++      PVOID                                   PrintfBufferAddress;    // pointer to buffer used for printf's from the adapter
++      
++      BOOLEAN                                 AdapterPrintfsToScreen;                 
++      BOOLEAN                                 AdapterConfigured;              // set to true when we know adapter can take FIBs
++      
++      void *                                  MiniPort;
++      
++      caddr_t                                 CommAddress;    // Base address of Comm area
++      paddr32_t                               CommPhysAddr;   // Physical Address of Comm area
++      size_t                                  CommSize;
++
++      OsKI_t                                  OsDep;                  // OS dependent kernel interfaces
++
++      
++} PCI_MINIPORT_COMMON_EXTENSION;
++
++typedef PCI_MINIPORT_COMMON_EXTENSION *PPCI_MINIPORT_COMMON_EXTENSION;
++
++typedef int
++(*PFSA_MINIPORT_INIT) (
++      IN PPCI_MINIPORT_COMMON_EXTENSION CommonExtension,
++      IN ULONG AdapterNumber,
++      IN ULONG PciBus,
++      IN ULONG PciSlot
++      );
++
++typedef struct _FSA_MINIPORT {
++      USHORT                          VendorId;
++      USHORT                          DeviceId;
++      USHORT                          SubVendorId;
++      USHORT                          SubSystemId;
++      PCHAR                           DevicePrefix;
++  PFSA_MINIPORT_INIT  InitRoutine;
++  PCHAR               DeviceName;
++  PCHAR               Vendor;
++  PCHAR               Model;
++} FSA_MINIPORT;
++typedef FSA_MINIPORT *PFSA_MINIPORT;
++
++
++#endif // _PCISUP_
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/perfpack.h linux/drivers/scsi/aacraid/include/perfpack.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/perfpack.h        Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/perfpack.h      Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,110 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   perfpack.h
++ *
++ * Abstract: This file defines the layout of the performance data that is passed
++ *           back from the FSA filesystem driver.
++ *
++ *    
++ --*/
++
++#ifndef _FSA_PERFPACK_H_
++#define _FSA_PERFPACK_H_      1
++
++static char *ident_perf = "aacraid_ident perfpack.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++//#define FSA_DO_PERF         1               /* enable the engineering counters */
++
++#ifdef FSA_DO_PERF
++//
++// engineering counters
++//
++typedef struct _FSA_PERF_DATA {
++                      ULONG FibsSent;
++                      ULONG ReadDirs;
++                      ULONG GetAttrs;
++                      ULONG SetAttrs;
++                      ULONG Lookups;
++                      ULONG ReadFibs;
++                      ULONG WriteFibs;
++                      ULONG CreateFibs;
++                      ULONG MakeDirs;
++                      ULONG RemoveFibs;
++                      ULONG RemoveDirs;
++                      ULONG RenameFibs;
++                      ULONG ReadDirPlus;
++                      ULONG FsStat;
++                      ULONG WriteBytes;
++                      ULONG ReadBytes;
++// NT FSA entry points
++                      ULONG FsaFsdCreateCount;
++                      ULONG FsaFsdCloseCount;
++                      ULONG FsaFsdReadCount;
++                      ULONG FsaFsdWriteCount;
++                      ULONG FsaFsdQueryInformationCount;
++
++                      struct _FsaFsdSetInfomation{
++                              ULONG FsaSetAllocationInfoCount;
++                              ULONG FsaSetBasicInfoCount;
++                              ULONG FsaSetDispositionInfoCount;
++                              ULONG FsaSetEndOfFileInfoCount;
++                              ULONG FsaSetPositionInfoCount;
++                              ULONG FsaSetRenameInfoCount;
++                              ULONG FsaClearArchiveBitCount;
++                      };
++
++                      ULONG FsaFsdFlushBuffersCount;
++                      ULONG FsaFsdQueryVolumeInfoCount;
++                      ULONG FsaFsdSetVolumeInfoCount;
++                      ULONG FsaFsdCleanupCount;
++                      ULONG FsaFsdDirectoryControlCount;
++                      ULONG FsaFsdFileSystemControlCount;
++                      ULONG FsaFsdLockControlCount;
++                      ULONG FsaFsdDeviceControlCount;
++                      ULONG FsaFsdShutdownCount;
++                      ULONG FsaFsdQuerySecurityInfo;
++                      ULONG FsaFsdSetSecurityInfo;
++                      ULONG FastIoCheckIfPossibleCount;
++                      ULONG FastIoReadCount;
++                      ULONG FastIoWriteCount;
++                      ULONG FastIoQueryBasicInfoCount;
++                      ULONG FastIoQueryStandardInfoCount;
++                      ULONG FastIoLockCount;
++                      ULONG FastIoUnlockSingleCount;
++                      ULONG FastIoUnlockAllCount;
++                      ULONG FastIoUnlockAllByKeyCount;
++                      ULONG FastIoDeviceControlCount;
++ } FSA_PERF_DATA;
++
++typedef FSA_PERF_DATA *PFSA_PERF_DATA;
++
++
++#else /* FSA_DO_PERF */
++
++//
++// engineering performance counters are disabled
++//
++#define FSA_DO_PERF_INC(Counter)              /* */
++#define FSA_DO_FSP_PERF_INC(Counter)  /* */
++
++#endif /* FSA_DO_PERF */
++
++#endif // _FSA_PERFPACK_H_
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/port.h linux/drivers/scsi/aacraid/include/port.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/port.h    Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/port.h  Thu Aug 16 18:16:55 2001
+@@ -0,0 +1,87 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   port.h
++ *
++ * Abstract: This module defines functions and structures that are in common among all miniports
++ *
++ *    
++ --*/
++
++#ifndef _PORT_
++#define _PORT_
++
++static char *ident_porth = "aacraid_ident port.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#ifdef DBG
++#define AfaPortPrint if (AfaPortPrinting) DbgPrint
++extern int AfaPortPrinting;
++#else
++#define AfaPortPrint 
++#endif /* DBG */
++
++extern int AfaPortPrinting;
++
++
++BOOLEAN
++AfaPortAllocateAdapterCommArea(
++      IN PVOID                Arg1,
++      IN OUT PVOID    *CommHeaderAddress,
++      IN ULONG                CommAreaSize,
++      IN ULONG                CommAreaAlignment
++      );
++
++
++BOOLEAN
++AfaPortFreeAdapterCommArea(
++      IN PVOID                Arg1
++      );
++
++
++AAC_STATUS
++AfaPortBuildSgMap(
++      PVOID Arg1,
++      IN PSGMAP_CONTEXT SgMapContext
++      );
++
++
++VOID
++AfaPortFreeDmaResources(
++      PVOID Arg1,
++    IN PSGMAP_CONTEXT SgMapContext
++    );
++
++
++BOOLEAN
++AfaPortAllocateAndMapFibSpace(
++      PVOID Arg1,
++    IN PMAPFIB_CONTEXT MapFibContext
++    );
++
++
++BOOLEAN
++AfaPortUnmapAndFreeFibSpace(
++      PVOID Arg1,
++    IN PMAPFIB_CONTEXT MapFibContext
++    );
++
++
++#endif // _PORT_
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/protocol.h linux/drivers/scsi/aacraid/include/protocol.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/protocol.h        Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/protocol.h      Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,249 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   protocol.h
++ *
++ * Abstract: Defines the commands and command data which enables the nt
++ *    filesystem driver to be the client of the fsa adapter
++ *    filesystem. This protocol is largely modeled after the NFS
++ *    V3 protocol with modifications allowed due to the unique
++ *    client/server model FSA works under.
++ *
++ *
++ *    
++ --*/
++
++#ifndef _PROTOCOL_H_
++#define _PROTOCOL_H_
++
++static char *ident_protocol = "aacraid_ident protocol.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#include <fsafs.h>      // definition of FSAFID; includes fsatypes.h
++#include <nvramioctl.h> // for NVRAMINFO definition
++
++// #define MDL_READ_WRITE
++
++//
++// Define the command values
++//
++typedef enum _FSA_COMMANDS {
++        Null = 0,
++        GetAttributes,
++        SetAttributes,
++        Lookup,
++        ReadLink,
++        Read,
++        Write,
++        Create,
++        MakeDirectory,
++        SymbolicLink,
++        MakeNode,
++        Removex,
++        RemoveDirectoryx, // bkpfix added x to this because already defined in nt
++        Rename,
++        Link,
++        ReadDirectory,
++        ReadDirectoryPlus,
++        FileSystemStatus,
++        FileSystemInfo,
++        PathConfigure,
++        Commit,
++        Mount,
++        UnMount,
++        Newfs,
++        FsCheck,
++        FsSync,
++              SimReadWrite,
++              SetFileSystemStatus,
++              BlockRead,
++              BlockWrite,
++              NvramIoctl,
++              FsSyncWait,
++              ClearArchiveBit,
++#ifdef MDL_READ_WRITE
++              MdlReadComplete,
++              MdlWriteComplete,
++              MdlRead,                        // these are used solely for stats, Mdl really controlled by 
++              MdlWrite,                       // flags field in Fib.
++#endif
++              SetAcl,
++              GetAcl,
++              AssignAcl,
++              FaultInsertion,         // Fault Insertion Command
++              CrazyCache,                     // crazycache
++              MAX_FSACOMMAND_NUM      //CJ: used for sizing stats array - leave last
++} _E_FSACOMMAND;
++
++#ifdef AAC_32BIT_ENUMS
++typedef       _E_FSACOMMAND   FSACOMMAND;
++#else
++typedef AAC_UINT32            FSACOMMAND;
++#endif
++
++
++
++//
++// Define the status returns
++//
++// See include\comm\errno.h for adapter kernel errno's
++typedef enum _FSASTATUS {
++      ST_OK = 0,
++      ST_PERM = 1,
++      ST_NOENT = 2,
++      ST_IO = 5,
++      ST_NXIO = 6,
++      ST_E2BIG = 7,
++      ST_ACCES = 13,
++      ST_EXIST = 17,
++      ST_XDEV = 18,
++      ST_NODEV = 19,
++      ST_NOTDIR = 20,
++      ST_ISDIR = 21,
++      ST_INVAL = 22,
++      ST_FBIG = 27,
++      ST_NOSPC = 28,
++      ST_ROFS = 30,
++      ST_MLINK = 31,
++      ST_WOULDBLOCK = 35,
++      ST_NAMETOOLONG = 63,
++      ST_NOTEMPTY = 66,
++      ST_DQUOT = 69,
++      ST_STALE = 70,
++      ST_REMOTE = 71,
++      ST_BADHANDLE = 10001,
++      ST_NOT_SYNC = 10002,
++      ST_BAD_COOKIE = 10003,
++      ST_NOTSUPP = 10004,
++      ST_TOOSMALL = 10005,
++      ST_SERVERFAULT = 10006,
++      ST_BADTYPE = 10007,
++      ST_JUKEBOX = 10008,
++      ST_NOTMOUNTED = 10009,
++      ST_MAINTMODE = 10010,
++      ST_STALEACL = 10011
++} _E_FSASTATUS;
++
++#ifdef AAC_32BIT_ENUMS
++typedef _E_FSASTATUS  FSASTATUS;
++#else
++typedef       AAC_UINT32              FSASTATUS;
++#endif
++
++//
++// On writes how does the client want the data written.
++//
++
++typedef enum _CACHELEVEL {
++      CSTABLE = 1,
++    CUNSTABLE
++} _E_CACHELEVEL;
++
++#ifdef AAC_32BIT_ENUMS
++typedef _E_CACHELEVEL CACHELEVEL;
++#else
++typedef       AAC_UINT32              CACHELEVEL;
++#endif
++
++//
++// Lets the client know at which level the data was commited on a write request
++//
++
++typedef enum _COMMITLEVEL {
++    CMFILE_SYNCH_NVRAM = 1,
++    CMDATA_SYNCH_NVRAM,
++    CMFILE_SYNCH,
++    CMDATA_SYNCH,
++    CMUNSTABLE
++} _E_COMMITLEVEL;
++
++#ifdef AAC_32BIT_ENUMS
++typedef _E_COMMITLEVEL        COMMITLEVEL;
++#else
++typedef AAC_UINT32            COMMITLEVEL;
++#endif
++
++
++
++//
++// The following are all the different commands or FIBs which can be sent to the
++// FSA filesystem. We will define a required subset which cannot return STATUS_NOT_IMPLEMENTED,
++// but others outside that subset are allowed to return not implemented. The client is then
++// responsible for dealing with the fact it is not implemented.
++//
++typedef AAC_INT8 FSASTRING[16];
++
++
++typedef AAC_UINT32    BYTECOUNT;      // only 32 bit-ism
++
++
++
++//
++// BlockRead
++//
++
++typedef struct _BLOCKREAD { // variable size struct
++
++    FSACOMMAND                Command;
++    AAC_UINT32                ContainerId;
++    BYTECOUNT                 BlockNumber;
++    BYTECOUNT                 ByteCount;
++      SGMAP                   SgMap;  // Must be last in struct because it is variable
++
++} BLOCKREAD;
++typedef BLOCKREAD *PBLOCKREAD;
++
++typedef struct _BLOCKREADRESPONSE {
++
++    FSASTATUS                 Status;
++    BYTECOUNT                 ByteCount;
++
++} BLOCKREADRESPONSE;
++typedef BLOCKREADRESPONSE *PBLOCKREADRESPONSE;
++
++//
++// BlockWrite
++//
++
++typedef struct _BLOCKWRITE {  // variable size struct
++
++    FSACOMMAND                Command;
++    AAC_UINT32                ContainerId;
++    BYTECOUNT                 BlockNumber;
++    BYTECOUNT                 ByteCount;
++    CACHELEVEL                Stable;
++      SGMAP                   SgMap;  // Must be last in struct because it is variable
++
++} BLOCKWRITE;
++typedef BLOCKWRITE *PBLOCKWRITE;
++
++
++typedef struct _BLOCKWRITERESPONSE {
++
++    FSASTATUS                 Status;
++    BYTECOUNT                 ByteCount;
++    COMMITLEVEL       Committed;
++
++} BLOCKWRITERESPONSE;
++typedef BLOCKWRITERESPONSE *PBLOCKWRITERESPONSE;
++
++
++
++#endif // _PROTOCOL_H_
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/revision.h linux/drivers/scsi/aacraid/include/revision.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/revision.h        Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/revision.h      Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,350 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   revision.h
++ *
++ * Abstract: This module contains all of the revision information for
++ *    the FSA product, as well as the support routines for
++ *    checking module compatibility.
++ *
++ *    Before editing anything in this module, make sure that
++ *    you read the comments. Some lines are changed automatically
++ *    as part of the build, and should never be changed by hand.
++ *
++ * Routines (all inlines):
++ *
++ *    RevGetBuildNumber - Retrieve current build number
++ *    RevGetExternalRev - Retrieve revision for external use
++ *    RevGetFullRevision - Retrieve full revision structure
++ *
++ *    RevCheckCompatibility - Checks compatibility base on internal table
++ *
++ *    RevCheckCompatibilityFullInfo - Check for static component
++ *    RevGetCompInfoTableSize - Get size for static component table
++ *    RevGetCompInfoTable - Get actual table to place on static component
++ *    RevGetBuildNumberFromInfo - Get build number for static component.
++ *
++ *
++ *    
++ --*/
++
++#ifndef _REVISION_H
++#define _REVISION_H
++
++static char *ident_revision = "aacraid_ident revision.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#include "version.h" // revision numbers kept separate so they can be used by resource compiler as well
++
++typedef int REV_BOOL;
++
++#define REV_TRUE 1
++#define REV_FALSE 0
++
++//
++//    Define Revision Levels for this product
++//
++//  IMPORTANT: Do NOT modify BUILD_NUMBER define, this is modified
++//                       automatically by the build.
++//
++//  Version is VMAJOR.MINOR-DASH TYPE (Build BUILD_NUMBER)
++//
++//    IMPORTANT: Don't access these revisions directly. They can be
++//                       accessed via, the RevGetXxxxx rouines.
++//
++
++
++#define REV_AS_LONGWORD \
++      ((REV_MAJOR << 24) | (REV_MINOR << 16) | (REV_TYPE << 8) | (REV_DASH))
++
++
++
++#ifndef BIOS
++
++//
++//    Enumerate the types of product levels we can have
++//
++enum {
++      RevType_Devo=1,         // Development mode, testing all of latest
++      RevType_Alpha,          // Alpha - Internal field test
++      RevType_Beta,           // Beta - External field test
++      RevType_Release         // Release - Retail version
++};
++
++//
++//    Define the basic structure for all revision information. Note
++//    that the ordering of the components is such that they should
++//    always increase. dash will be updated the most, then the version
++//    type, then minor and major.
++//
++typedef struct {
++      union {
++              struct {
++                      unsigned char dash;     // Dash version number
++                      unsigned char type;     // Type, 1=Devo, 2=Alpha, 3=Beta, 4=Release
++                      unsigned char minor;// Minor version minor
++                      unsigned char major;// Major version number
++              } comp;                         // Components to external viewed rev number
++              unsigned long ul;       // External revision as single 32-bit value
++      } external;                     // External revision number (union)
++      unsigned long buildNumber; // Automatically generated build number
++} FsaRevision;
++
++
++//
++//    Define simple routines to get basic revision information. The
++//    definitions should never be accessed directly. These routines
++//    are meant to be used to access all relevant information no matter
++//    how simple.
++//
++static inline unsigned long RevGetBuildNumber() {return REV_BUILD_NUMBER;}
++
++static inline unsigned long RevGetExternalRev() {return REV_AS_LONGWORD;}
++
++
++//
++//    Enumerate different components that may have to check
++//    compatibility. This list of components can be changed
++//    at any time.
++//
++//    IMPORTANT: ONLY add to the END of this enum structure. Otherwise,
++//                       incompatibilities between component rev checking will
++//                       cause wrong checking results.
++//
++typedef enum {
++      RevApplication = 1,     // Any user End application
++      RevDkiCli,                      // ADAPTEC proprietary interface (knows FIBs)
++      RevNetService,          // Network Service Revision (under API)
++      RevApi,                         // ADAPTEC User mode API
++      RevFileSysDriver,       // FSA File System Driver
++      RevMiniportDriver,      // FSA File System Miniport Driver
++      RevAdapterSW,           // Adapter Software (or NT Simulator)
++      RevMonitor,                     // Monitor for adapter hardware (MON960 for now)
++      RevRemoteApi            // The remote API.
++      // ALWAYS ADD NEW COMPONENTS HERE - AT END
++} RevComponent;
++
++//
++//    Define a structure so that we can create a compatibility table.
++//
++typedef struct {
++      RevComponent A,B;
++      unsigned long BuildNumOfB_RequiredByA;
++      unsigned long BuildNumOfA_RequiredByB;
++} RevCompareElement;
++
++//
++//    Now, define the table. This table should only be included once,
++//    in one program. If it is linked from 2 modules, there will likely
++//    be a multiply defined symbol error from the linker.
++//
++//    To fix this problem, REV_REFERENCE_ONLY can be defined. This will
++//    allow access to the revision information table without a redefinition
++//    of the tables.
++//
++extern const int                         RevCompareTableLength;
++
++extern const RevCompareElement RevCompareTable[];
++
++/********************************************************************\
++* Routine: RevCheckCompatibility(callerComp,compB,compB_BuildNumber)
++*
++*     The following routine is used to check compatibility between
++*     the calling component and a component that has some dependencies
++*     on it. If this routine returns REV_FALSE, it is expected that the caller
++*     will send an appropriate incompatibility message and stop.
++*
++*     This routine is only meant to check for compatibility in the
++*     absolute sense. If code wishes to execute a different path based
++*     on the CompB_BuildNumber, then this routine is not useful. The
++*     routine RevGetBuildNumber can be used to get the calling module's
++*     current build number for a comparison check.
++*
++*     The return value is REV_TRUE, if compatibility is possible, and REV_FALSE
++*     if the components are definitely not compatible, or there is an
++*     error when trying to figure it out. To be more specific:
++*
++*             1) REV_TRUE if component B is newer than calling component. (In this
++*                case, the revision check done by component B with respect to
++*                this component will give the real compatibility information.
++*                It is the only one with the knowledge, since this component
++*                could not look into the future.)
++*             2) REV_TRUE if calling component is more recent and table shows okay
++*             3) REV_FALSE if calling component more recent and table show not okay
++*             4) REV_FALSE if calling component is more recent and table entry to
++*                check does not exist.
++*
++*     Note that the CompB_BuildNumber must be attained by the calling
++*     routine through some mechanism done by the caller.
++*
++* Input:
++*
++*     callerComp - Name of component making this call
++*     compB - Name of component to check compatibility with
++*     compB_BuildNumber - Build number to component B
++*
++* Output:
++*
++*     None
++*
++* Return Value:
++*
++*     REV_TRUE - Component compatibility is possible, continue as usual. compB
++*                must give true compatibility information.
++*     REV_FALSE - Incompatible components, notify and end
++*
++\********************************************************************/
++static inline REV_BOOL RevCheckCompatibility(
++              RevComponent callerComp,
++              RevComponent compB,
++              unsigned long compB_BuildNumber)
++{
++      int i;
++      unsigned long RevForB;
++
++      //
++      //      Compatibility check is possible, so we should continue. When
++      //      compB makes this call in its own component, it will get the
++      //      true compatibility information, since only it can know.
++      //
++      if (RevGetBuildNumber() < compB_BuildNumber) return REV_TRUE;
++
++      //
++      //      Go through rev table. When the components are found in the
++      //      same table entry, return the approprate number.
++      //
++      for (i=0; i<RevCompareTableLength; i++) {
++              if (RevCompareTable[i].A == callerComp) {
++                      if (RevCompareTable[i].B == compB) {
++                              RevForB = RevCompareTable[i].BuildNumOfB_RequiredByA;
++                              return (compB_BuildNumber >= RevForB);
++                      }
++              } else if (RevCompareTable[i].B == callerComp) {
++                      if (RevCompareTable[i].A == compB) {
++                              RevForB = RevCompareTable[i].BuildNumOfA_RequiredByB;
++                              return (compB_BuildNumber >= RevForB);
++                      }
++              }
++      }
++
++      //
++      //      Uh oh! No relevant table entry was found (this should never
++      //      happen).
++      //
++      return REV_FALSE;
++}
++
++
++//
++//    Now create a structure that can be used by a FIB to check
++//    compatibility.
++//
++typedef struct _RevCheck {
++      RevComponent callingComponent;
++      FsaRevision callingRevision;
++} RevCheck;
++
++typedef struct _RevCheckResp {
++      REV_BOOL possiblyCompatible;
++      FsaRevision adapterSWRevision;
++} RevCheckResp;
++
++#endif /* bios */
++#endif /* _REVISION_H */
++
++//
++//    The following allows for inclusion of revision.h in other h
++//    files. when you include this file in another h file, simply
++//    define REV_REFERENCE_ONLY. This will be undefined later, so that
++//    the single C file inclusion in the module will be used to
++//    implement the global structures.
++//
++#ifndef REV_REFERENCE_ONLY
++#ifndef _REVISION_H_GLOBAL
++#define _REVISION_H_GLOBAL
++
++
++
++//
++//    The following array is the table of compatibility. This table
++//    can be modified in two ways:
++//
++//            1) A component which has an incompatible change done to
++//               it, can get a new build number.
++//
++//            2) A new component can be added, requiring more entries
++//               to be place into this table.
++//
++//
++//    In case (1), you must change the revision number in the appropriate
++//    column, based on which component absolutely requires an upgrade.
++//
++//    Example: A new FIB used by the API, in build number 105
++//            {RevApi,        RevAdapterSW,           100,  100}
++//                    ---> would be changed to <---
++//            {RevApi,        RevAdapterSW,           105,  100}
++//
++//    Example: A structure is changed for a FIB that only the API uses
++//            {RevApi,        RevAdapterSW,           100,  100}
++//                    ---> would be changed to <---
++//            {RevApi,        RevAdapterSW,           105,  105}
++//
++//
++//    In case (2), the less common case, the enumerated list of
++//    components must be changed to include the new component. Then
++//    entries need to be placed into this table.
++//
++//    Since the revisions must be communicated between the two
++//    components, it is likely that you would need to put in the
++//    current build number for both columns. That is the recommended
++//    way to start revision test.
++//
++const RevCompareElement RevCompareTable[] = {
++      // Component A          Component B                     MinBForA        MinAForB
++      // -----------          -----------                     --------        --------
++      {RevApplication,        RevApi,                         2120,           2120    },
++      {RevDkiCli,             RevApi,                         2120,           2120    },
++      {RevDkiCli,             RevFileSysDriver,               257,            257     },
++      {RevDkiCli,             RevMiniportDriver,              257,            257     },
++      {RevDkiCli,             RevAdapterSW,                   257,            257     },
++      {RevApi,                RevFileSysDriver,               2120,           2120    },
++      {RevApi,                RevMiniportDriver,              2120,           2120    },
++      {RevApi,                RevAdapterSW,                   2120,           2120    },
++      {RevApi,                RevNetService,                  2120,           2120    },
++      {RevFileSysDriver,      RevMiniportDriver,              100,            100     },
++      {RevFileSysDriver,      RevAdapterSW,                   257,            257     },
++      {RevMiniportDriver,     RevAdapterSW,                   257,            257     },
++      {RevMiniportDriver,     RevMonitor,                     100,            100     },
++      {RevApi,                RevNetService,                  2120,           2120    },
++      {RevApi,                RevRemoteApi,                   2120,           2120    },
++      {RevNetService,         RevRemoteApi,                   2120,           2120    }
++};
++
++const int RevCompareTableLength = sizeof(RevCompareTable)/sizeof(RevCompareElement);
++
++#endif /* _REVISION_H_GLOBAL */
++#endif /* REV_REFERENCE_ONLY */
++#undef REV_REFERENCE_ONLY
++
++
++
++
++
++
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/rx.h linux/drivers/scsi/aacraid/include/rx.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/rx.h      Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/rx.h    Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,81 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   rx.h
++ *
++ * Abstract: Prototypes and data structures unique to the Rx based controller board.
++ *
++ *    
++ --*/
++
++static char *ident_rxh = "aacraid_ident rx.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++typedef struct _Rx_ADAPTER_EXTENSION {
++
++      //
++      // The following must be first.
++      //
++      PPCI_MINIPORT_COMMON_EXTENSION  Common;
++      struct _Rx_ADAPTER_EXTENSION    *Next;                          // Next adapter miniport structure
++    USHORT                                                    LocalMaskInterruptControl;
++      PRx_DEVICE_REGISTERS                    Device;
++
++} Rx_ADAPTER_EXTENSION;
++
++    
++typedef Rx_ADAPTER_EXTENSION *PRx_ADAPTER_EXTENSION;
++
++
++
++#ifdef LINUX
++/*
++ * 
++ */
++
++#define Rx_READ_UCHAR(AEP,  CSR)                      *(volatile unsigned char *)  &((AEP)->Device->CSR)
++    
++
++
++#define Rx_READ_ULONG(AEP,  CSR)                      *(volatile unsigned int *)   &((AEP)->Device->CSR)
++#define Rx_WRITE_UCHAR(AEP,  CSR, Value)      *(volatile unsigned char *)  &((AEP)->Device->CSR) = (Value)
++
++
++#define Rx_WRITE_ULONG(AEP, CSR, Value)               *(volatile unsigned int *)   &((AEP)->Device->CSR) = (Value)
++
++#endif /* LINUX */
++
++
++VOID
++RxInterruptAdapter(
++      PVOID Arg1
++      );
++
++VOID
++RxNotifyAdapter(
++      PVOID Arg1,
++    IN HOST_2_ADAP_EVENT AdapterEvent
++    );
++
++VOID
++RxResetDevice(
++      PVOID Arg1
++      );
++
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/rxcommon.h linux/drivers/scsi/aacraid/include/rxcommon.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/rxcommon.h        Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/rxcommon.h      Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,105 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   rxcommon.h
++ *
++ * Abstract: Structures and defines for the i960 Rx chip.
++ *
++ *    
++ --*/
++
++#ifndef _Rx_COMMON_H_
++#define _Rx_COMMON_H_
++
++static char *ident_rxcommon = "aacraid_ident rxcommon.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++//
++// Rx Message Unit Registers
++//
++
++typedef volatile struct _StructRxMURegisters {
++                                                                              //       Local  |   PCI*        |       Name
++                                                                              //                      |               |
++      unsigned        ARSR;                                   //      1300h   |       00h     |       APIC Register Select Register
++      unsigned        reserved0;                              //      1304h   |       04h     |       Reserved
++      unsigned        AWR;                                    //      1308h   |       08h     |       APIC Window Register
++      unsigned        reserved1;                              //      130Ch   |       0Ch     |       Reserved
++      unsigned        IMRx[2];                                //      1310h   |       10h     |       Inbound Message Registers
++      unsigned        OMRx[2];                                //      1318h   |       18h     |       Outbound Message Registers
++      unsigned        IDR;                                    //      1320h   |       20h     |       Inbound Doorbell Register
++      unsigned        IISR;                                   //      1324h   |       24h     |       Inbound Interrupt Status Register
++      unsigned        IIMR;                                   //      1328h   |       28h     |       Inbound Interrupt Mask Register
++      unsigned        ODR;                                    //      132Ch   |       2Ch     |       Outbound Doorbell Register
++      unsigned        OISR;                                   //      1330h   |       30h     |       Outbound Interrupt Status Register
++      unsigned        OIMR;                                   //      1334h   |       34h     |       Outbound Interrupt Mask Register
++                                                                              // * Must access trhough ATU Inbound Translation Window
++
++}Rx_MU_CONFIG;
++typedef Rx_MU_CONFIG *PRx_MU_CONFIG;
++
++typedef volatile struct _Rx_Inbound {
++
++      unsigned        Mailbox[8];
++
++}Rx_Inbound;
++
++typedef Rx_Inbound *PRx_Inbound;
++
++#define       InboundMailbox0         IndexRegs.Mailbox[0]
++#define       InboundMailbox1         IndexRegs.Mailbox[1]
++#define       InboundMailbox2         IndexRegs.Mailbox[2]
++#define       InboundMailbox3         IndexRegs.Mailbox[3]
++#define       InboundMailbox4         IndexRegs.Mailbox[4]
++
++
++
++#define       INBOUNDDOORBELL_0       0x00000001
++#define INBOUNDDOORBELL_1     0x00000002
++#define INBOUNDDOORBELL_2     0x00000004
++#define INBOUNDDOORBELL_3     0x00000008
++#define INBOUNDDOORBELL_4     0x00000010
++#define INBOUNDDOORBELL_5     0x00000020
++#define INBOUNDDOORBELL_6     0x00000040
++
++
++#define       OUTBOUNDDOORBELL_0      0x00000001
++#define OUTBOUNDDOORBELL_1    0x00000002
++#define OUTBOUNDDOORBELL_2    0x00000004
++#define OUTBOUNDDOORBELL_3    0x00000008
++#define OUTBOUNDDOORBELL_4    0x00000010
++
++
++#define InboundDoorbellReg    MUnit.IDR
++
++#define OutboundDoorbellReg   MUnit.ODR
++
++
++typedef struct _Rx_DEVICE_REGISTERS {
++      Rx_MU_CONFIG                    MUnit;                  // 1300h - 1334h
++      unsigned                                reserved1[6];   // 1338h - 134ch
++      Rx_Inbound                              IndexRegs;
++} Rx_DEVICE_REGISTERS;
++
++typedef Rx_DEVICE_REGISTERS *PRx_DEVICE_REGISTERS;
++
++
++#endif // _Rx_COMMON_H_
++
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/sap1.h linux/drivers/scsi/aacraid/include/sap1.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/sap1.h    Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/sap1.h  Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,85 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   sap1.h
++ *
++ * Abstract: Prototypes and data structures unique to the Strong Arm based controller board.
++ *
++ *    
++ --*/
++#ifndef _SAP1_H_
++#define _SAP1_H_
++
++static char *ident_sap1h = "aacraid_ident sap1.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#define Sa_MINIPORT_REVISION                  1
++
++typedef struct _Sa_ADAPTER_EXTENSION {
++
++      //
++      // The following must be first.
++      //
++      PPCI_MINIPORT_COMMON_EXTENSION  Common;
++      struct _Sa_ADAPTER_EXTENSION    *Next;                  // Next adapter miniport structure
++      USHORT                                                  LocalMaskInterruptControl;
++      PSa_DEVICE_REGISTERS                    Device;
++
++} Sa_ADAPTER_EXTENSION;
++
++typedef Sa_ADAPTER_EXTENSION *PSa_ADAPTER_EXTENSION;
++
++ 
++
++#ifdef LINUX
++/*
++ * 
++ */
++
++ 
++#define Sa_READ_USHORT(AEP, CSR)                      *(volatile unsigned short *) &((AEP)->Device->CSR)
++#define Sa_READ_ULONG(AEP,  CSR)                      *(volatile unsigned int *)   &((AEP)->Device->CSR)
++
++ 
++#define Sa_WRITE_USHORT(AEP, CSR, Value)      *(volatile unsigned short *) &((AEP)->Device->CSR) = (Value)
++#define Sa_WRITE_ULONG(AEP, CSR, Value)               *(volatile unsigned int *)   &((AEP)->Device->CSR) = (Value)
++
++#endif /* LINUX */
++
++ 
++VOID
++SaInterruptAdapter(
++      PVOID Arg1
++      );
++
++VOID
++SaNotifyAdapter(
++      PVOID Arg1,
++    IN HOST_2_ADAP_EVENT AdapterEvent
++    );
++
++VOID
++SaResetDevice(
++      PVOID Arg1
++      );
++
++ 
++#endif /* _SAP1_H_ */
++
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/sap1common.h linux/drivers/scsi/aacraid/include/sap1common.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/sap1common.h      Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/sap1common.h    Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,111 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   sap1common.h
++ *
++ * Abstract: Structures and defines for the Drawbridge and StrongArm110 chip.
++ *    
++ --*/
++
++#ifndef _Sa_COMMON_H_
++#define _Sa_COMMON_H_
++
++static char *ident_sap1common = "aacraid_ident sap1common.h 1.0.6 2000/10/09 Adaptec, Inc.";
++
++//
++// SaP1 Message Unit Registers
++//
++
++typedef volatile struct _StructSaDrawbridge_CSR_RegisterMap {
++                                                                                              //       Offset |       Name
++      unsigned                        reserved[10];                   //      00h-27h |   Reserved
++      unsigned char           LUT_Offset;                             //              28h     |       Looup Table Offset
++      unsigned char           reserved1[3];                   //      29h-2bh |       Reserved
++      unsigned                        LUT_Data;                               //              2ch     |       Looup Table Data        
++      unsigned                        reserved2[26];                  //      30h-97h |       Reserved
++      unsigned short          PRICLEARIRQ;                    //              98h     |       Primary Clear Irq
++      unsigned short          SECCLEARIRQ;                    //              9ah     |       Secondary Clear Irq
++      unsigned short          PRISETIRQ;                              //              9ch     |       Primary Set Irq
++      unsigned short          SECSETIRQ;                              //              9eh     |       Secondary Set Irq
++      unsigned short          PRICLEARIRQMASK;                //              a0h     |       Primary Clear Irq Mask
++      unsigned short          SECCLEARIRQMASK;                //              a2h     |       Secondary Clear Irq Mask
++      unsigned short          PRISETIRQMASK;                  //              a4h     |       Primary Set Irq Mask
++      unsigned short          SECSETIRQMASK;                  //              a6h     |       Secondary Set Irq Mask
++      unsigned                        MAILBOX0;                               //              a8h     |       Scratchpad 0
++      unsigned                        MAILBOX1;                               //              ach     |       Scratchpad 1
++      unsigned                        MAILBOX2;                               //              b0h     |       Scratchpad 2
++      unsigned                        MAILBOX3;                               //              b4h     |       Scratchpad 3
++      unsigned                        MAILBOX4;                               //              b8h     |       Scratchpad 4
++      unsigned                        MAILBOX5;                               //              bch     |       Scratchpad 5
++      unsigned                        MAILBOX6;                               //              c0h     |       Scratchpad 6
++      unsigned                        MAILBOX7;                               //              c4h     |       Scratchpad 7
++
++      unsigned                        ROM_Setup_Data;                 //              c8h |   Rom Setup and Data
++      unsigned                        ROM_Control_Addr;               //              cch |   Rom Control and Address
++
++      unsigned                        reserved3[12];                  //      d0h-ffh |       reserved
++      unsigned                        LUT[64];                                // 100h-1ffh|   Lookup Table Entries
++
++      //
++      //  TO DO
++      //      need to add DMA, I2O, UART, etc registers form 80h to 364h
++      //
++
++}Sa_Drawbridge_CSR;
++
++typedef Sa_Drawbridge_CSR *PSa_Drawbridge_CSR;
++
++
++#define Mailbox0      SaDbCSR.MAILBOX0
++#define Mailbox1      SaDbCSR.MAILBOX1
++#define Mailbox2      SaDbCSR.MAILBOX2
++#define Mailbox3      SaDbCSR.MAILBOX3
++#define Mailbox4      SaDbCSR.MAILBOX4
++
++      
++#define Mailbox7      SaDbCSR.MAILBOX7
++      
++#define DoorbellReg_p SaDbCSR.PRISETIRQ
++#define DoorbellReg_s SaDbCSR.SECSETIRQ
++#define DoorbellClrReg_p SaDbCSR.PRICLEARIRQ
++
++
++#define       DOORBELL_0      0x00000001
++#define DOORBELL_1    0x00000002
++#define DOORBELL_2    0x00000004
++#define DOORBELL_3    0x00000008
++#define DOORBELL_4    0x00000010
++#define DOORBELL_5    0x00000020
++#define DOORBELL_6    0x00000040
++
++      
++#define PrintfReady                   DOORBELL_5
++#define PrintfDone                    DOORBELL_5
++      
++typedef struct _Sa_DEVICE_REGISTERS {
++      Sa_Drawbridge_CSR       SaDbCSR;                        // 98h - c4h
++} Sa_DEVICE_REGISTERS;
++      
++typedef Sa_DEVICE_REGISTERS *PSa_DEVICE_REGISTERS;
++
++      
++#endif // _Sa_COMMON_H_
++
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/include/version.h linux/drivers/scsi/aacraid/include/version.h
+--- linux-2.4.9/drivers/scsi/aacraid/include/version.h Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/include/version.h       Thu Aug 16 18:16:55 2001
+@@ -0,0 +1,40 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   version.h
++ *
++ * Abstract: Keeps track of build number for development purposes.
++ *    
++ --*/
++#ifndef _VERSION_H_
++#define _VERSION_H_
++
++static char *ident_version = "aacraid_ident version.h 1.0.7 2000/8/10 Adaptec, Inc.";
++
++#include "build_number.h"
++
++#define REV_MAJOR 3
++#define REV_MINOR 0
++#define REV_TYPE RevType_Release
++#define REV_DASH 0
++
++#define FSA_VERSION_STRING "3.0.0.5125\0"
++
++#endif /* _VERSION_H_ */
+diff -burN linux-2.4.9/drivers/scsi/aacraid/linit.c linux/drivers/scsi/aacraid/linit.c
+--- linux-2.4.9/drivers/scsi/aacraid/linit.c   Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/linit.c Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,1086 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   linit.c
++ *
++ * Abstract: Linux Driver entry module for Adaptec RAID Array Controller
++ *                            
++ *    Provides the following driver entry points:
++ *            AAC_DetectHostAdapter()
++ *            AAC_ReleaseHostAdapter()
++ *            AAC_QueueCommand()
++ *            AAC_ResetCommand()
++ *            AAC_BIOSDiskParameters()
++ *    
++ --*/
++
++static char *ident_linit = "aacraid_ident linit.c 1.0.6 2000/10/09 Adaptec, Inc.";
++
++/*------------------------------------------------------------------------------
++ *              D E F I N E S
++ *----------------------------------------------------------------------------*/
++#define AAC_DRIVER_VERSION                            "0.1.1"
++#define AAC_DRIVER_BUILD_DATE                 __DATE__
++#define MAX_DRIVER_QUEUE_DEPTH                        500
++
++/*------------------------------------------------------------------------------
++ *              I N C L U D E S
++ *----------------------------------------------------------------------------*/
++#include "osheaders.h"
++
++#include "AacGenericTypes.h"
++
++#include <linux/module.h>
++#include "sd.h"
++#include "linit.h"
++#include "aac_unix_defs.h"
++#include "fsatypes.h"
++#include "comstruc.h"
++#include "fsaport.h"
++#include "pcisup.h"
++#include "port.h"
++#include "afacomm.h"
++#include "nodetype.h"
++#include "comsup.h"
++#include "adapter.h"
++
++/*------------------------------------------------------------------------------
++ *              G L O B A L S
++ *----------------------------------------------------------------------------*/
++extern FSA_MINIPORT MiniPorts[];
++extern int CommPrinting;
++extern char DescriptionString[];
++extern char devicestr[];
++
++/*------------------------------------------------------------------------------
++ *              M O D U L E   G L O B A L S
++ *----------------------------------------------------------------------------*/
++aac_options_t g_options = { CMN_ERR_LEVEL, 0 };       // default message_level
++
++char g_DriverName[] = { "aacraid" };
++
++/*
++      The Loadable Kernel Module Installation Facility may pass us
++      a pointer to a driver specific options string to be parsed, 
++      we assign this to options string. 
++*/
++
++static char * aacraid_options = NULL;
++MODULE_PARM      ( aacraid_options, "s" );
++MODULE_PARM_DESC ( aacraid_options, "message_level:(int)  reverse_scan:1 (default 0)");
++
++
++static unsigned short perc_pciid[4] = { 0, 0, 0, 0 };
++MODULE_PARM      ( perc_pciid, "4h");
++MODULE_PARM_DESC ( perc_pciid, "PCI vendor,device,subsystem vendor,subsystem device, for non-auto-recognized Dell PERC controllers.");
++
++static unsigned short rx_pciid[4] = { 0, 0, 0, 0 };
++MODULE_PARM      ( rx_pciid, "4h");
++MODULE_PARM_DESC ( rx_pciid, "PCI vendor,device,subsystem vendor,subsystem device, for non-auto-recognized Adaptec Rx controllers.");
++
++static unsigned short sa_pciid[4] = { 0, 0, 0, 0 };
++MODULE_PARM      ( sa_pciid, "4h");
++MODULE_PARM_DESC ( sa_pciid, "PCI vendor,device,subsystem vendor,subsystem device, for non-auto-recognized Adaptec Sa controllers.");
++
++MODULE_AUTHOR ("Adaptec OEM RAID Solutions");
++
++
++
++PCI_MINIPORT_COMMON_EXTENSION *g_CommonExtensionPtrArray[ MAXIMUM_NUM_ADAPTERS ];
++unsigned g_HostAdapterCount = 0;
++unsigned g_chardev_major = 0;
++
++int g_single_command_done = FALSE;
++
++/*------------------------------------------------------------------------------
++ *              F U N C T I O N   P R O T O T Y P E S
++ *----------------------------------------------------------------------------*/
++int AacHba_Ioctl(
++      PCI_MINIPORT_COMMON_EXTENSION *CommonExtension,
++      int cmd,
++      void * arg );
++
++int AacHba_ProbeContainers( 
++      PCI_MINIPORT_COMMON_EXTENSION *CommonExtensionPtr );
++
++int AacHba_DoScsiCmd(
++      Scsi_Cmnd *scsi_cmnd_ptr,
++      int wait );
++
++void AacHba_DetachAdapter(
++      IN PVOID AdapterArg );
++
++int AacHba_ClassDriverInit(
++      PCI_MINIPORT_COMMON_EXTENSION * CommonExtensionPtr);
++
++void AacHba_AbortScsiCommand(
++      Scsi_Cmnd *scsi_cmnd_ptr );
++
++
++/*------------------------------------------------------------------------------
++ *              L O C A L   F U N C T I O N   P R O T O T Y P E S
++ *----------------------------------------------------------------------------*/
++static int parse_keyword(
++      char ** str_ptr, 
++      char * keyword );
++
++static void AAC_ParseDriverOptions( 
++      char * cmnd_line_options_str );
++
++static void AAC_AnnounceDriver( void );
++
++int AAC_ChardevIoctl(
++      struct inode * inode_ptr, 
++      struct file * file_ptr,
++      unsigned int cmd,
++      unsigned long arg );
++
++int AAC_ChardevOpen(
++      struct inode * inode_ptr,
++      struct file * file_ptr );
++
++int AAC_ChardevRelease(
++      struct inode * inode_ptr,
++      struct file * file_ptr );
++
++struct file_operations AAC_fops = {
++      NULL,               // module name
++      NULL,                           // lseek
++      NULL,                           // read
++      NULL,                           // write
++      NULL,                           // readdir
++      NULL,                           // poll
++      AAC_ChardevIoctl,       // ioctl
++      NULL,                           // mmap
++      AAC_ChardevOpen,        // open
++      NULL,                           // flush
++      AAC_ChardevRelease,     // release
++      NULL,                           // fsync
++      NULL,                           // fasync
++      NULL,                           // check media change
++      NULL,                           // revalidate
++      NULL                            // lock
++};
++
++/*------------------------------------------------------------------------------
++ *              F U N C T I O N S
++ *----------------------------------------------------------------------------*/
++/*------------------------------------------------------------------------------
++      AAC_AnnounceDriver()
++
++              Announce the driver name, version and date.
++ *----------------------------------------------------------------------------*/
++static void AAC_AnnounceDriver( void ){
++  printk(KERN_ALERT "%s, %s\n", 
++               "aacraid raid driver version", AAC_DRIVER_BUILD_DATE );   
++  schedule();
++}
++
++
++/*------------------------------------------------------------------------------
++      AAC_DetectHostAdapter()
++
++              Probe for AAC Host Adapters initialize, register, and report the 
++              configuration of each AAC Host Adapter found.
++
++      Preconditions:
++      Postconditions:
++              - Returns the number of adapters successfully initialized and 
++              registered.
++              - Initialize all data necessary for this particular SCSI driver.
++      Notes:
++              The detect routine must not call any of the mid level functions 
++              to queue commands because things are not guaranteed to be set 
++              up yet. The detect routine can send commands to the host adapter 
++              as long as the program control will not be passed to scsi.c in 
++              the processing of the command. Note especially that 
++              scsi_malloc/scsi_free must not be called.
++ *----------------------------------------------------------------------------*/
++int AAC_DetectHostAdapter (Scsi_Host_Template *HostTemplate)
++{
++              int index;
++              int ContainerId;
++              uint16_t vendor_id, device_id, sub_vendor_id, sub_system_id;
++              struct Scsi_Host *host_ptr;
++              PCI_MINIPORT_COMMON_EXTENSION *CommonExtensionPtr;
++              struct pci_dev *dev = NULL;
++              extern int NumMiniPorts;
++              fsadev_t *fsa_dev_ptr;
++              char *DeviceName;
++
++              struct pci_dev *devp;
++
++              int     first_index, last_index, increment;
++
++              CommPrinting = TRUE;
++
++              EXPORT_NO_SYMBOLS;
++
++              AAC_AnnounceDriver();
++
++              /* setting up the proc directory structure */
++              HostTemplate->proc_name = "aacraid";
++
++              if( aacraid_options != NULL ) AAC_ParseDriverOptions( aacraid_options );
++
++              /* If we were passed a PCI device ID, handle that first. */
++              if ( perc_pciid[0] != 0 ) {
++                      MiniPorts[0].VendorId    = perc_pciid[0];
++                      MiniPorts[0].DeviceId    = perc_pciid[1];
++                      MiniPorts[0].SubVendorId = perc_pciid[2];
++                      MiniPorts[0].SubSystemId = perc_pciid[3];
++              }
++              if ( rx_pciid[0] != 0 ) {
++                      MiniPorts[1].VendorId    = rx_pciid[0];
++                      MiniPorts[1].DeviceId    = rx_pciid[1];
++                      MiniPorts[1].SubVendorId = rx_pciid[2];
++                      MiniPorts[1].SubSystemId = rx_pciid[3];
++              }
++              if ( sa_pciid[0] != 0 ) {
++                      MiniPorts[2].VendorId    = sa_pciid[0];
++                      MiniPorts[2].DeviceId    = sa_pciid[1];
++                      MiniPorts[2].SubVendorId = sa_pciid[2];
++                      MiniPorts[2].SubSystemId = sa_pciid[3];
++              }
++
++              // NumMiniPorts & MiniPorts[] defined in aacid.c
++              if (g_options.reverse_scan == 0) {
++                              first_index = 0;
++                              last_index  = NumMiniPorts;
++                              increment   = 1;
++              } else {
++                              first_index = NumMiniPorts -1;
++                              last_index  = -1;
++                              increment   = -1;
++              }
++
++              for( index = first_index; index != last_index; index += increment )
++              {
++                              device_id = MiniPorts[index].DeviceId;
++                              vendor_id = MiniPorts[index].VendorId;
++                              DeviceName = MiniPorts[index].DeviceName;
++                              cmn_err(CE_DEBUG, "Checking %s %x/%x/%x/%x", 
++                                              DeviceName,     vendor_id, device_id,
++                                              MiniPorts[index].SubVendorId,
++                                              MiniPorts[index].SubSystemId);
++
++                              /* If vendor and device ID are 0, this is an unused entry, so skip! */
++                              if ( vendor_id == 0 && device_id == 0 ) continue;
++
++                              // pci_find_device traverses the pci_devices linked list for devices
++                              // with matching vendor and device ids.
++
++                              dev = NULL;     // start from beginning of list
++                              while( ( dev = pci_find_device( vendor_id, device_id, dev ) ) )
++                              {
++                                              if (pci_enable_device(dev)) continue;
++                
++                                              if( pci_read_config_word( dev, PCI_SUBSYSTEM_VENDOR_ID, &sub_vendor_id ) ){
++                                                              cmn_err(CE_WARN, "pci_read_config_word SUBSYS_VENDOR_ID failed");
++                                                              break;
++                                              }
++                                              if( pci_read_config_word( dev, PCI_SUBSYSTEM_ID, &sub_system_id ) ){
++                                                              cmn_err(CE_WARN, "pci_read_config_work SUBSYSTEM_ID failed");
++                                                              break;
++                                              }
++
++                                              cmn_err(CE_DEBUG, "     found: %x/%x/%x/%x", vendor_id, device_id, sub_vendor_id, sub_system_id);
++                                              if( ( sub_vendor_id != MiniPorts[index].SubVendorId ) || 
++                                                      ( sub_system_id != MiniPorts[index].SubSystemId ) ){
++                                                              continue;
++                                              }
++                      
++
++                                              printk(KERN_ALERT "%s device detected\n", DeviceName );
++                                              cmn_err(CE_DEBUG, "%x/%x/%x/%x", vendor_id, device_id, sub_vendor_id, sub_system_id);
++
++                                              // Increment the host adapter count
++                                              g_HostAdapterCount++;
++
++                                              // scsi_register() allocates memory for a Scsi_Hosts structure and
++                                              // links it into the linked list of host adapters. This linked list
++                                              // contains the data for all possible <supported> scsi hosts.
++                                              // This is similar to the Scsi_Host_Template, except that we have
++                                              // one entry for each actual physical host adapter on the system,
++                                              // stored as a linked list. If there are two AAC boards, then we
++                                              // will need to make two Scsi_Host entries, but there will be only
++                                              // one Scsi_Host_Template entry. The second argument to scsi_register()
++                                              // specifies the size of the extra memory we want to hold any device 
++                                              // specific information.
++                                              host_ptr = scsi_register( HostTemplate, sizeof( PCI_MINIPORT_COMMON_EXTENSION ) );
++
++                                              // These three parameters can be used to allow for wide SCSI 
++                                              // and for host adapters that support multiple buses.
++                                              host_ptr->max_id = 17;
++                                              host_ptr->max_lun = 8;
++                                              host_ptr->max_channel = 1;
++
++
++                                              host_ptr->irq = dev->irq;               // Adapter IRQ number
++                                              /* host_ptr->base = ( char * )(dev->resource[0].start & ~0xff); */
++                                              host_ptr->base = ( char * )(dev->resource[0].start);
++                                              scsi_set_pci_device(host_ptr, dev);
++
++                                              cmn_err( CE_DEBUG, "Device base address = 0x%lx [0x%lx]", host_ptr->base, dev->resource[0].start );
++                                              cmn_err( CE_DEBUG, "Device irq = 0x%lx", dev->irq );
++
++                                              // The unique_id field is a unique identifier that must be assigned
++                                              // so that we have some way of identifying each host adapter properly
++                                              // and uniquely. For hosts that do not support more than one card in the
++                                              // system, this does not need to be set. It is initialized to zero in
++                                              // scsi_register(). This is the value returned from OsGetDeviceInstance().
++
++                                              host_ptr->unique_id = g_HostAdapterCount - 1;
++                                              host_ptr->this_id = 16;                 // SCSI Id for the adapter itself
++
++                                              // Set the maximum number of simultaneous commands supported by the driver.
++                                              host_ptr->can_queue = MAX_DRIVER_QUEUE_DEPTH;
++
++                                              // Define the maximum number of scatter/gather elements supported by 
++                                              // the driver. 
++
++                                              host_ptr->sg_tablesize = 16;
++                                              host_ptr->max_sectors = 128;
++                                              host_ptr->cmd_per_lun = 1;              // untagged queue depth
++
++                                              // This function is called after the device list has been built to find
++                                              // tagged queueing depth supported for each device.
++
++                                              host_ptr->select_queue_depths = AAC_SelectQueueDepths;
++                                              CommonExtensionPtr = ( PCI_MINIPORT_COMMON_EXTENSION * )host_ptr->hostdata;
++                      
++                                              // attach a pointer back to Scsi_Host
++                                              CommonExtensionPtr->OsDep.scsi_host_ptr = host_ptr;     
++                                              CommonExtensionPtr->OsDep.MiniPortIndex =  index;
++
++                                              // Initialize the ordinal number of the device to -1
++                                              fsa_dev_ptr = &( CommonExtensionPtr->OsDep.fsa_dev );
++                                              for( ContainerId = 0; ContainerId < MAXIMUM_NUM_CONTAINERS; ContainerId++ )
++                                                              fsa_dev_ptr->ContainerDevNo[ContainerId] = -1;
++
++                                              // Call initialization routine
++                                              cmn_err (CE_DEBUG, "Initializing Hardware...\n");
++                                              if( ( *MiniPorts[index].InitRoutine )
++                                                      ( CommonExtensionPtr, host_ptr->unique_id, dev->bus->number, 0 ) != 0 )
++                                              {
++                                                              // device initialization failed
++                                                              cmn_err( CE_WARN, "%s:%d device initialization failed", DeviceName, host_ptr->unique_id );
++                                                              scsi_unregister( host_ptr );
++                                                              g_HostAdapterCount--;
++                                              } /* end if */
++                                              else
++                                              {
++                                                      cmn_err( CE_NOTE, "%s:%d device initialization successful", DeviceName, host_ptr->unique_id  );
++                                                      AacHba_ClassDriverInit( CommonExtensionPtr );
++                                                      cmn_err(CE_NOTE, "%s:%d AacHba_ClassDriverInit complete", DeviceName, host_ptr->unique_id);
++                                                      AacHba_ProbeContainers( CommonExtensionPtr );
++                                                      g_CommonExtensionPtrArray[ g_HostAdapterCount - 1 ] = CommonExtensionPtr;
++
++                                              } /* end else */
++
++                              } /* end while */
++
++              } /* end for */
++
++              if( g_HostAdapterCount ){
++                      if( !( g_chardev_major = register_chrdev( 0, devicestr, &AAC_fops ) ) )
++                              cmn_err( CE_WARN, "%s: unable to register %s device", DeviceName, devicestr);
++              }
++
++              HostTemplate->present = g_HostAdapterCount; // # of cards of this type found
++
++              return( g_HostAdapterCount ); 
++}
++
++
++/*------------------------------------------------------------------------------
++      AAC_ReleaseHostAdapter()
++
++              Release all resources previously acquired to support a specific Host 
++              Adapter and unregister the AAC Host Adapter.
++ *----------------------------------------------------------------------------*/
++int AAC_ReleaseHostAdapter( 
++      struct Scsi_Host *host_ptr )
++/*----------------------------------------------------------------------------*/
++{
++      PCI_MINIPORT_COMMON_EXTENSION *CommonExtensionPtr;
++
++      cmn_err( CE_DEBUG, "AAC_ReleaseHostAdapter" );
++
++      CommonExtensionPtr = ( PCI_MINIPORT_COMMON_EXTENSION * )host_ptr->hostdata;
++
++      // kill any threads we started
++      kill_proc( CommonExtensionPtr->OsDep.thread_pid, SIGKILL, 0 );
++
++      // Call the comm layer to detach from this adapter
++      AacHba_DetachAdapter( CommonExtensionPtr->Adapter );
++
++      // remove interrupt binding
++      OsDetachInterrupt( CommonExtensionPtr->MiniPort );
++
++      SaDetachDevice( CommonExtensionPtr );
++
++      // unregister adapter
++      scsi_unregister( host_ptr );
++
++      if( g_chardev_major )
++      {
++              unregister_chrdev( g_chardev_major, devicestr );
++              g_chardev_major = 0;
++      }
++
++      return( 0 ); // #REVISIT# return code
++}
++
++
++/*------------------------------------------------------------------------------
++      AAC_QueueCommand()
++
++              Queues a command for execution by the associated Host Adapter.
++ *----------------------------------------------------------------------------*/
++int AAC_QueueCommand(
++      Scsi_Cmnd *scsi_cmnd_ptr,
++      void ( *CompletionRoutine )( Scsi_Cmnd * ) )
++/*----------------------------------------------------------------------------*/
++{
++      int ret;
++      scsi_cmnd_ptr->scsi_done = CompletionRoutine;
++
++      // AacHba_DoScsiCmd() handles command processing, setting the 
++      // result code and calling completion routine. 
++      #ifdef SYNC_FIB
++      if( (ret = AacHba_DoScsiCmd( scsi_cmnd_ptr, 1 )) != 0 ) // call with wait = TRUE
++      #else
++      if( (ret = AacHba_DoScsiCmd( scsi_cmnd_ptr, 0 )) != 0 ) // call with wait = FALSE
++      #endif
++              cmn_err( CE_DEBUG, "AacHba_DoScsiCmd failed" );
++      return ret;
++} 
++
++
++/*------------------------------------------------------------------------------
++      AAC_Done()
++
++              Callback function for a non-queued command.
++
++      Postconditions
++              Sets g_single_command done to TRUE
++ *----------------------------------------------------------------------------*/
++void AAC_Done( 
++      Scsi_Cmnd * scsi_cmnd_ptr ) 
++/*----------------------------------------------------------------------------*/
++{
++      g_single_command_done = TRUE;
++}
++
++
++/*------------------------------------------------------------------------------
++      AAC_Command()
++      
++              Accepts a single command for execution by the associated Host Adapter.
++
++      Postconditions
++              Returns an int where:
++              Byte 0 = SCSI status code
++              Byte 1 = SCSI 1 byte message
++              Byte 2 = host error return
++              Byte 3 = mid level error return
++ *----------------------------------------------------------------------------*/
++int AAC_Command(
++      Scsi_Cmnd *scsi_cmnd_ptr )
++/*----------------------------------------------------------------------------*/
++{
++      scsi_cmnd_ptr->scsi_done = AAC_Done;
++
++      cmn_err( CE_DEBUG, "AAC_Command" );
++
++      // AacHba_DoScsiCmd() handles command processing, setting the 
++      // result code and calling completion routine.
++      g_single_command_done = FALSE;
++      
++      AacHba_DoScsiCmd( scsi_cmnd_ptr, 0 );
++      while( !g_single_command_done );
++      return( scsi_cmnd_ptr->result );
++} 
++
++
++/*------------------------------------------------------------------------------
++      AAC_AbortCommand()
++
++              Abort command if possible.
++ *----------------------------------------------------------------------------*/
++int AAC_AbortCommand( 
++      Scsi_Cmnd *scsi_cmnd_ptr )
++/*----------------------------------------------------------------------------*/
++{
++      int target = scsi_cmnd_ptr->target;
++      int hba = scsi_cmnd_ptr->host->unique_id;
++      int result = 0;
++      u_short interrupt_status;
++      PCI_MINIPORT_COMMON_EXTENSION *cep;
++      char   *DeviceName;
++
++      cmn_err( CE_WARN, "%s:%d ABORT", g_DriverName, hba, target );
++      AacHba_AbortScsiCommand( scsi_cmnd_ptr );
++
++      cep = ( PCI_MINIPORT_COMMON_EXTENSION * )( scsi_cmnd_ptr->host->hostdata );
++      DeviceName = MiniPorts[cep->OsDep.MiniPortIndex].DeviceName; 
++
++              /*
++              cmn_err( CE_WARN, "%s:%d Unable to abort command to target %d - "
++                "command already completed", DeviceName, hba, target);
++              result = SCSI_ABORT_NOT_RUNNING;
++
++              cmn_err(CE_WARN, "%s:%d Unable to abort command to target %d - "
++                 "no command found\n", DeviceName, hba, target);
++              result = SCSI_ABORT_NOT_RUNNING;
++
++              cmn_err(CE_WARN, "%s:%d Unable to abort command to target %d - "
++                 "command reset\n", DeviceName, hba, target);
++              result = SCSI_ABORT_PENDING;
++
++              cmn_err(CE_WARN, "%s:%d Unable to abort command to target %d - "
++                 "abort tag not supported\n", DeviceName, hba, target);
++              result = SCSI_ABORT_SNOOZE;
++
++              cmn_err(CE_WARN, "%s:%d Aborting command to target %d - pending",
++                 DeviceName, hba, target);
++              result = SCSI_ABORT_PENDING;
++
++              cmn_err(CE_WARN, "%s:%d Unable to abort command to target %d",
++                 DeviceName, hba, target);
++              result = SCSI_ABORT_BUSY;
++
++              cmn_err(CE_WARN, "%s:%d Aborted command to target %d\n",
++                 DeviceName, hba, target);
++              result = SCSI_ABORT_SUCCESS;
++              */
++
++      // Abort not supported yet
++      result = SCSI_ABORT_BUSY;
++      return result;
++}
++
++
++/*------------------------------------------------------------------------------
++      AAC_ResetCommand()
++
++              Reset command handling.
++ *----------------------------------------------------------------------------*/
++int AAC_ResetCommand( 
++      struct scsi_cmnd *scsi_cmnd_ptr, 
++      unsigned int reset_flags )
++/*----------------------------------------------------------------------------*/
++{
++      int target = scsi_cmnd_ptr->target;
++      int hba = scsi_cmnd_ptr->host->unique_id;
++      PCI_MINIPORT_COMMON_EXTENSION *cep;
++      char    *DeviceName;
++
++      cep = ( PCI_MINIPORT_COMMON_EXTENSION * )( scsi_cmnd_ptr->host->hostdata );
++      DeviceName = MiniPorts[cep->OsDep.MiniPortIndex].DeviceName;
++
++      cmn_err( CE_WARN, "%s:%d RESET", DeviceName, hba, target );
++
++      return SCSI_RESET_PUNT;
++}
++
++
++/*------------------------------------------------------------------------------
++      AAC_DriverInfo()
++
++              Returns the host adapter name
++ *----------------------------------------------------------------------------*/
++const char *AAC_DriverInfo( 
++      struct Scsi_Host *host_ptr )
++/*----------------------------------------------------------------------------*/
++{
++  PCI_MINIPORT_COMMON_EXTENSION *cep;
++  char        *DeviceName;
++
++  cep = ( PCI_MINIPORT_COMMON_EXTENSION * )( host_ptr->hostdata );
++  DeviceName = MiniPorts[cep->OsDep.MiniPortIndex].DeviceName;
++
++  cmn_err( CE_DEBUG, "AAC_DriverInfo" );
++  return (DeviceName);
++}
++
++
++/*------------------------------------------------------------------------------
++      AAC_BIOSDiskParameters()
++
++              Return the Heads/Sectors/Cylinders BIOS Disk Parameters for Disk.  
++              The default disk geometry is 64 heads, 32 sectors, and the appropriate 
++              number of cylinders so as not to exceed drive capacity.  In order for 
++              disks equal to or larger than 1 GB to be addressable by the BIOS
++              without exceeding the BIOS limitation of 1024 cylinders, Extended 
++              Translation should be enabled.   With Extended Translation enabled, 
++              drives between 1 GB inclusive and 2 GB exclusive are given a disk 
++              geometry of 128 heads and 32 sectors, and drives above 2 GB inclusive 
++              are given a disk geometry of 255 heads and 63 sectors.  However, if 
++              the BIOS detects that the Extended Translation setting does not match 
++              the geometry in the partition table, then the translation inferred 
++              from the partition table will be used by the BIOS, and a warning may 
++              be displayed.
++ *----------------------------------------------------------------------------*/
++int AAC_BIOSDiskParameters(
++      Scsi_Disk *scsi_disk_ptr, 
++      kdev_t device,
++      int *parameter_ptr )
++/*----------------------------------------------------------------------------*/
++{
++      AAC_BIOS_DiskParameters_T *disk_parameters = 
++              ( AAC_BIOS_DiskParameters_T *)parameter_ptr;
++      struct buffer_head * buffer_head_ptr;
++
++      cmn_err( CE_DEBUG, "AAC_BIOSDiskParameters" );
++
++      // Assuming extended translation is enabled - #REVISIT#
++      if( scsi_disk_ptr->capacity >= 2 * 1024 * 1024 ) // 1 GB in 512 byte sectors
++      {
++              if( scsi_disk_ptr->capacity >= 4 * 1024 * 1024 ) // 2 GB in 512 byte sectors
++              {
++                      disk_parameters->heads = 255;
++                      disk_parameters->sectors = 63;
++              }
++              else
++              {
++                      disk_parameters->heads = 128;
++                      disk_parameters->sectors = 32;
++              }
++      }
++      else
++      {
++              disk_parameters->heads = 64;
++              disk_parameters->sectors = 32;
++      }
++
++      disk_parameters->cylinders = scsi_disk_ptr->capacity
++              /( disk_parameters->heads * disk_parameters->sectors );
++
++      // Read the first 1024 bytes from the disk device
++      buffer_head_ptr = bread( 
++                                              MKDEV( MAJOR( device ), 
++                                              MINOR( device ) & ~0x0F ), 
++                                              0, 1024 );
++
++      if( buffer_head_ptr == NULL )
++              return( 0 );
++      /* 
++              If the boot sector partition table is valid, search for a partition 
++              table entry whose end_head matches one of the standard geometry 
++              translations ( 64/32, 128/32, 255/63 ).
++      */
++      if( *( unsigned short * )( buffer_head_ptr->b_data + 0x1fe ) == 0xaa55 )
++      {
++              struct partition *first_partition_entry =
++                      ( struct partition * )( buffer_head_ptr->b_data + 0x1be );
++              struct partition *partition_entry = first_partition_entry;
++              int saved_cylinders = disk_parameters->cylinders;
++              int partition_number;
++              unsigned char partition_entry_end_head, partition_entry_end_sector;
++
++              for( partition_number = 0; partition_number < 4; partition_number++ )
++              {
++                      partition_entry_end_head   = partition_entry->end_head;
++                      partition_entry_end_sector = partition_entry->end_sector & 0x3f;
++
++                      if( partition_entry_end_head == ( 64 - 1 ) )
++                      {
++                              disk_parameters->heads = 64;
++                              disk_parameters->sectors = 32;
++                              break;
++                      }
++                      else if( partition_entry_end_head == ( 128 - 1 ) )
++                      {
++                              disk_parameters->heads = 128;
++                              disk_parameters->sectors = 32;
++                              break;
++                      }
++                      else if( partition_entry_end_head == ( 255 - 1 ) ) 
++                      {
++                              disk_parameters->heads = 255;
++                              disk_parameters->sectors = 63;
++                              break;
++                      }
++                      partition_entry++;
++              }
++
++              if( partition_number == 4 )
++              {
++                      partition_entry_end_head   = first_partition_entry->end_head;
++                      partition_entry_end_sector = first_partition_entry->end_sector & 0x3f;
++              }
++
++              disk_parameters->cylinders = scsi_disk_ptr->capacity
++                      /( disk_parameters->heads * disk_parameters->sectors );
++
++              if( ( partition_number < 4 )  && ( partition_entry_end_sector == disk_parameters->sectors ) )
++              {
++                      if( disk_parameters->cylinders != saved_cylinders )
++                              cmn_err( CE_DEBUG, "Adopting geometry: heads=%d, sectors=%d from partition table %d",
++                                      disk_parameters->heads, disk_parameters->sectors, partition_number );
++              }
++              else if( ( partition_entry_end_head > 0 ) || ( partition_entry_end_sector > 0 ) )
++              {
++                      cmn_err( CE_DEBUG, "Strange geometry: heads=%d, sectors=%d in partition table %d",
++                              partition_entry_end_head + 1, partition_entry_end_sector, partition_number );
++                      cmn_err( CE_DEBUG, "Using geometry: heads=%d, sectors=%d",
++                                      disk_parameters->heads, disk_parameters->sectors );
++              }
++      }
++      
++      brelse( buffer_head_ptr );
++
++      return( 0 );
++}
++
++
++/*------------------------------------------------------------------------------
++      AAC_SelectQueueDepths()
++
++              Selects queue depths for each target device based on the host adapter's
++              total capacity and the queue depth supported by the target device.
++              A queue depth of one automatically disables tagged queueing.
++ *----------------------------------------------------------------------------*/
++void AAC_SelectQueueDepths(
++      struct Scsi_Host * host_ptr,
++      Scsi_Device * scsi_device_ptr )
++/*----------------------------------------------------------------------------*/
++{
++      Scsi_Device * device_ptr;
++
++      cmn_err( CE_DEBUG, "AAC_SelectQueueDepths" );
++      cmn_err( CE_DEBUG, "Device #   Q Depth   Online" );
++      cmn_err( CE_DEBUG, "---------------------------" );
++      for( device_ptr = scsi_device_ptr; device_ptr != NULL; device_ptr = device_ptr->next )
++              if( device_ptr->host == host_ptr )
++              {
++                      device_ptr->queue_depth = 10;           
++                      cmn_err( CE_DEBUG, "  %2d         %d        %d", 
++                              device_ptr->id, device_ptr->queue_depth, device_ptr->online );
++              }
++}
++
++
++/*------------------------------------------------------------------------------
++      AAC_SearchBiosSignature()
++
++              Locate adapter signature in BIOS
++ *----------------------------------------------------------------------------*/
++int AAC_SearchBiosSignature( void )
++/*----------------------------------------------------------------------------*/
++{
++      unsigned base;
++      unsigned namep;
++      int index;
++      int val;
++      char name_buf[32];
++      int result = FALSE;
++
++      for( base = 0xc8000; base < 0xdffff; base += 0x4000 )
++      {
++              val = readb( base );
++              if( val != 0x55 ) 
++                      continue;
++
++              result = TRUE;
++              namep = base + 0x1e;
++              memcpy_fromio( name_buf, namep, 32 );
++              name_buf[31] = '\0';
++      }
++      return( result );
++}
++
++
++/*------------------------------------------------------------------------------
++      AAC_Ioctl()
++
++              Handle SCSI ioctls
++ *----------------------------------------------------------------------------*/
++int AAC_Ioctl(
++      Scsi_Device * scsi_dev_ptr,
++      int cmd,
++      void * arg )
++/*----------------------------------------------------------------------------*/
++{
++      PCI_MINIPORT_COMMON_EXTENSION *CommonExtensionPtr;
++
++      cmn_err( CE_DEBUG, "AAC_Ioctl" );
++      CommonExtensionPtr = ( PCI_MINIPORT_COMMON_EXTENSION * )scsi_dev_ptr->host->hostdata;
++      return( AacHba_Ioctl( CommonExtensionPtr, cmd, arg ) );
++}
++
++
++
++/*------------------------------------------------------------------------------
++      AAC_ChardevOpen()
++      
++              Handle character device open
++      
++      Preconditions:
++      Postconditions:
++              Returns 0 if successful, -ENODEV or -EINVAL otherwise
++ *----------------------------------------------------------------------------*/
++int AAC_ChardevOpen(
++      struct inode * inode_ptr,
++      struct file * file_ptr )
++/*----------------------------------------------------------------------------*/
++{
++      unsigned minor_number;
++
++      cmn_err( CE_DEBUG, "AAC_ChardevOpen" );
++
++      // check device permissions in file_ptr->f_mode ??
++
++      // extract & check the minor number
++      minor_number = MINOR( inode_ptr->i_rdev );
++      if( minor_number > ( g_HostAdapterCount - 1 ) )
++      {
++              cmn_err( CE_WARN, "AAC_ChardevOpen: Minor number %d not supported", minor_number );
++              return( -ENODEV );
++      }
++
++      MOD_INC_USE_COUNT;
++
++      return( 0 );
++}
++
++
++/*------------------------------------------------------------------------------
++      AAC_ChardevRelease()
++      
++              Handle character device release.
++      
++      Preconditions:
++      Postconditions:
++              Returns 0 if successful, -ENODEV or -EINVAL otherwise
++ *----------------------------------------------------------------------------*/
++int AAC_ChardevRelease(
++      struct inode * inode_ptr,
++      struct file * file_ptr )
++/*----------------------------------------------------------------------------*/
++{
++      cmn_err( CE_DEBUG, "AAC_ChardevRelease" );
++
++      MOD_DEC_USE_COUNT;
++
++      return( 0 );
++}
++
++
++/*------------------------------------------------------------------------------
++      AAC_ChardevIoctl()
++      
++              Handle character device interface ioctls
++      
++      Preconditions:
++      Postconditions:
++              Returns 0 if successful, -ENODEV or -EINVAL otherwise
++ *----------------------------------------------------------------------------*/
++int AAC_ChardevIoctl(
++      struct inode * inode_ptr, 
++      struct file * file_ptr,
++      unsigned int cmd,
++      unsigned long arg )
++{
++      unsigned minor_number;
++      PCI_MINIPORT_COMMON_EXTENSION *CommonExtensionPtr;
++
++      cmn_err( CE_DEBUG, "AAC_ChardevIoctl" );
++
++      // check device permissions in file_ptr->f_mode ??
++
++      // extract & check the minor number
++      minor_number = MINOR( inode_ptr->i_rdev );
++      if( minor_number > ( g_HostAdapterCount - 1 ) )
++      {
++              cmn_err( CE_WARN, "AAC_ChardevIoctl: Minor number %d not supported", minor_number );
++              return( -ENODEV );
++      }
++
++      // get device pointer
++      CommonExtensionPtr = g_CommonExtensionPtrArray[ minor_number ];
++
++      // dispatch ioctl - AacHba_Ioctl() returns zero on success
++      if( AacHba_Ioctl( CommonExtensionPtr, cmd, ( void * )arg ) )
++              return( -EINVAL );
++
++      return( 0 );
++}
++
++
++/*------------------------------------------------------------------------------
++      parse_keyword()
++
++              Look for the keyword in str_ptr
++
++      Preconditions:
++      Postconditions:
++              If keyword found
++                      - return true and update the pointer str_ptr.
++              otherwise
++                      - return false
++ *----------------------------------------------------------------------------*/
++static int parse_keyword(
++      char ** str_ptr, 
++      char * keyword )
++/*----------------------------------------------------------------------------*/
++{
++      char * ptr = *str_ptr;
++      
++      while( *keyword != '\0' )
++      {
++              char string_char = *ptr++;
++              char keyword_char = *keyword++;
++
++              if ( ( string_char >= 'A' ) && ( string_char <= 'Z' ) )
++                      string_char += 'a' - 'Z';
++              if( ( keyword_char >= 'A' ) && ( keyword_char <= 'Z' ) ) 
++                      keyword_char += 'a' - 'Z';
++              if( string_char != keyword_char )
++                      return FALSE;
++      }
++      *str_ptr = ptr;
++      return TRUE;
++}
++
++
++/*------------------------------------------------------------------------------
++      AAC_ParseDriverOptions()
++
++      For modules the usage is:
++              insmod -f aacraid.o 'aacraid_options="<option_name:argument>"'
++ *----------------------------------------------------------------------------*/
++static void AAC_ParseDriverOptions( 
++      char * cmnd_line_options_str )
++/*----------------------------------------------------------------------------*/
++{
++      int message_level;
++      int reverse_scan;
++      char *cp;
++      char *endp;
++
++      cp = cmnd_line_options_str;
++
++      cmn_err(CE_DEBUG, "AAC_ParseDriverOptions: <%s>", cp);
++
++      while( *cp ) {
++              if( parse_keyword( &cp, "message_level:" ) ) {
++                      message_level = simple_strtoul( cp, 0, 0 );
++                      if( ( message_level < CE_TAIL ) && ( message_level >= 0 ) ) {
++                              g_options.message_level = message_level;
++                              cmn_err( CE_WARN, "%s: new message level = %d", g_DriverName, g_options.message_level );
++                      }
++                      else {
++                              cmn_err( CE_WARN, "%s: invalid message level = %d", g_DriverName, message_level );
++                      }
++              } else if (parse_keyword( &cp, "reverse_scan:" ) ) {
++                      reverse_scan = simple_strtoul( cp, 0, 0 );
++                      if (reverse_scan) {
++                              g_options.reverse_scan = 1;
++                              cmn_err( CE_WARN, "%s: reversing device discovery order", g_DriverName, g_options.message_level );
++                      }
++              }
++              else {
++                      cmn_err( CE_WARN, "%s: unknown command line option <%s>", g_DriverName, cp );
++              }
++
++              /*
++               * skip to next option,  accept " ", ";", and "," as delimiters
++               */
++              while ( *cp && (*cp != ' ')  && (*cp != ';')  && (*cp != ','))
++                      cp++;
++
++              if (*cp)                                 /* skip over the delimiter */
++                      cp++;
++      }
++
++}
++
++
++/*------------------------------------------------------------------------------
++      To use the low level SCSI driver support using the linux kernel loadable 
++      module interface we should initialize the global variable driver_interface  
++      (datatype Scsi_Host_Template) and then include the file scsi_module.c.
++ *----------------------------------------------------------------------------*/
++
++Scsi_Host_Template driver_template = AAC_HOST_TEMPLATE_ENTRY;
++
++#include "scsi_module.c"
++
++
++/*********************************************************************
++      AAC_ProcDirectoryInfo()
++
++              Implement /proc/scsi/<drivername>/<n>.
++              Used to export driver statistics and other infos to the world outside 
++              the kernel using the proc file system. Also provides an interface to
++              feed the driver with information.
++
++      Postconditions
++              For reads
++                      - if offset > 0 return 0
++                      - if offset == 0 write data to proc_buffer and set the start_ptr to
++                      beginning of proc_buffer, return the number of characters written.
++              For writes
++                      - writes currently not supported, return 0
++************************************************************/
++int AAC_ProcDirectoryInfo(
++      char *proc_buffer,              // read/write buffer
++      char **start_ptr,               // start of valid data in the buffer
++      off_t offset,                   // offset from the beginning of the imaginary file 
++      int bytes_available,    // bytes available
++      int host_no,                    // SCSI host number 
++      int write )                             // direction of dataflow: TRUE for writes, FALSE for reads      
++{
++      int length = 0;
++      cmn_err( CE_WARN, "AAC_ProcDirectoryInfo" );
++
++      if( ( write ) || ( offset > 0 ) )
++              return( 0 );
++
++      *start_ptr = proc_buffer;
++
++      return( sprintf(&proc_buffer[length], "%s  %d\n", "Raid Controller, scsi hba number", host_no ) );
++}
++
++void aac_allocate_SyncFibs (PCI_MINIPORT_COMMON_EXTENSION *CommonExtension)
++{
++  void                *BaseAddress;
++  ULONG               PhysAddress;
++  int         size;
++  int         npages;
++  int                 i;
++
++  AFA_COMM_ADAPTER            *Adapter;
++  Adapter = CommonExtension->Adapter;
++
++
++  // Allocate 1 fib for synch fibs
++  // Allocate 1 page.
++  BaseAddress = OsAllocMemory ( PAGE_SIZE, OS_ALLOC_MEM_SLEEP);
++  bzero(BaseAddress, PAGE_SIZE);
++  PhysAddress = virt_to_phys (BaseAddress);
++  Adapter->SyncFib = BaseAddress;
++  Adapter->SyncFibPhysicalAddress = PhysAddress;
++  cmn_err(CE_DEBUG,"aac_allocate_SyncFibs: syncFib: vaddr: 0x%x paddr: 0x%x ", BaseAddress, PhysAddress);
++
++}
+diff -burN linux-2.4.9/drivers/scsi/aacraid/osddi.c linux/drivers/scsi/aacraid/osddi.c
+--- linux-2.4.9/drivers/scsi/aacraid/osddi.c   Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/osddi.c Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,508 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *   osddi.c
++ *
++ * Abstract: This file contains all the proceedures which use LINUX specific Device 
++ *            Driver Interfaces.
++ *    
++ --*/
++
++static char *ident_osddi = "aacraid_ident osddi.c 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#include "osheaders.h"
++
++#include <linux/smp_lock.h>
++
++#ifdef fsid_t
++#undef fsid_t
++#endif
++#include "AacGenericTypes.h"
++#include "aac_unix_defs.h"
++#include "comstruc.h"
++#include "monkerapi.h"
++#include "protocol.h"
++#include "fsafs.h"
++
++#include "sap1common.h"
++#include "fsaport.h"
++#include "pcisup.h"
++#include "sap1.h"
++#include "nodetype.h"
++#include "comsup.h"
++#include "afacomm.h"
++#include "adapter.h"
++
++
++void AacSaPciIsr( 
++      int irq,
++      void * irq_data,
++      struct pt_regs *regs);
++
++void AacRxPciIsr( 
++      int irq,
++      void * irq_data,
++      struct pt_regs *regs);
++
++unsigned SaPciIsr (
++    IN PSa_ADAPTER_EXTENSION AdapterExtension );
++
++unsigned RxPciIsr (
++    IN PSa_ADAPTER_EXTENSION AdapterExtension );
++
++
++/*----------------------------------------------------------------------------*/
++VOID AfaCommInterruptHost(
++      PVOID                   AdapterArg,
++      ADAPTER_EVENT   AdapterEvent )
++/*----------------------------------------------------------------------------*/
++{
++      PAFA_COMM_ADAPTER       Adapter = ( PAFA_COMM_ADAPTER ) AdapterArg;
++      PCOMM_REGION CommRegion = Adapter->CommRegion;
++
++      switch (AdapterEvent) {
++
++        case HostNormRespQue:
++              OsSoftInterruptTrigger( CommRegion->HostNormRespQue.ConsumerRoutine );
++      
++      // #REVIEW# - what do we do with this
++      // if (FsaCommData.HardInterruptModeration)
++      //                      DisableInterrupt( Adapter, HostNormRespQue, TRUE );
++
++                      break;
++
++      case AdapNormCmdNotFull:
++              OsSoftInterruptTrigger( CommRegion->QueueNotFullDpc );
++                      break;
++
++        case HostNormCmdQue:
++              OsSoftInterruptTrigger( CommRegion->HostNormCmdQue.ConsumerRoutine );
++                      break;
++
++      case AdapNormRespNotFull:
++              OsSoftInterruptTrigger( CommRegion->QueueNotFullDpc );
++                      break;
++
++      // #REVIEW# - what do we do with these
++        case HostHighCmdQue:
++        case HostHighRespQue:
++        case AdapHighCmdNotFull:
++        case AdapHighRespNotFull:
++        case SynchCommandComplete:
++        case AdapInternalError:
++                break;
++      }
++}
++
++
++// get the device name associated with this instance of the device
++/*----------------------------------------------------------------------------*/
++char *OsGetDeviceName( 
++      void *AdapterExtension )
++/*----------------------------------------------------------------------------*/
++{
++      return( ( ( Sa_ADAPTER_EXTENSION * )AdapterExtension )->Common->
++              OsDep.scsi_host_ptr->hostt->name );
++}
++
++
++/*----------------------------------------------------------------------------*/
++int OsGetDeviceInstance( 
++      void *AdapterExtension )
++/*----------------------------------------------------------------------------*/
++{
++      return( ( int )( ( Sa_ADAPTER_EXTENSION * )AdapterExtension )->Common->
++              OsDep.scsi_host_ptr->unique_id );
++}
++
++
++/*------------------------------------------------------------------------------
++      OsMapDeviceRegisters()
++
++      Postconditions:
++              Return zero on success non-zero otherwise.
++ *----------------------------------------------------------------------------*/
++int OsMapDeviceRegisters( 
++      Sa_ADAPTER_EXTENSION *AdapterExtension )
++/*----------------------------------------------------------------------------*/
++{
++      PCI_MINIPORT_COMMON_EXTENSION *CommonExtension;
++
++      CommonExtension = AdapterExtension->Common;
++
++      if( AdapterExtension->Device = ( Sa_DEVICE_REGISTERS * )
++                      ioremap( ( unsigned long )CommonExtension->OsDep.scsi_host_ptr->base, 8192 ) )
++      {
++              cmn_err( CE_WARN, "Device mapped to virtual address 0x%x", AdapterExtension->Device ); 
++              return( 0 );
++      }
++      else
++      {       
++              cmn_err( CE_WARN, "OsMapDeviceRegisters: ioremap() failed" );
++              return( 1 );
++      }
++}
++
++
++/*------------------------------------------------------------------------------
++      OsUnMapDeviceRegisters()
++
++      Postconditions:
++ *----------------------------------------------------------------------------*/
++void OsUnMapDeviceRegisters( 
++      Sa_ADAPTER_EXTENSION *AdapterExtension )
++/*----------------------------------------------------------------------------*/
++{
++      iounmap( ( void * )AdapterExtension->Device );
++}
++
++
++/*----------------------------------------------------------------------------*/
++int OsAttachInterrupt( 
++      Sa_ADAPTER_EXTENSION *AdapterExtension ,
++      int     WhichIsr )
++/*----------------------------------------------------------------------------*/
++{
++      PCI_MINIPORT_COMMON_EXTENSION *CommonExtension;
++      void *irq_data;
++      void (*Isr)();
++
++      CommonExtension = AdapterExtension->Common;
++      irq_data = ( void * )AdapterExtension;
++
++      switch (WhichIsr) {
++              case SaISR:
++                      Isr = AacSaPciIsr;
++                      break;
++              case RxISR:
++                      Isr = AacRxPciIsr;
++                      break;
++              default:
++                      cmn_err(CE_WARN, "OsAttachInterrupt: invalid ISR case: 0x%x", WhichIsr);
++                      return( FAILURE );
++                      break;
++      }
++
++      
++      if      ( OsRegisterInterrupt (
++                              CommonExtension->OsDep.scsi_host_ptr->irq,      // interrupt number
++                              Isr,                                                                            // handler function
++                              irq_data )
++              ) 
++      {
++              cmn_err( CE_WARN, "OsAttachInterrupt: Failed for IRQ: 0x%x", 
++                      CommonExtension->OsDep.scsi_host_ptr->irq );
++              return( FAILURE );
++      }
++
++      return ( 0 );
++}
++
++
++/*----------------------------------------------------------------------------*/
++void AacSaPciIsr( 
++      int irq,
++      void * irq_data,
++      struct pt_regs *regs)
++/*----------------------------------------------------------------------------*/
++{
++      // call the actual interrupt handler
++      SaPciIsr( ( Sa_ADAPTER_EXTENSION * )irq_data );
++}
++
++/*----------------------------------------------------------------------------*/
++void AacRxPciIsr( 
++      int irq,
++      void * irq_data,
++      struct pt_regs *regs)
++/*----------------------------------------------------------------------------*/
++{
++      // call the actual interrupt handler
++      RxPciIsr( ( Sa_ADAPTER_EXTENSION * )irq_data );
++}
++
++
++/*----------------------------------------------------------------------------*/
++void OsDetachInterrupt( 
++      Sa_ADAPTER_EXTENSION *AdapterExtension )
++/*----------------------------------------------------------------------------*/
++{
++      PCI_MINIPORT_COMMON_EXTENSION *CommonExtension;
++      void *irq_data;
++
++      CommonExtension = AdapterExtension->Common;
++      irq_data = ( void * )AdapterExtension;
++
++      OsUnregisterInterrupt (
++              CommonExtension->OsDep.scsi_host_ptr->irq,      // interrupt number
++              irq_data );
++}
++
++
++/*----------------------------------------------------------------------------*/
++int OsAttachDMA( 
++      Sa_ADAPTER_EXTENSION *AdapterExtension )
++/*----------------------------------------------------------------------------*/
++{
++      return( 0 );
++}
++
++/*----------------------------------------------------------------------------*/
++int OsAttachHBA( 
++      Sa_ADAPTER_EXTENSION *AdapterExtension )
++/*----------------------------------------------------------------------------*/
++{
++      return( 0 );
++}
++
++/*----------------------------------------------------------------------------*/
++void OsDetachDevice( 
++      Sa_ADAPTER_EXTENSION *AdapterExtension )
++/*----------------------------------------------------------------------------*/
++{
++      OsUnMapDeviceRegisters( AdapterExtension );
++      return( 0 );
++}
++
++/*----------------------------------------------------------------------------*/
++ULONG *OsAllocCommPhysMem(
++      Sa_ADAPTER_EXTENSION    *AdapterExtension, 
++      ULONG                                   size,
++      ULONG                                   **virt_addr_pptr,
++      ULONG                                   *phys_addr_ptr )
++/*----------------------------------------------------------------------------*/
++{
++      if( ( *virt_addr_pptr = ( ULONG * )OsAllocMemory( size, GFP_KERNEL ) ) )
++      {
++              *phys_addr_ptr = OsVirtToPhys( ( volatile void * )*virt_addr_pptr );
++              if( !*phys_addr_ptr )
++              {
++                      cmn_err( CE_WARN, "OsAllocCommPhysMem: OsVirtToPhys failed" );
++              }
++                              
++              return( *virt_addr_pptr );
++      }
++      else
++              return( NULL );
++}
++
++OsAifKernelThread(
++      Sa_ADAPTER_EXTENSION    *AdapterExtension )
++{
++
++      struct fs_struct *fs;
++      int i;
++      struct task_struct *tsk;
++
++      tsk = current;
++
++
++      /*
++       * set up the name that will appear in 'ps'
++       * stored in  task_struct.comm[16].
++       */
++
++      sprintf(tsk->comm, "AIFd");
++
++
++      // use_init_fs_context();  only exists in 2.2.13 onward.
++
++      lock_kernel();
++
++      /*
++       * we were started as a result of loading the  module.
++       * free all of user space pages
++       */
++
++      exit_mm(tsk);
++
++      exit_files(tsk);
++
++      exit_fs(tsk);
++
++      fs = init_task.fs;
++      tsk->fs = fs;
++
++      tsk->session = 1;
++      tsk->pgrp = 1;
++
++      if (fs)
++              atomic_inc(&fs->count);
++
++      unlock_kernel();
++
++
++
++
++      NormCommandThread(AdapterExtension);
++      /* NOT REACHED */
++}
++
++/*----------------------------------------------------------------------------*/
++void OsStartKernelThreads(
++      Sa_ADAPTER_EXTENSION    *AdapterExtension )
++/*----------------------------------------------------------------------------*/
++{
++      PCI_MINIPORT_COMMON_EXTENSION   *CommonExtension;
++      AFA_COMM_ADAPTER                                *Adapter;
++      extern void                                     NormCommandThread(void *Adapter);
++
++      CommonExtension = AdapterExtension->Common;
++      Adapter = (AFA_COMM_ADAPTER *)CommonExtension->Adapter;
++
++      // 
++      // Start thread which will handle interrupts for this adapter
++      //
++      //kthread_spawn(FsaCommIntrHandler, AdapterExtension, "fsaintr",0);
++
++      //
++      // Start thread which will handle AdapterInititatedFibs from this adapter
++      //
++      CommonExtension->OsDep.thread_pid = 
++              kernel_thread( ( int ( * )( void * ) )OsAifKernelThread, Adapter, 0 );
++//            kernel_thread( ( int ( * )( void * ) )NormCommandThread, Adapter, 0 );
++}
++
++/*----------------------------------------------------------------------------*/
++BOOLEAN AfaPortAllocateAndMapFibSpace(
++      PVOID Arg1,
++    IN PMAPFIB_CONTEXT MapFibContext )
++/*----------------------------------------------------------------------------*/
++{
++      PVOID           BaseAddress;
++      ULONG           PhysAddress;
++
++      if( !( BaseAddress = (ULONG *)OsAllocMemory( MapFibContext->Size, GFP_KERNEL ) ) )
++      {
++              cmn_err( CE_WARN, "AfaPortAllocateAndMapFibSpace: OsAllocMemory failed" );
++              return( FALSE );
++      }
++
++      PhysAddress = OsVirtToPhys( BaseAddress );
++      
++      MapFibContext->FibVirtualAddress = BaseAddress;
++      MapFibContext->FibPhysicalAddress = (PVOID) PhysAddress;
++
++      return (TRUE);
++}
++
++/*----------------------------------------------------------------------------*/
++BOOLEAN AfaPortUnmapAndFreeFibSpace(
++      PVOID Arg1,
++    IN PMAPFIB_CONTEXT MapFibContext )
++/*----------------------------------------------------------------------------*/
++{
++      PPCI_MINIPORT_COMMON_EXTENSION CommonExtension = (PPCI_MINIPORT_COMMON_EXTENSION) Arg1;
++
++      OsFreeMemory( MapFibContext->FibVirtualAddress, 0 );
++
++      return (TRUE);
++}
++
++/*----------------------------------------------------------------------------*/
++BOOLEAN AfaPortFreeAdapterCommArea(
++      IN PVOID Arg1 )
++/*----------------------------------------------------------------------------*/
++{
++      PPCI_MINIPORT_COMMON_EXTENSION CommonExtension = (PPCI_MINIPORT_COMMON_EXTENSION) Arg1;
++
++      OsFreeMemory( CommonExtension->CommAddress, 0 );
++
++      return (TRUE);
++}
++
++
++/* ================================================================================ */
++/*
++ * Not sure if the functions below here ever get called in the current code
++ * These probably should be a different file.
++ */
++/*
++ddi_dma_attr_t AfaPortDmaAttributes = {
++      //rpbfix : we may want something different for I/O
++      DMA_ATTR_V0,
++      0,
++      0xffffffff,
++      0x0000ffff,
++      1,
++      1,
++      1,
++      0x0000ffff,
++      0x0000ffff,
++      17,
++      512,
++      0
++};
++*/
++
++AAC_STATUS
++AfaPortBuildSgMap(
++      PVOID Arg1,
++      IN PSGMAP_CONTEXT SgMapContext
++      )
++
++/*++
++
++Routine Description:
++
++      This routine build a scatter gather map using the information
++      in the SgMapContext.
++
++Arguments:
++
++      AdapterExtension - Pointer to adapter extension structure.
++    SgMapContext - Pointer to the SgMapContext for the request.
++
++
++Return Value:
++
++      AAC_STATUS      
++--*/
++{
++      printk( KERN_ALERT "AfaPortBuildSgMap: unimplemented function called" );
++      return (STATUS_UNSUCCESSFUL);
++}
++
++VOID
++AfaPortFreeDmaResources(
++      PVOID Arg1,
++    IN PSGMAP_CONTEXT SgMapContext
++    )
++
++/*++
++
++Routine Description:
++
++    Given a pointer to the IRP context will free all reserved DMA resources allocated for
++    the completed IO operation.
++
++Arguments:
++
++    Fib - Pointer to the Fib the caller wishes to have transfered over to the adapter.
++    Context - Pointer to the Irp Context we use to store the dma mapping information
++        we need to do and complete the IO.
++
++Return Value:
++
++    Nothing
++
++--*/
++{
++}
+diff -burN linux-2.4.9/drivers/scsi/aacraid/osfuncs.c linux/drivers/scsi/aacraid/osfuncs.c
+--- linux-2.4.9/drivers/scsi/aacraid/osfuncs.c Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/osfuncs.c       Thu Aug 16 18:15:01 2001
+@@ -0,0 +1,594 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *  osfuncs.c
++ *
++ * Abstract: Holds all of the O/S specific interface functions.
++ *    
++ --*/
++
++static char *ident_osfuncs = "aacraid_ident osfuncs.c 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#include "osheaders.h"
++
++//static LKINFO_DECL(fsa_locks, "fsa_locks",0);
++
++extern aac_options_t g_options;
++
++OS_SOFTINTR g_idle_task = { 0, 0, 0, 0 };
++wait_queue_t * g_wait_queue_ptr = NULL;
++wait_queue_t g_wait;
++
++void OsTimeoutHandler( 
++      struct semaphore * sem );
++
++int * OsIdleTask( void * data );
++
++//-----------------------------------------------------------------------------
++// Memory Allocation functions
++
++/*----------------------------------------------------------------------------*/
++void * OsAllocMemory(
++      OS_SIZE_T Size,
++      unsigned int Flags )
++/*----------------------------------------------------------------------------*/
++{
++      void *mem_ptr;
++
++      if( !( mem_ptr = kmalloc( Size, GFP_KERNEL ) ) )
++              cmn_err( CE_WARN, "OsAllocMemory: FAILED\n" );
++      return( mem_ptr );
++}
++
++
++/*----------------------------------------------------------------------------*/
++void OsFreeMemory(
++      void * Buffer,
++      OS_SIZE_T Size )
++/*----------------------------------------------------------------------------*/
++{
++      kfree( Buffer );
++}
++
++
++/*----------------------------------------------------------------------------*/
++int OsRegisterInterrupt(
++      unsigned int irq,               // interrupt number
++      void ( *handler )( int, void*, struct pt_regs * ),      // handler function
++      void *irq_data )                // argument to handler function
++/*----------------------------------------------------------------------------*/
++{
++  return( request_irq (irq, handler, SA_INTERRUPT | SA_SHIRQ, "aacraid", irq_data ) );
++}
++
++
++/*----------------------------------------------------------------------------*/
++void OsUnregisterInterrupt(
++      unsigned int irq,               // interrupt number
++      void *irq_data)
++/*----------------------------------------------------------------------------*/
++{
++      free_irq (
++              irq,                                                                            // interrupt number
++              irq_data );
++}
++
++
++/*----------------------------------------------------------------------------*/
++unsigned long OsVirtToPhys( 
++      void * virtual_address )
++/*----------------------------------------------------------------------------*/
++{
++      return( virt_to_phys( virtual_address ) );
++}
++
++
++//-----------------------------------------------------------------------------
++// MUTEX functions
++
++/*----------------------------------------------------------------------------*/
++OS_STATUS OsMutexInit( 
++      OS_MUTEX *Mutex,
++      OS_SPINLOCK_COOKIE Cookie )
++/*----------------------------------------------------------------------------*/
++{
++      Mutex->lock_var = 0;
++      //      bzero (&Mutex->wq, sizeof (Mutex->wq));
++      init_waitqueue_head (&Mutex->wq);
++      return ( 0 );
++}
++
++
++/*----------------------------------------------------------------------------*/
++void OsMutexDestroy( 
++      OS_MUTEX *Mutex )
++/*----------------------------------------------------------------------------*/
++{
++}
++
++
++/*----------------------------------------------------------------------------*/
++void OsMutexAcquire( 
++      OS_MUTEX *Mutex )
++/*----------------------------------------------------------------------------*/
++{
++  //  wait_queue_t wait = { current, NULL };
++      unsigned long time_stamp;
++
++      DECLARE_WAITQUEUE (wait, current);
++
++      time_stamp = jiffies;
++
++      if( test_and_set_bit( 0, &( Mutex->lock_var ) ) != 0 )
++      {
++              if( in_interrupt() )
++                      panic( "OsMutexAcquire going to sleep at interrupt time\n" );
++              current->state = TASK_INTERRUPTIBLE;
++              add_wait_queue( &( Mutex->wq ), &wait );
++              while( test_and_set_bit( 0, &( Mutex->lock_var ) ) != 0 )
++                      schedule();
++              remove_wait_queue( &( Mutex->wq ), &wait );
++      }
++
++      if( ( jiffies - 1 ) > time_stamp )
++              cmn_err( CE_WARN, "Mutex %ld locked out for %ld ticks", 
++                      Mutex, jiffies - time_stamp );
++}
++
++
++/*----------------------------------------------------------------------------*/
++void OsMutexRelease( 
++      OS_MUTEX *Mutex )
++/*----------------------------------------------------------------------------*/
++{
++      if( test_and_clear_bit( 0, &( Mutex->lock_var ) ) == 0 )
++              cmn_err( CE_WARN, "OsMutexRelease: mutex not locked" );
++      wake_up_interruptible( &( Mutex->wq ) );
++}
++
++// see man hierarchy(D5)
++#define FSA_LOCK 1
++
++//-----------------------------------------------------------------------------
++// Spinlock functions
++
++/*----------------------------------------------------------------------------*/
++OS_SPINLOCK * OsSpinLockAlloc( void ) 
++/*----------------------------------------------------------------------------*/
++{
++      OS_SPINLOCK *SpinLock;
++      int i;
++
++
++      SpinLock = ( OS_SPINLOCK * )kmalloc( sizeof( OS_SPINLOCK ), GFP_KERNEL );
++
++      if (SpinLock == NULL)
++              cmn_err (CE_WARN, "WARNING: OsSpinLockAlloc Failed!!!");
++      
++      SpinLock->spin_lock = SPIN_LOCK_UNLOCKED;
++      for( i = 0; i < NR_CPUS; i++ )
++              SpinLock->cpu_lock_count[ i ] = 0;
++      return( SpinLock );
++}
++
++
++/*----------------------------------------------------------------------------*/
++OS_STATUS OsSpinLockInit( 
++      OS_SPINLOCK *SpinLock,
++      OS_SPINLOCK_COOKIE Cookie )
++/*----------------------------------------------------------------------------*/
++{
++      return( 0 );
++}
++
++
++/*----------------------------------------------------------------------------*/
++void OsSpinLockDestroy( 
++      OS_SPINLOCK *SpinLock )
++/*----------------------------------------------------------------------------*/
++{
++      kfree( SpinLock );
++      SpinLock = NULL;
++}
++
++
++/*----------------------------------------------------------------------------*/
++void OsSpinLockAcquire( 
++      OS_SPINLOCK *SpinLock )
++/*----------------------------------------------------------------------------*/
++{
++      unsigned cpu_id;
++
++      if( SpinLock )
++      {
++              cpu_id = smp_processor_id();
++              if( SpinLock->cpu_lock_count[ cpu_id ] ){
++                      cmn_err (CE_PANIC, "CPU %d trying to acquire lock again: lock count = %d\n",
++                               cpu_id, SpinLock->cpu_lock_count[ cpu_id ]);
++              }                 
++              
++              spin_lock_irqsave( &( SpinLock->spin_lock ), SpinLock->cpu_flags[ cpu_id ] );
++              SpinLock->cpu_lock_count[ cpu_id ]++;
++         
++      } else {
++              cmn_err( CE_WARN, "OsSpinLockAcquire: lock does not exist" );
++      }
++}
++
++
++/*----------------------------------------------------------------------------*/
++void OsSpinLockRelease( 
++      OS_SPINLOCK *SpinLock )
++/*----------------------------------------------------------------------------*/
++{
++      unsigned cpu_id;
++
++      if( SpinLock )
++      {
++              cpu_id = smp_processor_id();
++              SpinLock->cpu_lock_count[ cpu_id ]--;
++              spin_unlock_irqrestore( &( SpinLock->spin_lock ), SpinLock->cpu_flags[ cpu_id ] );
++      }
++      else
++              cmn_err( CE_WARN, "OsSpinLockRelease: lock does not exist" );
++}
++
++
++/*----------------------------------------------------------------------------*/
++inline int OsSpinLockOwned(
++      OS_SPINLOCK *SpinLock )
++/*----------------------------------------------------------------------------*/
++{
++      return spin_is_locked (&SpinLock->spin_lock);
++}
++
++
++//-----------------------------------------------------------------------------
++// CvLock functions
++
++/*----------------------------------------------------------------------------*/
++OS_CVLOCK *OsCvLockAlloc( void ) 
++{
++      OS_CVLOCK *cv_lock;
++
++
++#ifdef CVLOCK_USE_SPINLOCK
++      cv_lock = OsSpinLockAlloc(); 
++#else
++      cv_lock = ( OS_CVLOCK * )kmalloc( sizeof( OS_CVLOCK ), GFP_KERNEL );
++      cv_lock->wq = NULL;
++      cv_lock->lock_var = 0;
++#endif
++
++      return( cv_lock );
++}
++
++
++/*----------------------------------------------------------------------------*/
++OS_STATUS OsCvLockInit( 
++      OS_CVLOCK *cv_lock,
++      OS_SPINLOCK_COOKIE Cookie )
++/*----------------------------------------------------------------------------*/
++{
++      return ( 0 );
++}
++
++
++/*----------------------------------------------------------------------------*/
++void OsCvLockDestroy( 
++      OS_CVLOCK *cv_lock )
++/*----------------------------------------------------------------------------*/
++{
++      if( cv_lock )
++              kfree( cv_lock );
++      cv_lock = NULL;
++}
++
++
++/*----------------------------------------------------------------------------*/
++void OsCvLockAcquire (OS_CVLOCK *cv_lock)
++{
++#ifdef CVLOCK_USE_SPINLOCK
++              OsSpinLockAcquire( cv_lock );
++#else
++              OsMutexAcquire( cv_lock );
++#endif
++}
++
++
++/*----------------------------------------------------------------------------*/
++void OsCvLockRelease( 
++      OS_CVLOCK *cv_lock )
++/*----------------------------------------------------------------------------*/
++{
++#ifdef CVLOCK_USE_SPINLOCK
++              OsSpinLockRelease( cv_lock );
++#else
++              OsMutexRelease( cv_lock );
++#endif
++}
++
++
++/*----------------------------------------------------------------------------*/
++int OsCvLockOwned(
++      OS_CVLOCK *cv_lock )
++/*----------------------------------------------------------------------------*/
++{
++      return( 1 );
++}
++
++
++//-----------------------------------------------------------------------------
++// Conditional variable functions
++
++/*----------------------------------------------------------------------------*/
++void OsCv_init ( 
++      OS_CV_T *cv_ptr )
++/*----------------------------------------------------------------------------*/
++{
++      cv_ptr->lock_var = 1;
++      init_waitqueue_head (&cv_ptr->wq);
++}
++
++
++/*----------------------------------------------------------------------------*/
++void OsCv_destroy( 
++      OS_CV_T  *cv_ptr )
++/*----------------------------------------------------------------------------*/
++{
++}
++
++
++/*______________________________________________________________________________
++ -
++ -
++ -----------------------------------------------------------------------------*/
++OsCv_wait (OS_CV_T *cv_ptr, OS_CVLOCK *cv_lock_ptr)
++{
++      unsigned long flags;
++
++      DECLARE_WAITQUEUE (wait, current);
++      
++      if( in_interrupt() )
++              panic( "OsCv_wait going to sleep at interrupt time\n" );
++
++      cv_ptr->type = TASK_UNINTERRUPTIBLE;
++      current->state = TASK_UNINTERRUPTIBLE;
++
++      add_wait_queue( &cv_ptr->wq, &wait );
++
++      OsCvLockRelease( cv_lock_ptr );
++      schedule();
++
++      while( test_and_set_bit( 0, &( cv_ptr->lock_var ) ) != 0 )
++      {
++              if( in_interrupt() )
++                      panic( "OsCv_wait going to sleep at interrupt time\n" );
++              schedule();
++      }
++
++      remove_wait_queue( &( cv_ptr->wq ), &wait );
++
++      OsCvLockAcquire( cv_lock_ptr );
++}
++
++
++/*----------------------------------------------------------------------------*/
++int OsCv_wait_sig( 
++      OS_CV_T *cv_ptr,
++      OS_CVLOCK *cv_lock_ptr ) 
++/*----------------------------------------------------------------------------*/
++{
++      unsigned long flags;
++      int signal_state = 1;
++
++      DECLARE_WAITQUEUE (wait, current);
++      
++      if( in_interrupt() )
++              panic( "OsCv_wait_sig going to sleep at interrupt time\n" );
++
++      cv_ptr->type = TASK_INTERRUPTIBLE;
++      current->state = TASK_INTERRUPTIBLE;
++
++      add_wait_queue( &( cv_ptr->wq ), &wait );
++
++      OsCvLockRelease( cv_lock_ptr );
++      schedule();
++
++      while( ( test_and_set_bit( 0, &( cv_ptr->lock_var ) ) != 0 ) && 
++                      ( !signal_pending( current ) ) )
++      {
++              if( in_interrupt() )
++                      panic( "OsCv_wait_sig going to sleep at interrupt time\n" );
++              schedule();
++      }
++
++      if( signal_pending( current ) )
++              signal_state = 0;
++      
++      remove_wait_queue( &( cv_ptr->wq ), &wait );
++      
++      OsCvLockAcquire( cv_lock_ptr );
++      return( signal_state );
++}
++
++
++/*----------------------------------------------------------------------------*/
++void OsCv_signal( 
++      OS_CV_T *cv_ptr )
++/*----------------------------------------------------------------------------*/
++{
++
++      clear_bit( 0, &( cv_ptr->lock_var ) );
++      if( cv_ptr->type == TASK_INTERRUPTIBLE )
++                      wake_up_interruptible( &( cv_ptr->wq ) );
++      else{
++                      wake_up( &( cv_ptr->wq ) );
++      }
++}
++
++
++// return time in seconds
++/*----------------------------------------------------------------------------*/
++unsigned long OsGetSeconds( void )
++/*----------------------------------------------------------------------------*/
++{
++      return( jiffies/HZ );
++}
++
++
++//-----------------------------------------------------------------------------
++// Deferred procedure call functions
++
++// create a soft interrupt object
++/*----------------------------------------------------------------------------*/
++int OsSoftInterruptAdd( 
++      OS_SOFTINTR **ptr,
++      void * handler,
++      void * data )
++/*----------------------------------------------------------------------------*/
++{
++      OS_SOFTINTR *tmp_ptr;
++
++      if( !( tmp_ptr = ( OS_SOFTINTR * )kmalloc( sizeof( OS_SOFTINTR ), GFP_KERNEL ) ) )
++              return( -1 );
++      tmp_ptr->routine = handler;
++      tmp_ptr->data = data;
++      tmp_ptr->sync = 0;
++      INIT_LIST_HEAD(&tmp_ptr->list);
++
++      *ptr = tmp_ptr; 
++
++      return( 0 );
++}
++
++/*
++      Use kernel_thread( ( int ( * )( void * ) )OsIdleTask, NULL, 0 ); to start
++*/
++/*----------------------------------------------------------------------------*/
++int * OsIdleTask( void * data )
++/*----------------------------------------------------------------------------*/
++{
++      DECLARE_WAITQUEUE (wait, current);
++
++      while( 1 )
++      {
++              current->state = TASK_INTERRUPTIBLE;
++              add_wait_queue( &g_wait_queue_ptr, &wait );
++              schedule();
++              remove_wait_queue( &g_wait_queue_ptr, &wait );
++              wait.task =  current;
++              wait.task_list.next = NULL;
++      }
++      return( NULL );
++}
++
++
++// dispatch a soft interrupt 
++/*----------------------------------------------------------------------------*/
++void OsSoftInterruptTrigger( 
++      OS_SOFTINTR *soft_intr_ptr )
++/*----------------------------------------------------------------------------*/
++{
++      // call the completion routine directly
++      soft_intr_ptr->routine( soft_intr_ptr->data );
++}
++
++
++// delete a soft interrupt object
++/*----------------------------------------------------------------------------*/
++void OsSoftInterruptRemove( 
++      OS_SOFTINTR *arg )
++/*----------------------------------------------------------------------------*/
++{
++      if( arg )
++              kfree( arg );
++      arg = NULL;
++}
++
++
++/*----------------------------------------------------------------------------*/
++void OsSleep( 
++      unsigned time )         // in seconds
++/*----------------------------------------------------------------------------*/
++{
++      struct semaphore sem;
++      struct timer_list timer_var;
++      
++      init_MUTEX_LOCKED (&sem);
++
++      //      if( in_interrupt() )
++      //              panic( "OsSleep going to sleep at interrupt time\n" );
++
++      init_timer( &timer_var );
++      timer_var.function = ( void ( * )( unsigned long ) )OsTimeoutHandler;
++      timer_var.data = ( unsigned long )&sem;
++      timer_var.expires = jiffies + time * HZ;
++
++      add_timer( &timer_var );
++      down( &sem );
++
++      del_timer( &timer_var );
++}
++
++
++/*----------------------------------------------------------------------------*/
++void OsTimeoutHandler( 
++      struct semaphore * sem )
++/*----------------------------------------------------------------------------*/
++{
++      if( sem != NULL )
++              up( sem );
++}
++
++
++/*----------------------------------------------------------------------------*/
++void printk_err(
++      int flag, 
++      char *fmt, 
++      ...)
++/*----------------------------------------------------------------------------*/
++{
++      char    buf[256];
++      va_list ap;
++
++      va_start(ap, fmt);
++      (void) vsprintf(buf, fmt, ap);
++      va_end(ap);
++      
++      if( flag <= g_options.message_level )
++              printk(KERN_ALERT "%s\n", buf);
++}
++
++/*  void aac_show_tasks (struct list_head *our_tasks){ */
++ 
++/*            cmn_err (CE_DEBUG, "Entering aac_show_tasks"); */
++
++/*            if (our_tasks->next == NULL || our_tasks->next == 0) */
++/*                            cmn_err (CE_DEBUG, "list_head->next is NULL or 0"); */
++/*            else */
++/*                            cmn_err (CE_DEBUG, "list_head->next: 0x%x", our_tasks->next); */
++
++/*            if (our_tasks->prev == NULL || our_tasks->prev == 0) */
++/*                            cmn_err (CE_DEBUG, "list_head->prev is NULL or 0"); */
++/*            else */
++/*                            cmn_err (CE_DEBUG, "list_head->prev: 0x%x", our_tasks->prev); */
++
++/*  } */
+diff -burN linux-2.4.9/drivers/scsi/aacraid/ossup.c linux/drivers/scsi/aacraid/ossup.c
+--- linux-2.4.9/drivers/scsi/aacraid/ossup.c   Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/ossup.c Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,199 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *  ossup.c
++ *
++ * 
++ *
++ --*/
++
++static char *ident_ossup = "aacraid_ident ossup.c 1.0.6 2000/10/09 Adaptec, Inc.";
++
++#include "osheaders.h"
++
++#include "aac_unix_defs.h"
++
++
++AAC_STATUS
++ExInitializeZone(
++    IN PZONE_HEADER Zone,
++    IN ULONG BlockSize,
++    IN PVOID InitialSegment,
++    IN ULONG InitialSegmentSize
++    )
++
++/*++
++
++Routine Description:
++
++    This function initializes a zone header.  Once successfully
++    initialized, blocks can be allocated and freed from the zone, and
++    the zone can be extended.
++
++Arguments:
++
++    Zone - Supplies the address of a zone header to be initialized.
++
++    BlockSize - Supplies the block size of the allocatable unit within
++                the zone.  The size must be larger that the size of the
++                initial segment, and must be 64-bit aligned.
++
++    InitialSegment - Supplies the address of a segment of storage.  The
++                     first ZONE_SEGMENT_HEADER-sized portion of the segment
++                     is used by the zone allocator.  The remainder of
++                     the segment is carved up into fixed size
++                     (BlockSize) blocks and is made available for
++                     allocation and deallocation from the zone.  The
++                     address of the segment must be aligned on a 64-bit
++                     boundary.
++
++    InitialSegmentSize - Supplies the size in bytes of the InitialSegment.
++
++Return Value:
++
++    STATUS_UNSUCCESSFUL - BlockSize or InitialSegment was not aligned on
++                          64-bit boundaries, or BlockSize was larger than
++                          the initial segment size.
++
++    STATUS_SUCCESS - The zone was successfully initialized.
++
++--*/
++
++{
++    ULONG i;
++    PCHAR p;
++
++
++    Zone->BlockSize = BlockSize;
++
++    Zone->SegmentList.Next = &((PZONE_SEGMENT_HEADER) InitialSegment)->SegmentList;
++    ((PZONE_SEGMENT_HEADER) InitialSegment)->SegmentList.Next = NULL;
++    ((PZONE_SEGMENT_HEADER) InitialSegment)->Reserved = NULL;
++
++    Zone->FreeList.Next = NULL;
++
++    p = (PCHAR)InitialSegment + sizeof(ZONE_SEGMENT_HEADER);
++
++    for (i = sizeof(ZONE_SEGMENT_HEADER);
++         i <= InitialSegmentSize - BlockSize;
++         i += BlockSize
++        ) {
++        ((PSINGLE_LIST_ENTRY)p)->Next = Zone->FreeList.Next;
++        Zone->FreeList.Next = (PSINGLE_LIST_ENTRY)p;
++        p += BlockSize;
++    }
++    Zone->TotalSegmentSize = i;
++
++#if 0
++    DbgPrint( "EX: ExInitializeZone( %lx, %lx, %lu, %lu, %lx )\n",
++              Zone, InitialSegment, InitialSegmentSize,
++              BlockSize, p
++            );
++#endif
++
++    return STATUS_SUCCESS;
++}
++
++AAC_STATUS
++ExExtendZone(
++    IN PZONE_HEADER Zone,
++    IN PVOID Segment,
++    IN ULONG SegmentSize
++    )
++
++/*++
++
++Routine Description:
++
++    This function extends a zone by adding another segment's worth of
++    blocks to the zone.
++
++Arguments:
++
++    Zone - Supplies the address of a zone header to be extended.
++
++    Segment - Supplies the address of a segment of storage.  The first
++              ZONE_SEGMENT_HEADER-sized portion of the segment is used by the
++              zone allocator.  The remainder of the segment is carved up
++              into fixed-size (BlockSize) blocks and is added to the
++              zone.  The address of the segment must be aligned on a 64-
++              bit boundary.
++
++    SegmentSize - Supplies the size in bytes of Segment.
++
++Return Value:
++
++    STATUS_UNSUCCESSFUL - BlockSize or Segment was not aligned on
++                          64-bit boundaries, or BlockSize was larger than
++                          the segment size.
++
++    STATUS_SUCCESS - The zone was successfully extended.
++
++--*/
++
++{
++    ULONG i;
++    PCHAR p;
++
++
++    ((PZONE_SEGMENT_HEADER) Segment)->SegmentList.Next = Zone->SegmentList.Next;
++    Zone->SegmentList.Next = &((PZONE_SEGMENT_HEADER) Segment)->SegmentList;
++
++    p = (PCHAR)Segment + sizeof(ZONE_SEGMENT_HEADER);
++
++    for (i = sizeof(ZONE_SEGMENT_HEADER);
++         i <= SegmentSize - Zone->BlockSize;
++         i += Zone->BlockSize
++        ) {
++
++        ((PSINGLE_LIST_ENTRY)p)->Next = Zone->FreeList.Next;
++        Zone->FreeList.Next = (PSINGLE_LIST_ENTRY)p;
++        p += Zone->BlockSize;
++    }
++    Zone->TotalSegmentSize += i;
++
++#if 0
++    DbgPrint( "EX: ExExtendZone( %lx, %lx, %lu, %lu, %lx )\n",
++              Zone, Segment, SegmentSize, Zone->BlockSize, p
++            );
++#endif
++
++    return STATUS_SUCCESS;
++}
++
++DbgPrint()
++{
++}
++
++/* Function: InqStrCopy()
++ *
++ * Arguments: [2] pointer to char
++ *
++ * Purpose: Copy a String from one location to another
++ * without copying \0
++ */
++void
++InqStrCopy(char *a, char *b)
++{
++
++      while(*a != (char)0) 
++              *b++ = *a++;
++}
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/port.c linux/drivers/scsi/aacraid/port.c
+--- linux-2.4.9/drivers/scsi/aacraid/port.c    Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/port.c  Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,287 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *  port.c
++ *
++ * Abstract: All support routines for FSA communication which are miniport specific.
++ *
++ --*/
++
++static char *ident_port = "aacraid_ident port.c 1.0.7 2000/10/11 Adaptec, Inc.";
++
++#include "osheaders.h"
++
++
++#include "AacGenericTypes.h"
++
++#include "aac_unix_defs.h"
++
++#include "fsatypes.h"
++#include "comstruc.h"
++#include "protocol.h"
++
++#include "fsaport.h"
++#include "fsaioctl.h"
++
++#include "pcisup.h"
++#include "port.h"
++
++int AfaPortPrinting = 1;
++
++extern AAC_STATUS AfaPort_Err_Adapter_Printf;
++extern AAC_STATUS AfaPort_Warn_Adapter_Printf;
++extern AAC_STATUS AfaPort_Info_Adapter_Printf;
++extern AAC_STATUS AfaPort_Err_FastAfa_Load_Driver;
++
++
++
++VOID
++AfaPortLogError(
++      IN PPCI_MINIPORT_COMMON_EXTENSION CommonExtension,
++      IN AAC_STATUS ErrorCode,
++      IN PUCHAR StringBuffer,
++      IN ULONG StringLength
++      )
++/*++
++
++Routine Description:
++
++      Does all of the work to log an error log entry
++Arguments:
++
++      CommonExtension - Pointer to the adapter that caused the error.
++
++      ErrorCode - Which error is being logged.
++
++      StringBuffer - Pointer to optional String for error log entry.
++
++      StringLength - Length of StringBuffer.
++
++Return Value:
++
++    Nothing
++
++--*/
++
++{
++
++}
++
++BOOLEAN
++AfaPortGetNextAdapterNumber(
++    IN  PDRIVER_OBJECT  DriverObject,
++      OUT PDEVICE_OBJECT      *FsaDeviceObject,
++      OUT PFILE_OBJECT        *FileObject,
++      OUT PULONG                      AdapterNumber
++      )
++{
++}
++BOOLEAN
++AfaPortAllocateAdapterCommArea(
++      IN PVOID                Arg1,
++      IN OUT PVOID    *CommHeaderAddress,
++      IN ULONG                CommAreaSize,
++      IN ULONG                CommAreaAlignment
++      )
++{
++      PPCI_MINIPORT_COMMON_EXTENSION CommonExtension = (PPCI_MINIPORT_COMMON_EXTENSION) Arg1;
++      PVOID BaseAddress;
++      PHYSICAL_ADDRESS PhysicalBaseAddress;
++      ULONG TotalSize, BytesToAlign;
++      size_t          RealLength;
++      uint_t          Count;
++//    ULONG SizeOfFastIoComm = sizeof(FASTIO_STRUCT);
++//    ULONG AdapterFibsSize = PAGE_SIZE;
++      ULONG AdapterFibsSize = 4096;
++      ULONG PrintfBufferSize = 256;
++      PADAPTER_INIT_STRUCT InitStruct;
++      extern int MiniPortRevision;
++      ULONG   PhysAddress;
++
++//    TotalSize = AdapterFibsSize + sizeof(ADAPTER_INIT_STRUCT) + CommAreaSize + CommAreaAlignment +
++//             SizeOfFastIoComm + PrintfBufferSize;
++      TotalSize = AdapterFibsSize + sizeof(ADAPTER_INIT_STRUCT) + CommAreaSize + CommAreaAlignment +
++               PrintfBufferSize;
++
++
++      OsAllocCommPhysMem(CommonExtension->MiniPort, TotalSize, &BaseAddress, &PhysAddress);
++
++      CommonExtension->CommAddress  = BaseAddress;
++      CommonExtension->CommPhysAddr = PhysAddress;
++      CommonExtension->CommSize         = TotalSize;
++
++      PhysicalBaseAddress.HighPart = 0;
++      PhysicalBaseAddress.LowPart = PhysAddress;
++
++      CommonExtension->InitStruct = (PADAPTER_INIT_STRUCT)((PUCHAR)(BaseAddress) + AdapterFibsSize);
++      CommonExtension->PhysicalInitStruct = (PADAPTER_INIT_STRUCT)((PUCHAR)(PhysicalBaseAddress.LowPart) + AdapterFibsSize);
++
++      InitStruct = CommonExtension->InitStruct;
++
++      InitStruct->InitStructRevision = ADAPTER_INIT_STRUCT_REVISION;
++      InitStruct->MiniPortRevision = MiniPortRevision;
++      InitStruct->FilesystemRevision = CommonExtension->FilesystemRevision;
++
++      //
++      // Adapter Fibs are the first thing allocated so that they start page aligned
++      //
++      InitStruct->AdapterFibsVirtualAddress = BaseAddress;
++      InitStruct->AdapterFibsPhysicalAddress = (PVOID) PhysicalBaseAddress.LowPart;
++      InitStruct->AdapterFibsSize = AdapterFibsSize;
++      InitStruct->AdapterFibAlign = sizeof(FIB);
++
++      //
++      // Increment the base address by the amount already used
++      //
++      BaseAddress = (PVOID)((PUCHAR)(BaseAddress) + AdapterFibsSize + sizeof(ADAPTER_INIT_STRUCT));
++      PhysicalBaseAddress.LowPart = (ULONG)((PUCHAR)(PhysicalBaseAddress.LowPart) + AdapterFibsSize + sizeof(ADAPTER_INIT_STRUCT));
++
++      //
++      // Align the beginning of Headers to CommAreaAlignment
++      //
++      BytesToAlign = (CommAreaAlignment - ((ULONG)(BaseAddress) & (CommAreaAlignment - 1)));
++      BaseAddress = (PVOID)((PUCHAR)(BaseAddress) + BytesToAlign);
++      PhysicalBaseAddress.LowPart = (ULONG)((PUCHAR)(PhysicalBaseAddress.LowPart) + BytesToAlign);
++
++      //
++      // Fill in addresses of the Comm Area Headers and Queues
++      //
++      *CommHeaderAddress = BaseAddress;
++      InitStruct->CommHeaderAddress = (PVOID)PhysicalBaseAddress.LowPart;
++
++      //
++      //      Increment the base address by the size of the CommArea
++      //
++      BaseAddress = (PVOID)((PUCHAR)(BaseAddress) + CommAreaSize);
++      PhysicalBaseAddress.LowPart = (ULONG)((PUCHAR)(PhysicalBaseAddress.LowPart) + CommAreaSize);
++
++
++      //
++      // Place the Printf buffer area after the Fast I/O comm area.
++      //
++      CommonExtension->PrintfBufferAddress = (PVOID)(BaseAddress);
++      InitStruct->PrintfBufferAddress = (PVOID)PhysicalBaseAddress.LowPart;
++      InitStruct->PrintfBufferSize = PrintfBufferSize;
++      bzero (BaseAddress, PrintfBufferSize);
++
++      AfaPortPrint("FsaAllocateAdapterCommArea: allocated a common buffer of 0x%x bytes from address 0x%x to address 0x%x\n",
++                       TotalSize, InitStruct->AdapterFibsVirtualAddress,
++                       (PUCHAR)(InitStruct->AdapterFibsVirtualAddress) + TotalSize);
++
++      AfaPortPrint("Mapped on to PCI address 0x%x\n", InitStruct->AdapterFibsPhysicalAddress);
++
++      return (TRUE);
++}
++
++AAC_STATUS
++AfaPortCreate (
++    IN PDEVICE_OBJECT DeviceObject,
++    IN PIRP Irp
++    )
++/*++
++
++Routine Description:
++
++      The routine will get called each time a user issues a CreateFile on the DeviceObject
++      for the adapter.
++
++      The main purpose of this routine is to set up any data structures that may be needed
++      to handle any requests made on this DeviceObject.
++
++Arguments:
++
++      DeviceObject - Pointer to device object representing adapter
++
++      Irp - Pointer to Irp that caused this open
++
++
++Return Value:
++
++      Status value returned from File system driver AdapterOpen
++
++--*/
++
++{
++}
++
++AAC_STATUS
++AfaPortClose (
++    IN PDEVICE_OBJECT DeviceObject,
++    IN PIRP Irp
++    )
++/*++
++
++Routine Description:
++
++      This routine will get called each time a user issues a CloseHandle on the DeviceObject
++      for the adapter.
++
++      The main purpose of this routine is to cleanup any data structures that have been set up
++      while this FileObject has been opened.
++
++Arguments:
++
++      DeviceObject - Pointer to device object representing adapter
++
++      Irp - Pointer to Irp that caused this close
++
++Return Value:
++
++      Status value returned from File system driver AdapterClose
++
++--*/
++
++{
++
++}
++
++AAC_STATUS
++AfaPortDeviceControl (
++    IN PDEVICE_OBJECT DeviceObject,
++    IN PIRP Irp
++    )
++{
++
++}
++
++ULONG
++AfaPortGetMaxPhysicalPage(
++      IN PPCI_MINIPORT_COMMON_EXTENSION       CommonExtension
++      )
++/*++
++
++Routine Description:
++
++      This routine determines the max physical page in host memory.
++
++Arguments:
++
++      AdapterExtension
++
++Return Value:
++
++      Max physical page in host memory.
++
++--*/
++{
++
++}
++
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/rx.c linux/drivers/scsi/aacraid/rx.c
+--- linux-2.4.9/drivers/scsi/aacraid/rx.c      Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/rx.c    Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,917 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *  rx.c
++ *
++ * Abstract: Hardware miniport for Drawbridge specific hardware functions.
++ *
++ --*/
++
++static char *ident_rx = "aacraid_ident rx.c 1.0.7 2000/10/11 Adaptec, Inc.";
++
++#include "osheaders.h"
++
++
++#include "AacGenericTypes.h"
++
++#include "aac_unix_defs.h"
++
++#include "fsatypes.h"
++#include "comstruc.h"
++#include "fsact.h"
++#include "protocol.h"
++
++#define DEFINE_PCI_IDS
++#include "rxcommon.h"
++#include "monkerapi.h"
++
++#include "fsaport.h"
++#include "fsaioctl.h"
++
++#include "pcisup.h"
++#include "rx.h"
++
++#include "port.h"
++
++#define BugCheckFileId                   (FSAFS_BUG_CHECK_CYCLONESUP)
++
++// #define RxBugCheck(A,B,C) { KeBugCheckEx(0x00000AFA, __LINE__, (ULONG)A, (ULONG)B,(ULONG)C ); }
++
++#define RxBugCheck(A, B, C) { cmn_err(CE_PANIC, "aacdisk : line %s, 0x%x, 0x%x, 0x%x ", __LINE__, A, B, C);  }
++
++#define NUM_TICKS_PER_SECOND (1000 * 1000 * 10) /* time is in 100 nanoseconds */
++
++
++//
++// The list of all the Rx adapter structures
++//
++
++PRx_ADAPTER_EXTENSION RxAdapterList;
++
++int
++RxInitDevice(
++      IN PPCI_MINIPORT_COMMON_EXTENSION CommonExtension,
++      IN ULONG AdapterNumber,
++      IN ULONG PciBus,
++      IN ULONG PciSlot
++);
++
++BOOLEAN
++RxSendSynchFib(
++      PVOID Arg1,
++      ULONG FibPhysicalAddress
++      );
++
++FSA_USER_VAR  RxUserVars[] = {
++      { "AfaPortPrinting", (PULONG)&AfaPortPrinting, NULL },
++};
++
++
++//
++// Declare private use routines for this modual
++//
++
++u_int
++RxPciIsr (
++    IN PRx_ADAPTER_EXTENSION AdapterExtension
++    )
++
++/*++
++
++Routine Description:
++
++    The Isr routine for fsa Rx based adapter boards.
++
++Arguments:
++
++
++Return Value:
++
++      TRUE - if the interrupt was handled by this isr
++      FALSE - if the interrupt was not handled by this isr
++
++--*/
++
++{
++      ULONG   DoorbellBits;
++      UCHAR   InterruptStatus, Mask;
++      u_int OurInterrupt = INTR_UNCLAIMED;
++
++      //cmn_err(CE_WARN, "RxPciIsr entered\n");
++
++      InterruptStatus = Rx_READ_UCHAR(AdapterExtension, MUnit.OISR);
++
++      //
++      // Read mask and invert because drawbridge is reversed.
++      //
++      // This allows us to only service interrupts that have been enabled.
++      //
++
++      Mask = ~(Rx_READ_UCHAR(AdapterExtension, MUnit.OIMR));
++
++      // Check to see if this is our interrupt.  If it isn't just return FALSE.
++
++
++      if (InterruptStatus & Mask) {
++
++              DoorbellBits = Rx_READ_ULONG(AdapterExtension, OutboundDoorbellReg);
++
++              OurInterrupt = INTR_CLAIMED;
++
++              if (DoorbellBits & DoorBellPrintfReady) {
++
++                      ULONG Length, Level;
++                      unsigned char *cp;
++
++                      cp = AdapterExtension->Common->PrintfBufferAddress;
++
++                      //
++                      // The size of the Printfbuffer is set in port.c
++                      // There is no variable or define for it
++                      //
++                      if (Length > 255)
++                              Length = 255;
++
++                      if (cp[Length] != 0) {
++                              // cmn_err (CE_NOTE, "byte %d is 0x%x, should be 0", Length, cp[Length]);
++                              cp[Length] = 0;
++                      }
++
++                      if (Level == LOG_HIGH_ERROR)
++                              cmn_err (CE_WARN, "%s:%s", OsGetDeviceName(AdapterExtension), AdapterExtension->Common->PrintfBufferAddress);
++                      else
++                              cmn_err (CE_NOTE, "%s:%s", OsGetDeviceName(AdapterExtension), AdapterExtension->Common->PrintfBufferAddress);
++
++                      bzero (AdapterExtension->Common->PrintfBufferAddress, 256);
++
++                      Rx_WRITE_ULONG(AdapterExtension, MUnit.ODR,DoorBellPrintfReady); //clear PrintfReady
++
++                      Rx_WRITE_ULONG(AdapterExtension, InboundDoorbellReg,DoorBellPrintfDone);
++
++
++              } else if (DoorbellBits & DoorBellAdapterNormCmdReady) {        // Adapter -> Host Normal Command Ready
++
++                      AdapterExtension->Common->AdapterFuncs.InterruptHost(AdapterExtension->Common->Adapter, HostNormCmdQue);
++                      Rx_WRITE_ULONG(AdapterExtension, MUnit.ODR, DoorBellAdapterNormCmdReady);
++
++              } else if (DoorbellBits & DoorBellAdapterNormRespReady) {       // Adapter -> Host Normal Response Ready
++
++                      AdapterExtension->Common->AdapterFuncs.InterruptHost(AdapterExtension->Common->Adapter, HostNormRespQue);
++                      Rx_WRITE_ULONG(AdapterExtension, MUnit.ODR,DoorBellAdapterNormRespReady);
++
++              } else if (DoorbellBits & DoorBellAdapterNormCmdNotFull) {      // Adapter -> Host Normal Command Not Full
++
++                      AdapterExtension->Common->AdapterFuncs.InterruptHost(AdapterExtension->Common->Adapter, AdapNormCmdNotFull);
++                      Rx_WRITE_ULONG(AdapterExtension, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
++
++              } else if (DoorbellBits & DoorBellAdapterNormRespNotFull) {     // Adapter -> Host Normal Response Not Full
++
++                      AdapterExtension->Common->AdapterFuncs.InterruptHost(AdapterExtension->Common->Adapter, AdapNormRespNotFull);
++                      Rx_WRITE_ULONG(AdapterExtension, MUnit.ODR, DoorBellAdapterNormRespNotFull);
++
++              }
++
++      }
++      return(OurInterrupt);
++}
++
++VOID
++RxEnableInterrupt(
++      PVOID                                           Arg1,
++      ADAPTER_EVENT                           AdapterEvent,
++      BOOLEAN                                         AtDeviceIrq
++      )
++/*++
++
++Routine Description:
++
++      This routine will enable the corresponding adapter event to cause an interrupt on 
++      the host.
++
++Arguments:
++
++      AdapterExtension - Which adapter to enable.
++
++      AdapterEvent - Which adapter event.
++
++      AtDeviceIrq - Whether the system is in DEVICE irql
++
++Return Value:
++
++    Nothing.
++
++--*/
++{
++      PPCI_MINIPORT_COMMON_EXTENSION CommonExtension = (PPCI_MINIPORT_COMMON_EXTENSION) Arg1;
++      PRx_ADAPTER_EXTENSION AdapterExtension = (PRx_ADAPTER_EXTENSION) CommonExtension->MiniPort;
++
++      //cmn_err(CE_WARN, "RxEnableInterrupt");
++      switch (AdapterEvent) {
++
++        case HostNormCmdQue:
++
++              AdapterExtension->LocalMaskInterruptControl &= ~(OUTBOUNDDOORBELL_1);
++
++              break;
++
++        case HostNormRespQue:
++
++              AdapterExtension->LocalMaskInterruptControl &= ~(OUTBOUNDDOORBELL_2);
++
++              break;
++
++      case AdapNormCmdNotFull:
++
++              AdapterExtension->LocalMaskInterruptControl &= ~(OUTBOUNDDOORBELL_3);
++
++              break;
++
++      case AdapNormRespNotFull:
++
++              AdapterExtension->LocalMaskInterruptControl &= ~(OUTBOUNDDOORBELL_4);
++
++              break;
++
++      }
++
++}
++
++VOID
++RxDisableInterrupt(
++      PVOID                                           Arg1,
++      ADAPTER_EVENT                           AdapterEvent,
++      BOOLEAN                                         AtDeviceIrq
++      )
++/*++
++
++Routine Description:
++
++      This routine will disable the corresponding adapter event to cause an interrupt on 
++      the host.
++
++Arguments:
++
++      AdapterExtension - Which adapter to enable.
++
++      AdapterEvent - Which adapter event.
++
++      AtDeviceIrq - Whether the system is in DEVICE irql
++
++Return Value:
++
++    Nothing.
++
++--*/
++{
++      PPCI_MINIPORT_COMMON_EXTENSION CommonExtension = (PPCI_MINIPORT_COMMON_EXTENSION) Arg1;
++      PRx_ADAPTER_EXTENSION AdapterExtension = (PRx_ADAPTER_EXTENSION) CommonExtension->MiniPort;
++
++      //cmn_err(CE_WARN, "RxEnableInterrupt");
++
++      switch (AdapterEvent) {
++
++
++        case HostNormCmdQue:
++
++              AdapterExtension->LocalMaskInterruptControl |= (OUTBOUNDDOORBELL_1);
++
++              break;
++
++        case HostNormRespQue:
++
++              AdapterExtension->LocalMaskInterruptControl |= (OUTBOUNDDOORBELL_2);
++
++              break;
++
++      case AdapNormCmdNotFull:
++
++              AdapterExtension->LocalMaskInterruptControl |= (OUTBOUNDDOORBELL_3);
++
++              break;
++
++
++      case AdapNormRespNotFull:
++
++              AdapterExtension->LocalMaskInterruptControl |= (OUTBOUNDDOORBELL_4);
++
++              break;
++
++      }
++
++}
++
++
++
++RxDetachDevice(
++      IN PPCI_MINIPORT_COMMON_EXTENSION CommonExtension
++      )
++{
++      PRx_ADAPTER_EXTENSION AdapterExtension = CommonExtension->MiniPort;
++
++      //
++      // Free the register mapping.
++      //
++
++      OsDetachDevice( AdapterExtension);
++
++      OsFreeMemory( AdapterExtension, sizeof(Rx_ADAPTER_EXTENSION) );
++
++}
++
++int
++RxInitDevice(
++      IN PPCI_MINIPORT_COMMON_EXTENSION CommonExtension,
++      IN ULONG AdapterNumber,
++      IN ULONG PciBus,
++      IN ULONG PciSlot
++)
++
++/*++
++
++Routine Description:
++
++      Scans the PCI bus looking for the Rx card. When found all resources for the
++      device will be allocated and the interrupt vectors and csrs will be allocated and
++      mapped.
++
++      The device_interface in the commregion will be allocated and linked to the comm region.
++
++Arguments:
++
++
++Return Value:
++
++    TRUE - if the device was setup with not problems
++    FALSE - if the device could not be mapped and init successfully
++
++--*/
++
++{
++      AAC_STATUS Status;
++      PRx_ADAPTER_EXTENSION AdapterExtension = NULL;
++      FSA_NEW_ADAPTER NewAdapter;
++      ULONG StartTime, EndTime, WaitTime;
++      ULONG InitStatus;
++      int instance;
++      int nIntrs;
++      char * name;
++
++    AfaPortPrint("In init device.\n");
++
++      //cmn_err(CE_WARN, "In RxInitDevice");
++
++//    AdapterExtension->Common->AdapterIndex = AdapterIndex;
++      CommonExtension->AdapterNumber = AdapterNumber;
++
++
++      CommonExtension->PciBusNumber = PciBus;
++      CommonExtension->PciSlotNumber = PciSlot;
++
++
++      AdapterExtension = OsAllocMemory( sizeof(Rx_ADAPTER_EXTENSION), OS_ALLOC_MEM_SLEEP );
++      AdapterExtension->Common = CommonExtension;
++      CommonExtension->MiniPort = AdapterExtension;
++
++      instance = OsGetDeviceInstance(AdapterExtension);
++      name     = OsGetDeviceName(AdapterExtension);
++      //
++      // Map in the registers from the adapter, register space 0 is config space,
++      // register space 1 is the memery space.
++      //
++
++      if (OsMapDeviceRegisters(AdapterExtension)) {
++
++              cmn_err(CE_CONT, "%s%d: can't map device registers\n",
++                              OsGetDeviceName(AdapterExtension), instance);
++              return(FAILURE);
++      }
++
++      //
++      // Check to see if the board failed any self tests.
++      //
++
++      if (Rx_READ_ULONG( AdapterExtension, IndexRegs.Mailbox[7]) & SELF_TEST_FAILED) {
++
++              cmn_err(CE_CONT, "%s%d: adapter self-test failed\n",
++                              OsGetDeviceName(AdapterExtension), instance);
++              return(FAILURE);
++
++      }
++      //cmn_err(CE_WARN, "RxInitDevice: %s%d: adapter passwd self-test\n",
++      //                      OsGetDeviceName(AdapterExtension), instance);
++
++      //
++      // Check to see if the board panic'd while booting.
++      //
++
++      if (Rx_READ_ULONG( AdapterExtension, IndexRegs.Mailbox[7]) & KERNEL_PANIC) {
++
++              cmn_err(CE_CONT, "%s%d: adapter kernel panic'd\n",
++                              OsGetDeviceName(AdapterExtension), instance);
++              return(FAILURE);
++
++      }
++
++      StartTime = OsGetSeconds();
++      WaitTime = 0;
++
++
++      //
++      //  Wait for the adapter to be up and running. Wait up until 3 minutes.
++      //
++
++      while (!(Rx_READ_ULONG( AdapterExtension, IndexRegs.Mailbox[7]) & KERNEL_UP_AND_RUNNING)) {
++      
++              EndTime = OsGetSeconds();
++
++              WaitTime = EndTime - StartTime;
++
++              if ( WaitTime > (3 * 10) ) {
++
++                      InitStatus = Rx_READ_ULONG( AdapterExtension, IndexRegs.Mailbox[7]) >> 16;
++
++                      cmn_err(CE_CONT, "%s%d: adapter kernel failed to start, init status = %d\n",
++                                      OsGetDeviceName(AdapterExtension), instance, InitStatus);
++                      return(FAILURE);
++
++              }
++      }
++
++      if (OsAttachInterrupt(AdapterExtension,RxISR)) {
++              cmn_err(CE_WARN, "%s%d RxInitDevice: failed OsAttachIntterupt", name, instance);
++              return(FAILURE);
++      }
++
++
++      if (OsAttachDMA(AdapterExtension)) {
++              cmn_err(CE_WARN, "%s%d SaInitDevice: failed OsAttachDMA", name, instance);
++              return(FAILURE);
++      }
++
++      //
++      // Fill in the function dispatch table.
++      //
++
++      AdapterExtension->Common->AdapterFuncs.SizeOfFsaPortFuncs = sizeof(FSAPORT_FUNCS);
++      AdapterExtension->Common->AdapterFuncs.AllocateAdapterCommArea = AfaPortAllocateAdapterCommArea;
++      AdapterExtension->Common->AdapterFuncs.FreeAdapterCommArea = AfaPortFreeAdapterCommArea;
++      AdapterExtension->Common->AdapterFuncs.BuildSgMap = AfaPortBuildSgMap;
++      AdapterExtension->Common->AdapterFuncs.FreeDmaResources = AfaPortFreeDmaResources;
++      AdapterExtension->Common->AdapterFuncs.AllocateAndMapFibSpace = AfaPortAllocateAndMapFibSpace;
++      AdapterExtension->Common->AdapterFuncs.UnmapAndFreeFibSpace = AfaPortUnmapAndFreeFibSpace;
++      AdapterExtension->Common->AdapterFuncs.InterruptAdapter = RxInterruptAdapter;
++      AdapterExtension->Common->AdapterFuncs.EnableInterrupt = RxEnableInterrupt;
++      AdapterExtension->Common->AdapterFuncs.DisableInterrupt = RxDisableInterrupt;
++      AdapterExtension->Common->AdapterFuncs.NotifyAdapter = RxNotifyAdapter;
++      AdapterExtension->Common->AdapterFuncs.ResetDevice = RxResetDevice;
++      AdapterExtension->Common->AdapterFuncs.InterruptHost = NULL;
++
++      AdapterExtension->Common->AdapterFuncs.SendSynchFib = RxSendSynchFib;
++
++      NewAdapter.AdapterExtension = CommonExtension;
++      NewAdapter.AdapterFuncs = &AdapterExtension->Common->AdapterFuncs;
++      NewAdapter.AdapterInterruptsBelowDpc = FALSE;
++      NewAdapter.AdapterUserVars = RxUserVars;
++      NewAdapter.AdapterUserVarsSize = sizeof(RxUserVars) / sizeof(FSA_USER_VAR);
++
++      NewAdapter.Dip = CommonExtension->OsDep.dip;
++
++      
++      if (AfaCommInitNewAdapter( &NewAdapter ) == NULL) {
++              
++              cmn_err(CE_WARN, "AfaCommInitNewAdapter failed\n");
++              return (FAILURE);
++      }
++
++
++      AdapterExtension->Common->Adapter = NewAdapter.Adapter;
++
++      if (AdapterExtension->Common->Adapter == NULL) {
++
++              AfaPortLogError(AdapterExtension->Common, FAILURE, NULL, 0);
++              cmn_err(CE_WARN, "%s%d RxInitDevice: No Adapter pointer", name, instance);
++
++
++              return (FAILURE);
++      }
++
++
++      //
++      // Start any kernel threads needed
++      //
++      OsStartKernelThreads(AdapterExtension);
++
++      //
++      // Tell the adapter that all is configure, and it can start accepting requests
++      //
++
++      RxStartAdapter(AdapterExtension);
++
++
++#ifdef AACDISK
++#endif
++
++
++      //
++      // Put this adapter into the list of Rx adapters
++      //
++
++      AdapterExtension->Next = RxAdapterList;
++      RxAdapterList = AdapterExtension;
++
++      AdapterExtension->Common->AdapterConfigured = TRUE;
++
++
++#ifdef AACDISK
++      //
++      // Call the disk layer to initialize itself.
++      //
++
++      AfaDiskInitNewAdapter( AdapterExtension->Common->AdapterNumber, AdapterExtension->Common->Adapter );
++#endif
++
++
++init_done:
++
++      AdapterExtension->Common->AdapterPrintfsToScreen = FALSE;
++
++
++
++      OsAttachHBA(AdapterExtension);
++
++    return(0);
++}
++
++VOID
++RxStartAdapter(
++      PRx_ADAPTER_EXTENSION AdapterExtension
++      )
++{
++      ULONG ReturnStatus;
++      LARGE_INTEGER HostTime;
++      ULONG ElapsedSeconds;
++      PADAPTER_INIT_STRUCT InitStruct;
++
++      //cmn_err(CE_WARN, "RxStartAdapter");
++      //
++      // Fill in the remaining pieces of the InitStruct.
++      //
++
++      InitStruct = AdapterExtension->Common->InitStruct;
++
++      InitStruct->HostPhysMemPages = AfaPortGetMaxPhysicalPage(AdapterExtension->Common);
++
++      ElapsedSeconds = OsGetSeconds();
++
++      InitStruct->HostElapsedSeconds = ElapsedSeconds;
++
++      //
++      // Tell the adapter we are back and up and running so it will scan its command
++      // queues and enable our interrupts
++      //
++
++      AdapterExtension->LocalMaskInterruptControl =
++              (DoorBellPrintfReady | OUTBOUNDDOORBELL_1 | OUTBOUNDDOORBELL_2 | OUTBOUNDDOORBELL_3 | OUTBOUNDDOORBELL_4);
++
++      //
++      // First clear out all interrupts.  Then enable the one's that we can handle.
++      //
++
++      Rx_WRITE_UCHAR( AdapterExtension, MUnit.OIMR, 0xff);
++      Rx_WRITE_ULONG( AdapterExtension, MUnit.ODR, 0xffffffff);
++//    Rx_WRITE_UCHAR(AdapterExtension, MUnit.OIMR, ~(UCHAR)OUTBOUND_DOORBELL_INTERRUPT_MASK);
++      Rx_WRITE_UCHAR( AdapterExtension, MUnit.OIMR, 0xfb);
++
++      RxSendSynchCommand(AdapterExtension, 
++                                       INIT_STRUCT_BASE_ADDRESS, 
++                                       (ULONG) AdapterExtension->Common->PhysicalInitStruct,
++                                       0,
++                                       0,
++                                       0,
++                                       &ReturnStatus);
++
++}
++
++
++VOID
++RxResetDevice(
++      PVOID Arg1
++    )
++
++{
++}
++
++VOID
++RxInterruptAdapter(
++      PVOID Arg1
++      )
++/*++
++
++Routine Description:
++
++      The will cause the adapter to take a break point.
++
++Arguments:
++
++      None
++
++Return Value:
++
++    Nothing
++
++--*/
++{
++      PPCI_MINIPORT_COMMON_EXTENSION CommonExtension = (PPCI_MINIPORT_COMMON_EXTENSION) Arg1;
++      PRx_ADAPTER_EXTENSION AdapterExtension = (PRx_ADAPTER_EXTENSION) CommonExtension->MiniPort;
++
++      ULONG ReturnStatus;
++
++      RxSendSynchCommand(AdapterExtension, 
++                                         BREAKPOINT_REQUEST,
++                                         0,
++                                         0,
++                                         0,
++                                         0,
++                                         &ReturnStatus);
++
++}
++
++VOID
++RxNotifyAdapter(
++      PVOID Arg1,
++    IN HOST_2_ADAP_EVENT AdapterEvent
++    )
++/*++
++
++Routine Description:
++
++    Will read the adapter CSRs to find the reason the adapter has
++    interrupted us.
++
++Arguments:
++
++    AdapterEvent - Enumerated type the returns the reason why we were interrutped.
++
++Return Value:
++
++    Nothing
++
++--*/
++{
++      PPCI_MINIPORT_COMMON_EXTENSION CommonExtension = (PPCI_MINIPORT_COMMON_EXTENSION) Arg1;
++      PRx_ADAPTER_EXTENSION AdapterExtension = (PRx_ADAPTER_EXTENSION) CommonExtension->MiniPort;
++      ULONG ReturnStatus;
++
++      //cmn_err(CE_WARN, "RxNotifyAdapter %d", AdapterEvent);
++
++    switch (AdapterEvent) {
++        case AdapNormCmdQue:
++
++                      Rx_WRITE_ULONG(AdapterExtension, MUnit.IDR,INBOUNDDOORBELL_1);
++            break;
++
++        case HostNormRespNotFull:
++
++                      Rx_WRITE_ULONG(AdapterExtension, MUnit.IDR,INBOUNDDOORBELL_4);
++            break;
++
++        case AdapNormRespQue:
++
++                      Rx_WRITE_ULONG(AdapterExtension, MUnit.IDR,INBOUNDDOORBELL_2);
++            break;
++
++        case HostNormCmdNotFull:
++
++                      Rx_WRITE_ULONG(AdapterExtension, MUnit.IDR,INBOUNDDOORBELL_3);
++            break;
++
++        case HostShutdown:
++
++//                    RxSendSynchCommand(AdapterExtension, HOST_CRASHING, 0, 0, 0, 0, &ReturnStatus);
++
++            break;
++
++              case FastIo:
++                      Rx_WRITE_ULONG(AdapterExtension, MUnit.IDR,INBOUNDDOORBELL_6);
++                      break;
++
++              case AdapPrintfDone:
++                      Rx_WRITE_ULONG(AdapterExtension, MUnit.IDR,INBOUNDDOORBELL_5);
++                      break;
++
++        default:
++
++                      RxBugCheck(0,0,0);
++            AfaPortPrint("Notify requested with an invalid request 0x%x.\n",AdapterEvent);
++            break;
++    }
++}
++
++AAC_STATUS
++RxSendSynchCommand(
++      PVOID Arg1,
++      ULONG Command,
++      ULONG Parameter1,
++      ULONG Parameter2,
++      ULONG Parameter3,
++      ULONG Parameter4,
++      PULONG  ReturnStatus
++      )
++/*++
++
++Routine Description:
++
++      This routine will send a synchronous comamnd to the adapter and wait for its
++      completion.
++
++Arguments:
++
++      AdapterExtension - Pointer to adapter extension structure.
++      Command - Which command to send
++      Parameter1 - 4  - Parameters for command
++      ReturnStatus - return status from adapter after completion of command
++
++
++Return Value:
++
++      AAC_STATUS
++
++--*/
++{
++      PRx_ADAPTER_EXTENSION AdapterExtension = (PRx_ADAPTER_EXTENSION) Arg1;
++      ULONG StartTime,EndTime,WaitTime;
++      BOOLEAN CommandSucceeded;
++
++      //cmn_err(CE_WARN, "RxSendSyncCommand");
++      //
++      // Write the Command into Mailbox 0
++      //
++
++      Rx_WRITE_ULONG( AdapterExtension, InboundMailbox0, Command);
++
++      //
++      // Write the parameters into Mailboxes 1 - 4
++      //
++
++      Rx_WRITE_ULONG( AdapterExtension, InboundMailbox1, Parameter1);
++      Rx_WRITE_ULONG( AdapterExtension, InboundMailbox2, Parameter2);
++      Rx_WRITE_ULONG( AdapterExtension, InboundMailbox3, Parameter3);
++      Rx_WRITE_ULONG( AdapterExtension, InboundMailbox4, Parameter4);
++
++      //
++      // Clear the synch command doorbell to start on a clean slate.
++      //
++              
++      Rx_WRITE_ULONG( AdapterExtension, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
++
++      //
++      // disable doorbell interrupts
++      //
++
++      Rx_WRITE_UCHAR( AdapterExtension, MUnit.OIMR, 
++                                      Rx_READ_UCHAR(AdapterExtension, MUnit.OIMR) | 0x04);
++
++      //
++      // force the completion of the mask register write before issuing the interrupt.
++      //
++
++      Rx_READ_UCHAR ( AdapterExtension, MUnit.OIMR);
++
++      //
++      // Signal that there is a new synch command
++      //
++
++      Rx_WRITE_ULONG( AdapterExtension, InboundDoorbellReg, INBOUNDDOORBELL_0);
++
++      CommandSucceeded = FALSE;
++
++      StartTime = OsGetSeconds();
++      WaitTime = 0;
++
++      while (WaitTime < 30) { // wait up to 30 seconds
++
++              drv_usecwait(5);                                // delay 5 microseconds to let Mon960 get info.
++
++              //
++              // Mon110 will set doorbell0 bit when it has completed the command.
++              //
++
++              if (Rx_READ_ULONG(AdapterExtension, OutboundDoorbellReg) & OUTBOUNDDOORBELL_0) {
++
++                      //
++                      // clear the doorbell.
++                      //
++
++                      Rx_WRITE_ULONG(AdapterExtension, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
++
++                      CommandSucceeded = TRUE;
++                      break;
++              }
++
++              EndTime = OsGetSeconds();
++              WaitTime = EndTime - StartTime;
++
++      }
++
++      if (CommandSucceeded != TRUE) {
++
++              //
++              // restore interrupt mask even though we timed out
++              //
++
++              Rx_WRITE_UCHAR(AdapterExtension, MUnit.OIMR, 
++                                         Rx_READ_ULONG(AdapterExtension, MUnit.OIMR) & 0xfb);
++
++              return (STATUS_IO_TIMEOUT);
++
++      }
++
++      //
++      // Pull the synch status from Mailbox 0.
++      //
++
++      *ReturnStatus = Rx_READ_ULONG(AdapterExtension, IndexRegs.Mailbox[0]);
++
++      //
++      // Clear the synch command doorbell.
++      //
++              
++      Rx_WRITE_ULONG(AdapterExtension, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
++
++      //
++      // restore interrupt mask
++      //
++
++      Rx_WRITE_UCHAR(AdapterExtension, MUnit.OIMR, 
++                                 Rx_READ_ULONG(AdapterExtension, MUnit.OIMR) & 0xfb);
++
++      //
++      // Return SUCCESS
++      //
++
++      return (STATUS_SUCCESS);
++
++}
++
++BOOLEAN
++RxSendSynchFib(
++      PVOID Arg1,
++      ULONG FibPhysicalAddress
++      )
++/*++
++
++Routine Description:
++
++      This routine will send a synchronous fib to the adapter and wait for its
++      completion.
++
++Arguments:
++
++      AdapterExtension - Pointer to adapter extension structure.
++      FibPhysicalAddress - Physical address of fib to send.
++
++
++Return Value:
++
++      BOOLEAN
++
++--*/
++{
++      PPCI_MINIPORT_COMMON_EXTENSION CommonExtension = (PPCI_MINIPORT_COMMON_EXTENSION) Arg1;
++      PRx_ADAPTER_EXTENSION AdapterExtension = (PRx_ADAPTER_EXTENSION) CommonExtension->MiniPort;
++      ULONG returnStatus;
++
++      if (RxSendSynchCommand( AdapterExtension,
++                                                  SEND_SYNCHRONOUS_FIB,
++                                                  FibPhysicalAddress,
++                                                  0,
++                                                  0,
++                                                  0,
++                                                  &returnStatus ) != STATUS_SUCCESS ) {
++
++              return (FALSE);
++              
++      }
++      
++      return (TRUE);
++                                                                              
++}
++
++
+diff -burN linux-2.4.9/drivers/scsi/aacraid/sap1sup.c linux/drivers/scsi/aacraid/sap1sup.c
+--- linux-2.4.9/drivers/scsi/aacraid/sap1sup.c Wed Dec 31 18:00:00 1969
++++ linux/drivers/scsi/aacraid/sap1sup.c       Thu Aug 16 13:41:30 2001
+@@ -0,0 +1,859 @@
++/*++
++ * Adaptec aacraid device driver for Linux.
++ *
++ * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, or (at your option)
++ * any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; see the file COPYING.  If not, write to
++ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Module Name:
++ *  sap1sup.c
++ *
++ * Abstract: Drawbridge specific support functions
++ *
++ --*/
++
++static char *ident_sap1 = "aacraid_ident sap1sup.c 1.0.7 2000/10/11 Adaptec, Inc.";
++
++#include "osheaders.h"
++
++
++#include "AacGenericTypes.h"
++
++#include "aac_unix_defs.h"
++
++#include "fsatypes.h"
++#include "comstruc.h"
++#include "fsact.h"
++#include "protocol.h"
++
++#define DEFINE_PCI_IDS
++#include "sap1common.h"
++#include "monkerapi.h"
++
++#include "fsaport.h"
++#include "fsaioctl.h"
++
++
++#include "pcisup.h"
++#include "sap1.h"
++
++#include "port.h"
++
++#include "nodetype.h"
++#include "comsup.h"
++#include "afacomm.h"
++#include "adapter.h"
++
++#define BugCheckFileId                   (FSAFS_BUG_CHECK_CYCLONESUP)
++
++// #define SaBugCheck(A,B,C) { KeBugCheckEx(0x00000AFA, __LINE__, (ULONG)A, (ULONG)B,(ULONG)C ); }
++
++#define SaBugCheck(A, B, C) { cmn_err(CE_PANIC, "aacdisk : line %s, 0x%x, 0x%x, 0x%x ", __LINE__, A, B, C);  }
++
++#define NUM_TICKS_PER_SECOND (1000 * 1000 * 10) /* time is in 100 nanoseconds */
++
++int MiniPortRevision = Sa_MINIPORT_REVISION;
++
++
++//
++// The list of all the Sa adapter structures
++//
++
++PSa_ADAPTER_EXTENSION SaAdapterList;
++
++int
++SaInitDevice(
++      IN PPCI_MINIPORT_COMMON_EXTENSION CommonExtension,
++      IN ULONG AdapterNumber,
++      IN ULONG PciBus,
++      IN ULONG PciSlot
++);
++
++BOOLEAN
++SaSendSynchFib(
++      PVOID Arg1,
++      ULONG FibPhysicalAddress
++      );
++
++FSA_USER_VAR  SaUserVars[] = {
++      { "AfaPortPrinting", (PULONG)&AfaPortPrinting, NULL },
++};
++
++
++//
++// Declare private use routines for this modual
++//
++
++
++/*++
++
++Routine Description:
++
++    The Isr routine for fsa Sa based adapter boards.
++
++Arguments:
++
++
++Return Value:
++
++      TRUE - if the interrupt was handled by this isr
++      FALSE - if the interrupt was not handled by this isr
++
++--*/
++u_int
++SaPciIsr (IN PSa_ADAPTER_EXTENSION AdapterExtension)
++{
++              USHORT InterruptStatus, Mask;
++              u_int OurInterrupt = INTR_UNCLAIMED;
++
++      InterruptStatus = Sa_READ_USHORT( AdapterExtension, DoorbellReg_p);
++
++      //
++      // Read mask and invert because drawbridge is reversed.
++      //
++      // This allows us to only service interrupts that have been enabled.
++      //
++
++      Mask = ~(Sa_READ_USHORT( AdapterExtension, SaDbCSR.PRISETIRQMASK));
++
++      // Check to see if this is our interrupt.  If it isn't just return FALSE.
++
++
++      if (InterruptStatus & Mask) {
++
++              OurInterrupt = INTR_CLAIMED;
++
++              if (InterruptStatus & PrintfReady) {
++
++                      ULONG Length, Level;
++                      unsigned char *cp;
++
++                      cp = AdapterExtension->Common->PrintfBufferAddress;
++
++                      //
++                      // The size of the Printbuffer is set in port.c
++                      // There is no variable or define for it
++                      //
++                      if (Length > 255)
++                              Length = 255;
++
++                      if (cp[Length] != 0) {
++                              // cmn_err (CE_NOTE, "byte %d is 0x%x, should be 0", Length, cp[Length]);
++                              cp[Length] = 0;
++                      }
++
++                      if (Level == LOG_HIGH_ERROR)
++                              cmn_err (CE_WARN, "%s:%s", OsGetDeviceName(AdapterExtension), AdapterExtension->Common->PrintfBufferAddress);
++                      else
++                              cmn_err (CE_NOTE, "%s:%s", OsGetDeviceName(AdapterExtension), AdapterExtension->Common->PrintfBufferAddress);
++
++                      bzero (AdapterExtension->Common->PrintfBufferAddress, 256);
++
++                      Sa_WRITE_USHORT( AdapterExtension, DoorbellClrReg_p,PrintfReady); //clear PrintfReady
++
++                      Sa_WRITE_USHORT( AdapterExtension, DoorbellReg_s,PrintfDone);
++
++              } else if (InterruptStatus & DOORBELL_1) {      // Adapter -> Host Normal Command Ready
++
++                      AdapterExtension->Common->AdapterFuncs.InterruptHost(AdapterExtension->Common->Adapter, HostNormCmdQue);
++                      Sa_WRITE_USHORT( AdapterExtension, DoorbellClrReg_p, DOORBELL_1);
++
++              } else if (InterruptStatus & DOORBELL_2) {      // Adapter -> Host Normal Response Ready
++
++                              AdapterExtension->Common->AdapterFuncs.InterruptHost(AdapterExtension->Common->Adapter, HostNormRespQue);
++                              Sa_WRITE_USHORT( AdapterExtension, DoorbellClrReg_p,DOORBELL_2);
++
++              } else if (InterruptStatus & DOORBELL_3) {      // Adapter -> Host Normal Command Not Full
++
++                      AdapterExtension->Common->AdapterFuncs.InterruptHost(AdapterExtension->Common->Adapter, AdapNormCmdNotFull);
++                      Sa_WRITE_USHORT( AdapterExtension, DoorbellClrReg_p, DOORBELL_3);
++
++              } else if (InterruptStatus & DOORBELL_4) {      // Adapter -> Host Normal Response Not Full
++
++                      AdapterExtension->Common->AdapterFuncs.InterruptHost(AdapterExtension->Common->Adapter, AdapNormRespNotFull);
++                      Sa_WRITE_USHORT( AdapterExtension, DoorbellClrReg_p, DOORBELL_4);
++
++              }
++
++      }
++      return(OurInterrupt);
++}
++
++
++/*++
++
++Routine Description:
++
++      This routine will enable the corresponding adapter event to cause an interrupt on 
++      the host.
++
++Arguments:
++
++      AdapterExtension - Which adapter to enable.
++
++      AdapterEvent - Which adapter event.
++
++      AtDeviceIrq - Whether the system is in DEVICE irql
++
++Return Value:
++
++    Nothing.
++
++--*/
++VOID
++SaEnableInterrupt (PVOID Arg1, ADAPTER_EVENT AdapterEvent, BOOLEAN AtDeviceIrq)
++{
++      PPCI_MINIPORT_COMMON_EXTENSION CommonExtension = (PPCI_MINIPORT_COMMON_EXTENSION) Arg1;
++      PSa_ADAPTER_EXTENSION AdapterExtension = (PSa_ADAPTER_EXTENSION) CommonExtension->MiniPort;
++
++      switch (AdapterEvent) {
++
++        case HostNormCmdQue:
++
++              Sa_WRITE_USHORT( AdapterExtension,  SaDbCSR.PRICLEARIRQMASK, DOORBELL_1 );
++
++              break;
++
++        case HostNormRespQue:
++
++              Sa_WRITE_USHORT( AdapterExtension,  SaDbCSR.PRICLEARIRQMASK, DOORBELL_2 );
++
++              break;
++
++      case AdapNormCmdNotFull:
++
++              Sa_WRITE_USHORT( AdapterExtension,  SaDbCSR.PRICLEARIRQMASK, DOORBELL_3 );
++
++              break;
++
++      case AdapNormRespNotFull:
++
++              Sa_WRITE_USHORT( AdapterExtension,  SaDbCSR.PRICLEARIRQMASK, DOORBELL_4 );
++
++              break;
++
++      }
++
++}
++
++
++
++/*++
++
++Routine Description:
++
++      This routine will disable the corresponding adapter event to cause an interrupt on 
++      the host.
++
++Arguments:
++
++      AdapterExtension - Which adapter to enable.
++
++      AdapterEvent - Which adapter event.
++
++      AtDeviceIrq - Whether the system is in DEVICE irql
++
++Return Value:
++
++    Nothing.
++
++--*/
++VOID
++SaDisableInterrupt (PVOID Arg1,       ADAPTER_EVENT AdapterEvent, BOOLEAN AtDeviceIrq)
++{
++      PPCI_MINIPORT_COMMON_EXTENSION CommonExtension = (PPCI_MINIPORT_COMMON_EXTENSION) Arg1;
++      PSa_ADAPTER_EXTENSION AdapterExtension = (PSa_ADAPTER_EXTENSION) CommonExtension->MiniPort;
++
++      switch (AdapterEvent) {
++
++
++        case HostNormCmdQue:
++
++              Sa_WRITE_USHORT( AdapterExtension,  SaDbCSR.PRISETIRQMASK, DOORBELL_1 );
++
++              break;
++
++        case HostNormRespQue:
++
++              Sa_WRITE_USHORT( AdapterExtension,  SaDbCSR.PRISETIRQMASK, DOORBELL_2 );
++
++              break;
++
++      case AdapNormCmdNotFull:
++
++              Sa_WRITE_USHORT( AdapterExtension,  SaDbCSR.PRISETIRQMASK, DOORBELL_3 );
++
++              break;
++
++
++      case AdapNormRespNotFull:
++
++              Sa_WRITE_USHORT( AdapterExtension,  SaDbCSR.PRISETIRQMASK, DOORBELL_4 );
++
++              break;
++
++      }
++
++}
++
++
++SaDetachDevice (IN PPCI_MINIPORT_COMMON_EXTENSION CommonExtension)
++{
++      PSa_ADAPTER_EXTENSION AdapterExtension = CommonExtension->MiniPort;
++
++      //
++      // Free the register mapping.
++      //
++
++      OsDetachDevice(AdapterExtension);
++
++      OsFreeMemory( AdapterExtension, sizeof(Sa_ADAPTER_EXTENSION) );
++
++}
++
++
++/*++
++
++Routine Description:
++
++      Scans the PCI bus looking for the Sa card. When found all resources for the
++      device will be allocated and the interrupt vectors and csrs will be allocated and
++      mapped.
++
++      The device_interface in the commregion will be allocated and linked to the comm region.
++
++Arguments:
++
++
++Return Value:
++
++    TRUE - if the device was setup with not problems
++    FALSE - if the device could not be mapped and init successfully
++
++--*/
++int
++SaInitDevice (IN PPCI_MINIPORT_COMMON_EXTENSION CommonExtension,
++                        IN ULONG AdapterNumber, IN ULONG PciBus,
++                        IN ULONG PciSlot)
++{
++      AAC_STATUS Status;
++      PSa_ADAPTER_EXTENSION AdapterExtension = NULL;
++      FSA_NEW_ADAPTER NewAdapter;
++      ULONG StartTime, EndTime, WaitTime;
++      ULONG InitStatus;
++      int instance;
++      char *name;
++
++    AfaPortPrint("In init device.\n");
++
++      CommonExtension->AdapterNumber = AdapterNumber;
++
++      CommonExtension->PciBusNumber = PciBus;
++      CommonExtension->PciSlotNumber = PciSlot;
++
++      AdapterExtension = OsAllocMemory( sizeof(Sa_ADAPTER_EXTENSION), OS_ALLOC_MEM_SLEEP );
++      AdapterExtension->Common = CommonExtension;
++      CommonExtension->MiniPort = AdapterExtension;
++
++      instance = OsGetDeviceInstance(AdapterExtension);
++      name     = OsGetDeviceName(AdapterExtension);
++
++      //
++      // Map in the registers from the adapter, register space 0 is config space,
++      // register space 1 is the memery space.
++      //
++
++      if (OsMapDeviceRegisters(AdapterExtension)){
++              cmn_err(CE_WARN, "%s%d SaInitDevice: failed OsMapDeviceRegisters", name, instance);
++              return(FAILURE);
++      }
++
++
++      //
++      // Check to see if the board failed any self tests.
++      //
++
++      if (Sa_READ_ULONG( AdapterExtension, Mailbox7) & SELF_TEST_FAILED) {
++
++              cmn_err(CE_WARN, "%s%d: adapter self-test failed\n",
++                              name, instance);
++              return(FAILURE);
++      }
++
++      //
++      // Check to see if the board panic'd while booting.
++      //
++
++      if (Sa_READ_ULONG( AdapterExtension, Mailbox7) & KERNEL_PANIC) {
++
++              cmn_err(CE_WARN, "%s%d: adapter kernel panic'd\n",
++                              name, instance);
++              return(FAILURE);
++      }
++
++
++      StartTime = OsGetSeconds();
++      WaitTime = 0;
++
++
++      //
++      //  Wait for the adapter to be up and running. Wait up until 3 minutes.
++      //
++
++      while (!(Sa_READ_ULONG( AdapterExtension, Mailbox7) & KERNEL_UP_AND_RUNNING)) {
++      
++              EndTime = OsGetSeconds();
++
++              WaitTime = EndTime - StartTime;
++
++              if ( WaitTime > (3 * 60) ) {
++
++                      InitStatus = Sa_READ_ULONG( AdapterExtension, Mailbox7) >> 16;
++
++                      cmn_err(CE_WARN, "%s%d: adapter kernel failed to start, init status = %d\n",
++                                      name, instance, InitStatus);
++                      return(FAILURE);
++
++              }
++      }
++
++      if (OsAttachInterrupt(AdapterExtension, SaISR)) {
++              cmn_err(CE_WARN, "%s%d SaInitDevice: failed OsAttachIntterupt", name, instance);
++              return(FAILURE);
++      }
++
++      if (OsAttachDMA(AdapterExtension)) {
++              cmn_err(CE_WARN, "%s%d SaInitDevice: failed OsAttachDMA", name, instance);
++              return(FAILURE);
++      }
++
++
++      //
++      // Fill in the function dispatch table.
++      //
++
++      AdapterExtension->Common->AdapterFuncs.SizeOfFsaPortFuncs = sizeof(FSAPORT_FUNCS);
++      AdapterExtension->Common->AdapterFuncs.AllocateAdapterCommArea = AfaPortAllocateAdapterCommArea;
++      AdapterExtension->Common->AdapterFuncs.FreeAdapterCommArea = AfaPortFreeAdapterCommArea;
++      AdapterExtension->Common->AdapterFuncs.BuildSgMap = AfaPortBuildSgMap;
++      AdapterExtension->Common->AdapterFuncs.FreeDmaResources = AfaPortFreeDmaResources;
++      AdapterExtension->Common->AdapterFuncs.AllocateAndMapFibSpace = AfaPortAllocateAndMapFibSpace;
++      AdapterExtension->Common->AdapterFuncs.UnmapAndFreeFibSpace = AfaPortUnmapAndFreeFibSpace;
++      AdapterExtension->Common->AdapterFuncs.InterruptAdapter = SaInterruptAdapter;
++      AdapterExtension->Common->AdapterFuncs.EnableInterrupt = SaEnableInterrupt;
++      AdapterExtension->Common->AdapterFuncs.DisableInterrupt = SaDisableInterrupt;
++      AdapterExtension->Common->AdapterFuncs.NotifyAdapter = SaNotifyAdapter;
++      AdapterExtension->Common->AdapterFuncs.ResetDevice = SaResetDevice;
++      AdapterExtension->Common->AdapterFuncs.InterruptHost = NULL;
++
++      AdapterExtension->Common->AdapterFuncs.SendSynchFib = SaSendSynchFib;
++
++      NewAdapter.AdapterExtension = CommonExtension;
++      NewAdapter.AdapterFuncs = &AdapterExtension->Common->AdapterFuncs;
++      NewAdapter.AdapterInterruptsBelowDpc = FALSE;
++      NewAdapter.AdapterUserVars = SaUserVars;
++      NewAdapter.AdapterUserVarsSize = sizeof(SaUserVars) / sizeof(FSA_USER_VAR);
++
++      NewAdapter.Dip = CommonExtension->OsDep.dip;
++
++      
++      if ( AfaCommInitNewAdapter( &NewAdapter ) == NULL) {
++                      cmn_err(CE_WARN, "SaInitDevice: AfaCommInitNewAdapter failed\n");
++                      return (FAILURE);
++      };
++
++
++      AdapterExtension->Common->Adapter = NewAdapter.Adapter;
++
++      if (AdapterExtension->Common->Adapter == NULL) {
++
++              AfaPortLogError(AdapterExtension->Common, FAILURE, NULL, 0);
++              cmn_err(CE_WARN, "%s%d SaInitDevice: No Adapter pointer", name, instance);
++
++              return (FAILURE); 
++      }
++
++
++    //
++      // Start any kernel threads needed
++      OsStartKernelThreads(AdapterExtension);
++
++      //
++      // Tell the adapter that all is configure, and it can start accepting requests
++      //
++
++      SaStartAdapter(AdapterExtension);
++
++
++
++      //
++      // Put this adapter into the list of Sa adapters
++      //
++
++      AdapterExtension->Next = SaAdapterList;
++      SaAdapterList = AdapterExtension;
++
++      AdapterExtension->Common->AdapterConfigured = TRUE;
++
++
++#ifdef AACDISK
++      //
++      // Call the disk layer to initialize itself.
++      //
++
++      AfaDiskInitNewAdapter( AdapterExtension->Common->AdapterNumber, AdapterExtension->Common->Adapter );
++#endif
++
++
++init_done:
++
++      AdapterExtension->Common->AdapterPrintfsToScreen = FALSE;
++
++      OsAttachHBA(AdapterExtension);
++
++      return (0);
++
++init_error:
++
++      return (FAILURE);
++}
++
++
++
++VOID
++SaStartAdapter (PSa_ADAPTER_EXTENSION AdapterExtension)
++{
++      ULONG ReturnStatus;
++      LARGE_INTEGER HostTime;
++      ULONG ElapsedSeconds;
++      PADAPTER_INIT_STRUCT InitStruct;
++
++      //
++      // Fill in the remaining pieces of the InitStruct.
++      //
++
++      InitStruct = AdapterExtension->Common->InitStruct;
++
++      InitStruct->HostPhysMemPages = AfaPortGetMaxPhysicalPage(AdapterExtension->Common);
++
++      ElapsedSeconds = OsGetSeconds();
++
++      InitStruct->HostElapsedSeconds = ElapsedSeconds;
++
++      //
++      // Tell the adapter we are back and up and running so it will scan its command
++      // queues and enable our interrupts
++      //
++
++      AdapterExtension->LocalMaskInterruptControl =
++              (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4);
++
++
++      //
++      // First clear out all interrupts.  Then enable the one's that we can handle.
++      //
++
++      Sa_WRITE_USHORT( AdapterExtension,  SaDbCSR.PRISETIRQMASK, (USHORT) 0xffff );
++      Sa_WRITE_USHORT( AdapterExtension,  SaDbCSR.PRICLEARIRQMASK,
++                                      (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4) );
++
++      SaSendSynchCommand(AdapterExtension, 
++                         INIT_STRUCT_BASE_ADDRESS, 
++                         (ULONG) AdapterExtension->Common->PhysicalInitStruct,
++                         0,
++                         0,
++                         0,
++                         &ReturnStatus);
++
++}
++
++
++VOID
++SaResetDevice (PVOID Arg1){
++
++}
++
++
++/*++
++
++Routine Description:
++
++      The will cause the adapter to take a break point.
++
++Arguments:
++
++      None
++
++Return Value:
++
++    Nothing
++
++--*/
++VOID
++SaInterruptAdapter (PVOID Arg1)
++{
++      PPCI_MINIPORT_COMMON_EXTENSION CommonExtension = (PPCI_MINIPORT_COMMON_EXTENSION) Arg1;
++      PSa_ADAPTER_EXTENSION AdapterExtension = (PSa_ADAPTER_EXTENSION) CommonExtension->MiniPort;
++
++      ULONG ReturnStatus;
++
++      SaSendSynchCommand(AdapterExtension, 
++                         BREAKPOINT_REQUEST,
++                         0,
++                         0,
++                         0,
++                         0,
++                         &ReturnStatus);
++
++}
++
++
++/*++
++
++Routine Description:
++
++    Will read the adapter CSRs to find the reason the adapter has
++    interrupted us.
++
++Arguments:
++
++    AdapterEvent - Enumerated type the returns the reason why we were interrutped.
++
++Return Value:
++
++    Nothing
++
++--*/
++VOID
++SaNotifyAdapter (PVOID Arg1, IN HOST_2_ADAP_EVENT AdapterEvent)
++{
++      PPCI_MINIPORT_COMMON_EXTENSION CommonExtension = (PPCI_MINIPORT_COMMON_EXTENSION) Arg1;
++      PSa_ADAPTER_EXTENSION AdapterExtension = (PSa_ADAPTER_EXTENSION) CommonExtension->MiniPort;
++      ULONG ReturnStatus;
++
++    switch (AdapterEvent) {
++        case AdapNormCmdQue:
++
++                      Sa_WRITE_USHORT( AdapterExtension, DoorbellReg_s,DOORBELL_1);
++            break;
++
++        case HostNormRespNotFull:
++
++                      Sa_WRITE_USHORT( AdapterExtension, DoorbellReg_s,DOORBELL_4);
++            break;
++
++        case AdapNormRespQue:
++
++                      Sa_WRITE_USHORT( AdapterExtension, DoorbellReg_s,DOORBELL_2);
++            break;
++
++        case HostNormCmdNotFull:
++
++                      Sa_WRITE_USHORT( AdapterExtension, DoorbellReg_s,DOORBELL_3);
++            break;
++
++        case HostShutdown:
++
++//                    SaSendSynchCommand(AdapterExtension, HOST_CRASHING, 0, 0, 0, 0, &ReturnStatus);
++
++            break;
++
++              case FastIo:
++                      Sa_WRITE_USHORT( AdapterExtension, DoorbellReg_s,DOORBELL_6);
++                      break;
++
++              case AdapPrintfDone:
++                      Sa_WRITE_USHORT( AdapterExtension, DoorbellReg_s,DOORBELL_5);
++                      break;
++
++        default:
++
++                      SaBugCheck(0,0,0);
++            AfaPortPrint("Notify requested with an invalid request 0x%x.\n",AdapterEvent);
++            break;
++    }
++}
++
++
++/*++
++
++Routine Description:
++
++      This routine will send a synchronous comamnd to the adapter and wait for its
++      completion.
++
++Arguments:
++
++      AdapterExtension - Pointer to adapter extension structure.
++      Command - Which command to send
++      Parameter1 - 4  - Parameters for command
++      ReturnStatus - return status from adapter after completion of command
++
++
++Return Value:
++
++      AAC_STATUS
++
++--*/
++AAC_STATUS
++SaSendSynchCommand(
++                 PVOID Arg1,
++                 ULONG Command,
++                 ULONG Parameter1,
++                 ULONG Parameter2,
++                 ULONG Parameter3,
++                 ULONG Parameter4,
++                 PULONG       ReturnStatus
++      )
++{
++      PSa_ADAPTER_EXTENSION AdapterExtension = (PSa_ADAPTER_EXTENSION) Arg1;
++      ULONG StartTime,EndTime,WaitTime;
++      BOOLEAN CommandSucceeded;
++
++      //
++      // Write the Command into Mailbox 0
++      //
++
++      Sa_WRITE_ULONG( AdapterExtension, Mailbox0, Command);
++
++      //
++      // Write the parameters into Mailboxes 1 - 4
++      //
++
++      Sa_WRITE_ULONG( AdapterExtension, Mailbox1, Parameter1);
++      Sa_WRITE_ULONG( AdapterExtension, Mailbox2, Parameter2);
++      Sa_WRITE_ULONG( AdapterExtension, Mailbox3, Parameter3);
++      Sa_WRITE_ULONG( AdapterExtension, Mailbox4, Parameter4);
++
++      //
++      // Clear the synch command doorbell to start on a clean slate.
++      //
++              
++      Sa_WRITE_USHORT( AdapterExtension, DoorbellClrReg_p, DOORBELL_0);
++
++      //
++      // Signal that there is a new synch command
++      //
++
++      Sa_WRITE_USHORT( AdapterExtension, DoorbellReg_s, DOORBELL_0);
++
++      CommandSucceeded = FALSE;
++
++      StartTime = OsGetSeconds();
++      WaitTime = 0;
++
++      while (WaitTime < 30) { // wait up to 30 seconds
++
++              drv_usecwait(5);                                // delay 5 microseconds to let Mon960 get info.
++
++              //
++              // Mon110 will set doorbell0 bit when it has completed the command.
++              //
++
++              if( Sa_READ_USHORT( AdapterExtension, DoorbellReg_p) & DOORBELL_0 )  {
++
++                      CommandSucceeded = TRUE;
++                      break;
++              }
++
++              EndTime = OsGetSeconds();
++              WaitTime = EndTime - StartTime;
++
++      }
++
++      if (CommandSucceeded != TRUE) {
++
++              return (STATUS_IO_TIMEOUT);
++
++      }
++
++      //
++      // Clear the synch command doorbell.
++      //
++              
++      Sa_WRITE_USHORT( AdapterExtension, DoorbellClrReg_p, DOORBELL_0);
++
++      //
++      // Pull the synch status from Mailbox 0.
++      //
++
++      *ReturnStatus = Sa_READ_ULONG( AdapterExtension, Mailbox0);
++
++      //
++      // Return SUCCESS
++      //
++
++      return (STATUS_SUCCESS);
++
++}
++
++
++/*++
++
++Routine Description:
++
++      This routine will send a synchronous fib to the adapter and wait for its
++      completion.
++
++Arguments:
++
++      AdapterExtension - Pointer to adapter extension structure.
++      FibPhysicalAddress - Physical address of fib to send.
++
++
++Return Value:
++
++      BOOLEAN
++
++--*/
++BOOLEAN
++SaSendSynchFib (PVOID Arg1, ULONG FibPhysicalAddress)
++{
++      PPCI_MINIPORT_COMMON_EXTENSION CommonExtension = (PPCI_MINIPORT_COMMON_EXTENSION) Arg1;
++      PSa_ADAPTER_EXTENSION AdapterExtension = (PSa_ADAPTER_EXTENSION) CommonExtension->MiniPort;
++      ULONG returnStatus;
++
++      if (SaSendSynchCommand( AdapterExtension,
++                                                  SEND_SYNCHRONOUS_FIB,
++                                                  FibPhysicalAddress,
++                                                  0,
++                                                  0,
++                                                  0,
++                                                  &returnStatus ) != STATUS_SUCCESS ) {
++
++              return (FALSE);
++              
++      }
++      
++      return (TRUE);
++                                                                              
++}
++
++BOOLEAN
++WriteFlash(
++      PVOID AdapterExtension,
++      ULONG *MappedBuffer)
++{
++      return (FALSE);
++}
++
++BOOLEAN
++ReadFlash(
++      PVOID AdapterExtension,
++      ULONG *MappedBuffer)
++{
++      return (FALSE);
++}
++
+diff -burN linux-2.4.9/drivers/scsi/scsi_scan.c linux/drivers/scsi/scsi_scan.c
+--- linux-2.4.9/drivers/scsi/scsi_scan.c       Thu Aug 16 13:40:31 2001
++++ linux/drivers/scsi/scsi_scan.c     Thu Aug 16 18:10:10 2001
+@@ -160,6 +160,8 @@
+       {"SONY", "TSL",       "*", BLIST_FORCELUN},  // DDS3 & DDS4 autoloaders
+       {"DELL", "PERCRAID", "*", BLIST_FORCELUN},
+       {"HP", "NetRAID-4M", "*", BLIST_FORCELUN},
++      {"ADAPTEC", "AACRAID", "*", BLIST_FORCELUN},
++      {"ADAPTEC", "Adaptec 5400S", "*", BLIST_FORCELUN},
+       /*
+        * Must be at end of list...
This page took 0.643608 seconds and 4 git commands to generate.