diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/Config.in linux.gamma/drivers/scsi/Config.in
--- linux.15p3/drivers/scsi/Config.in	Mon Nov 12 11:59:25 2001
+++ linux.gamma/drivers/scsi/Config.in	Mon Nov 19 11:42:23 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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/Makefile linux.gamma/drivers/scsi/Makefile
--- linux.15p3/drivers/scsi/Makefile	Mon Nov 12 11:59:25 2001
+++ linux.gamma/drivers/scsi/Makefile	Mon Nov 19 11:42:23 2001
@@ -64,6 +64,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
@@ -203,3 +204,6 @@
 	mv script.h 53c700_d.h
 
 53c700.o: 53c700_d.h
+
+aacraid.o:
+	cd aacraid; make
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/ChangeLog linux.gamma/drivers/scsi/aacraid/ChangeLog
--- linux.15p3/drivers/scsi/aacraid/ChangeLog	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/ChangeLog	Tue Nov 27 21:08:22 2001
@@ -0,0 +1,46 @@
+2001-11-05  Matt Domsch <Matt_Domsch@dell.com>
+* Applied patch from Jon Fraser to rx.c and sap1sup.c to fix printing of
+error messages from firmware.
+* Re-diff'd against 2.4.13 and released patch
+	
+2001-10-10  Matt Domsch <Matt_Domsch@dell.com>
+* Re-diff'd against 2.4.11 and released patch
+
+2001-10-09  Matt Domsch <Matt_Domsch@dell.com>
+* Added two new PCI IDs
+
+2001-09-25  Matt Domsch <Matt_Domsch@dell.com>
+* Added MODULE_DESCRIPTION and MODULE_LICENSE tags
+* Removed extra unnecessary flags being passed by the Makefile
+* released patch against 2.4.10
+
+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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/Makefile linux.gamma/drivers/scsi/aacraid/Makefile
--- linux.15p3/drivers/scsi/aacraid/Makefile	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/Makefile	Tue Nov 27 22:18:42 2001
@@ -0,0 +1,154 @@
+#
+# Makefile aacraid Raid Controller
+#
+
+###############################################################################
+### SOURCE FILES DEFINES
+###############################################################################
+
+CFILES_DRIVER=\
+	./aachba.c \
+	./commctrl.c \
+	./comminit.c \
+	./commsup.c \
+	./dpcsup.c \
+	./linit.c \
+	./osddi.c \
+	./zone.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 \
+	osddi.o \
+	aachba.o \
+	commctrl.o \
+	comminit.o \
+	commsup.o \
+	dpcsup.o \
+	zone.o \
+	rx.o \
+	sap1sup.o
+
+TARGET_OFILES= ${OFILES_DRIVER}
+
+###############################################################################
+### GENERAL DEFINES
+###############################################################################
+
+#  Remember that we're doing a chdir one level lower, so we need an extra ../
+INCS= \
+	-I./include \
+	-I../../../include -I..
+
+COMMON_FLAGS=\
+	-DCVLOCK_USE_SPINLOCK -DLINUX \
+	${INCS}
+
+AACFLAGS=${CFLAGS} ${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
+
+zone.o: ./zone.c
+	$(CC) $(COMMON_FLAGS) $(AACFLAGS) -c -o zone.o ./zone.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
+
+port.o:  ./port.c
+	$(CC) $(COMMON_FLAGS) $(AACFLAGS) -c -o port.o ./port.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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/README linux.gamma/drivers/scsi/aacraid/README
--- linux.15p3/drivers/scsi/aacraid/README	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/README	Tue Nov 27 21:08:22 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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/aachba.c linux.gamma/drivers/scsi/aacraid/aachba.c
--- linux.15p3/drivers/scsi/aacraid/aachba.c	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/aachba.c	Wed Nov 28 01:20:26 2001
@@ -0,0 +1,1312 @@
+/*++
+ * 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...
+ *
+--*/
+
+#include "os.h"
+
+/*	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(struct hw_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 {
+	u8 inqd_pdt;	/* Peripheral qualifier | Peripheral Device Type  */
+	u8 inqd_dtq;	/* RMB | Device Type Qualifier  */
+	u8 inqd_ver;	/* ISO version | ECMA version | ANSI-approved version */
+	u8 inqd_rdf;	/* AENC | TrmIOP | Response data format */
+	u8 inqd_len;	/* Additional length (n-4) */
+	u8 inqd_pad1[2];/* Reserved - must be zero */
+	u8 inqd_pad2;	/* RelAdr | WBus32 | WBus16 |  Sync  | Linked |Reserved| CmdQue | SftRe */
+	u8 inqd_vid[8];	/* Vendor ID */
+	u8 inqd_pid[16];/* Product ID */
+	u8 inqd_prl[4];	/* Product Revision Level */
+};
+
+struct sense_data {
+	u8 error_code;		/* 70h (current errors), 71h(deferred errors) */
+	u8 valid:1;		/* A valid bit of one indicates that the information  */
+	/* field contains valid information as defined in the
+	 * SCSI-2 Standard.
+	 */
+	u8 segment_number;	/* Only used for COPY, COMPARE, or COPY AND VERIFY Commands */
+	u8 sense_key:4;		/* Sense Key */
+	u8 reserved:1;
+	u8 ILI:1;		/* Incorrect Length Indicator */
+	u8 EOM:1;		/* End Of Medium - reserved for random access devices */
+	u8 filemark:1;		/* Filemark - reserved for random access devices */
+
+	u8 information[4];	/* for direct-access devices, contains the unsigned 
+				 * logical block address or residue associated with 
+				 * the sense key 
+				 */
+	u8 add_sense_len;	/* number of additional sense bytes to follow this field */
+	u8 cmnd_info[4];	/* not used */
+	u8 ASC;			/* Additional Sense Code */
+	u8 ASCQ;		/* Additional Sense Code Qualifier */
+	u8 FRUC;		/* Field Replaceable Unit Code - not used */
+	u8 bit_ptr:3;		/* indicates which byte of the CDB or parameter data
+				 * was in error
+				 */
+	u8 BPV:1;		/* bit pointer valid (BPV): 1- indicates that 
+				 * the bit_ptr field has valid value
+				 */
+	u8 reserved2:2;
+	u8 CD:1;		/* command data bit: 1- illegal parameter in CDB.
+				 * 0- illegal parameter in data.
+				 */
+	u8 SKSV:1;
+	u8 field_ptr[2];	/* byte of the CDB or parameter data in error */
+};
+
+/*------------------------------------------------------------------------------
+ *              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 sense_data[MAXIMUM_NUM_CONTAINERS];
+static void get_sd_devname(int disknum, char *buffer);
+
+
+/**
+ *	aachba_containers	-	list containers
+ *	@common: adapter to probe
+ *
+ *	Make a list of all containers on this controller
+ */
+int aachba_containers(struct aac_dev *dev)
+{
+	fsadev_t *fsa_dev_ptr;
+	int index, status;
+	PMNTINFO DiskInfo;
+	PMNTINFORESPONSE DiskInfoResponse;
+	struct fib * fibptr;
+	unsigned instance;
+
+	fsa_dev_ptr = &(dev->OsDep.fsa_dev);
+	instance = dev->OsDep.scsi_host_ptr->unique_id;
+
+	if (!(fibptr = fib_alloc(dev))) {
+		printk(KERN_WARNING "aachba_containers: fib_alloc failed.\n");
+		return -ENOMEM;
+	}
+
+	for (index = 0; index < MAXIMUM_NUM_CONTAINERS; index++) {
+		fib_init(fibptr);
+		DiskInfo = (PMNTINFO) fib_data(fibptr);
+
+		DiskInfo->Command = VM_NameServe;
+		DiskInfo->MntCount = index;
+		DiskInfo->MntType = FT_FILESYS;
+
+		status = fib_send(ContainerCommand,
+						    fibptr,
+						    sizeof (MNTINFO),
+						    FsaNormal,
+						    TRUE,
+						    NULL, TRUE, NULL, NULL);
+		if (status) {
+			printk(KERN_WARNING "ProbeContainers: SendFIB failed.\n");
+			status = -EINVAL;
+			break;
+		}
+		DiskInfoResponse = (PMNTINFORESPONSE) fib_data(fibptr);
+
+		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;
+		}
+		fib_complete(fibptr);
+		// If there are no more containers, then stop asking.
+		if ((index + 1) >= DiskInfoResponse->MntRespCount)
+			break;
+	}
+	fib_free(fibptr);
+	g_fsa_dev_array[instance] = fsa_dev_ptr;
+	return status;
+}
+
+/*------------------------------------------------------------------------------
+	AacHba_ProbeContainer()
+
+		Probe a single container.
+ *----------------------------------------------------------------------------*/
+int AacHba_ProbeContainer(struct aac_dev *dev, int cid)
+{
+	fsadev_t *fsa_dev_ptr;
+	int status;
+	PMNTINFO DiskInfo;
+	PMNTINFORESPONSE DiskInfoResponse;
+	struct fib * fibptr;
+	unsigned instance;
+
+	fsa_dev_ptr = &(dev->OsDep.fsa_dev);
+	instance = dev->OsDep.scsi_host_ptr->unique_id;
+
+	if (!(fibptr = fib_alloc(dev))) {
+		printk(KERN_WARNING "aachba_containers: fib_alloc failed.\n");
+		return STATUS_UNSUCCESSFUL;
+	}
+
+	fib_init(fibptr);
+
+	DiskInfo = (PMNTINFO) fib_data(fibptr);
+
+	DiskInfo->Command = VM_NameServe;
+	DiskInfo->MntCount = cid;
+	DiskInfo->MntType = FT_FILESYS;
+
+	status = fib_send(ContainerCommand,
+					    fibptr,
+					    sizeof (MNTINFO),
+					    FsaNormal,
+					    TRUE, NULL, TRUE, NULL, NULL);
+	if (status) {
+		printk(KERN_WARNING "ProbeContainers: SendFIB Failed.\n");
+		goto error;
+	}
+
+	DiskInfoResponse = (PMNTINFORESPONSE) fib_data(fibptr);
+
+	if ((DiskInfoResponse->Status == ST_OK) &&
+	    (DiskInfoResponse->MntTable[0].VolType != CT_NONE)) {
+		fsa_dev_ptr->ContainerValid[cid] = TRUE;
+		fsa_dev_ptr->ContainerType[cid] = DiskInfoResponse->MntTable[0].VolType;
+		fsa_dev_ptr->ContainerSize[cid] = DiskInfoResponse->MntTable[0].Capacity;
+		if (DiskInfoResponse->MntTable[0].ContentState & FSCS_READONLY)
+			fsa_dev_ptr->ContainerReadOnly[cid] = TRUE;
+	}
+
+error:
+	fib_complete(fibptr);
+	fib_free(fibptr);
+
+	return status;
+}
+
+void set_sense(char *sense_buf, u8 sense_key, u8 sense_code,
+		    u8 a_sense_code, u8 incorrect_length,
+		    u8 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
+	}
+}
+
+/*------------------------------------------------------------------------------
+	aac_io_done()
+
+		Call SCSI completion routine after acquiring io_request_lock
+
+  	Preconditions:
+	Postconditions:
+ *----------------------------------------------------------------------------*/
+
+static void aac_io_done(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);
+}
+
+/*------------------------------------------------------------------------------
+	__aac_io_done()
+
+		Call SCSI completion routine
+
+  	Preconditions:
+	Postconditions:
+ *----------------------------------------------------------------------------*/
+
+static void __aac_io_done(Scsi_Cmnd * scsi_cmnd_ptr)
+{
+	scsi_cmnd_ptr->scsi_done(scsi_cmnd_ptr);
+}
+
+static void read_callback(void *Context, struct fib * fibptr, int FibStatus)
+{
+	struct aac_dev *dev;
+	BLOCKREADRESPONSE *BlockReadResponse;
+	Scsi_Cmnd *scsi_cmnd_ptr;
+	unsigned long lba;
+	int cid;
+
+	scsi_cmnd_ptr = (Scsi_Cmnd *) Context;
+
+	dev = (struct aac_dev *)scsi_cmnd_ptr->host->hostdata;
+	cid =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];
+	dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %ld, t = %ld.\n",
+	       smp_processor_id(), lba, jiffies));
+
+	if (fibptr == 0) {
+		printk(KERN_WARNING "read_callback: no fib context.\n");
+		scsi_cmnd_ptr->result = DID_ERROR << 16;
+		aac_io_done(scsi_cmnd_ptr);
+		return;
+	}
+
+	BlockReadResponse = (PBLOCKREADRESPONSE) fib_data(fibptr);
+
+	if (BlockReadResponse->Status == ST_OK)
+		scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
+	else {
+		printk(KERN_WARNING "read_callback: read failed, status = %d\n", BlockReadResponse->Status);
+		scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
+		set_sense((char *) &sense_data[cid],
+				    SENKEY_HW_ERR,
+				    SENCODE_INTERNAL_TARGET_FAILURE,
+				    ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
+				    0, 0);
+	}
+
+	fib_complete(fibptr);
+	fib_free(fibptr);
+
+	aac_io_done(scsi_cmnd_ptr);
+}
+
+static void write_callback(void *Context, struct fib * fibptr, int FibStatus)
+{
+	struct aac_dev *dev;
+	BLOCKWRITERESPONSE *BlockWriteResponse;
+	Scsi_Cmnd *scsi_cmnd_ptr;
+	unsigned long lba;
+	int cid;
+
+	scsi_cmnd_ptr = (Scsi_Cmnd *) Context;
+
+	dev = (struct aac_dev *)scsi_cmnd_ptr->host->hostdata;
+
+	cid = 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];
+	dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %ld, t = %ld.\n",
+	       smp_processor_id(), lba, jiffies));
+	if (fibptr == 0) {
+		printk(KERN_WARNING "write_callback: no fib context.\n");
+		scsi_cmnd_ptr->result = DID_ERROR << 16;
+		aac_io_done(scsi_cmnd_ptr);
+		return;
+	}
+
+	BlockWriteResponse = (PBLOCKWRITERESPONSE) fib_data(fibptr);
+	if (BlockWriteResponse->Status == ST_OK)
+		scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
+	else {
+		printk(KERN_WARNING "write_callback: write failed, status = %d\n", BlockWriteResponse->Status);
+		scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
+		set_sense((char *) &sense_data[cid],
+				    SENKEY_HW_ERR,
+				    SENCODE_INTERNAL_TARGET_FAILURE,
+				    ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
+				    0, 0);
+	}
+
+	fib_complete(fibptr);
+	fib_free(fibptr);
+
+	aac_io_done(scsi_cmnd_ptr);
+}
+
+int aac_read(Scsi_Cmnd * scsi_cmnd_ptr, int cid, int wait)
+{
+	unsigned long lba;
+	unsigned long count;
+	unsigned long byte_count;
+	int status;
+
+	PBLOCKREAD BlockReadDisk;
+	PBLOCKREADRESPONSE BlockReadResponse;
+	uint16_t FibSize;
+	struct aac_dev *dev;
+	struct fib * cmd_fibcontext;
+
+	dev = (struct aac_dev *)scsi_cmnd_ptr->host->hostdata;
+
+	// Get block address and transfer length
+	if (scsi_cmnd_ptr->cmnd[0] == SS_READ)	// 6 byte command
+	{
+		dprintk((KERN_DEBUG "aachba: received a read(6) command on target %d.\n", cid));
+
+		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 {
+		dprintk((KERN_DEBUG "aachba: received a read(10) command on target %d.\n", cid));
+
+		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];
+	}
+	dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %lu, t = %ld.\n", smp_processor_id(), lba, jiffies));
+
+	//-------------------------------------------------------------------------
+	// Alocate and initialize a Fib
+	//  Setup BlockRead command
+	if (!(cmd_fibcontext = fib_alloc(dev))) {
+		printk(KERN_WARNING "aac_read: fib_alloc failed\n");
+		scsi_cmnd_ptr->result = DID_ERROR << 16;
+		__aac_io_done(scsi_cmnd_ptr);
+		return (-1);
+	}
+
+	fib_init(cmd_fibcontext);
+
+	BlockReadDisk = (PBLOCKREAD) fib_data(cmd_fibcontext);
+	BlockReadDisk->Command = VM_CtBlockRead;
+	BlockReadDisk->ContainerId = cid;
+	BlockReadDisk->BlockNumber = lba;
+	BlockReadDisk->ByteCount = count * 512;
+	BlockReadDisk->SgMap.SgCount = 1;
+
+	if (BlockReadDisk->ByteCount > (64 * 1024)) {
+		printk(KERN_WARNING "aac_read: READ request is larger than 64K.\n");
+		scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
+
+		set_sense((char *) &sense_data[cid],
+				    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 *)virt_to_bus(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)) {
+				printk(KERN_WARNING "aac_read: Segment byte count is larger than 64K.\n");
+				scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
+
+				set_sense((char *)
+						    &sense_data
+						    [cid],
+						    SENKEY_ILLEGAL,
+						    SENCODE_INVALID_CDB_FIELD,
+						    ASENCODE_INVALID_CDB_FIELD,
+						    0, 0, 7, 0);
+
+				goto err_return;
+			}
+		}
+		BlockReadDisk->SgMap.SgCount = scsi_cmnd_ptr->use_sg;
+
+		if (BlockReadDisk->SgMap.SgCount > MAX_DRIVER_SG_SEGMENT_COUNT) {
+			printk(KERN_WARNING "aac_read: READ request with SgCount > %d.\n", 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 *) virt_to_bus(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)) {
+			printk(KERN_WARNING "aac_read: Single segment byte count is larger than 64K.\n");
+			printk(KERN_WARNING "aac_read: ByteCount: %d.\n",	BlockReadDisk->ByteCount);
+			printk(KERN_WARNING "aac_read: SG ELEMENTS: %d.\n", scsi_cmnd_ptr->use_sg);
+			scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
+
+			set_sense((char *)
+					    &sense_data[cid],
+					    SENKEY_ILLEGAL,
+					    SENCODE_INVALID_CDB_FIELD,
+					    ASENCODE_INVALID_CDB_FIELD, 0,
+					    0, 7, 0);
+
+			goto err_return;
+		}
+	}
+
+	if (byte_count != BlockReadDisk->ByteCount)
+		printk(KERN_WARNING "aac_read: byte_count != BlockReadDisk->ByteCount.\n");
+
+	//-------------------------------------------------------------------------
+	// 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 = fib_send(ContainerCommand,
+						    cmd_fibcontext,
+						    FibSize,
+						    FsaNormal,
+						    TRUE,
+						    NULL, TRUE, NULL, NULL);
+
+		BlockReadResponse = (PBLOCKREADRESPONSE)fib_data(cmd_fibcontext);
+		fib_complete(cmd_fibcontext);
+		fib_free(cmd_fibcontext);
+
+		if (BlockReadResponse->Status != ST_OK) {
+			printk(KERN_WARNING "aac_read: BlockReadCommand failed with status: %d.\n", BlockReadResponse->Status);
+			scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
+
+			set_sense((char *)
+					    &sense_data[cid],
+					    SENKEY_HW_ERR,
+					    SENCODE_INTERNAL_TARGET_FAILURE,
+					    ASENCODE_INTERNAL_TARGET_FAILURE,
+					    0, 0, 0, 0);
+
+			__aac_io_done(scsi_cmnd_ptr);
+			return (-1);
+		} else
+			scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
+
+		__aac_io_done(scsi_cmnd_ptr);
+		return (0);
+	} else {
+		status = fib_send(ContainerCommand,
+						    cmd_fibcontext,
+						    FibSize,
+						    FsaNormal,
+						    FALSE,
+						    NULL,
+						    TRUE,
+						    (PCOMM_FIB_CALLBACK)
+						    read_callback,
+						    (void *) scsi_cmnd_ptr);
+		// Check that the command queued to the controller
+		if (status != STATUS_PENDING) {
+			printk(KERN_WARNING "aac_read: fib_send 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:
+	__aac_io_done(scsi_cmnd_ptr);
+
+	fib_complete(cmd_fibcontext);
+	fib_free(cmd_fibcontext);
+
+	return -1;
+}
+
+int aac_write(Scsi_Cmnd * scsi_cmnd_ptr, int cid, int wait)
+{
+	unsigned long lba;
+	unsigned long count;
+	unsigned long byte_count;
+	int status;
+
+	PBLOCKWRITE BlockWriteDisk;
+	PBLOCKWRITERESPONSE BlockWriteResponse;
+	uint16_t FibSize;
+	struct aac_dev *dev;
+	struct fib * cmd_fibcontext;
+
+	dev = (struct aac_dev *)scsi_cmnd_ptr->host->hostdata;
+
+	// 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 {
+		dprintk((KERN_DEBUG "aachba: received a write(10) command on target %d.\n", cid));
+		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];
+	}
+	dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %lu, t = %ld.\n", smp_processor_id(), lba, jiffies));
+	//-------------------------------------------------------------------------
+	// Alocate and initialize a Fib
+	//  Setup BlockWrite command
+	if (!(cmd_fibcontext = fib_alloc(dev))) {
+		printk(KERN_WARNING "aac_write: fib_alloc failed\n");
+		scsi_cmnd_ptr->result = DID_ERROR << 16;
+		__aac_io_done(scsi_cmnd_ptr);
+		return -1;
+	}
+
+	fib_init(cmd_fibcontext);
+
+	BlockWriteDisk = (PBLOCKWRITE) fib_data(cmd_fibcontext);
+	BlockWriteDisk->Command = VM_CtBlockWrite;
+	BlockWriteDisk->ContainerId = cid;
+	BlockWriteDisk->BlockNumber = lba;
+	BlockWriteDisk->ByteCount = count * 512;
+	BlockWriteDisk->SgMap.SgCount = 1;
+
+	if (BlockWriteDisk->ByteCount > (64 * 1024)) {
+		struct scatterlist *scatterlist_ptr;
+		scatterlist_ptr = (struct scatterlist *) scsi_cmnd_ptr->request_buffer;
+
+		printk(KERN_WARNING "\n");
+		printk(KERN_WARNING "aac_write: WRITE request is larger than 64K.\n");
+		printk(KERN_WARNING "aac_write: ByteCount: %d.\n", BlockWriteDisk->ByteCount);
+
+		scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
+		set_sense((char *) &sense_data[cid],
+				    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) virt_to_bus(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)) {
+				printk(KERN_WARNING "aac_write: Segment byte count is larger than 64K.\n");
+				scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
+
+				set_sense((char *) &sense_data[cid],
+						    SENKEY_ILLEGAL,
+						    SENCODE_INVALID_CDB_FIELD,
+						    ASENCODE_INVALID_CDB_FIELD,
+						    0, 0, 7, 0);
+
+				goto err_return;
+			}
+		}
+		BlockWriteDisk->SgMap.SgCount = scsi_cmnd_ptr->use_sg;
+
+		if (BlockWriteDisk->SgMap.SgCount > MAX_DRIVER_SG_SEGMENT_COUNT) {
+			printk(KERN_WARNING "aac_write: WRITE request with SgCount > %d.\n", 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) virt_to_bus(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)) {
+			printk(KERN_WARNING "aac_write: Single segment byte count is larger than 64K.\n");
+
+			scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
+			set_sense((char *) &sense_data[cid],
+					    SENKEY_ILLEGAL,
+					    SENCODE_INVALID_CDB_FIELD,
+					    ASENCODE_INVALID_CDB_FIELD, 0,
+					    0, 7, 0);
+
+			goto err_return;
+		}
+	}
+
+	if (byte_count != BlockWriteDisk->ByteCount)
+		printk(KERN_WARNING "aac_write: byte_count != BlockReadDisk->ByteCount.\n");
+	//-------------------------------------------------------------------------
+	// 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 = fib_send(ContainerCommand,
+						    cmd_fibcontext,
+						    FibSize,
+						    FsaNormal,
+						    TRUE,
+						    NULL, TRUE, NULL, NULL);
+
+		BlockWriteResponse = (PBLOCKWRITERESPONSE) fib_data(cmd_fibcontext);
+
+		fib_complete(cmd_fibcontext);
+		fib_free(cmd_fibcontext);
+
+		if (BlockWriteResponse->Status != ST_OK) {
+			printk(KERN_WARNING "aac_write: BlockWriteCommand failed with status: %d\n", BlockWriteResponse->Status);
+			scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;;
+			set_sense((char *)
+					    &sense_data[cid],
+					    SENKEY_HW_ERR,
+					    SENCODE_INTERNAL_TARGET_FAILURE,
+					    ASENCODE_INTERNAL_TARGET_FAILURE,
+					    0, 0, 0, 0);
+			__aac_io_done(scsi_cmnd_ptr);
+			return (-1);
+		} else
+			scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
+
+		__aac_io_done(scsi_cmnd_ptr);
+		return (0);
+	} else {
+		status = fib_send(ContainerCommand,
+				    cmd_fibcontext,
+				    FibSize,
+				    FsaNormal,
+				    FALSE,
+				    NULL,
+				    TRUE,
+				    (PCOMM_FIB_CALLBACK)
+				    write_callback,
+				    (void *) scsi_cmnd_ptr);
+
+		// Check that the command queued to the controller
+		if (status != STATUS_PENDING) {
+			printk(KERN_WARNING "aac_write: fib_send 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:
+	__aac_io_done(scsi_cmnd_ptr);
+
+	fib_complete(cmd_fibcontext);
+	fib_free(cmd_fibcontext);
+
+	return -1;
+}
+
+
+/**
+ *	aac_scsi_cmd()		-	Process SCSI command
+ *	@scsi_cmnd_ptr:		SCSI command block
+ *	@wait:			1 if the user wants to await completion
+ *
+ *	Emulate a SCSI command and queue the required request for the
+ *	aacraid firmware.
+ */
+ 
+int aac_scsi_cmd(Scsi_Cmnd * scsi_cmnd_ptr, int wait)
+{
+	int cid = 0;
+	fsadev_t *fsa_dev_ptr;
+	int MiniPortIndex;
+	struct aac_dev *dev = (struct aac_dev *)scsi_cmnd_ptr->host->hostdata;
+	
+	MiniPortIndex = dev->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)) {
+			dprintk((KERN_DEBUG
+			       "The bus, target or lun is out of range = %d, %d, %d.\n",
+			       scsi_cmnd_ptr->channel,
+			       scsi_cmnd_ptr->target, scsi_cmnd_ptr->lun));
+			scsi_cmnd_ptr->result = DID_BAD_TARGET << 16;
+
+			__aac_io_done(scsi_cmnd_ptr);
+
+			return (-1);
+		}
+
+		cid = 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[cid] == 0) {
+			switch (scsi_cmnd_ptr->cmnd[0]) {
+			case SS_INQUIR:
+			case SS_RDCAP:
+			case SS_TEST:
+				spin_unlock_irq(&io_request_lock);
+				AacHba_ProbeContainer(dev, cid);
+				spin_lock_irq(&io_request_lock);
+			default:
+				break;
+			}
+		}
+		// If the target container still doesn't exist, return failure
+		if (fsa_dev_ptr->ContainerValid[cid] == 0) {
+
+			scsi_cmnd_ptr->result = DID_BAD_TARGET << 16;
+			__aac_io_done(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)) {
+		dprintk((KERN_WARNING "Only INQUIRY & TUR command supported for controller, rcvd = 0x%x.\n", scsi_cmnd_ptr->cmnd[0]));
+
+		scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
+
+		set_sense((char *) &sense_data[cid],
+				    SENKEY_ILLEGAL,
+				    SENCODE_INVALID_COMMAND,
+				    ASENCODE_INVALID_COMMAND, 0, 0, 0, 0);
+
+		__aac_io_done(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;
+
+			dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsi_cmnd_ptr->target));
+			inq_data_ptr = (struct inquiry_data *)scsi_cmnd_ptr->request_buffer;
+			memset(inq_data_ptr, 0, 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
+			setinqstr(MiniPortIndex,
+				      (void *) (inq_data_ptr->inqd_vid),
+				      fsa_dev_ptr->ContainerType[cid]);
+
+			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;
+			__aac_io_done(scsi_cmnd_ptr);
+
+			return (0);
+		}
+
+	case SS_RDCAP:
+		{
+			int capacity;
+			char *cp;
+
+			dprintk((KERN_DEBUG "READ CAPACITY command.\n"));
+			capacity = fsa_dev_ptr->ContainerSize[cid] - 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;
+			__aac_io_done(scsi_cmnd_ptr);
+
+			return (0);
+		}
+
+	case SS_MODESEN:
+		{
+			char *mode_buf;
+
+			dprintk((KERN_DEBUG "MODE SENSE command.\n"));
+			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;
+			__aac_io_done(scsi_cmnd_ptr);
+
+			return (0);
+		}
+
+		// These commands are all No-Ops
+	case SS_TEST:
+		dprintk((KERN_DEBUG "TEST UNIT READY command.\n"));
+		scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
+		__aac_io_done(scsi_cmnd_ptr);
+		return (0);
+
+	case SS_REQSEN:
+		dprintk((KERN_DEBUG "REQUEST SENSE command.\n"));
+
+		memcpy(scsi_cmnd_ptr->sense_buffer, &sense_data[cid], sizeof (struct sense_data));
+		memset(&sense_data[cid], 0, sizeof (struct sense_data));
+
+		scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
+		__aac_io_done(scsi_cmnd_ptr);
+		return (0);
+
+	case SS_LOCK:
+		dprintk((KERN_DEBUG "LOCK command.\n"));
+
+		if (scsi_cmnd_ptr->cmnd[4])
+			fsa_dev_ptr->ContainerLocked[cid] = 1;
+		else
+			fsa_dev_ptr->ContainerLocked[cid] = 0;
+
+		scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
+		__aac_io_done(scsi_cmnd_ptr);
+		return (0);
+
+	case SS_RESERV:
+		dprintk((KERN_DEBUG "RESERVE command.\n"));
+		scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
+		__aac_io_done(scsi_cmnd_ptr);
+		return (0);
+
+	case SS_RELES:
+		dprintk((KERN_DEBUG "RELEASE command.\n"));
+		scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
+		__aac_io_done(scsi_cmnd_ptr);
+		return (0);
+
+	case SS_REZERO:
+		dprintk((KERN_DEBUG "REZERO command"));
+		scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
+		__aac_io_done(scsi_cmnd_ptr);
+		return (0);
+
+	case SS_REASGN:
+		dprintk((KERN_DEBUG "REASSIGN command"));
+		scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
+		__aac_io_done(scsi_cmnd_ptr);
+		return (0);
+
+	case SS_SEEK:
+		dprintk((KERN_DEBUG "SEEK command.\n"));
+		scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
+		__aac_io_done(scsi_cmnd_ptr);
+		return (0);
+
+	case SS_ST_SP:
+		dprintk((KERN_DEBUG "START/STOP command.\n"));
+		scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
+		__aac_io_done(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[cid] = DEVICE_NR(scsi_cmnd_ptr->request.rq_dev);
+
+		return (aac_read(scsi_cmnd_ptr, cid, wait));
+		break;
+
+	case SS_WRITE:
+	case SM_WRITE:
+
+		return (aac_write(scsi_cmnd_ptr, cid, wait));
+		break;
+	}
+	//
+	// Unhandled commands
+	//
+	printk(KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsi_cmnd_ptr->cmnd[0]);
+	scsi_cmnd_ptr->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
+
+	set_sense((char *) &sense_data[cid],
+			    SENKEY_ILLEGAL, SENCODE_INVALID_COMMAND,
+			    ASENCODE_INVALID_COMMAND, 0, 0, 0, 0);
+
+	__aac_io_done(scsi_cmnd_ptr);
+	return -1;
+}
+
+int aac_dev_ioctl(struct aac_dev *dev, int cmd, void *arg)
+{
+	switch (cmd) {
+	case FSACTL_QUERY_DISK:
+		return AacHba_QueryDisk(dev, arg);
+	case FSACTL_DELETE_DISK:
+		return AacHba_DeleteDisk(dev, arg);
+	case FSACTL_FORCE_DELETE_DISK:
+		return AacHba_ForceDeleteDisk(dev, arg);
+	case 2131:
+		return aachba_containers(dev);
+	default:
+		return -ENOTTY;
+	}
+}
+
+/*------------------------------------------------------------------------------
+	AacHba_QueryDisk()
+
+	Postconditions:
+		Return values
+		0       = OK
+		-EFAULT = Bad address
+		-EINVAL = Bad container number
+ *----------------------------------------------------------------------------*/
+int AacHba_QueryDisk(struct aac_dev *dev, void *arg)
+{
+	UNIX_QUERY_DISK QueryDisk;
+	fsadev_t *fsa_dev_ptr;
+
+	fsa_dev_ptr = &(dev->OsDep.fsa_dev);
+
+	if (copy_from_user(&QueryDisk, arg, 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 = dev->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 (copy_to_user(arg, &QueryDisk, sizeof (UNIX_QUERY_DISK)))
+		return -EFAULT;
+	return 0;
+}
+
+/*------------------------------------------------------------------------------
+	get_sd_devname()
+ *----------------------------------------------------------------------------*/
+
+static void get_sd_devname(int 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(struct aac_dev *dev, void *arg)
+{
+	DELETE_DISK DeleteDisk;
+	fsadev_t *fsa_dev_ptr;
+
+	fsa_dev_ptr = &(dev->OsDep.fsa_dev);
+
+	if (copy_from_user(&DeleteDisk, arg, 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(struct aac_dev *dev, void *arg)
+{
+	DELETE_DISK DeleteDisk;
+	fsadev_t *fsa_dev_ptr;
+
+	fsa_dev_ptr = &(dev->OsDep.fsa_dev);
+
+	if (copy_from_user(&DeleteDisk, arg, 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;
+	}
+}
+
+void aac_detach(struct aac_dev *dev)
+{
+	AacCommDetachAdapter(dev);
+}
+
+void AacHba_AbortScsiCommand(Scsi_Cmnd * scsi_cmnd_ptr)
+{
+	struct aac_dev *dev = (struct aac_dev *) scsi_cmnd_ptr->host->hostdata;
+	u16 interrupt_status;
+
+	interrupt_status = Sa_READ_USHORT(dev, DoorbellReg_p);
+	printk(KERN_WARNING "interrupt_status = %d\n", interrupt_status);
+
+	if (interrupt_status & DOORBELL_1) {	// dev -> Host Normal Command Ready
+		printk(KERN_WARNING "DOORBELL_1: dev -> Host Normal Command Ready\n");
+	}
+
+	if (interrupt_status & DOORBELL_2) {	// dev -> Host Normal Response Ready
+		printk(KERN_WARNING "DOORBELL_2: dev -> Host Normal Response Ready\n");
+	}
+
+	if (interrupt_status & DOORBELL_3) {	// dev -> Host Normal Command Not Full
+		printk(KERN_WARNING "DOORBELL_3: dev -> Host Normal Command Not Full\n");
+	}
+
+	if (interrupt_status & DOORBELL_4) {	// dev -> Host Normal Response Not Full
+		printk(KERN_WARNING "DOORBELL_4: dev -> Host Normal Response Not Full\n");
+	}
+
+}
+
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/commctrl.c linux.gamma/drivers/scsi/aacraid/commctrl.c
--- linux.15p3/drivers/scsi/aacraid/commctrl.c	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/commctrl.c	Wed Nov 28 00:38:35 2001
@@ -0,0 +1,409 @@
+/*++
+ * 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
+ *
+--*/
+
+#include "os.h"
+#include "revision.h"
+
+static u32 check_revision(struct aac_dev * dev, void *arg)
+{
+	RevCheck APIRevCheck;
+	RevCheckResp APIRevCheckResp;
+	RevComponent APICallingComponent;
+	unsigned long APIBuildNumber;
+
+	if (copy_from_user((void *)&APIRevCheck, arg, sizeof(RevCheck)))
+		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 (copy_to_user(arg, (void *) &APIRevCheckResp, sizeof(RevCheckResp)))
+		return -EFAULT;
+	return 0;
+}
+
+
+/**
+ *	ioctl_send_fib	-	send a FIB from userspace
+ *	@dev:	adapter is being processed
+ *	@arg:	arguments to the ioctl call
+ *	
+ *	This routine sends a fib to the adapter on behalf of a user level
+ *	program.
+ */
+ 
+static int ioctl_send_fib(struct aac_dev * dev, void *arg)
+{
+	struct hw_fib * kfib;
+	struct fib *fibptr;
+
+	fibptr = fib_alloc(dev);
+	kfib = fibptr->fib;
+
+	//
+	// First copy in the header so that we can check the size field.
+	//
+
+	if (copy_from_user((caddr_t)kfib, arg, sizeof(FIB_HEADER))) {
+		fib_free(fibptr);
+		return -EFAULT;
+	}
+
+	//
+	//	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(struct hw_fib) - sizeof(FIB_HEADER)) {
+		fib_free(fibptr);
+		return -EINVAL;
+	}
+
+	if (copy_from_user((caddr_t) kfib, arg, kfib->header.Size + sizeof(FIB_HEADER))) {
+		fib_free(fibptr);
+		return -EFAULT;
+	}
+
+	if (kfib->header.Command == TakeABreakPt) {
+		InterruptAdapter(dev);
+		//
+		// 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 (fib_send(kfib->header.Command, fibptr, kfib->header.Size , FsaNormal,
+			TRUE, NULL, TRUE, NULL, NULL) != FSA_SUCCESS) 
+		{
+			fib_free(fibptr);
+			return -EINVAL;
+		}
+		if (fib_complete(fibptr) != FSA_SUCCESS) {
+			fib_free(fibptr);
+			return -EINVAL;
+		}
+	}
+	//
+	//	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(struct hw_fib));
+
+	if (copy_to_user(arg, (void *)kfib, kfib->header.Size)) {
+		fib_free(fibptr);
+		return -EFAULT;
+	}
+	fib_free(fibptr);
+	return 0;
+}
+
+
+/**
+ *	ioctl_aif_thread	-	create AIF thread
+ *	@dev: device
+ *
+ *	Create an AIF handler for this device
+ */
+ 
+static int ioctl_aif_thread(struct aac_dev * dev)
+{
+	return (NormCommandThread(dev));
+}
+
+
+/**
+ *	open_getadapter_fib	-	Get the next fib
+ *
+ *	This routine will get the next Fib, if available, from the AdapterFibContext
+ *	passed in from the user.
+ */
+
+static int open_getadapter_fib(struct aac_dev * dev, void *arg)
+{
+	PGET_ADAPTER_FIB_CONTEXT fibctx;
+	int status;
+	unsigned long flags;
+	//
+	// The context must be allocated from NonPagedPool because we need to use MmIsAddressValid.
+	//
+	fibctx = kmalloc(sizeof(GET_ADAPTER_FIB_CONTEXT), GFP_KERNEL);
+	if (fibctx == NULL) {
+		status = -ENOMEM;
+	} else {
+		fibctx->type = FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT;
+		fibctx->size = sizeof(GET_ADAPTER_FIB_CONTEXT);
+		//
+		// Initialize the conditional variable use to wait for the next AIF.
+		//
+		init_MUTEX_LOCKED(&fibctx->UserEvent);
+		//
+		// Set WaitingForFib to FALSE to indicate we are not in a WaitForSingleObject
+		//
+		fibctx->WaitingForFib = FALSE;
+		//
+		// Initialize the FibList and set the count of fibs on the list to 0.
+		//
+		fibctx->FibCount = 0;
+		InitializeListHead(&fibctx->FibList);
+		fibctx->jiffies = jiffies/HZ;
+		//
+		// Now add this context onto the adapter's AdapterFibContext list.
+		//
+		spin_lock_irqsave(&dev->fib_lock, flags);
+		InsertTailList(&dev->fib_list, &fibctx->NextContext);
+		spin_unlock_irqrestore(&dev->fib_lock, flags);
+		if (copy_to_user(arg,  &fibctx, sizeof(PGET_ADAPTER_FIB_CONTEXT))) {
+			status = -EFAULT;
+		} else {
+			status = 0;
+		}	
+	}
+	return status;
+}
+
+/**
+ *	next_getadapter_fib	-	get the next fib
+ *	@dev: adapter to use
+ *	@arg: ioctl argument
+ *	
+ * 	This routine will get the next Fib, if available, from the AdapterFibContext
+ *	passed in from the user.
+ */
+
+static int next_getadapter_fib(struct aac_dev * dev, void *arg)
+{
+	GET_ADAPTER_FIB_IOCTL AdapterFibIoctl;
+	PGET_ADAPTER_FIB_CONTEXT fibctx, aifcp;
+	struct hw_fib * fib;
+	int status;
+	PLIST_ENTRY entry;
+	int found;
+	unsigned long flags;
+	
+	if(copy_from_user((void *)&AdapterFibIoctl, arg, sizeof(GET_ADAPTER_FIB_IOCTL)))
+		return -EFAULT;
+	//
+	// Extract the AdapterFibContext from the Input parameters.
+	//
+	fibctx = (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 = dev->fib_list.next;
+
+	while(entry != &dev->fib_list) {
+		aifcp = CONTAINING_RECORD ( entry, GET_ADAPTER_FIB_CONTEXT, NextContext );
+		if(fibctx == aifcp) {   // We found a winner
+			found = 1;
+			break;
+		}
+		entry = entry->next;
+	}
+	if (found == 0)
+		return -EINVAL;
+
+	if ( (fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||
+		 (fibctx->size != sizeof(GET_ADAPTER_FIB_CONTEXT)) )
+		return -EINVAL;
+	status = STATUS_SUCCESS;
+	spin_lock_irqsave(&dev->fib_lock, flags);
+	//
+	// If there are no fibs to send back, then either wait or return EAGAIN
+	//
+return_fib:
+	if (!IsListEmpty(&fibctx->FibList)) {
+		PLIST_ENTRY entry;
+		//
+		// Pull the next fib from the FibList
+		//
+		entry = RemoveHeadList(&fibctx->FibList);
+		fib = CONTAINING_RECORD(entry, struct hw_fib, header.FibLinks);
+		fibctx->FibCount--;
+		spin_unlock_irqrestore(&dev->fib_lock, flags);
+		if (copy_to_user(AdapterFibIoctl.AifFib, fib, sizeof(struct hw_fib))) {
+			kfree(fib);
+			return -EFAULT;
+		}	
+		//
+		// Free the space occupied by this copy of the fib.
+		//
+		kfree(fib);
+		status = 0;
+		fibctx->jiffies = jiffies/HZ;
+	} else {
+		spin_unlock_irqrestore(&dev->fib_lock, flags);
+		if (AdapterFibIoctl.Wait) {
+			if(down_interruptible(&fibctx->UserEvent)==0) {
+				status = -EINTR;
+			} else {
+				/* Lock again and retry */
+				spin_lock_irqsave(&dev->fib_lock, flags);
+				goto return_fib;
+			}
+		} else {
+			status = -EAGAIN;
+		}	
+	}
+	return status;
+}
+
+/**
+ *	close_getadapter_fib	-	close down user fib context
+ *	@dev: adapter
+ *	@arg: ioctl arguments
+ *
+ *	This routine will close down the fibctx passed in from the user.
+ */
+ 
+static int close_getadapter_fib(struct aac_dev * dev, void *arg)
+{
+	PGET_ADAPTER_FIB_CONTEXT fibctx, aifcp;
+	u32 status;
+	unsigned long flags;
+	PLIST_ENTRY entry;
+	int found;
+
+	//
+	// Extract the fibctx from the Input parameters
+	//
+
+	fibctx = arg;
+
+	//
+	// 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 = dev->fib_list.next;
+
+	while(entry != &dev->fib_list) {
+		aifcp = CONTAINING_RECORD(entry, GET_ADAPTER_FIB_CONTEXT, NextContext);
+		if(fibctx == aifcp) {   // We found a winner
+			found = 1;
+			break;
+		}
+		entry = entry->next;
+	}
+
+	if(found == 0)
+		return 0; // Already Gone
+
+	if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||
+		 (fibctx->size != sizeof(GET_ADAPTER_FIB_CONTEXT))) {
+		return -EINVAL;
+	}
+	spin_lock_irqsave(dev->fib_lock, flags);
+	status = FsaCloseAdapterFibContext(dev, fibctx);
+	spin_unlock_irqrestore(dev->fib_lock, flags);
+	return status;
+}
+
+int FsaCloseAdapterFibContext(struct aac_dev * dev, PGET_ADAPTER_FIB_CONTEXT fibctx)
+{
+	struct hw_fib * fib;
+
+	//
+	// First free any FIBs that have not been consumed yet.
+	//
+	while (!IsListEmpty(&fibctx->FibList)) {
+		PLIST_ENTRY entry;
+		//
+		// Pull the next fib from the FibList
+		//
+		entry = RemoveHeadList(&fibctx->FibList);
+		fib = CONTAINING_RECORD( entry, struct hw_fib, header.FibLinks );
+		fibctx->FibCount--;
+		//
+		// Free the space occupied by this copy of the fib.
+		//
+		kfree(fib);
+	}
+	//
+	// Remove the Context from the AdapterFibContext List
+	//
+	RemoveEntryList(&fibctx->NextContext);
+	//
+	// Invalidate context
+	//
+	fibctx->type = 0;
+	//
+	// Free the space occupied by the Context
+	//
+	kfree(fibctx);
+	return STATUS_SUCCESS;
+}
+
+int aac_do_ioctl(struct aac_dev * dev, int cmd, void *arg)
+{
+	int status;
+	
+	/*
+	 *	HBA gets first crack
+	 */
+	 
+	status = aac_dev_ioctl(dev, cmd, arg);
+	if(status != -ENOTTY)
+		return status;
+
+	switch (cmd) {
+	case FSACTL_SENDFIB:
+		status = ioctl_send_fib(dev, arg);
+		break;
+	case FSACTL_AIF_THREAD:
+	  	status = ioctl_aif_thread(dev);	
+		break;
+	case FSACTL_OPEN_GET_ADAPTER_FIB:
+		status = open_getadapter_fib(dev, arg);
+		break;
+	case FSACTL_GET_NEXT_ADAPTER_FIB:
+		status = next_getadapter_fib(dev, arg);
+		break;
+	case FSACTL_CLOSE_GET_ADAPTER_FIB:
+		status = close_getadapter_fib(dev, arg);
+		break;
+	case FSACTL_MINIPORT_REV_CHECK:
+		status = check_revision(dev, arg);
+		break;
+	default:
+		status = -ENOTTY;
+	  	break;	
+	}
+	return status;
+}
+
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/comminit.c linux.gamma/drivers/scsi/aacraid/comminit.c
--- linux.15p3/drivers/scsi/aacraid/comminit.c	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/comminit.c	Wed Nov 28 01:20:51 2001
@@ -0,0 +1,489 @@
+/*++
+ * 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.
+ *
+ --*/
+
+#include "os.h"
+
+FSA_COMM_DATA FsaCommData;
+
+static u32 HardInterruptModeration1Changed(struct aac_dev * dev, unsigned long NewValue)
+{
+	//
+	// If we are using interrupt moderation, then disable the interrupt
+	// until we need to use it.
+	//
+	if (FsaCommData.HardInterruptModeration1)
+		DisableInterrupt(dev, AdapNormCmdNotFull, FALSE);
+	else
+		EnableInterrupt(dev, AdapNormCmdNotFull, FALSE);
+	return STATUS_SUCCESS;
+}
+
+static u32 FsaFibTimeoutChanged(struct aac_dev * dev, unsigned long NewValue)
+{
+	//
+	// scale the new timeout from seconds to 100 nsec units
+	//
+//	FsaCommData.AdapterTimeout = RtlConvertLongToLargeInteger(-10*1000*1000*NewValue);
+	return (STATUS_SUCCESS);
+}
+
+/*++
+
+Routine Description:
+    This is the initialization routine for the FileArray Comm layer device driver.
+
+Arguments:
+
+
+Return Value:
+
+    u32 - The function value is the final status from the initialization
+        operation.
+
+--*/
+u32 AacCommDriverEntry(void)
+{
+	//
+	// Load the global timeout value for the adapter timeout
+	// Also init the global that enables or disables adapter timeouts
+	//
+	FsaCommData.FibTimeoutSeconds = 180;
+	FsaCommData.EnableAdapterTimeouts = TRUE; 
+	FsaCommData.EnableInterruptModeration = FALSE;
+	return STATUS_SUCCESS;
+}
+
+int AfaPortAllocateAdapterCommArea(struct aac_dev *dev, void **CommHeaderAddress, unsigned long CommAreaSize, unsigned long CommAreaAlignment)
+{
+	unsigned char *base;
+	unsigned long size, BytesToAlign;
+	unsigned long fibsize = 4096;
+	unsigned long PrintfBufferSize = 256;
+	PADAPTER_INIT_STRUCT init;
+	extern int MiniPortRevision;
+	unsigned long phys;
+
+	size = fibsize + sizeof(ADAPTER_INIT_STRUCT) + CommAreaSize + CommAreaAlignment + PrintfBufferSize;
+
+
+	OsAllocCommPhysMem(dev, size, (unsigned long **)&base, &phys);
+
+	dev->CommAddress  = (void *)base;
+	dev->CommPhysAddr = phys;
+	dev->CommSize     = size;
+
+	dev->InitStruct = (PADAPTER_INIT_STRUCT)(base + fibsize);
+	dev->PhysicalInitStruct = (PADAPTER_INIT_STRUCT)(phys + fibsize);
+
+	init = dev->InitStruct;
+
+	init->InitStructRevision = ADAPTER_INIT_STRUCT_REVISION;
+	init->MiniPortRevision = MiniPortRevision;
+	init->FilesystemRevision = dev->FilesystemRevision;
+
+	//
+	// Adapter Fibs are the first thing allocated so that they start page aligned
+	//
+	init->AdapterFibsVirtualAddress = base;
+	init->AdapterFibsPhysicalAddress = (void *) phys;
+	init->AdapterFibsSize = fibsize;
+	init->AdapterFibAlign = sizeof(struct hw_fib);
+
+	//
+	// Increment the base address by the amount already used
+	//
+	base = base + fibsize + sizeof(ADAPTER_INIT_STRUCT);
+	phys = phys + fibsize + sizeof(ADAPTER_INIT_STRUCT);
+
+	//
+	// Align the beginning of Headers to CommAreaAlignment
+	//
+	BytesToAlign = (CommAreaAlignment - ((unsigned long)(base) & (CommAreaAlignment - 1)));
+	base = base + BytesToAlign;
+	phys = phys + BytesToAlign;
+	//
+	// Fill in addresses of the Comm Area Headers and Queues
+	//
+	*CommHeaderAddress = (unsigned long *)base;
+	init->CommHeaderAddress = (void *)phys;
+	//
+	//	Increment the base address by the size of the CommArea
+	//
+	base = base + CommAreaSize;
+	phys = phys + CommAreaSize;
+	//
+	// Place the Printf buffer area after the Fast I/O comm area.
+	//
+	dev->PrintfBufferAddress = (void *)base;
+	init->PrintfBufferAddress = (void *)phys;
+	init->PrintfBufferSize = PrintfBufferSize;
+	memset(base, 0, PrintfBufferSize);
+	return TRUE;
+}
+    
+static void aac_queue_init(struct aac_dev * dev, PCOMM_QUE Queue, QUEUE_TYPES WhichQueue)
+{
+	Queue->NumOutstandingIos = 0;
+	Queue->Adapter = dev;
+	InitializeListHead(&Queue->OutstandingIoQueue);
+	    
+	/*
+	 *	FIXME: surely this can be done even if they are not needed
+	 */
+	switch (WhichQueue) {
+        case HostNormCmdQueue:
+        case HostHighCmdQueue:
+		init_waitqueue_head(&Queue->CommandReady);
+		InitializeListHead(&Queue->CommandQueue);
+		break;
+        case HostNormRespQueue:
+	case HostHighRespQueue:
+		break;
+        case AdapNormCmdQueue:
+        case AdapHighCmdQueue:
+        case AdapNormRespQueue:
+        case AdapHighRespQueue:
+		init_waitqueue_head(&Queue->QueueFull);
+		break;
+	}
+}
+
+/**
+ *	aac_send_shutdown		-	shutdown an adapter
+ *	@dev: Adapter to shutdown
+ *
+ *	This routine will send a VM_CloseAll (shutdown) request to the adapter.
+ */
+
+u32 aac_send_shutdown(struct aac_dev * dev)
+{
+	struct fib * fibctx;
+	PCLOSECOMMAND cmd;
+	u32 status;
+
+	fibctx = fib_alloc(dev);
+	fib_init(fibctx);
+
+	cmd = (PCLOSECOMMAND) fib_data(fibctx);
+
+	cmd->Command = VM_CloseAll;
+	cmd->ContainerId = 0xffffffff;
+
+	status = fib_send( ContainerCommand, fibctx, sizeof(CLOSECOMMAND), FsaNormal, TRUE, NULL, TRUE, NULL, NULL );
+
+	if (status == STATUS_SUCCESS)
+		fib_complete(fibctx);
+	fib_free(fibctx);
+	return status;
+}
+
+
+/*++
+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.
+--*/
+
+int AacCommDetachAdapter (struct aac_dev *detach)
+{
+	struct aac_dev **dev = &FsaCommData.AdapterList;
+	
+	while(*dev)
+	{
+		if(*dev == detach)
+		{
+			*dev = detach->next;
+			aac_send_shutdown(detach);
+			FsaFreeFibContextZone(detach);
+			AfaPortFreeAdapterCommArea(detach);
+			// FIXME _ CommRegion wants pci maps
+			kfree(detach->CommRegion);
+			return TRUE;
+		}
+		dev=&((*dev)->next);
+	}
+	BUG();
+	return FALSE;
+}
+
+struct aac_dev *AfaCommInitNewAdapter (struct aac_dev *dev)
+{
+	//
+	// Ok now init the communication subsystem
+	//
+	dev->CommRegion = (PCOMM_REGION) kmalloc(sizeof(COMM_REGION), GFP_KERNEL);
+	if (dev->CommRegion == NULL) {
+		printk(KERN_ERR "Error could not allocate comm region.\n");
+		return NULL;
+	}
+	memset(dev->CommRegion, 0, sizeof(COMM_REGION));
+
+	if (!CommInit(dev))
+		return NULL;
+	//
+	// Initialize the list of AdapterFibContext's.
+	//
+	InitializeListHead(&dev->fib_list);
+
+	//
+	// Initialize the fast mutex used for synchronization of the adapter fibs
+	//
+	spin_lock_init(&dev->fib_lock);
+
+
+	//
+	// Add this adapter in to our dev List.
+	//
+	dev->next = FsaCommData.AdapterList;
+	FsaCommData.AdapterList = dev;
+	return dev;
+}
+
+    
+/**
+ *	CommInit	-	Initialise FSA data structures
+ *	@dev:	Adapter to intialise
+ *
+ *	Initializes the data structures that are required for the FSA commuication
+ *	interface to operate. 
+ *	Returns
+ *		TRUE - if we were able to init the commuication interface.
+ *		FALSE - If there were errors initing. This is a fatal error.
+ */
+ 
+int CommInit(struct aac_dev * dev)
+{
+	unsigned long hdrsize = (sizeof(QUEUE_INDEX) * NUMBER_OF_COMM_QUEUES) * 2;
+	unsigned long queuesize = sizeof(QUEUE_ENTRY) * TOTAL_QUEUE_ENTRIES;
+	PQUEUE_INDEX headers;
+	PQUEUE_ENTRY queues;
+	unsigned long size;
+	PCOMM_REGION comm = dev->CommRegion;
+
+	//
+	//  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.
+	//
+	spin_lock_init(&dev->FibContextZoneSpinLock);
+	dev->FibContextZoneExtendSize = 64;
+
+	//
+	//
+	// Allocate the physically contigous space for the commuication queue
+	// headers. 
+	//
+
+	size = hdrsize + queuesize;
+
+	dprintk(("PORTALLOC\n"));
+	if (!AfaPortAllocateAdapterCommArea(dev, (void * *)&headers, size, QUEUE_ALIGNMENT))
+		return FALSE;
+	dprintk(("PORTALLOC-OK\n"));
+
+	queues = (PQUEUE_ENTRY)((unsigned char *)headers + hdrsize);
+
+	// Adapter to Host normal priority Command queue
+	comm->HostNormCmdQue.Headers.ProducerIndex = headers++;
+	comm->HostNormCmdQue.Headers.ConsumerIndex = headers++;
+	*comm->HostNormCmdQue.Headers.ProducerIndex = HOST_NORM_CMD_ENTRIES;
+	*comm->HostNormCmdQue.Headers.ConsumerIndex = HOST_NORM_CMD_ENTRIES;
+
+	comm->HostNormCmdQue.SavedIrql = 0;
+	comm->HostNormCmdQue.BaseAddress = queues;
+	comm->HostNormCmdQue.QueueEntries = HOST_NORM_CMD_ENTRIES;
+	spin_lock_init(&comm->HostNormCmdQue.QueueLockData);
+	comm->HostNormCmdQue.QueueLock=&comm->HostNormCmdQue.QueueLockData;
+	aac_queue_init(dev, &comm->HostNormCmdQue, HostNormCmdQueue);
+
+    
+	queues += HOST_NORM_CMD_ENTRIES;
+
+	// Adapter to Host high priority command queue
+    
+	comm->HostHighCmdQue.Headers.ProducerIndex = headers++;
+	comm->HostHighCmdQue.Headers.ConsumerIndex = headers++;
+	*comm->HostHighCmdQue.Headers.ProducerIndex = HOST_HIGH_CMD_ENTRIES;
+	*comm->HostHighCmdQue.Headers.ConsumerIndex = HOST_HIGH_CMD_ENTRIES;
+
+	comm->HostHighCmdQue.SavedIrql = 0;
+	comm->HostHighCmdQue.BaseAddress = queues;
+	comm->HostHighCmdQue.QueueEntries = HOST_HIGH_CMD_ENTRIES;
+	spin_lock_init(&comm->HostHighCmdQue.QueueLockData);
+	comm->HostHighCmdQue.QueueLock=&comm->HostHighCmdQue.QueueLockData;
+	aac_queue_init(dev, &comm->HostHighCmdQue, HostHighCmdQueue);
+    
+	queues += HOST_HIGH_CMD_ENTRIES;
+
+	// Host to adapter normal priority command queue
+    
+	comm->AdapNormCmdQue.Headers.ProducerIndex = headers++;
+	comm->AdapNormCmdQue.Headers.ConsumerIndex = headers++;
+	*comm->AdapNormCmdQue.Headers.ProducerIndex = ADAP_NORM_CMD_ENTRIES;
+	*comm->AdapNormCmdQue.Headers.ConsumerIndex = ADAP_NORM_CMD_ENTRIES;
+
+	comm->AdapNormCmdQue.SavedIrql = 0;    
+	comm->AdapNormCmdQue.BaseAddress = queues;
+	comm->AdapNormCmdQue.QueueEntries = ADAP_NORM_CMD_ENTRIES;
+	aac_queue_init(dev, &comm->AdapNormCmdQue, AdapNormCmdQueue);
+    
+	queues += ADAP_NORM_CMD_ENTRIES;
+
+	// host to adapter high priority command queue
+   
+	comm->AdapHighCmdQue.Headers.ProducerIndex = headers++;
+	comm->AdapHighCmdQue.Headers.ConsumerIndex = headers++;
+	*comm->AdapHighCmdQue.Headers.ProducerIndex = ADAP_HIGH_CMD_ENTRIES;
+	*comm->AdapHighCmdQue.Headers.ConsumerIndex = ADAP_HIGH_CMD_ENTRIES;
+
+	comm->AdapHighCmdQue.SavedIrql = 0;    
+	comm->AdapHighCmdQue.BaseAddress = queues;
+	comm->AdapHighCmdQue.QueueEntries = ADAP_HIGH_CMD_ENTRIES;
+	aac_queue_init(dev, &comm->AdapHighCmdQue, AdapHighCmdQueue);
+    
+	queues += ADAP_HIGH_CMD_ENTRIES;
+
+	// adapter to host normal priority response queue
+    
+	comm->HostNormRespQue.Headers.ProducerIndex = headers++;
+	comm->HostNormRespQue.Headers.ConsumerIndex = headers++;
+	*comm->HostNormRespQue.Headers.ProducerIndex = HOST_NORM_RESP_ENTRIES;
+	*comm->HostNormRespQue.Headers.ConsumerIndex = HOST_NORM_RESP_ENTRIES;
+
+	comm->HostNormRespQue.SavedIrql = 0;    
+	comm->HostNormRespQue.BaseAddress = queues;
+	comm->HostNormRespQue.QueueEntries = HOST_NORM_RESP_ENTRIES;
+	spin_lock_init(&comm->HostNormRespQue.QueueLockData);
+	comm->HostNormRespQue.QueueLock=&comm->HostNormRespQue.QueueLockData;
+	aac_queue_init(dev, &comm->HostNormRespQue, HostNormRespQueue);
+    
+	queues += HOST_NORM_RESP_ENTRIES;
+
+	// adapter to host high priority response queue
+	comm->HostHighRespQue.Headers.ProducerIndex = headers++;
+	comm->HostHighRespQue.Headers.ConsumerIndex = headers++;
+	*comm->HostHighRespQue.Headers.ProducerIndex = HOST_HIGH_RESP_ENTRIES;
+	*comm->HostHighRespQue.Headers.ConsumerIndex = HOST_HIGH_RESP_ENTRIES;
+
+	comm->HostHighRespQue.SavedIrql = 0;    
+	comm->HostHighRespQue.BaseAddress = queues;
+	comm->HostHighRespQue.QueueEntries = HOST_HIGH_RESP_ENTRIES;
+	spin_lock_init(&comm->HostHighRespQue.QueueLockData);
+	aac_queue_init(dev, &comm->HostHighRespQue, HostHighRespQueue);
+   
+	queues += HOST_HIGH_RESP_ENTRIES;
+
+	// host to adapter normal priority response queue
+    
+	comm->AdapNormRespQue.Headers.ProducerIndex = headers++;
+	comm->AdapNormRespQue.Headers.ConsumerIndex = headers++;
+	*comm->AdapNormRespQue.Headers.ProducerIndex = ADAP_NORM_RESP_ENTRIES;
+	*comm->AdapNormRespQue.Headers.ConsumerIndex = ADAP_NORM_RESP_ENTRIES;
+	comm->AdapNormRespQue.SavedIrql = 0;    
+	comm->AdapNormRespQue.BaseAddress = queues;
+	comm->AdapNormRespQue.QueueEntries = ADAP_NORM_RESP_ENTRIES;
+	aac_queue_init(dev, &comm->AdapNormRespQue, AdapNormRespQueue);
+
+	queues += ADAP_NORM_RESP_ENTRIES;
+
+	// host to adapter high priority response queue
+    
+	comm->AdapHighRespQue.Headers.ProducerIndex = headers++;
+	comm->AdapHighRespQue.Headers.ConsumerIndex = headers++;
+	*comm->AdapHighRespQue.Headers.ProducerIndex = ADAP_HIGH_RESP_ENTRIES;
+	*comm->AdapHighRespQue.Headers.ConsumerIndex = ADAP_HIGH_RESP_ENTRIES;
+
+	comm->AdapHighRespQue.SavedIrql = 0;    
+	comm->AdapHighRespQue.BaseAddress = queues;
+	comm->AdapHighRespQue.QueueEntries = ADAP_HIGH_RESP_ENTRIES;
+	aac_queue_init(dev, &comm->AdapHighRespQue, AdapHighRespQueue);
+
+	comm->AdapNormCmdQue.QueueLock = comm->HostNormRespQue.QueueLock;
+	comm->AdapHighCmdQue.QueueLock = comm->HostHighRespQue.QueueLock;
+	comm->AdapNormRespQue.QueueLock = comm->HostNormCmdQue.QueueLock;
+	comm->AdapHighRespQue.QueueLock = comm->HostHighCmdQue.QueueLock;
+
+	return TRUE;
+}
+
+
+/**
+ *	AfaCommBugcheckHandler	-	shut down adapter on a bug check
+ *	@Buffer: unused
+ *	@Length: the size of the buffer
+ *
+ *	This routine will shutdown the adapter if there is a bugcheck and
+ * 	one day copy the shutdown data from the adapter response into the
+ *	buffer so it will show up in the host dump file.
+ */
+
+void AfaCommBugcheckHandler(void * Buffer, unsigned long Length)
+{
+	struct aac_dev * dev = FsaCommData.AdapterList;
+	while (dev) {
+		NotifyAdapter(dev, HostShutdown);
+		dev = dev->next;
+	}
+}	
+
+void AfaCommProbeDisks(struct aac_dev * dev)
+{
+	PMNTINFO info;
+	PMNTINFORESPONSE reply;
+	u32 status;
+	struct fib * fibctx;
+    
+	fibctx = fib_alloc(dev);
+
+	fib_init(fibctx);
+
+	info = (PMNTINFO) fibctx->fib->data;
+	info->Command = VM_NameServe;
+	info->MntCount = 0;
+	info->MntType = FT_FILESYS;
+
+	status = fib_send(ContainerCommand, fibctx, sizeof(MNTINFO),
+	                 FsaNormal, TRUE, NULL, TRUE, NULL, NULL);
+
+	reply = (PMNTINFORESPONSE) fibctx->fib->data;
+	if (reply->MntRespCount)
+		printk(KERN_INFO  "container found on adapter, size = 0x%x blocks\n", 
+				reply->MntTable[0].Capacity);
+	else
+		printk(KERN_INFO "no containers found on adapter\n");
+					
+	fib_complete(fibctx);
+	fib_free(fibctx);				 
+}
+
+
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/commsup.c linux.gamma/drivers/scsi/aacraid/commsup.c
--- linux.15p3/drivers/scsi/aacraid/commsup.c	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/commsup.c	Wed Nov 28 01:24:28 2001
@@ -0,0 +1,1239 @@
+/*++
+ * 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.
+ *
+ *
+ --*/
+
+#include "os.h"
+
+
+/*++
+Routine Description:
+	This routine will free all resources used by a given segment.
+Arguments:
+	dev - The adapter that this struct fib will communicate with.
+	zone - The segment to release resources from.
+Return Value:
+	TRUE - All resources were properly freed.
+	FALSE - An Error occured while freeing resources.
+--*/
+int FsaFreeFibContextSegment(struct aac_dev *dev, PFIB_CONTEXT_ZONE_SEGMENT zone)
+{
+	// FIXME - check nothing needed per FIB here
+	AfaPortUnmapAndFreeFibSpace(dev, &zone->mapping);
+	kfree(zone->segment);
+	kfree(zone);
+	return TRUE;
+}
+
+/*++
+Routine Description:
+	This routine will walk through the FibContextSegmentList and free up all
+	resources used by the FibContextZone.
+Arguments:
+	dev - The adapter that this struct fib will communicate with.
+Return Value:
+	TRUE - All resources were properly freed.
+	FALSE - An Error occured while freeing resources.
+--*/
+int FsaFreeFibContextZone(struct aac_dev * dev)
+{
+	PFIB_CONTEXT_ZONE_SEGMENT zone, next;
+	zone = dev->FibContextSegmentList;
+
+	while (zone) {
+		next = zone->next;
+		FsaFreeFibContextSegment(dev, zone);
+		zone = next;
+	}
+	return (TRUE);
+}
+
+int FsaExtendFibContextZone(struct aac_dev * dev)
+{
+	int growby;
+	unsigned long ZoneSegmentAllocSize, FibAllocSize;
+	void * segment;
+	struct fib * fibptr;
+	struct hw_fib * fib;
+	void * FibPhysicalAddress;
+	int i;
+	PFIB_CONTEXT_ZONE_SEGMENT zone;
+	unsigned long flags;
+	
+	//
+	// Allocate space to describe this zone segment.
+	//
+
+	dprintk((KERN_DEBUG "Entered FsaExtendFibContextZone.\n"));
+	zone = kmalloc(sizeof(FIB_CONTEXT_ZONE_SEGMENT), GFP_KERNEL);
+	if (zone == NULL)
+		return FALSE;
+
+	growby = dev->FibContextZoneExtendSize;
+	ZoneSegmentAllocSize = (growby * sizeof(struct fib)) + sizeof(ZONE_SEGMENT_HEADER);
+
+	segment = kmalloc(ZoneSegmentAllocSize, GFP_KERNEL);
+	if (segment == NULL) {
+		kfree(zone);
+		return (FALSE);
+	}	
+	memset(segment, 0, ZoneSegmentAllocSize );
+
+	zone->segment = segment;
+	zone->segsize = ZoneSegmentAllocSize;
+	zone->growby = growby;
+
+	FibAllocSize = growby * sizeof(struct hw_fib);
+
+	zone->mapping.Size = FibAllocSize;
+	AfaPortAllocateAndMapFibSpace(dev, &zone->mapping);
+
+	fib = zone->mapping.FibVirtualAddress;
+	FibPhysicalAddress = zone->mapping.FibPhysicalAddress;
+	memset(fib, 0, FibAllocSize);
+	// Account for the ZONE_SEGMENT_HEADER before the first actual fibptr.
+	for (i = 0, fibptr = (struct fib *)((unsigned char *)segment + sizeof(ZONE_SEGMENT_HEADER));
+		 i < growby; i++, fibptr++) {
+		fibptr->dev = dev;
+		fibptr->fib = fib;
+		fibptr->data = (void *) fibptr->fib->data;
+		init_MUTEX_LOCKED(&fibptr->event_wait);
+		spin_lock_init(&fibptr->event_lock);
+		fib->header.XferState = 0xffffffff;
+		fib->header.SenderSize = sizeof(struct hw_fib);
+		fibptr->LogicalFibAddress.LowPart = (unsigned long) FibPhysicalAddress;
+		fib = (struct hw_fib *)((unsigned char *)fib + sizeof(struct hw_fib));
+		FibPhysicalAddress = (void *)((unsigned char *)FibPhysicalAddress + sizeof(struct hw_fib));
+	}
+	//
+	// If FibContextZone.TotalSegmentSize is non-zero, then a zone has already been
+	// initialized, we just need to extend it.
+	//
+	if (dev->FibContextZone.TotalSegmentSize) {
+		spin_lock_irqsave(&dev->FibContextZoneSpinLock, flags);
+		ExExtendZone(&dev->FibContextZone, segment, ZoneSegmentAllocSize);
+		spin_unlock_irqrestore(&dev->FibContextZoneSpinLock, flags);
+	} else {
+		if (ExInitializeZone(&dev->FibContextZone, sizeof(struct fib),
+    	                      segment, ZoneSegmentAllocSize) != STATUS_SUCCESS)
+			BUG();
+	}
+	//
+	// Add this segment to the adapter's list of segments
+	//
+
+	zone->next = dev->FibContextSegmentList;
+	dev->FibContextSegmentList = zone;
+	return TRUE;
+}
+
+/*++
+Routine Description:
+    This routine creates a new struct fib record
+Arguments:
+	dev - The adapter that this struct fib will communicate with.
+Return Value:
+	struct fib * - returns a pointer to the newly allocate struct fib Record
+--*/
+
+struct fib * fib_alloc(struct aac_dev *dev)
+{
+	struct fib * fibptr;
+	int FullZoneLoopCounter = 0;
+        unsigned long flags;
+        
+        //
+	// 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.
+        //
+
+	spin_lock_irqsave(dev->FibContextZoneSpinLock, flags);
+
+	while (ExIsFullZone( &dev->FibContextZone )) 
+	{
+		if(++FullZoneLoopCounter > 10)
+			BUG();
+		spin_unlock_irqrestore(&dev->FibContextZoneSpinLock, flags);
+                // bmb debug
+                dprintk((KERN_DEBUG "Extending FibContextZone.\n"));
+		if (FsaExtendFibContextZone(dev) == FALSE) {
+			return NULL;
+		}
+		spin_lock_irqsave(&dev->FibContextZoneSpinLock, flags);
+	}
+	//
+	//  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.
+	//
+	fibptr = (struct fib *) ExAllocateFromZone( &dev->FibContextZone );
+	spin_unlock_irqrestore(dev->FibContextZoneSpinLock, flags);
+	//
+	//  Set the proper node type code and node byte size
+	//
+	fibptr->type = FSAFS_NTC_FIB_CONTEXT;
+	fibptr->size = sizeof( struct fib );
+	// 
+	// Null out fields that depend on being zero at the start of each I/O
+	//
+	fibptr->fib->header.XferState = 0;
+	fibptr->callback = NULL;
+	fibptr->callback_data = NULL;
+	//
+	//  return and tell the caller
+	//
+	return fibptr;
+}
+/*++
+Routine Description:
+	This routine deallocates and removes the specified struct fib record
+	from the Fsafs in memory data structures.  It should only be called
+	by FsaCompleteRequest.
+Arguments:
+   	fibptr - Supplies the struct fib to remove
+Return Value:
+	None
+--*/
+void fib_free(struct fib * fibptr)
+{
+	unsigned long flags;
+
+	ASSERT(fibptr->type == FSAFS_NTC_FIB_CONTEXT);
+
+	spin_lock_irqsave(fibptr->dev->FibContextZoneSpinLock, flags);
+
+	if (fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT) {
+		FsaCommData.TimedOutFibs++;
+		fibptr->next = fibptr->dev->FibContextTimedOutList;
+		fibptr->dev->FibContextTimedOutList = fibptr;
+	} else {
+		ASSERT(fibptr->fib->header.XferState == 0);
+		if (fibptr->fib->header.XferState != 0) {
+			printk(KERN_WARNING "fib_free, XferState != 0, fibptr = 0x%p, XferState = 0x%x\n", 
+					 fibptr, fibptr->fib->header.XferState);
+		}
+		ExFreeToZone( &fibptr->dev->FibContextZone, fibptr );
+	}	
+	spin_unlock_irqrestore(fibptr->dev->FibContextZoneSpinLock, flags);
+	//
+	//  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:
+	STATUS_SUCCESS if a Fib was returned to the caller.
+	STATUS_UNSUCCESSFUL if event was an invalid event. 
+--*/
+u32 fib_init(struct fib * fibptr)
+{
+	struct hw_fib * fib = fibptr->fib;
+
+	fib->header.StructType = TFib;
+	fib->header.Size = sizeof(struct hw_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(struct hw_fib);
+	return STATUS_SUCCESS;
+}
+
+/*++
+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:
+	STATUS_SUCCESS if a Fib was returned to the caller.
+	STATUS_UNSUCCESSFUL if event was an invalid event. 
+--*/
+
+u32 fib_dealloc(struct fib * fibptr)
+{
+	struct hw_fib * fib = fibptr->fib;
+	if(fib->header.StructType != TFib) 
+		BUG();
+	fib->header.XferState = 0;        
+	return(STATUS_SUCCESS);
+}
+
+//
+// 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.
+--*/
+int GetEntry (struct aac_dev * dev, QUEUE_TYPES WhichQueue, PQUEUE_ENTRY *entry, PQUEUE_INDEX Index, unsigned long *DontInterrupt)
+{
+	unsigned long QueueOffset;
+	int status;
+	PCOMM_REGION CommRegion;
+
+	CommRegion = dev->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;
+			printk(KERN_WARNING "dev High Command Queue full, %ld outstanding.\n",
+					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
+			printk(KERN_WARNING "dev Norm Command Queue full, %ld outstanding.\n",
+					CommRegion->AdapNormCmdQue.NumOutstandingIos);
+			status = FALSE;
+		} else {        
+			//
+			// The success case just falls through and returns the a valid queue entry.
+			//
+			*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;
+			printk(KERN_WARNING "dev High Resp Queue full, %ld outstanding.\n",
+					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; 
+			printk(KERN_WARNING "dev Norm Resp Queue full, %ld outstanding.\n",
+					CommRegion->AdapNormRespQue.NumOutstandingIos);
+		} else {        
+		       	//
+			// The success case just falls through and returns the a valid queue entry.
+			//
+
+	        	*entry = CommRegion->AdapNormRespQue.BaseAddress + *Index;
+			status = TRUE;
+		}     
+	} else {
+		printk(KERN_CRIT "GetEntry: invalid queue %d.\n", WhichQueue);
+		status = FALSE;
+	}
+	return status;
+}
+   
+
+
+
+int GetQueueEntryTimeouts = 0;
+
+static PCOMM_QUE queue_find(struct aac_dev *dev, QUEUE_TYPES index)
+{
+	PCOMM_REGION CommRegion;
+	CommRegion = dev->CommRegion;
+
+	switch(index)
+	{
+		case AdapHighCmdQueue:
+			return &CommRegion->AdapHighCmdQue;
+		case AdapNormCmdQueue:
+			return &CommRegion->AdapNormCmdQue;
+		case AdapHighRespQueue:
+        		return &CommRegion->AdapHighRespQue;
+		case AdapNormRespQueue:
+			return &CommRegion->AdapNormRespQue;
+		default:
+			return NULL;
+	}
+}
+
+static int queue_is_reply(PQUEUE_INDEX index)
+{
+	switch((int)index)
+	{
+		case AdapHighRespQueue:
+		case AdapNormRespQueue:
+			return 1;
+		default:
+			return 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.
+
+    fibptr 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. 
+
+--*/
+u32 GetQueueEntry (struct aac_dev * dev, PQUEUE_INDEX Index, QUEUE_TYPES WhichQueue, struct hw_fib * fib, int Wait, struct fib * fibptr, unsigned long *DontInterrupt)
+{
+	PQUEUE_ENTRY QueueEntry = NULL;
+	int MapAddress = FALSE;
+	PCOMM_REGION CommRegion;
+	PCOMM_QUE q;
+
+	CommRegion = dev->CommRegion;
+	
+	q = queue_find(dev, WhichQueue);
+	if(q==NULL)
+		BUG();
+		
+	spin_lock_irqsave(q->QueueLock, q->SavedIrql);
+	    
+	if (WhichQueue == AdapHighCmdQueue) 
+	{
+		// if no entries wait for some if caller wants to
+        	while ( !GetEntry(dev, AdapHighCmdQueue, &QueueEntry, Index, DontInterrupt) ) { 
+			printk(KERN_CRIT "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(dev, AdapNormCmdQueue, &QueueEntry, Index, DontInterrupt) ) { 
+			printk(KERN_CRIT "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(dev, 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(dev, 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 = (unsigned long)(fibptr->LogicalFibAddress.LowPart);
+	//
+	// Return
+	//
+	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.
+
+--*/
+u32 InsertQueueEntry(struct aac_dev * dev, QUEUE_INDEX Index,
+QUEUE_TYPES WhichQueue, unsigned long DontInterrupt) {
+	PCOMM_REGION CommRegion; PCOMM_QUE q = queue_find(dev,
+	WhichQueue);
+
+	CommRegion = dev->CommRegion;
+	
+	if(q == NULL) BUG();
+	//
+	// We have already verified the queue in getentry, but we still have
+	// to make sure we don't wrap here too.
+	//
+
+	*(q->Headers.ProducerIndex) = Index + 1;
+	spin_unlock_irqrestore(q->QueueLock, q->SavedIrql);
+
+	if (WhichQueue == AdapHighCmdQueue) {
+		if (!DontInterrupt) NotifyAdapter(dev, AdapHighCmdQue);
+	}
+	else if (WhichQueue == AdapNormCmdQueue) {
+		if (!DontInterrupt) NotifyAdapter(dev, AdapNormCmdQue);
+	}
+	else if (WhichQueue == AdapHighRespQueue) {
+		if (!DontInterrupt) NotifyAdapter(dev, AdapHighRespQue);
+	}
+	else if (WhichQueue == AdapNormRespQueue) {
+		if (!DontInterrupt) NotifyAdapter(dev, AdapNormRespQue);
+	}
+	return(FSA_SUCCESS);
+}
+
+//
+// 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. 
+
+	--*/
+u32 fib_send(FIB_COMMAND Command, struct fib * fibptr, unsigned long Size,  COMM_PRIORITIES Priority, int Wait, void * WaitOn, int ResponseExpected, PCOMM_FIB_CALLBACK callback, void * callback_data)
+{
+	QUEUE_INDEX Index;
+	QUEUE_TYPES WhichQueue;
+	LARGE_INTEGER Timeout;
+	struct aac_dev * dev = fibptr->dev;
+	unsigned long DontInterrupt = FALSE;
+	struct hw_fib * fib = fibptr->fib;
+	PCOMM_QUE OurQueue;
+	unsigned long flags;
+
+	Timeout = FsaCommData.AdapterTimeout;
+
+	if (!(fib->header.XferState & HostOwned))
+		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) {
+		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 = (unsigned long)fibptr; // 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 = (unsigned long)fib;
+	fib->header.Command = Command;
+	fib->header.XferState |= SentFromHost;
+	fibptr->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 = &dev->CommRegion->AdapHighCmdQue;
+	} else {
+		fib->header.XferState |= NormalPriority;
+		WhichQueue = AdapNormCmdQueue;
+		OurQueue = &dev->CommRegion->AdapNormCmdQue;
+	}
+	if (Wait) {
+		spin_lock_irqsave(&fibptr->event_lock, flags);
+	}
+
+	if ( GetQueueEntry( dev, &Index, WhichQueue, fib, TRUE, fibptr, &DontInterrupt) != FSA_SUCCESS )
+		return(STATUS_UNSUCCESSFUL);
+		// bmb debug
+	dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",Index));
+	dprintk((KERN_DEBUG "Fib contents:.\n"));
+	dprintk((KERN_DEBUG "  Command =               %d.\n", fib->header.Command));
+	dprintk((KERN_DEBUG "  XferState  =            %x.\n", fib->header.XferState));
+
+	//
+	// Fill in the Callback and CallbackContext if we are not going to wait.
+	//
+	if (!Wait) {
+		fibptr->callback = callback;
+		fibptr->callback_data = callback_data;
+	}
+
+	FIB_COUNTER_INCREMENT(FsaCommData.FibsSent);
+	InsertTailList( &OurQueue->OutstandingIoQueue, &fibptr->queue);
+	OurQueue->NumOutstandingIos++;
+
+	fibptr->done = 0;
+
+	if(InsertQueueEntry( dev, 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) {
+		spin_unlock_irqrestore(&fibptr->event_lock, flags);
+		down(&fibptr->event_wait);
+		if(fibptr->done == 0)
+			BUG();
+			
+		if ( (fibptr->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( callback );
+
+	if (ResponseExpected)
+		return(STATUS_PENDING);
+	else
+		return(STATUS_SUCCESS);
+}
+
+int GetConsumerEntry(struct aac_dev * dev, PCOMM_QUE OurQueue, 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;
+	int 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;
+		status = TRUE;
+	}
+	return(status);
+}
+
+int ConsumerEntryAvailable(struct aac_dev * dev, PCOMM_QUE OurQueue)
+{
+	return (*OurQueue->Headers.ProducerIndex != *OurQueue->Headers.ConsumerIndex);
+}
+
+void FreeConsumerEntry(struct aac_dev * dev, 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.
+--*/
+{
+	int 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;
+		default:
+			BUG();
+			return;
+		}
+		NotifyAdapter(dev, Notify);
+	}
+}        
+
+u32 fib_adapter_complete(struct fib * fibptr, unsigned short 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
+	dev - Pointer to which adapter sent this FIB
+Return Value:
+	STATUS_SUCCESS if a Fib was returned to the caller.
+	STATUS_ERROR if event was an invalid event. 
+--*/
+{
+	struct hw_fib * fib = fibptr->fib;
+	struct aac_dev * dev = fibptr->dev;
+	unsigned long nointr = 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 ) {
+        	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(dev, &Index, AdapHighRespQueue, fib, TRUE, NULL, &nointr) != STATUS_SUCCESS) {
+				return(FSA_FATAL);
+			}
+			if (InsertQueueEntry(dev,  Index,  AdapHighRespQueue, 
+            					(nointr & (int)FsaCommData.EnableInterruptModeration)) != STATUS_SUCCESS) {
+			}
+		}
+		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(dev, &Index, AdapNormRespQueue, fib, TRUE, NULL, &nointr) != STATUS_SUCCESS) 
+			{
+				return(FSA_FATAL);
+			}
+			if (InsertQueueEntry(dev, Index, AdapNormRespQueue, 
+				(nointr & (int)FsaCommData.EnableInterruptModeration)) != STATUS_SUCCESS) 
+			{
+			}
+		}
+	}
+	else 
+	{
+        	printk(KERN_WARNING "fib_complete: Unknown xferstate detected.\n");
+        	BUG();
+	}   
+	return(STATUS_SUCCESS);
+}
+
+/*++
+
+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. 
+
+--*/
+u32 fib_complete(struct fib * fibptr)
+{
+	struct hw_fib * fib = fibptr->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 ) {
+        return(STATUS_UNSUCCESSFUL);
+    }
+
+	
+    //
+    // 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(fibptr->LogicalFibAddress.LowPart != 0);
+
+        return( fib_dealloc(fibptr) ); 
+	
+    //
+    // 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(fibptr->LogicalFibAddress.LowPart != 0);
+		return( fib_dealloc(fibptr) ); 
+	} else if (fib->header.XferState & HostOwned) {
+	        return(fib_dealloc(fibptr));
+	} else {
+	        printk(KERN_WARNING "fib_complete: Unknown xferstate detected.\n");
+		BUG();
+	}   
+	return STATUS_SUCCESS;
+}
+
+void HandleDriverAif(struct aac_dev * dev, struct fib * fibptr)
+/*++
+
+Routine Description:
+
+	This routine handles a driver notify fib from the adapter and dispatches it to 
+	the appropriate routine for handling.
+
+Arguments:
+
+	dev - Which adapter this fib is from
+	fibptr - Pointer to fibptr from adapter.
+    
+Return Value:
+
+    Nothing.
+    
+--*/
+{
+	struct hw_fib * fib = fibptr->fib;
+	//
+	// Set the status of this FIB to be Invalid parameter.
+	//
+	//	*(FSASTATUS *)fib->data = ST_INVAL;
+	*(FSASTATUS *)fib->data = ST_OK;
+	fib_adapter_complete(fibptr, sizeof(FSASTATUS));
+}
+
+/*++
+
+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.
+    
+--*/
+int NormCommandThread(struct aac_dev * dev)
+{
+	struct hw_fib *fib, *newfib;
+	struct fib fibptr; // for error logging
+	PCOMM_REGION CommRegion = dev->CommRegion;
+	PGET_ADAPTER_FIB_CONTEXT AdapterFibContext;
+	unsigned long flags;
+	DECLARE_WAITQUEUE(wait, current);
+	//
+	// We can only have one thread per adapter for AIF's.
+	//
+
+	if (dev->AifThreadStarted)
+		return -EINVAL;
+
+	//
+	// Let the DPC know it has a place to send the AIF's to.
+	//
+	dev->AifThreadStarted = TRUE;
+	memset(&fibptr, 0, sizeof(struct fib));
+	
+	add_wait_queue(&CommRegion->HostNormCmdQue.CommandReady, &wait);
+
+	set_current_state(TASK_INTERRUPTIBLE);
+
+	while(1) 
+	{
+		spin_lock_irqsave(CommRegion->HostNormCmdQue.QueueLock, flags);
+		while(!IsListEmpty(&(CommRegion->HostNormCmdQue.CommandQueue))) {
+			PLIST_ENTRY entry;
+			PAIFCOMMANDTOHOST AifCommandToHost;
+
+			set_current_state(TASK_RUNNING);
+			
+			entry = RemoveHeadList(&(CommRegion->HostNormCmdQue.CommandQueue));
+			spin_unlock_irqrestore(CommRegion->HostNormCmdQue.QueueLock, flags);
+			fib = CONTAINING_RECORD( entry, struct hw_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.
+			//
+			memset(&fibptr, 0, sizeof(struct fib));
+			fibptr.type = FSAFS_NTC_FIB_CONTEXT;
+			fibptr.size = sizeof( struct fib );
+			fibptr.fib = fib;
+			fibptr.data = fib->data;
+			fibptr.dev = dev;
+			//
+			// We only handle AifRequest fibs from the adapter.
+			//
+			ASSERT(fib->header.Command == AifRequest);
+			AifCommandToHost = (PAIFCOMMANDTOHOST) fib->data;
+			if (AifCommandToHost->command == AifCmdDriverNotify) {
+				HandleDriverAif( dev, &fibptr );
+			} else {
+				/* The u32 here is important and intended. We are using
+				   32bit wrapping time to fit the adapter field */
+				   
+				u32 time_now, time_last;
+				unsigned long flagv;
+				
+				time_now = jiffies/HZ;
+
+				spin_lock_irqsave(&dev->fib_lock, flagv);
+				entry = dev->fib_list.next;
+				//
+				// 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 != &dev->fib_list) {
+					//
+					// 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 = AdapterFibContext->jiffies;
+						//
+						// has it been > 2 minutes since the last read off the queue?
+						//
+						if ((time_now - time_last) > 120) {
+							entry = entry->next;
+							// printk (KERN_WARNING "aifd: Flushing orphaned AdapterFibContext: idle %d seconds, %d fibs",
+							//		 time_now - time_last,
+							//		 AdapterFibContext->FibCount);
+							FsaCloseAdapterFibContext ( dev, AdapterFibContext );
+							continue;
+						}
+					}
+					//  Warning: no sleep allowed while holding spinlock
+					newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC);
+					if (newfib) {
+						//
+						// Make the copy of the FIB
+						//
+						memcpy(newfib, fib, sizeof(struct hw_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.
+						//
+						up(&AdapterFibContext->UserEvent);
+					} else {
+						printk(KERN_WARNING "aifd: didn't allocate NewFib.\n");
+					}
+					entry = entry->next;
+				}
+				//
+				// Set the status of this FIB
+				//
+				*(FSASTATUS *)fib->data = ST_OK;
+				fib_adapter_complete( &fibptr, sizeof(FSASTATUS) );
+				spin_unlock_irqrestore(&dev->fib_lock, flagv);
+			}
+			spin_lock_irqsave(CommRegion->HostNormCmdQue.QueueLock, flags);
+		}
+		//
+		// There are no more AIF's,  call cv_wait_sig to wait for more
+		// to process.
+		//
+		spin_unlock_irqrestore(CommRegion->HostNormCmdQue.QueueLock, flags);
+		schedule();
+
+		if(signal_pending(current))
+		{
+			remove_wait_queue(&CommRegion->HostNormCmdQue.CommandReady, &wait);
+			dev->AifThreadStarted = FALSE;
+			return -EINTR;
+		}				 
+		set_current_state(TASK_INTERRUPTIBLE);
+	}
+}
+    
+
+void *fib_data(struct fib * fibctx)
+{
+	return ((void *)fibctx->fib->data);
+}	    
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/dpcsup.c linux.gamma/drivers/scsi/aacraid/dpcsup.c
--- linux.15p3/drivers/scsi/aacraid/dpcsup.c	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/dpcsup.c	Wed Nov 28 01:05:15 2001
@@ -0,0 +1,231 @@
+/*
+ * 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.
+ *
+ *
+ --*/
+
+#include "os.h"
+
+/*++
+
+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.
+
+    q is a pointer to the queue structure we will operate on.
+
+Return Value:
+    Nothing.
+
+--*/
+unsigned int HostResponseNormalDpc (PCOMM_QUE q)
+{
+	struct aac_dev * dev = q->Adapter;
+	PQUEUE_ENTRY QueueEntry;
+	struct hw_fib * fib;
+	struct fib * fibctx;
+	int Consumed = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(q->QueueLock, flags);	
+
+	//
+	// 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( dev, q, &QueueEntry) ) {
+		int IsFastResponse;
+
+		IsFastResponse = (int) (QueueEntry->FibAddress & 0x01);
+		fib = (struct hw_fib *) (QueueEntry->FibAddress & ~0x01);
+		FreeConsumerEntry(dev, q, HostNormRespQueue);
+		fibctx = (struct fib *)fib->header.SenderData;
+		ASSERT(fibctx->fib == fib);
+
+		//
+		// Remove this fibctx 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 (!(fibctx->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
+			RemoveEntryList(&fibctx->queue);
+			dev->CommRegion->AdapNormCmdQue.NumOutstandingIos--;
+		} else {
+			printk(KERN_WARNING "aacraid: FIB timeout.\n");
+			continue;
+		}
+		spin_unlock_irqrestore(q->QueueLock, flags);
+
+		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) {
+				*pStatus = ST_OK;
+			}
+		}
+
+		if (fib->header.XferState & (NoResponseExpected | Async) ) 
+		{
+			ASSERT(fibctx->callback);
+
+	        	if (fib->header.XferState & NoResponseExpected)
+				FIB_COUNTER_INCREMENT(FsaCommData.NoResponseRecved);
+			else 
+				FIB_COUNTER_INCREMENT(FsaCommData.AsyncRecved);
+			//
+			// NOTE:  we can not touch the fibctx after this call, because it may have been
+			// deallocated.
+			//
+			fibctx->callback(fibctx->callback_data, fibctx, STATUS_SUCCESS);
+		} else {
+			unsigned long flagv;
+			spin_lock_irqsave(&fibctx->event_lock, flagv);
+			fibctx->done = 1;
+			up(&fibctx->event_wait);
+			spin_unlock_irqrestore(&fibctx->event_lock, flagv);
+			FIB_COUNTER_INCREMENT(FsaCommData.NormalRecved);
+		}
+		Consumed++;
+		spin_lock_irqsave(q->QueueLock, flags);
+	}
+
+	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( dev, HostNormRespQue, FALSE );
+
+		if (ConsumerEntryAvailable( dev, q ) ) {
+			DisableInterrupt( dev, HostNormRespQue, FALSE );
+			goto loop;
+		}
+	}
+	spin_unlock_irqrestore(q->QueueLock, flags);
+	return 0;
+}
+
+
+/*++
+
+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.
+
+    q 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.
+
+--*/
+unsigned int HostCommandNormDpc (PCOMM_QUE q)
+{
+	struct aac_dev * dev = q->Adapter;
+	PQUEUE_ENTRY QueueEntry;
+	unsigned long flags;
+
+	spin_lock_irqsave(q->QueueLock, flags);
+
+	//
+	// 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(dev, q, &QueueEntry))
+	{
+		struct hw_fib * fib;
+		fib = (struct hw_fib *)QueueEntry->FibAddress;
+
+		if (dev->AifThreadStarted) {
+		        InsertTailList(&q->CommandQueue, &fib->header.FibLinks);
+	 	        FreeConsumerEntry(dev, q, HostNormCmdQueue);
+		        wake_up_interruptible(&q->CommandReady);
+		} else {
+			struct fib fibctx;
+	 	        FreeConsumerEntry(dev, q, HostNormCmdQueue);
+			spin_unlock_irqrestore(q->QueueLock, flags);
+			memset(&fibctx, 0, sizeof(struct fib));
+			fibctx.type = FSAFS_NTC_FIB_CONTEXT;
+			fibctx.size = sizeof(struct fib);
+			fibctx.fib = fib;
+			fibctx.data = fib->data;
+			fibctx.dev = dev;
+
+			//
+			// Set the status of this FIB
+			//
+
+			*(FSASTATUS *)fib->data = ST_OK;
+			fib_adapter_complete( &fibctx, sizeof(FSASTATUS) );
+			spin_lock_irqsave(q->QueueLock, flags);
+		}		
+	}
+	spin_unlock_irqrestore(q->QueueLock, flags);
+	return 0;
+}
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/AacGenericTypes.h linux.gamma/drivers/scsi/aacraid/include/AacGenericTypes.h
--- linux.15p3/drivers/scsi/aacraid/include/AacGenericTypes.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/AacGenericTypes.h	Tue Nov 20 12:33:57 2001
@@ -0,0 +1,43 @@
+/*++
+ * 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
+
+//
+// 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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/aac_unix_defs.h linux.gamma/drivers/scsi/aacraid/include/aac_unix_defs.h
--- linux.15p3/drivers/scsi/aacraid/include/aac_unix_defs.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/aac_unix_defs.h	Wed Nov 28 00:23:09 2001
@@ -0,0 +1,218 @@
+/*++
+ * 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
+
+#define 	AAC_MAX_ADAPTERS	64
+
+#ifndef	TRUE
+#define TRUE	1
+#define FALSE	0
+#endif
+
+#define PAGE_SIZE	4096
+
+typedef struct {
+	unsigned long	LowPart;
+	unsigned long	HighPart;
+} LARGE_INTEGER;
+
+typedef LARGE_INTEGER	PHYSICAL_ADDRESS;
+
+//
+//  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 *)( \
+                                                  (char *)(address) - \
+                                                  (char *)(&((type *)0)->field)))
+
+typedef void *	PFILE_OBJECT;
+
+#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
+
+//
+// Zone Allocation
+//
+
+typedef struct _ZONE_SEGMENT_HEADER {
+    SINGLE_LIST_ENTRY SegmentList;
+    void * Reserved;
+} ZONE_SEGMENT_HEADER, *PZONE_SEGMENT_HEADER;
+
+typedef struct _ZONE_HEADER {
+    SINGLE_LIST_ENTRY FreeList;
+    SINGLE_LIST_ENTRY SegmentList;
+    unsigned long BlockSize;
+    unsigned long TotalSegmentSize;
+} ZONE_HEADER, *PZONE_HEADER;
+
+
+//++
+//
+// void *
+// ExAllocateFromZone(
+//     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) \
+    (void *)((Zone)->FreeList.Next); \
+    if ( (Zone)->FreeList.Next ) (Zone)->FreeList.Next = (Zone)->FreeList.Next->Next
+
+
+//++
+//
+// BOOLEAN
+// ExIsFullZone(
+//     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 )
+
+
+//
+//  Doubly-linked list manipulation routines.  Implemented as macros
+//  but logically these are procedures.
+//
+
+//
+//  VOID
+//  InitializeListHead(
+//      PLIST_ENTRY head
+//      );
+//
+
+#define InitializeListHead(head) (\
+    (head)->next = (head)->prev = (head))
+
+//
+//  BOOLEAN
+//  IsListEmpty(
+//      PLIST_ENTRY head
+//      );
+//
+
+#define IsListEmpty(head) \
+    ((head)->next == (head))
+
+//
+//  PLIST_ENTRY
+//  RemoveHeadList(
+//      PLIST_ENTRY head
+//      );
+//
+
+#define RemoveHeadList(head) \
+    (head)->next;\
+    {RemoveEntryList((head)->next)}
+
+
+//
+//  VOID
+//  RemoveEntryList(
+//      PLIST_ENTRY entry
+//      );
+//
+
+#define RemoveEntryList(entry) {\
+    PLIST_ENTRY _EX_prev;\
+    PLIST_ENTRY _EX_next;\
+    _EX_next = (entry)->next;\
+    _EX_prev = (entry)->prev;\
+    _EX_prev->next = _EX_next;\
+    _EX_next->prev = _EX_prev;\
+    }
+
+//
+//  VOID
+//  InsertTailList(
+//      PLIST_ENTRY head,
+//      PLIST_ENTRY entry
+//      );
+//
+
+#define InsertTailList(head,entry) {\
+    PLIST_ENTRY _EX_prev;\
+    PLIST_ENTRY _EX_head;\
+    _EX_head = (head);\
+    _EX_prev = _EX_head->prev;\
+    (entry)->next = _EX_head;\
+    (entry)->prev = _EX_prev;\
+    _EX_prev->next = (entry);\
+    _EX_head->prev = (entry);\
+    }
+
+#endif /* AAC_UNIX_DEFS */
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/adapter.h linux.gamma/drivers/scsi/aacraid/include/adapter.h
--- linux.15p3/drivers/scsi/aacraid/include/adapter.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/adapter.h	Wed Nov 28 00:20:33 2001
@@ -0,0 +1,134 @@
+/*++
+ * 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_
+
+typedef struct _GET_ADAPTER_FIB_CONTEXT {
+	NODE_TYPE_CODE 		type;	// used for verification of structure	
+	NODE_BYTE_SIZE 		size;
+	u32			jiffies;	// used for cleanup
+	LIST_ENTRY		NextContext;	// used to link context's into a linked list
+	struct semaphore 	UserEvent;	// this is used to wait for the next fib to arrive.
+	int			WaitingForFib;	// Set to true when thread is in WaitForSingleObject
+	unsigned long		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;
+	unsigned long	segsize;
+	void *		segment;
+	unsigned long	growby;
+	struct fib_context mapping;
+} FIB_CONTEXT_ZONE_SEGMENT;
+typedef FIB_CONTEXT_ZONE_SEGMENT *PFIB_CONTEXT_ZONE_SEGMENT;
+
+struct aac_dev
+{
+	struct aac_dev	*next;
+	const char	*name;
+	int		id;
+
+	u16		irq_mask;
+	 //
+	//  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;
+	spinlock_t			FibContextZoneSpinLock;
+	int 				FibContextZoneExtendSize;
+	PFIB_CONTEXT_ZONE_SEGMENT	FibContextSegmentList;
+	void *				FibContextTimedOutList;
+	PCOMM_REGION			CommRegion;
+
+	//
+	// 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			fib_list;
+	spinlock_t			fib_lock;
+
+	FSAPORT_FUNCS			AdapterFuncs;
+	unsigned long			FilesystemRevision; 	// Main driver's revision number
+	
+	
+	PADAPTER_INIT_STRUCT		InitStruct;				// Holds initialization info to communicate with adapter
+	void *				PhysicalInitStruct; 	// Holds physical address of the init struct
+	
+	
+	void *				PrintfBufferAddress;	// pointer to buffer used for printf's from the adapter
+	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
+	//
+	// The following is the device specific extension.
+	//
+	union
+	{
+		PSa_DEVICE_REGISTERS Sa;
+		PRx_DEVICE_REGISTERS Rx;
+	} Device;
+	void				*Dip;
+	//
+	// The following is the number of the individual adapter..i.e. \Device\Afa0
+	//
+	long				devNumber;
+	AFACOMM_FUNCS			CommFuncs;
+	int				AifThreadStarted;
+};
+
+#define AllocateAndMapFibSpace(dev, MapFibContext) \
+	dev->AdapterFuncs.AllocateAndMapFibSpace(dev, MapFibContext)
+
+#define UnmapAndFreeFibSpace(dev, MapFibContext) \
+	dev->AdapterFuncs.UnmapAndFreeFibSpace(dev, MapFibContext)
+
+#define InterruptAdapter(dev) \
+	dev->AdapterFuncs.InterruptAdapter(dev)
+
+#define NotifyAdapter(dev, AdapterEvent) \
+	dev->AdapterFuncs.NotifyAdapter(dev, AdapterEvent)
+
+#define EnableInterrupt(dev, AdapterEvent, AtDeviceIrq) \
+	dev->AdapterFuncs.EnableInterrupt(dev, AdapterEvent, AtDeviceIrq)
+
+#define DisableInterrupt(dev, AdapterEvent, AtDeviceIrq) \
+	dev->AdapterFuncs.DisableInterrupt(dev, AdapterEvent, AtDeviceIrq)
+
+
+#endif // _ADAPTER_
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/afacomm.h linux.gamma/drivers/scsi/aacraid/include/afacomm.h
--- linux.15p3/drivers/scsi/aacraid/include/afacomm.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/afacomm.h	Tue Nov 27 22:45:01 2001
@@ -0,0 +1,41 @@
+/*++
+ * 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_
+
+struct fib;
+
+typedef void (*PCOMM_FIB_CALLBACK)(void *FibCallbackContext, struct fib *FibContext, u32 Status);
+
+typedef struct _AFACOMM_FUNCS {
+	PFSA_ADAPTER_ADDR_TO_SYSTEM_ADDR	AdapterAddressToSystemAddress;
+} AFACOMM_FUNCS;
+typedef AFACOMM_FUNCS *PAFACOMM_FUNCS;
+
+#endif // _AFACOMM_
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/aifstruc.h linux.gamma/drivers/scsi/aacraid/include/aifstruc.h
--- linux.15p3/drivers/scsi/aacraid/include/aifstruc.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/aifstruc.h	Tue Nov 20 14:02:51 2001
@@ -0,0 +1,317 @@
+/*++
+ * 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
+
+#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	u32		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	u32		AifJobType;
+#endif
+
+union SrcContainer {
+	u32 from;
+	u32 master;
+	u32 container;
+};
+
+union DstContainer {
+	u32 to;
+	u32 slave;
+	u32 container;
+};
+
+
+struct AifContainers {
+	union SrcContainer src;
+	union DstContainer dst;
+};
+
+union AifJobClient {
+	
+	struct AifContainers container;	// For Container nd file system progress ops;
+	s32 scsi_dh;			// For SCSI progress ops
+};
+
+struct AifJobDesc {
+	u32 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;
+	u32 finalTick;
+	u32 currentTick;
+	u32 jobSpecificData1;
+	u32 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	u32				AifEventNotifyType;
+#endif
+
+struct AifEnsGeneric {
+	s8 text[132];				// Generic text
+};
+
+struct AifEnsDeviceFailure {
+	s32 deviceHandle;	// SCSI device handle
+};
+
+struct AifEnsMirrorFailover {
+	u32 container;		// Container with failed element
+	u32 failedSlice;		// Old slice which failed
+	u32 creatingSlice;	// New slice used for auto-create
+};
+
+struct AifEnsContainerChange {
+	u32 container[2];		// container that changed, -1 if no container
+};
+
+struct AifEnsContainerEvent {
+	u32 container;		// container number 
+	u32 eventType;		// event type
+};
+
+struct AifEnsEnclosureEvent {
+	u32 empID;				// enclosure management processor number 
+	u32 unitID;			// unitId, fan id, power supply id, slot id, tempsensor id. 
+	u32 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 {
+	u32	eventType;
+	u32	DsNum[2];
+	u32	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	u32				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 s8 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	u32		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
+	u32 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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/build_number.h linux.gamma/drivers/scsi/aacraid/include/build_number.h
--- linux.15p3/drivers/scsi/aacraid/include/build_number.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/build_number.h	Tue Nov 20 14:04:05 2001
@@ -0,0 +1,37 @@
+/*++
+ * 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 
+
+#define REV_BUILD_NUMBER 5125 
+
+
+#endif  // _BUILD_NUMBER_H 
+
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/commdata.h linux.gamma/drivers/scsi/aacraid/include/commdata.h
--- linux.15p3/drivers/scsi/aacraid/include/commdata.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/commdata.h	Tue Nov 27 17:05:21 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:
+ *   commdata.h
+ *
+ * Abstract: Define the communication layer of the adapter
+ *
+ *
+ *
+ --*/
+#ifndef _COMMDATA_
+#define _COMMDATA_
+
+typedef struct _FSA_COMM_DATA {
+	//
+	// A list of all adapters we have configured.
+	// 
+  
+	struct aac_dev * AdapterList;
+	unsigned long 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;
+	int EnableAdapterTimeouts;
+
+	unsigned long FibTimeoutIncrement;
+  
+	unsigned long FibsSent;
+	unsigned long FibRecved;
+	unsigned long NoResponseSent;
+	unsigned long NoResponseRecved;
+	unsigned long AsyncSent;
+	unsigned long AsyncRecved;
+	unsigned long NormalSent;
+	unsigned long NormalRecved;
+	unsigned long TimedOutFibs;
+	
+	// 
+	// If this value is set to 1 then interrupt moderation will occur 
+	// in the base commuication support.
+	//
+	unsigned long EnableInterruptModeration;
+	int HardInterruptModeration;
+	int HardInterruptModeration1;
+	int PeakFibsConsumed;
+	int ZeroFibsConsumed;
+	int EnableFibTimeoutBreak;
+	unsigned long FibTimeoutSeconds;
+	unsigned long           MeterFlag;
+} FSA_COMM_DATA;
+
+typedef FSA_COMM_DATA *PFSA_COMM_DATA;
+
+extern FSA_COMM_DATA FsaCommData;
+
+
+#endif // _COMMDATA_
+
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/commerr.h linux.gamma/drivers/scsi/aacraid/include/commerr.h
--- linux.15p3/drivers/scsi/aacraid/include/commerr.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/commerr.h	Tue Nov 20 14:03:46 2001
@@ -0,0 +1,123 @@
+/*++
+ * 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_
+
+//
+//  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                ((u32)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    ((u32)0xA007000EL)
+
+#endif /* _FSAERR_ */
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/commfibcontext.h linux.gamma/drivers/scsi/aacraid/include/commfibcontext.h
--- linux.15p3/drivers/scsi/aacraid/include/commfibcontext.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/commfibcontext.h	Wed Nov 28 01:06:33 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:
+ *   commfibcontext.h
+ *
+ * Abstract: defines the _COMM_FIB_CONTEXT strcuture
+ *
+ *
+ *
+ --*/
+#ifndef _COMM_FIB_CONTEXT_
+#define _COMM_FIB_CONTEXT_
+
+struct fib {
+	void *		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 type;
+	NODE_BYTE_SIZE size;
+
+	//
+	//	The Adapter that this I/O is destined for.
+	//
+
+	struct aac_dev *dev;
+	PHYSICAL_ADDRESS LogicalFibAddress;	/* 64 bit */
+
+	//
+	// This is the event the sendfib routine will wait on if the
+	// caller did not pass one and this is synch io.
+	//
+
+	struct semaphore event_wait;
+	
+	//
+	// Lock the queue 
+	//
+	spinlock_t	event_lock;
+
+	unsigned long	done;	// gets set to 1 when fib is complete
+	PCOMM_FIB_CALLBACK callback;
+	void *callback_data;
+	unsigned long	flags;
+	//
+	// The following is used to put this fib context onto the Outstanding I/O queue.
+	//
+	LIST_ENTRY	queue;
+
+	void *	data;
+	struct hw_fib *fib;		/* Actual shared object */
+} __attribute__((aligned(64)));		/* FIXME: check if needed */
+
+#define FIB_CONTEXT_FLAG_TIMED_OUT		(0x00000001)
+
+#endif /* _COMM_FIB_CONTEXT_ */
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/comprocs.h linux.gamma/drivers/scsi/aacraid/include/comprocs.h
--- linux.15p3/drivers/scsi/aacraid/include/comprocs.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/comprocs.h	Tue Nov 27 09:07:02 2001
@@ -0,0 +1,82 @@
+/*++
+ * 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_
+
+#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
+
+#endif // _COMPROCS_
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/comproto.h linux.gamma/drivers/scsi/aacraid/include/comproto.h
--- linux.15p3/drivers/scsi/aacraid/include/comproto.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/comproto.h	Thu Nov 22 10:08:29 2001
@@ -0,0 +1,46 @@
+/*++
+ * 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
+
+//
+// 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.
+//
+
+#endif // _COMM_PROTO
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/comstruc.h linux.gamma/drivers/scsi/aacraid/include/comstruc.h
--- linux.15p3/drivers/scsi/aacraid/include/comstruc.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/comstruc.h	Wed Nov 28 00:24:10 2001
@@ -0,0 +1,398 @@
+/*++
+ * 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
+
+//
+// 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 u32 QUEUE_INDEX;
+
+typedef QUEUE_INDEX *PQUEUE_INDEX;
+
+typedef struct _QUEUE_ENTRY {
+    u32 Size;                     // Size in bytes of the Fib which this QE points to
+    u32 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 u32			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	u32				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	u32			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	u32		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	u32			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 *next;
+   struct _LIST_ENTRY *prev;
+} 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 {
+	u32 XferState;			// Current transfer state for this CCB
+	u16 Command;			// Routing information for the destination
+	u8 StructType;			// Type FIB
+	u8 Flags;			// Flags for FIB
+	u16 Size;			// Size of this FIB in bytes
+	u16 SenderSize;			// Size of the FIB in the sender (for response sizing)
+	u32 SenderFibAddress;		// Host defined data in the FIB
+	u32 ReceiverFibAddress;		// Logical address of this FIB for the adapter
+	u32 SenderData;			// Place holder for the sender to store data
+	union {
+		struct {
+		    u32 _ReceiverTimeStart; 	// Timestamp for receipt of fib
+		    u32 _ReceiverTimeDone;	// Timestamp for completion of fib
+		} _s;
+		LIST_ENTRY _FibLinks;	// Used to link Adapter Initiated Fibs on the host
+	} _u;
+} FIB_HEADER;
+
+#define FibLinks			_u._FibLinks
+
+#define FIB_DATA_SIZE_IN_BYTES (512 - sizeof(FIB_HEADER))
+
+
+struct hw_fib {
+	FIB_HEADER header;
+	u8 data[FIB_DATA_SIZE_IN_BYTES];		// Command specific data
+};
+
+//
+// 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 u16 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 {
+	u32		InitStructRevision;
+	u32		MiniPortRevision;
+	u32		FilesystemRevision;
+	void *		CommHeaderAddress;
+	void *		FastIoCommAreaAddress;
+	void *		AdapterFibsPhysicalAddress;
+	void *		AdapterFibsVirtualAddress;
+	u32		AdapterFibsSize;
+	u32		AdapterFibAlign;
+	void *		PrintfBufferAddress;
+	u32		PrintfBufferSize;
+	u32		HostPhysMemPages;		// number of 4k pages of host physical memory
+	u32		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	u32		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	u32		LOG_LEVEL;
+#endif
+
+
+#endif //_COMM_STRUCT
+
+
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/comsup.h linux.gamma/drivers/scsi/aacraid/include/comsup.h
--- linux.15p3/drivers/scsi/aacraid/include/comsup.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/comsup.h	Tue Nov 27 19:23:09 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:
+ *   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
+
+//
+// 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
+	u32	 		QueueEntries;   	// Number of queue entries on this queue
+	wait_queue_head_t	QueueFull;      	// Event to wait on if the queue is full
+	wait_queue_head_t	CommandReady;   	// Indicates there is a Command ready from the adapter on this queue.
+                                        		// This is only valid for adapter to host command queues.                                        
+	spinlock_t	 	*QueueLock;     	// Spinlock for this queue must take this lock before accessing the lock
+	spinlock_t		QueueLockData;		// Actual lock (used only on one side of the lock)
+	unsigned long		SavedIrql;      	// Previous IRQL when the spin lock is taken
+	u32			Padding;		// Padding - FIXME - can remove I believe
+	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.
+	unsigned long		NumOutstandingIos;	// Number of entries on outstanding queue.
+	void *			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
+
+	//
+	// 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
+	//
+
+//	OS_SOFTINTR *QueueNotFullDpc;
+} COMM_REGION;
+typedef COMM_REGION *PCOMM_REGION;
+
+int NormCommandThread(struct aac_dev * Adapter);
+
+#endif // _COMM_SUP
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/fsact.h linux.gamma/drivers/scsi/aacraid/include/fsact.h
--- linux.15p3/drivers/scsi/aacraid/include/fsact.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/fsact.h	Tue Nov 20 12:34:36 2001
@@ -0,0 +1,163 @@
+/*++
+ * 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_
+
+//#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	u32		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)
+*/
+	u32  fsTotalSize;	// consumed by fs, incl. metadata
+	u32  fsBlockSize;
+	u32  fsFragSize;
+	u32  fsMaxExtendSize;
+	u32  fsSpaceUnits;
+	u32  fsMaxNumFiles;
+	u32  fsNumFreeFiles;
+	u32  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 {
+
+   u32    ObjectId;
+   FSASTRING  FileSystemName;   // if applicable
+   ContainerCreationInfo   CreateInfo; // if applicable
+   u32    Capacity;
+   FSAVOLTYPE VolType;          // substrate structure
+   FTYPE      ObjType;          // FT_FILESYS, FT_DATABASE, etc.
+   u32     ContentState;     // unready for mounting, readonly, etc.
+
+   union ContentManagerInfo
+              ObjExtension;     // Info specific to content manager (eg, filesystem)
+
+   u32    AlterEgoId;       // != ObjectId <==> snapshot or broken mirror exists
+
+} MNTOBJ;
+
+
+#define FSCS_READONLY	0x0002	// possible result of broken mirror
+
+
+
+typedef struct _MNTINFO {
+
+   VMCOMMAND  Command;
+   FTYPE      MntType;
+   u32     MntCount;
+
+} MNTINFO;
+typedef MNTINFO *PMNTINFO;
+
+typedef struct _MNTINFORESPONSE {
+
+   FSASTATUS Status;
+   FTYPE     MntType;           // should be same as that requested
+   u32    MntRespCount;
+   MNTOBJ    MntTable[1];
+
+} MNTINFORESPONSE;
+typedef MNTINFORESPONSE *PMNTINFORESPONSE;
+
+
+//
+// The following command is sent to shut down each container.
+//
+
+typedef struct _CLOSECOMMAND {
+
+   VMCOMMAND  Command;
+   u32	  ContainerId;
+
+} CLOSECOMMAND;
+typedef CLOSECOMMAND *PCLOSECOMMAND;
+
+
+#endif /* _FSACT_H_ */
+
+
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/fsafs.h linux.gamma/drivers/scsi/aacraid/include/fsafs.h
--- linux.15p3/drivers/scsi/aacraid/include/fsafs.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/fsafs.h	Tue Nov 20 12:34:42 2001
@@ -0,0 +1,75 @@
+/*++
+ * 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
+
+#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 {u32  hint; // last used hint for fast reclaim
+		u32  f1;	  // opaque
+		u32  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 {
+		s8	fid_data[FIDSIZE];
+		struct	fhandle fsafid;
+	} fidu;
+} FSAFID;					/* FSA File ID type */
+
+								
+#endif /* _FSAFS_H_ */
+
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/fsaioctl.h linux.gamma/drivers/scsi/aacraid/include/fsaioctl.h
--- linux.15p3/drivers/scsi/aacraid/include/fsaioctl.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/fsaioctl.h	Tue Nov 20 12:34:50 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:
+ *   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_
+
+#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 {
+	s32	ContainerNumber;
+	s32	Bus;
+	s32	Target;
+	s32	Lun;
+	u32	Valid;
+	u32	Locked;
+	u32	Deleted;
+	s32	Instance;
+	s8	diskDeviceName[10];
+	u32 UnMapped;
+} UNIX_QUERY_DISK;
+typedef UNIX_QUERY_DISK *PUNIX_QUERY_DISK;
+
+
+typedef struct _DELETE_DISK {
+	u32	NtDiskNumber;
+	u32	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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/fsaport.h linux.gamma/drivers/scsi/aacraid/include/fsaport.h
--- linux.15p3/drivers/scsi/aacraid/include/fsaport.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/fsaport.h	Tue Nov 27 23:45:28 2001
@@ -0,0 +1,83 @@
+/*++
+ * 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_
+
+//
+// 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;
+	void * 		MapRegBase;
+	unsigned long 		NumberMapRegs;
+	PSGMAP		SgMapPtr;
+	unsigned long		ByteCount;		// Used to check the Mdl length.
+	int		WriteToDevice;
+	struct buf	*bp;
+} SGMAP_CONTEXT;
+typedef SGMAP_CONTEXT *PSGMAP_CONTEXT;
+
+struct fib_context
+{
+	// Removed 4 byte PMDL here..
+	void * 		MapRegBase;
+	unsigned long 	NumberMapRegs;
+	void *		FibVirtualAddress;
+	unsigned long	Size;
+	void *		FibPhysicalAddress;
+};
+
+struct aac_dev;
+
+typedef void (*PFSA_INTERRUPT_ADAPTER)(struct aac_dev *dev);
+typedef void (*PFSA_NOTIFY_ADAPTER)(struct aac_dev *dev, HOST_2_ADAP_EVENT AdapterEvent);
+typedef void (*PFSA_RESET_DEVICE)(struct aac_dev *dev);
+typedef void *(*PFSA_ADAPTER_ADDR_TO_SYSTEM_ADDR)(struct aac_dev *dev, void *AdapterAddress);
+typedef void (*PFSA_INTERRUPT_HOST)(struct aac_dev *Adapter, u32 AdapterEvent);
+typedef void (*PFSA_ENABLE_INTERRUPT)(struct aac_dev *Adapter, u32 AdapterEvent, int AtDeviceIrq);
+typedef void (*PFSA_DISABLE_INTERRUPT)(struct aac_dev *Adapter, u32 AdapterEvent, int AtDeviceIrq);
+
+typedef struct _FSAPORT_FUNCS {
+	PFSA_INTERRUPT_ADAPTER			InterruptAdapter;
+	PFSA_NOTIFY_ADAPTER			NotifyAdapter;
+	PFSA_ENABLE_INTERRUPT			EnableInterrupt;
+	PFSA_DISABLE_INTERRUPT			DisableInterrupt;
+	PFSA_ADAPTER_ADDR_TO_SYSTEM_ADDR	AdapterAddressToSystemAddress;
+	PFSA_INTERRUPT_HOST			InterruptHost;
+} FSAPORT_FUNCS;
+
+typedef FSAPORT_FUNCS *PFSAPORT_FUNCS;
+
+#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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/fsatypes.h linux.gamma/drivers/scsi/aacraid/include/fsatypes.h
--- linux.15p3/drivers/scsi/aacraid/include/fsatypes.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/fsatypes.h	Tue Nov 20 12:34:28 2001
@@ -0,0 +1,206 @@
+/*++
+ * 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
+
+//
+// Define a 64-bit address structure for use on
+// a 32-bit processor architecture.
+//
+typedef struct {
+	u32		lo32;
+	u32		hi32;
+} AAC_UINT64S, *PAAC_UINT64S;
+
+//
+// Container Types
+//
+typedef struct {
+   u32 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	u32		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	u32	FTYPE;
+#endif
+
+
+
+//
+// Host side memory scatter gather list
+// Used by the adapter for read, write, and readdirplus operations
+//
+typedef  u8 * HOSTADDRESS;
+
+typedef struct _SGENTRY {
+	u8 * 		SgAddress;		/* 32-bit Base address. */
+	u32		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 {
+	u32		SgCount;
+	SGENTRY			SgEntry[1];
+} SGMAP;
+typedef SGMAP *PSGMAP;
+
+
+
+//
+// SGMAP64
+//
+// This is the SGMAP structure for 64-bit container commands.
+//
+typedef struct _SGMAP64 {
+	u8	SgCount;
+	u8	SgSectorsPerPage;
+	u16	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 {
+
+	u32	tv_sec;		/* seconds (maybe, depends upon host) */
+	u32	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
+{
+
+	u8 		ViaBuildNumber;		// e.g., 588
+	u8 		MicroSecond;		// e.g., 588
+	u8	 	Via;				// e.g.,	1 = FSU,
+										//			2 = API,
+	u8	 	YearsSince1900; 	// e.g., 1997 = 97
+	u32		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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/linit.h linux.gamma/drivers/scsi/aacraid/include/linit.h
--- linux.15p3/drivers/scsi/aacraid/include/linit.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/linit.h	Wed Nov 28 01:14:51 2001
@@ -0,0 +1,86 @@
+/*++
+ * 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_
+
+#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_procinfo,	/* ProcFS Info Func           */ \
+	detect:         	aac_detect,		/* Detect Host Adapter        */ \
+	release:        	aac_release,		/* 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_biosparm,		/* 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	/* Enable Clustering          */ \
+}
+
+
+/*------------------------------------------------------------------------------
+ *              T Y P E D E F S / S T R U C T S
+ *----------------------------------------------------------------------------*/
+struct diskparm
+{
+	int heads;
+	int sectors;
+	int cylinders;
+};
+
+
+/*------------------------------------------------------------------------------
+ *              P R O G R A M   G L O B A L S
+ *----------------------------------------------------------------------------*/
+
+const char *aac_driverinfo(struct Scsi_Host *);
+
+#endif /* _LINIT_H_ */
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/monkerapi.h linux.gamma/drivers/scsi/aacraid/include/monkerapi.h
--- linux.15p3/drivers/scsi/aacraid/include/monkerapi.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/monkerapi.h	Tue Nov 20 13:47:49 2001
@@ -0,0 +1,84 @@
+/*++
+ * 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
+
+#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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/nodetype.h linux.gamma/drivers/scsi/aacraid/include/nodetype.h
--- linux.15p3/drivers/scsi/aacraid/include/nodetype.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/nodetype.h	Tue Nov 27 18:37:32 2001
@@ -0,0 +1,62 @@
+/*++
+ * 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 short in the structure and is
+ *  followed by a short containing the size, in bytes, of the structure.
+ *
+ --*/
+#ifndef _NODETYPE_
+#define _NODETYPE_
+
+typedef short NODE_TYPE_CODE;
+
+
+#define FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT ((NODE_TYPE_CODE)0x030b)
+#define FSAFS_NTC_FIB_CONTEXT            ((NODE_TYPE_CODE)0x030c)
+
+
+typedef short 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)
+
+
+#endif // _NODETYPE_
+
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/nvramioctl.h linux.gamma/drivers/scsi/aacraid/include/nvramioctl.h
--- linux.15p3/drivers/scsi/aacraid/include/nvramioctl.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/nvramioctl.h	Tue Nov 20 12:33:12 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:
+ *   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
+
+/*
+ * 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 u32	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 u32		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	u32				NVBATT_TRANSITION;
+#endif
+
+/*
+ * NVRAM Info structure returned for NVRAM_GetInfo call
+ */
+typedef struct _NVRAMDEVINFO {
+	u32		NV_Enabled;		/* write caching enabled */
+	u32		NV_Error;		/* device in error state */
+	u32		NV_NDirty;		/* count of dirty NVRAM buffers */
+	u32		NV_NActive;		/* count of NVRAM buffers being written */
+} NVRAMDEVINFO, *PNVRAMDEVINFO;
+
+typedef struct _NVRAMINFO {
+	NVSTATUS		NV_Status;				/* nvram subsystem status */
+	NVBATTSTATUS	NV_BattStatus;			/* battery status */
+	u32		NV_Size;				/* size of WriteCache NVRAM in bytes */
+	u32		NV_BufSize;				/* size of NVRAM buffers in bytes */
+	u32		NV_NBufs;				/* number of NVRAM buffers */
+	u32		NV_NDirty;				/* count of dirty NVRAM buffers */
+	u32		NV_NClean;				/* count of clean NVRAM buffers */
+	u32		NV_NActive;				/* count of NVRAM buffers being written */
+	u32		NV_NBrokered;			/* count of brokered NVRAM buffers */
+	NVRAMDEVINFO	NV_DevInfo[NFILESYS];	/* per device info */
+	u32		NV_BattNeedsReconditioning;	/* boolean */
+	u32		NV_TotalSize;			/* total size of all non-volatile memories in bytes */
+} NVRAMINFO, *PNVRAMINFO;
+
+#endif /* !_NVRAMIOCTL_H_ */
+
+
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/os.h linux.gamma/drivers/scsi/aacraid/include/os.h
--- linux.15p3/drivers/scsi/aacraid/include/os.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/os.h	Wed Nov 28 01:27:02 2001
@@ -0,0 +1,118 @@
+#include "osheaders.h"
+#include "AacGenericTypes.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 "nodetype.h"
+#include "comsup.h"
+#include "sap1common.h"
+#include "sap1.h"
+#include "rxcommon.h"
+#include "rx.h"
+#include "afacomm.h"
+#include "adapter.h"
+#include "commfibcontext.h"
+#include "fsact.h"
+#include "fsaioctl.h"
+#include "protocol.h"
+#include "commdata.h"
+#include "comprocs.h"
+#include "monkerapi.h"
+
+#define dprintk(x)
+
+int OsMapDeviceRegisters(struct aac_dev *dev);
+void OsUnMapDeviceRegisters(struct aac_dev *dev);
+int OsAttachInterrupt(struct aac_dev *dev, void (*Isr)(int, void *, struct pt_regs *));
+unsigned long *OsAllocCommPhysMem(struct aac_dev *dev, unsigned long size, unsigned long **virt_addr_pptr, unsigned long *phys_addr_ptr);
+void OsAifKernelThread(struct aac_dev *dev);
+int OsStartKernelThreads(struct aac_dev *dev);
+int AfaPortAllocateAndMapFibSpace(struct aac_dev *dev, struct fib_context * MapFibContext);
+int AfaPortUnmapAndFreeFibSpace(struct aac_dev *dev, struct fib_context * MapFibContext);
+int AfaPortFreeAdapterCommArea(struct aac_dev *dev);
+
+u32 ExInitializeZone(PZONE_HEADER Zone, unsigned long BlockSize, void * InitialSegment, unsigned long InitialSegmentSize);
+u32 ExExtendZone(PZONE_HEADER Zone, void * Segment, unsigned long SegmentSize);
+void ExFreeToZone(PZONE_HEADER Zone, void *Block);
+
+void setinqstr(int MiniPortIndex, void *dataPtr,int tindex);
+
+/* commsup */
+int FsaFreeFibContextSegment(struct aac_dev *Adapter, PFIB_CONTEXT_ZONE_SEGMENT ZoneSegment);
+int FsaFreeFibContextZone(struct aac_dev *Adapter);
+struct fib * fib_alloc(struct aac_dev *Adapter);
+void fib_free(struct fib * Context);
+u32 fib_init(struct fib * Context);
+u32 fib_dealloc(struct fib * Context);
+u32 GetResponse(PCOMM_QUE ResponseQueue, struct hw_fib * Fib);
+int GetEntry (struct aac_dev * Adapter, QUEUE_TYPES WhichQueue, PQUEUE_ENTRY *Entry, PQUEUE_INDEX Index, unsigned long *DontInterrupt);
+u32 GetQueueEntry (struct aac_dev * Adapter, PQUEUE_INDEX Index, QUEUE_TYPES WhichQueue, struct hw_fib * Fib, int Wait, struct fib * FibContext, unsigned long *DontInterrupt);
+u32 InsertQueueEntry(struct aac_dev * Adapter, QUEUE_INDEX Index, QUEUE_TYPES WhichQueue, unsigned long DontInterrupt);
+u32 fib_send(FIB_COMMAND Command, struct fib * Context, unsigned long Size,  COMM_PRIORITIES Priority, int Wait, void * WaitOn, int ResponseExpected, PCOMM_FIB_CALLBACK FibCallback, void * FibCallbackContext);
+int GetConsumerEntry(struct aac_dev * Adapter, PCOMM_QUE OurQueue, PQUEUE_ENTRY *Entry);
+int ConsumerEntryAvailable(struct aac_dev * Adapter, PCOMM_QUE OurQueue);
+void FreeConsumerEntry(struct aac_dev * Adapter, PCOMM_QUE OurQueue, QUEUE_TYPES WhichQueue);
+u32 fib_adapter_complete(struct fib * Context, unsigned short Size);
+u32 fib_complete(struct fib * Context);
+void HandleDriverAif(struct aac_dev * Adapter, struct fib * FibContext);
+int NormCommandThread(struct aac_dev * Adapter);
+void *fib_data(struct fib * Context);
+
+/* CommInit */
+u32 AacCommDriverEntry(void);
+int AacCommDetachAdapter(struct aac_dev *Adapter);
+struct aac_dev *AfaCommInitNewAdapter(struct aac_dev *dev);
+int CommInit(struct aac_dev * dev);
+u32 CommInitialize(struct aac_dev * Adapter);
+void AfaCommBugcheckHandler(void * Buffer, unsigned long Length);
+void AfaCommProbeDisks(struct aac_dev * dev);
+
+/* aachba */
+int aachba_classinit(struct aac_dev *dev);
+int aachba_containers(struct aac_dev *dev);
+int AacHba_ProbeContainer(struct aac_dev *dev, int ContainerId);
+int aac_scsi_cmd(Scsi_Cmnd *scsi_cmnd_ptr, int wait);
+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 aac_dev_ioctl(struct aac_dev *dev, int cmd, void *arg);
+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(struct aac_dev *dev, void *arg);
+int AacHba_ForceDeleteDisk(struct aac_dev *dev, void *arg);
+int AacHba_DeleteDisk(struct aac_dev *dev, void *arg);
+void aac_detach(struct aac_dev *dev);
+int AacCommDetachAdapter(struct aac_dev *Adapter);
+void AacHba_AbortScsiCommand(Scsi_Cmnd *scsi_cmnd_ptr);
+
+/* commctrl */
+int aac_do_ioctl(struct aac_dev * Adapter, int cmd, void *arg);
+int AfaCommCtlSendFib(struct aac_dev * Adapter, void *arg);
+int AfaCommCtlAifThread(struct aac_dev * Adapter);
+int FsaCtlOpenGetAdapterFib(struct aac_dev * Adapter, void *arg);
+int FsaCtlGetNextAdapterFib(struct aac_dev * Adapter, void *arg);
+int FsaCtlCloseGetAdapterFib(struct aac_dev * Adapter, void *arg);
+int FsaCloseAdapterFibContext(struct aac_dev * Adapter, PGET_ADAPTER_FIB_CONTEXT AdapterFibContext);
+
+/* rx */
+void RxStartAdapter(struct aac_dev *dev);
+u32 RxSendSynchCommand(struct aac_dev *Arg1, unsigned long Command, unsigned long Parameter1, unsigned long Parameter2, unsigned long Parameter3, unsigned long Parameter4, unsigned long *ReturnStatus);
+int RxInitDevice(struct aac_dev *dev, unsigned long AdapterNumber);
+
+/* sa1sup */
+void SaStartAdapter(struct aac_dev *dev);
+u32 SaSendSynchCommand(struct aac_dev *Arg1, unsigned long Command, unsigned long Parameter1, unsigned long Parameter2, unsigned long Parameter3, unsigned long Parameter4, unsigned long *ReturnStatus);
+int SaInitDevice(struct aac_dev *dev, unsigned long AdapterNumber);
+
+/* dpcsup */
+unsigned int CommonNotFullDpc(PCOMM_REGION CommRegion);
+unsigned int HostResponseNormalDpc(PCOMM_QUE OurQueue);
+unsigned int HostResponseHighDpc(PCOMM_QUE OurQueue);
+unsigned int HostCommandHighDpc(PCOMM_QUE OurQueue);
+unsigned int HostCommandNormDpc(PCOMM_QUE OurQueue);
+
+/* port */
+int AfaPortAllocateAdapterCommArea(struct aac_dev *dev, void **CommHeaderAddress, unsigned long CommAreaSize, unsigned long CommAreaAlignment);
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/osheaders.h linux.gamma/drivers/scsi/aacraid/include/osheaders.h
--- linux.15p3/drivers/scsi/aacraid/include/osheaders.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/osheaders.h	Tue Nov 27 19:21:28 2001
@@ -0,0 +1,116 @@
+/*++
+ * 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_
+
+#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/semaphore.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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/ostypes.h linux.gamma/drivers/scsi/aacraid/include/ostypes.h
--- linux.15p3/drivers/scsi/aacraid/include/ostypes.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/ostypes.h	Tue Nov 20 16:59:18 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:
+ *   ostypes.h
+ *
+ * Abstract: Holds all of the O/S specific types.
+ *
+ --*/
+/*------------------------------------------------------------------------------
+ *              D E F I N E S
+ *----------------------------------------------------------------------------*/
+#ifndef _OSTYPES_H_
+#define _OSTYPES_H_
+
+#include <linux/types.h>
+
+#define MAXIMUM_NUM_CONTAINERS	64		// 4 Luns * 16 Targets
+#define MAXIMUM_NUM_ADAPTERS	8
+
+/*------------------------------------------------------------------------------
+ *              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);
+
+#define ASSERT(expr) ((void) 0)
+
+#endif // _OSTYPES_H_
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/pcisup.h linux.gamma/drivers/scsi/aacraid/include/pcisup.h
--- linux.15p3/drivers/scsi/aacraid/include/pcisup.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/pcisup.h	Tue Nov 27 19:40:56 2001
@@ -0,0 +1,47 @@
+/*++
+ * 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_
+
+	
+/*
+ * define which interrupt handler needs to be installed
+ */
+
+struct aac_driver_ident
+{
+	u16				vendor;
+	u16				device;
+	u16				subsystem_vendor;
+	u16				subsystem_device;
+	int 				(*init)(struct aac_dev *dev, unsigned long num);
+	char *				name;
+	char *				vname;
+	char *				model;
+};
+
+
+#endif // _PCISUP_
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/perfpack.h linux.gamma/drivers/scsi/aacraid/include/perfpack.h
--- linux.15p3/drivers/scsi/aacraid/include/perfpack.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/perfpack.h	Tue Nov 20 14:02:39 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:
+ *   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
+
+//#define FSA_DO_PERF		1		/* enable the engineering counters */
+
+#ifdef FSA_DO_PERF
+//
+// engineering counters
+//
+typedef struct _FSA_PERF_DATA {
+	unsigned long FibsSent;
+	unsigned long ReadDirs;
+	unsigned long GetAttrs;
+	unsigned long SetAttrs;
+	unsigned long Lookups;
+	unsigned long ReadFibs;
+	unsigned long WriteFibs;
+	unsigned long CreateFibs;
+	unsigned long MakeDirs;
+	unsigned long RemoveFibs;
+	unsigned long RemoveDirs;
+	unsigned long RenameFibs;
+	unsigned long ReadDirPlus;
+	unsigned long FsStat;
+	unsigned long WriteBytes;
+	unsigned long ReadBytes;
+// NT FSA entry points
+	unsigned long FsaFsdCreateCount;
+	unsigned long FsaFsdCloseCount;
+	unsigned long FsaFsdReadCount;
+	unsigned long FsaFsdWriteCount;
+	unsigned long FsaFsdQueryInformationCount;
+	struct _FsaFsdSetInfomation{
+		unsigned long FsaSetAllocationInfoCount;
+		unsigned long FsaSetBasicInfoCount;
+		unsigned long FsaSetDispositionInfoCount;
+		unsigned long FsaSetEndOfFileInfoCount;
+		unsigned long FsaSetPositionInfoCount;
+		unsigned long FsaSetRenameInfoCount;
+		unsigned long FsaClearArchiveBitCount;
+	};
+
+	unsigned long FsaFsdFlushBuffersCount;
+	unsigned long FsaFsdQueryVolumeInfoCount;
+	unsigned long FsaFsdSetVolumeInfoCount;
+	unsigned long FsaFsdCleanupCount;
+	unsigned long FsaFsdDirectoryControlCount;
+	unsigned long FsaFsdFileSystemControlCount;
+	unsigned long FsaFsdLockControlCount;
+	unsigned long FsaFsdDeviceControlCount;
+	unsigned long FsaFsdShutdownCount;
+	unsigned long FsaFsdQuerySecurityInfo;
+	unsigned long FsaFsdSetSecurityInfo;
+	unsigned long FastIoCheckIfPossibleCount;
+	unsigned long FastIoReadCount;
+	unsigned long FastIoWriteCount;
+	unsigned long FastIoQueryBasicInfoCount;
+	unsigned long FastIoQueryStandardInfoCount;
+	unsigned long FastIoLockCount;
+	unsigned long FastIoUnlockSingleCount;
+	unsigned long FastIoUnlockAllCount;
+	unsigned long FastIoUnlockAllByKeyCount;
+	unsigned long 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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/port.h linux.gamma/drivers/scsi/aacraid/include/port.h
--- linux.15p3/drivers/scsi/aacraid/include/port.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/port.h	Wed Nov 21 13:08:10 2001
@@ -0,0 +1,32 @@
+/*++
+ * 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_
+
+#endif // _PORT_
+
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/protocol.h linux.gamma/drivers/scsi/aacraid/include/protocol.h
--- linux.15p3/drivers/scsi/aacraid/include/protocol.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/protocol.h	Tue Nov 20 13:47:42 2001
@@ -0,0 +1,247 @@
+/*++
+ * 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_
+
+#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 u32		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	u32		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	u32		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 u32		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 s8 FSASTRING[16];
+
+
+typedef u32	BYTECOUNT;	// only 32 bit-ism
+
+
+
+//
+// BlockRead
+//
+
+typedef struct _BLOCKREAD { // variable size struct
+
+    FSACOMMAND 		Command;
+    u32 		ContainerId;
+    u32 		BlockNumber;
+    u32 		ByteCount;
+	SGMAP			SgMap;	// Must be last in struct because it is variable
+
+} BLOCKREAD;
+typedef BLOCKREAD *PBLOCKREAD;
+
+typedef struct _BLOCKREADRESPONSE {
+
+    FSASTATUS 		Status;
+    u32 		ByteCount;
+
+} BLOCKREADRESPONSE;
+typedef BLOCKREADRESPONSE *PBLOCKREADRESPONSE;
+
+//
+// BlockWrite
+//
+
+typedef struct _BLOCKWRITE {	// variable size struct
+
+    FSACOMMAND 		Command;
+    u32 		ContainerId;
+    u32 		BlockNumber;
+    u32 		ByteCount;
+    CACHELEVEL 		Stable;
+	SGMAP			SgMap;	// Must be last in struct because it is variable
+
+} BLOCKWRITE;
+typedef BLOCKWRITE *PBLOCKWRITE;
+
+
+typedef struct _BLOCKWRITERESPONSE {
+
+    FSASTATUS 		Status;
+    u32 		ByteCount;
+    COMMITLEVEL 	Committed;
+
+} BLOCKWRITERESPONSE;
+typedef BLOCKWRITERESPONSE *PBLOCKWRITERESPONSE;
+
+
+
+#endif // _PROTOCOL_H_
+
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/revision.h linux.gamma/drivers/scsi/aacraid/include/revision.h
--- linux.15p3/drivers/scsi/aacraid/include/revision.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/revision.h	Tue Nov 20 14:56:40 2001
@@ -0,0 +1,347 @@
+/*++
+ * 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
+
+#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(void) {return REV_BUILD_NUMBER;}
+static inline unsigned long RevGetExternalRev(void) {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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/rx.h linux.gamma/drivers/scsi/aacraid/include/rx.h
--- linux.15p3/drivers/scsi/aacraid/include/rx.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/rx.h	Tue Nov 27 19:50:47 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:
+ *   rx.h
+ *
+ * Abstract: Prototypes and data structures unique to the Rx based controller board.
+ *
+ *	
+ --*/
+
+#ifndef __RX_H
+#define __RX_H
+
+#define Rx_READ_UCHAR(AEP,  CSR)	*(volatile unsigned char *)  &((AEP)->Device.Rx->CSR)
+#define Rx_READ_ULONG(AEP,  CSR)	*(volatile unsigned int *)   &((AEP)->Device.Rx->CSR)
+#define Rx_WRITE_UCHAR(AEP,  CSR, Value)*(volatile unsigned char *)  &((AEP)->Device.Rx->CSR) = (Value)
+#define Rx_WRITE_ULONG(AEP, CSR, Value) *(volatile unsigned int *)   &((AEP)->Device.Rx->CSR) = (Value)
+
+void RxInterruptAdapter(struct aac_dev *dev);
+void RxNotifyAdapter(struct aac_dev *dev, HOST_2_ADAP_EVENT AdapterEvent);
+
+
+#endif
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/rxcommon.h linux.gamma/drivers/scsi/aacraid/include/rxcommon.h
--- linux.15p3/drivers/scsi/aacraid/include/rxcommon.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/rxcommon.h	Tue Nov 20 16:43:34 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:
+ *   rxcommon.h
+ *
+ * Abstract: Structures and defines for the i960 Rx chip.
+ *
+ *	
+ --*/
+
+#ifndef _Rx_COMMON_H_
+#define _Rx_COMMON_H_
+
+//
+// Rx Message Unit Registers
+//
+
+typedef volatile struct _StructRxMURegisters {
+						//	 Local	|   PCI*	|	Name
+						//			|		|
+	u32	ARSR;				//	1300h	|	00h	|	APIC Register Select Register
+	u32	reserved0;			//	1304h	|	04h	|	Reserved
+	u32	AWR;				//	1308h	|	08h	|	APIC Window Register
+	u32	reserved1;			//	130Ch	|	0Ch	|	Reserved
+	u32	IMRx[2];			//	1310h	|	10h	|	Inbound Message Registers
+	u32	OMRx[2];			//	1318h	|	18h	|	Outbound Message Registers
+	u32	IDR;				//	1320h	|	20h	|	Inbound Doorbell Register
+	u32	IISR;				//	1324h	|	24h	|	Inbound Interrupt Status Register
+	u32	IIMR;				//	1328h	|	28h	|	Inbound Interrupt Mask Register
+	u32	ODR;				//	132Ch	|	2Ch	|	Outbound Doorbell Register
+	u32	OISR;				//	1330h	|	30h	|	Outbound Interrupt Status Register
+	u32	OIMR;				//	1334h	|	34h	|	Outbound Interrupt Mask Register
+						// * Must access through ATU Inbound Translation Window
+}Rx_MU_CONFIG;
+typedef Rx_MU_CONFIG *PRx_MU_CONFIG;
+
+typedef volatile struct _Rx_Inbound {
+	u32	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
+	u32				reserved1[6];	// 1338h - 134ch
+	Rx_Inbound			IndexRegs;
+} Rx_DEVICE_REGISTERS;
+
+typedef Rx_DEVICE_REGISTERS *PRx_DEVICE_REGISTERS;
+
+
+#endif // _Rx_COMMON_H_
+
+
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/sap1.h linux.gamma/drivers/scsi/aacraid/include/sap1.h
--- linux.15p3/drivers/scsi/aacraid/include/sap1.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/sap1.h	Tue Nov 27 11:05:51 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:
+ *   sap1.h
+ *
+ * Abstract: Prototypes and data structures unique to the Strong Arm based controller board.
+ *
+ *	
+ --*/
+#ifndef _SAP1_H_
+#define _SAP1_H_
+
+#define Sa_MINIPORT_REVISION			1
+
+#define Sa_READ_USHORT(AEP, CSR)			*(volatile unsigned short *) &((AEP)->Device.Sa->CSR)
+#define Sa_READ_ULONG(AEP,  CSR)			*(volatile unsigned int *)   &((AEP)->Device.Sa->CSR)
+#define Sa_WRITE_USHORT(AEP, CSR, Value)	*(volatile unsigned short *) &((AEP)->Device.Sa->CSR) = (Value)
+#define Sa_WRITE_ULONG(AEP, CSR, Value)		*(volatile unsigned int *)   &((AEP)->Device.Sa->CSR) = (Value)
+ 
+#endif /* _SAP1_H_ */
+
+
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/include/sap1common.h linux.gamma/drivers/scsi/aacraid/include/sap1common.h
--- linux.15p3/drivers/scsi/aacraid/include/sap1common.h	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/include/sap1common.h	Tue Nov 20 13:42:17 2001
@@ -0,0 +1,108 @@
+/*++
+ * 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_
+
+//
+// SaP1 Message Unit Registers
+//
+
+typedef volatile struct _StructSaDrawbridge_CSR_RegisterMap {
+						//	 Offset |	Name
+	u32	reserved[10];			//	00h-27h |   Reserved
+	u8	LUT_Offset;			//		28h	|	Looup Table Offset
+	u8	reserved1[3];			// 	29h-2bh	|	Reserved
+	u32	LUT_Data;			//		2ch	|	Looup Table Data	
+	u32	reserved2[26];			//	30h-97h	|	Reserved
+	u16	PRICLEARIRQ;			//		98h	|	Primary Clear Irq
+	u16	SECCLEARIRQ;			//		9ah	|	Secondary Clear Irq
+	u16	PRISETIRQ;			//		9ch	|	Primary Set Irq
+	u16	SECSETIRQ;			//		9eh	|	Secondary Set Irq
+	u16	PRICLEARIRQMASK;		//		a0h	|	Primary Clear Irq Mask
+	u16	SECCLEARIRQMASK;		//		a2h	|	Secondary Clear Irq Mask
+	u16	PRISETIRQMASK;			//		a4h	|	Primary Set Irq Mask
+	u16	SECSETIRQMASK;			//		a6h	|	Secondary Set Irq Mask
+	u32	MAILBOX0;			//		a8h	|	Scratchpad 0
+	u32	MAILBOX1;			//		ach	|	Scratchpad 1
+	u32	MAILBOX2;			//		b0h	|	Scratchpad 2
+	u32	MAILBOX3;			//		b4h	|	Scratchpad 3
+	u32	MAILBOX4;			//		b8h	|	Scratchpad 4
+	u32	MAILBOX5;			//		bch	|	Scratchpad 5
+	u32	MAILBOX6;			//		c0h	|	Scratchpad 6
+	u32	MAILBOX7;			//		c4h	|	Scratchpad 7
+
+	u32	ROM_Setup_Data;			//		c8h | 	Rom Setup and Data
+	u32	ROM_Control_Addr;		//		cch | 	Rom Control and Address
+
+	u32	reserved3[12];			//	d0h-ffh	| 	reserved
+	u32	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 Mailbox5	SaDbCSR.MAILBOX5
+#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 -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/linit.c linux.gamma/drivers/scsi/aacraid/linit.c
--- linux.15p3/drivers/scsi/aacraid/linit.c	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/linit.c	Wed Nov 28 01:28:06 2001
@@ -0,0 +1,749 @@
+/*++
+ * 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_detect()
+ *		aac_release()
+ *		aac_queuecommand()
+ *		aac_resetcommand()
+ *		aac_biosparm()
+ *	
+ */
+
+/*------------------------------------------------------------------------------
+ *              D E F I N E S
+ *----------------------------------------------------------------------------*/
+
+#define AAC_DRIVER_VERSION		"0.1.1ac1"
+#define AAC_DRIVER_BUILD_DATE		__DATE__
+#define MAX_DRIVER_QUEUE_DEPTH		500
+
+/*------------------------------------------------------------------------------
+ *              I N C L U D E S
+ *----------------------------------------------------------------------------*/
+#include "osheaders.h"
+#include <linux/module.h>
+#include <linux/string.h>
+#include "sd.h"
+#include "os.h"
+
+#define AAC_DRIVERNAME	"aacraid"
+
+MODULE_AUTHOR ("Adaptec OEM RAID Solutions");
+MODULE_DESCRIPTION ("Supports Dell PERC2, 2/Si, 3/Si, 3/Di, and HP NetRAID-4M devices.  http://domsch.com/linux/");
+MODULE_LICENSE ("GPL");
+
+struct aac_dev *aac_devices[ MAXIMUM_NUM_ADAPTERS ];
+
+static unsigned aac_count = 0;
+static int aac_cfg_major = -1;
+static int g_single_command_done = FALSE;
+static char *container_types[] = {
+        "None",
+        "Volume",
+        "Mirror",
+        "Stripe",
+        "RAID5",
+        "SSRW",
+        "SSRO",
+        "Morph",
+        "Legacy",
+        "RAID4",
+        "RAID10",             
+        "RAID00",             
+        "V-MIRRORS",          
+        "PSEUDO R4",          
+	"RAID50",
+        "Unknown"
+};
+
+/*
+ * 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.
+ */
+
+static struct aac_driver_ident aac_drivers[] = {
+	{ 0x0000, 0x0000, 0x0000, 0x0000, RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* Dell unknown - uses perc_pciid */
+	{ 0x0000, 0x0000, 0x0000, 0x0000, RxInitDevice, "aacraid", "ADAPTEC  ", "AACRAID         " }, /* unknown - uses rx_pciid */
+	{ 0x0000, 0x0000, 0x0000, 0x0000, SaInitDevice, "aacraid", "ADAPTEC  ", "AACRAID         " }, /* unknown - uses sa_pciid */
+	{ 0x1028, 0x0001, 0x1028, 0x0001, RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* PERC 2/Si */
+	{ 0x1028, 0x0002, 0x1028, 0x0002, RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* PERC 3/Di */
+	{ 0x1028, 0x0003, 0x1028, 0x0003, RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* PERC 3/Si */
+	{ 0x1028, 0x0004, 0x1028, 0x00d0, RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* PERC 3/Si */
+	{ 0x1028, 0x0002, 0x1028, 0x00d1, RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* PERC 3/Di */
+	{ 0x1028, 0x0002, 0x1028, 0x00d9, RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* PERC 3/Di */
+	{ 0x1028, 0x000a, 0x1028, 0x0106, RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* PERC 3/Di */
+	{ 0x1028, 0x000a, 0x1028, 0x011b, RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* PERC 3/Di */
+	{ 0x1028, 0x000a, 0x1028, 0x0121, RxInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* PERC 3/Di */
+	{ 0x1011, 0x0046, 0x9005, 0x1364, SaInitDevice, "percraid", "DELL    ", "PERCRAID        " }, /* Dell PERC2 "Quad Channel" */
+	{ 0x1011, 0x0046, 0x9005, 0x0365, SaInitDevice, "aacraid",  "ADAPTEC ", "Adaptec 5400S   " }, /* Adaptec 5400S */
+	{ 0x1011, 0x0046, 0x103c, 0x10c2, SaInitDevice, "hpnraid",  "HP      ", "NetRAID-4M      " }  /* HP NetRAID-4M */
+};
+
+#define NUM_MINIPORTS	(sizeof(aac_drivers) / sizeof(struct aac_driver_ident))
+static int num_aacdrivers = NUM_MINIPORTS;
+
+static int aac_cfg_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg);
+static int aac_cfg_open(struct inode * inode, struct file * file);
+static int aac_cfg_release(struct inode * inode,struct file * file);
+
+static struct file_operations aac_cfg_fops = {
+	owner: THIS_MODULE,
+	ioctl: aac_cfg_ioctl,
+	open: aac_cfg_open,
+	release: aac_cfg_release
+};
+
+static int aac_detect(Scsi_Host_Template *);
+static int aac_release(struct Scsi_Host *);
+static int aac_queuecommand(Scsi_Cmnd *, void (*CompletionRoutine)(Scsi_Cmnd *));
+static int aac_command(Scsi_Cmnd *);
+static int aac_abortcommand(Scsi_Cmnd *scsi_cmnd_ptr);
+static int aac_resetcommand(Scsi_Cmnd *, unsigned int);
+static int aac_biosparm(Scsi_Disk *, kdev_t, int *);
+static int aac_procinfo(char *, char **, off_t, int, int, int);
+static int aac_ioctl(Scsi_Device *, int, void *);
+
+static void aac_queuedepth(struct Scsi_Host *, Scsi_Device *);
+
+/**
+ *	aac_detect	-	Probe for aacraid cards
+ *	@template: SCSI driver template
+ *
+ *	Probe for AAC Host Adapters initialize, register, and report the 
+ *	configuration of each AAC Host Adapter found.
+ *	Returns the number of adapters successfully initialized and 
+ *	registered.
+ *	Initializes 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.
+ *
+ */
+ 
+static int aac_detect(Scsi_Host_Template *template)
+{
+	int index;
+	int container;
+	u16 vendor_id, device_id, sub_vendor_id = 0, sub_system_id = 0;
+	struct Scsi_Host *host_ptr;
+	struct pci_dev *dev = NULL;
+	struct aac_dev *aac;
+	fsadev_t *fsa_dev_ptr;
+	char *name = NULL;
+	
+	printk(KERN_INFO "%s, %s\n", "aacraid raid driver version", AAC_DRIVER_BUILD_DATE );   
+
+	/* setting up the proc directory structure */
+	template->proc_name = "aacraid";
+
+	// num_aacdrivers & aac_drivers[] defined in aacid.c
+
+	for( index = 0; index != num_aacdrivers; index++ )
+	{
+		device_id = aac_drivers[index].device;
+		vendor_id = aac_drivers[index].vendor;
+		name = aac_drivers[index].name;
+		dprintk((KERN_DEBUG "Checking %s %x/%x/%x/%x.\n", 
+			name, vendor_id, device_id,
+			aac_drivers[index].subsystem_vendor,
+			aac_drivers[index].subsystem_device));
+
+		/* 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;
+			pci_set_master(dev);
+
+			if((dev->subsystem_vendor != aac_drivers[index].subsystem_vendor) || 
+			   (dev->subsystem_device != aac_drivers[index].subsystem_device))
+					continue;
+
+			dprintk((KERN_DEBUG "%s device detected.\n", name));
+			dprintk((KERN_DEBUG "%x/%x/%x/%x.\n", vendor_id, device_id, sub_vendor_id, sub_system_id));
+			// Increment the host adapter count
+			aac_count++;
+			// 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( template, sizeof(struct aac_dev) );
+			// 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 = dev->resource[0].start;
+			scsi_set_pci_device(host_ptr, dev);
+			dprintk((KERN_DEBUG "Device base address = 0x%lx [0x%lx].\n", host_ptr->base, dev->resource[0].start));
+			dprintk((KERN_DEBUG "Device irq = 0x%x.\n", 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 as aac->id.
+
+			host_ptr->unique_id = aac_count - 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_queuedepth;
+			aac = (struct aac_dev *)host_ptr->hostdata;
+			// attach a pointer back to Scsi_Host
+			aac->OsDep.scsi_host_ptr = host_ptr;	
+			aac->OsDep.MiniPortIndex =  index;
+			aac->name = aac->OsDep.scsi_host_ptr->hostt->name;
+			aac->id = aac->OsDep.scsi_host_ptr->unique_id;
+			// Initialize the ordinal number of the device to -1
+			fsa_dev_ptr = &( aac->OsDep.fsa_dev );
+			for( container = 0; container < MAXIMUM_NUM_CONTAINERS; container++ )
+				fsa_dev_ptr->ContainerDevNo[container] = -1;
+
+			// Call initialization routine
+			dprintk((KERN_DEBUG "Initializing Hardware...\n"));
+			if((*aac_drivers[index].init)(aac , host_ptr->unique_id) != 0 )
+			{
+				// device initialization failed
+				printk(KERN_WARNING "%s:%d device initialization failed.\n", name, host_ptr->unique_id);
+				scsi_unregister( host_ptr );
+				aac_count--;
+			} 
+			else
+			{
+				printk(KERN_NOTICE "%s:%d device initialization successful.\n", name, host_ptr->unique_id);
+				aachba_containers(aac);
+				aac_devices[ aac_count - 1 ] = aac;
+			}
+		}
+	}
+
+	if( aac_count ){
+		if((aac_cfg_major = register_chrdev( 0, "aac", &aac_cfg_fops))<0)
+			printk(KERN_WARNING "%s: unable to register %s device.\n", name, "aac");
+	}
+
+	template->present = aac_count; // # of cards of this type found
+	return aac_count;
+}
+
+/**
+ *	aac_release	-	release SCSI host resources
+ *	@host_ptr: SCSI host to clean up
+ *
+ *	Release all resources previously acquired to support a specific Host 
+ *	Adapter and unregister the AAC Host Adapter.
+ *
+ *	BUGS: Does not wait for the thread it kills to die.
+ */
+
+static int aac_release(struct Scsi_Host *host_ptr)
+{
+	struct aac_dev *dev;
+	dprintk((KERN_DEBUG "aac_release.\n"));
+	dev = (struct aac_dev *)host_ptr->hostdata;
+	// kill any threads we started
+	kill_proc(dev->OsDep.thread_pid, SIGKILL, 0);
+	// FIXME: We must wait for the thread to die, need a completion here
+	// Call the comm layer to detach from this adapter
+	aac_detach(dev);
+	// Check free orderings...
+	// remove interrupt binding
+	free_irq(host_ptr->irq, dev);
+	iounmap((void * )dev->Device.Sa);
+	// unregister adapter
+	scsi_unregister(host_ptr);
+	/*
+	 *	FIXME: This assumes no hot plugging is going on...
+	 */
+	if( aac_cfg_major >= 0 )
+	{
+		unregister_chrdev(aac_cfg_major, "aac");
+		aac_cfg_major = -1;
+	}
+	return 0;
+}
+
+/**
+ *	aac_queuecommand	-	queue a SCSI command
+ *	@scsi_cmnd_ptr:	SCSI command to queue
+ *	@CompletionRoutine: Function to call on command completion
+ *
+ *	Queues a command for execution by the associated Host Adapter.
+ */ 
+
+static int aac_queuecommand(Scsi_Cmnd *scsi_cmnd_ptr, void (*CompletionRoutine)(Scsi_Cmnd *))
+{
+	int ret;
+
+	scsi_cmnd_ptr->scsi_done = CompletionRoutine;
+	// aac_scsi_cmd() handles command processing, setting the 
+	// result code and calling completion routine. 
+#ifdef SYNC_FIB
+	if((ret = aac_scsi_cmd(scsi_cmnd_ptr, 1)) != 0)	// call with wait = TRUE
+#else
+	if((ret = aac_scsi_cmd(scsi_cmnd_ptr, 0)) != 0)	// call with wait = FALSE
+#endif
+		dprintk((KERN_DEBUG "aac_scsi_cmd failed.\n"));
+	return ret;
+} 
+
+
+/**
+ *	aac_done	-	Callback function for a non-queued command.
+ *	@scsi_cmnd_ptr:	SCSI command block to wait for
+ *
+ *	Sets g_single_command done to TRUE. This lets aac_command complete. 
+ *	This function is obsolete.
+ *
+ *	Bugs: Doesn't actually work properly with multiple controllers
+ */
+ 
+static void aac_done(Scsi_Cmnd * scsi_cmnd_ptr) 
+{
+	g_single_command_done = TRUE;
+}
+
+/**
+ *	aac_command	-	synchronous SCSI command execution
+ *	@scsi_cmnd_ptr:	SCSI command to issue
+ *
+ *	Accepts a single command for execution by the associated Host Adapter.
+ *	Waits until it completes an then 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
+ */
+ 
+static int aac_command(Scsi_Cmnd *scsi_cmnd_ptr )
+{
+	scsi_cmnd_ptr->scsi_done = aac_done;
+	dprintk((KERN_DEBUG "aac_command.\n"));
+
+	// aac_scsi_cmd() handles command processing, setting the 
+	// result code and calling completion routine.
+	g_single_command_done = FALSE;
+	
+	aac_scsi_cmd(scsi_cmnd_ptr, 0);
+	while(!g_single_command_done)
+		rmb();
+	return scsi_cmnd_ptr->result;
+} 
+
+/**
+ *	aac_abortcommand	-	Abort command if possible.
+ *	@scsi_cmnd_ptr:	SCSI command block to abort
+ *
+ *	Called when the midlayer wishes to abort a command. We don't support
+ *	this facility, and our firmware looks after life for us. We just
+ *	report the command as busy. 
+ */
+ 
+static int aac_abortcommand(Scsi_Cmnd *scsi_cmnd_ptr )
+{
+	return SCSI_ABORT_BUSY;
+}
+
+/**
+ *	aac_resetcommand	-	Reset command handling
+ *	@scsi_cmnd_ptr:	SCSI command block causing the reset
+ *	@reset_flags: Reset hints from the midlayer code
+ *
+ *	Issue a reset of a SCSI command. We are ourselves not truely a SCSI
+ *	controller and our firmware will do the work for us anyway. Thus this
+ *	is a no-op. We just return SCSI_RESET_PUNT
+ */
+ 
+static int aac_resetcommand(struct scsi_cmnd *scsi_cmnd_ptr, unsigned int reset_flags )
+{
+	return SCSI_RESET_PUNT;
+}
+
+/**
+ *	aac_driverinfo		-	Returns the host adapter name
+ *	@host_ptr:	Scsi host to report on
+ *
+ *	Returns a static string describing the device in question
+ */
+
+const char *aac_driverinfo(struct Scsi_Host *host_ptr)
+{
+	struct aac_dev *dev = (struct aac_dev *)host_ptr->hostdata;
+	return aac_drivers[dev->OsDep.MiniPortIndex].name;
+}
+
+/**
+ *	aac_biosparm	-	return BIOS parameters for disk
+ *	@disk: SCSI disk object to process
+ *	@device: kdev_t of the disk in question
+ *	@geom: geometry block to fill in
+ *
+ *	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.
+ */
+ 
+static int aac_biosparm(Scsi_Disk *disk, kdev_t device, int *geom )
+{
+	struct diskparm *param = (struct diskparm *)geom;
+	struct buffer_head * buf;
+
+	dprintk((KERN_DEBUG "aac_biosparm.\n"));
+
+	// Assuming extended translation is enabled - #REVISIT#
+	if( disk->capacity >= 2 * 1024 * 1024 ) // 1 GB in 512 byte sectors
+	{
+		if( disk->capacity >= 4 * 1024 * 1024 ) // 2 GB in 512 byte sectors
+		{
+			param->heads = 255;
+			param->sectors = 63;
+		}
+		else
+		{
+			param->heads = 128;
+			param->sectors = 32;
+		}
+	}
+	else
+	{
+		param->heads = 64;
+		param->sectors = 32;
+	}
+
+	param->cylinders = disk->capacity/(param->heads * param->sectors);
+
+	// Read the first 1024 bytes from the disk device
+	
+#warning "Block size assumption is wrong to start with"
+	buf = bread(MKDEV(MAJOR(device), MINOR(device)&~0x0F), 0, 1024);
+	if(buf == 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 *)(buf->b_data + 0x1fe) == cpu_to_le16(0xaa55))
+	{
+		struct partition *first = (struct partition * )(buf->b_data + 0x1be);
+		struct partition *entry = first;
+		int saved_cylinders = param->cylinders;
+		int num;
+		unsigned char end_head, end_sec;
+
+		for(num = 0; num < 4; num++)
+		{
+			end_head = entry->end_head;
+			end_sec = entry->end_sector & 0x3f;
+
+			if(end_head == 63)
+			{
+				param->heads = 64;
+				param->sectors = 32;
+				break;
+			}
+			else if(end_head == 127)
+			{
+				param->heads = 128;
+				param->sectors = 32;
+				break;
+			}
+			else if(end_head == 254) 
+			{
+				param->heads = 255;
+				param->sectors = 63;
+				break;
+			}
+			entry++;
+		}
+
+		if(num == 4)
+		{
+			end_head = first->end_head;
+			end_sec = first->end_sector & 0x3f;
+		}
+
+		param->cylinders = disk->capacity / (param->heads * param->sectors);
+
+		if(num < 4 && end_sec == param->sectors)
+		{
+			if(param->cylinders != saved_cylinders)
+				dprintk((KERN_DEBUG "Adopting geometry: heads=%d, sectors=%d from partition table %d.\n",
+					param->heads, param->sectors, num));
+		}
+		else if(end_head > 0 || end_sec > 0)
+		{
+			dprintk((KERN_DEBUG "Strange geometry: heads=%d, sectors=%d in partition table %d.\n",
+				end_head + 1, end_sec, num));
+			dprintk((KERN_DEBUG "Using geometry: heads=%d, sectors=%d.\n",
+					param->heads, param->sectors));
+		}
+	}
+	brelse(buf);
+	return 0;
+}
+
+/**
+ *	aac_queuedepth		-	compute queue depths
+ *	@host:	SCSI host in question
+ *	@dev:	SCSI device we are considering
+ *
+ *	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.
+ */
+
+static void aac_queuedepth(struct Scsi_Host * host, Scsi_Device * dev )
+{
+	Scsi_Device * dptr;
+
+	dprintk((KERN_DEBUG "aac_queuedepth.\n"));
+	dprintk((KERN_DEBUG "Device #   Q Depth   Online\n"));
+	dprintk((KERN_DEBUG "---------------------------\n"));
+	for(dptr = dev; dptr != NULL; dptr = dptr->next)
+	{
+		if(dptr->host == host)
+		{
+			dptr->queue_depth = 10;		
+			dprintk((KERN_DEBUG "  %2d         %d        %d\n", 
+				dptr->id, dptr->queue_depth, dptr->online));
+		}
+	}
+}
+
+/*------------------------------------------------------------------------------
+	aac_ioctl()
+
+		Handle SCSI ioctls
+ *----------------------------------------------------------------------------*/
+static int aac_ioctl(Scsi_Device * scsi_dev_ptr, int cmd, void * arg)
+/*----------------------------------------------------------------------------*/
+{
+	struct aac_dev *dev;
+	dprintk((KERN_DEBUG "aac_ioctl.\n"));
+	dev = (struct aac_dev *)scsi_dev_ptr->host->hostdata;
+	return aac_do_ioctl(dev, cmd, arg);
+}
+
+/**
+ *	aac_cfg_open		-	open a configuration file
+ *	@inode: inode being opened
+ *	@file: file handle attached
+ *
+ *	Called when the configuration device is opened. Does the needed
+ *	set up on the handle and then returns
+ *
+ *	Bugs: This needs extending to check a given adapter is present
+ *	so we can support hot plugging, and to ref count adapters.
+ */
+
+static int aac_cfg_open(struct inode * inode, struct file * file )
+{
+	unsigned minor_number = MINOR(inode->i_rdev);
+	if(minor_number >= aac_count)
+		return -ENODEV;
+	return 0;
+}
+
+/**
+ *	aac_cfg_release		-	close down an AAC config device
+ *	@inode: inode of configuration file
+ *	@file: file handle of configuration file
+ *	
+ *	Called when the last close of the configuration file handle
+ *	is performed.
+ */
+ 
+static int aac_cfg_release(struct inode * inode, struct file * file )
+{
+	return 0;
+}
+
+/**
+ *	aac_cfg_ioctl		-	AAC configuration request
+ *	@inode: inode of device
+ *	@file: file handle
+ *	@cmd: ioctl command code
+ *	@arg: argument
+ *
+ *	Handles a configuration ioctl. Currently this involves wrapping it
+ *	up and feeding it into the nasty windowsalike glue layer.
+ *
+ *	Bugs: Needs locking against parallel ioctls
+ *	Bugs: Needs to handle hot plugging
+ */
+ 
+static int aac_cfg_ioctl(struct inode * inode,  struct file * file, unsigned int cmd, unsigned long arg )
+{
+	struct aac_dev *dev = aac_devices[MINOR(inode->i_rdev)];
+	// dispatch ioctl - aac_do_ioctl() returns zero on success
+	if(aac_do_ioctl(dev, cmd, (void *)arg ))
+		return -EINVAL;
+	return 0;
+}
+
+/*
+ *	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.
+ */
+ 
+static Scsi_Host_Template driver_template = AAC_HOST_TEMPLATE_ENTRY;
+
+#include "scsi_module.c"
+
+/**
+ *	aac_procinfo	-	Implement /proc/scsi/<drivername>/<n>
+ *	@proc_buffer: memory buffer for I/O
+ *	@start_ptr: pointer to first valid data
+ *	@offset: offset into file
+ *	@bytes_available: space left
+ *	@host_no: scsi host ident
+ *	@write: direction of I/O
+ *
+ *	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.
+ *
+ *		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
+ *
+ *	Bugs:	Only offset zero is handled
+ */
+
+static int aac_procinfo(
+	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	
+{
+	if(write || offset > 0)
+		return 0;
+	*start_ptr = proc_buffer;
+	return sprintf(proc_buffer, "%s  %d\n", "Raid Controller, scsi hba number", host_no);
+}
+
+/* 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;
+
+/**
+ *	InqStrCopy	-	string merge
+ *	@a:	string to copy from
+ *	@b:	string to copy to
+ *
+ * 	Copy a String from one location to another
+ *	without copying \0
+ */
+
+static void InqStrCopy(char *a, char *b)
+{
+
+	while(*a != (char)0) 
+		*b++ = *a++;
+}
+
+
+/* Function: setinqstr
+ *
+ * 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 setinqstr(int devtype, void *data, int tindex)
+{
+	INQSTRP str;
+	char *findit;
+	struct aac_driver_ident *mp;
+
+	mp = &aac_drivers[devtype];
+   
+	str = (INQSTRP)(data); /* cast data to type INQSTRP */
+
+	InqStrCopy (mp->vname, str->vid); 
+	InqStrCopy (mp->model, str->pid); /* last six chars reserved for vol type */
+
+	findit = str->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", str->prl);
+}
+
+
+EXPORT_NO_SYMBOLS;
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/osddi.c linux.gamma/drivers/scsi/aacraid/osddi.c
--- linux.15p3/drivers/scsi/aacraid/osddi.c	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/osddi.c	Wed Nov 28 01:25:31 2001
@@ -0,0 +1,126 @@
+/*++
+ * 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.
+ *	
+ --*/
+
+#include "osheaders.h"
+
+#include <linux/smp_lock.h>
+
+#ifdef fsid_t
+#undef fsid_t
+#endif
+#include "os.h"
+
+/*------------------------------------------------------------------------------
+	OsMapDeviceRegisters()
+
+	Postconditions:
+		Return zero on success non-zero otherwise.
+ *----------------------------------------------------------------------------*/
+int OsMapDeviceRegisters(struct aac_dev *dev)
+{
+	if((dev->Device.Sa = (Sa_DEVICE_REGISTERS *)
+			ioremap((unsigned long)dev->OsDep.scsi_host_ptr->base, 8192))!=NULL)
+	{
+		printk(KERN_WARNING "Device mapped to virtual address 0x%p.\n", dev->Device.Sa ); 
+		return( 0 );
+	}
+	else
+	{	
+		printk(KERN_WARNING "OsMapDeviceRegisters: ioremap() failed.\n" );
+		return( 1 );
+	}
+}
+
+unsigned long *OsAllocCommPhysMem(struct aac_dev *dev, unsigned long size, unsigned long **virt_addr_pptr, unsigned long *phys_addr_ptr )
+{
+	if( ( *virt_addr_pptr = ( unsigned long * )kmalloc( size, GFP_KERNEL ) ) )
+	{
+		*phys_addr_ptr = virt_to_bus( ( volatile void * )*virt_addr_pptr );
+		if( !*phys_addr_ptr )
+		{
+			printk(KERN_WARNING "OsAllocCommPhysMem: virt_to_bus failed.\n");
+		}
+				
+		return( *virt_addr_pptr );
+	}
+	else
+		return( NULL );
+}
+
+void OsAifKernelThread(struct aac_dev *dev)
+{
+	/*
+	 * set up the name that will appear in 'ps'
+	 * stored in  task_struct.comm[16].
+	 */
+	sprintf(current->comm, "AIFd");
+
+	daemonize();
+	NormCommandThread(dev);
+	/* NOT REACHED */
+}
+
+int OsStartKernelThreads(struct aac_dev *dev)
+{
+	//
+	// Start thread which will handle AdapterInititatedFibs from this adapter
+	//
+	dev->OsDep.thread_pid = kernel_thread((int (*)(void *))OsAifKernelThread, dev, 0);
+	return 0;
+}
+
+int AfaPortAllocateAndMapFibSpace(struct aac_dev *dev, struct fib_context *map)
+{
+	void * 		BaseAddress;
+	unsigned long	PhysAddress;
+
+	if(!(BaseAddress = (unsigned long *)kmalloc(map->Size,GFP_KERNEL)))
+	{
+		printk(KERN_WARNING "AfaPortAllocateAndMapFibSpace: kmalloc failed.\n");
+		return FALSE;
+	}
+
+	PhysAddress = virt_to_bus(BaseAddress);
+	
+	map->FibVirtualAddress = BaseAddress;
+	map->FibPhysicalAddress = (void *)PhysAddress;
+
+	return TRUE;
+}
+
+int AfaPortUnmapAndFreeFibSpace(struct aac_dev *dev, struct fib_context *map )
+{
+	kfree(map->FibVirtualAddress);
+	return TRUE;
+}
+
+int AfaPortFreeAdapterCommArea(struct aac_dev *dev)
+{
+	kfree(dev->CommAddress);
+	return TRUE;
+}
+
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/rx.c linux.gamma/drivers/scsi/aacraid/rx.c
--- linux.15p3/drivers/scsi/aacraid/rx.c	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/rx.c	Wed Nov 28 00:09:19 2001
@@ -0,0 +1,517 @@
+/*++
+ * 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.
+ *
+ --*/
+
+#include "os.h"
+
+#define NUM_TICKS_PER_SECOND (1000 * 1000 * 10) /* time is in 100 nanoseconds */
+
+
+//
+// The list of all the Rx adapter structures
+//
+
+int RxInitDevice(struct aac_dev *dev, unsigned long devNumber);
+
+//
+// Declare private use routines for this modual
+//
+
+static void aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
+
+/*++
+
+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
+
+--*/
+
+{
+	struct aac_dev *dev = dev_id;
+	unsigned long	bellbits;
+	u8	intstat, mask;
+
+	intstat = Rx_READ_UCHAR(dev, 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(dev, MUnit.OIMR));
+
+	// Check to see if this is our interrupt.  If it isn't just return FALSE.
+
+	if (intstat & mask) {
+		bellbits = Rx_READ_ULONG(dev, OutboundDoorbellReg);
+		if (bellbits & DoorBellPrintfReady) {
+			unsigned long Length, MailboxValue, Level;
+			unsigned char *cp;
+			MailboxValue = Rx_READ_ULONG (dev,
+						      IndexRegs.Mailbox[5]);
+			Length = MailboxValue & 0xffff;
+			Level = (MailboxValue >> 16) & 0xffff;
+			cp = dev->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) {
+				cp[Length] = 0;
+			}
+
+			if (Level == LOG_HIGH_ERROR)
+				printk(KERN_WARNING "%s:%s.\n", dev->name, (char *)dev->PrintfBufferAddress);
+			else
+				printk(KERN_INFO "%s:%s.\n", dev->name, (char *)dev->PrintfBufferAddress);
+			
+			memset(dev->PrintfBufferAddress, 0,  256);
+
+			Rx_WRITE_ULONG(dev, MUnit.ODR,DoorBellPrintfReady); //clear PrintfReady
+			Rx_WRITE_ULONG(dev, InboundDoorbellReg,DoorBellPrintfDone);
+		} else if (bellbits & DoorBellAdapterNormCmdReady) {	// dev -> Host Normal Command Ready
+			HostCommandNormDpc(&dev->CommRegion->HostNormCmdQue);
+			Rx_WRITE_ULONG(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
+		} else if (bellbits & DoorBellAdapterNormRespReady) {	// dev -> Host Normal Response Ready
+			HostResponseNormalDpc(&dev->CommRegion->HostNormRespQue);
+			Rx_WRITE_ULONG(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
+		} else if (bellbits & DoorBellAdapterNormCmdNotFull) {	// dev -> Host Normal Command Not Full
+			Rx_WRITE_ULONG(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
+		} else if (bellbits & DoorBellAdapterNormRespNotFull) {	// dev -> Host Normal Response Not Full
+			Rx_WRITE_ULONG(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
+		}
+	}
+}
+
+/*++
+Routine Description:
+	This routine will enable the corresponding adapter event to cause an interrupt on 
+	the host.
+Arguments:
+	dev - Which adapter to enable.
+	AdapterEvent - Which adapter event.
+	AtDeviceIrq - Whether the system is in DEVICE irql
+Return Value:
+	Nothing.
+*/
+
+void RxEnableInterrupt(struct aac_dev * dev, u32 AdapterEvent, int AtDeviceIrq)
+{
+	switch (AdapterEvent) {
+
+	case HostNormCmdQue:
+		dev->irq_mask &= ~(OUTBOUNDDOORBELL_1);
+		break;
+
+	case HostNormRespQue:
+		dev->irq_mask &= ~(OUTBOUNDDOORBELL_2);
+		break;
+
+	case AdapNormCmdNotFull:
+		dev->irq_mask &= ~(OUTBOUNDDOORBELL_3);
+		break;
+
+	case AdapNormRespNotFull:
+		dev->irq_mask &= ~(OUTBOUNDDOORBELL_4);
+		break;
+	}
+}
+
+/*++
+
+Routine Description:
+	This routine will disable the corresponding adapter event to cause an interrupt on 
+	the host.
+
+Arguments:
+	dev - Which adapter to enable.
+	AdapterEvent - Which adapter event.
+	AtDeviceIrq - Whether the system is in DEVICE irql
+
+Return Value:
+	Nothing.
+--*/
+void RxDisableInterrupt(struct aac_dev *dev, u32 AdapterEvent, int AtDeviceIrq)
+{
+	switch (AdapterEvent) {
+
+	case HostNormCmdQue:
+		dev->irq_mask |= (OUTBOUNDDOORBELL_1);
+		break;
+
+	case HostNormRespQue:
+		dev->irq_mask |= (OUTBOUNDDOORBELL_2);
+		break;
+
+	case AdapNormCmdNotFull:
+		dev->irq_mask |= (OUTBOUNDDOORBELL_3);
+		break;
+
+	case AdapNormRespNotFull:
+		dev->irq_mask |= (OUTBOUNDDOORBELL_4);
+		break;
+	}
+}
+
+/*++
+
+Routine Description:
+	The will cause the adapter to take a break point.
+Arguments:
+	None
+Return Value:
+	Nothing
+--*/
+void RxInterruptAdapter(struct aac_dev *dev)
+{
+	unsigned long ReturnStatus;
+	RxSendSynchCommand(dev, 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 RxNotifyAdapter(struct aac_dev *dev, HOST_2_ADAP_EVENT AdapterEvent)
+{
+	switch (AdapterEvent) {
+
+	case AdapNormCmdQue:
+		Rx_WRITE_ULONG(dev, MUnit.IDR,INBOUNDDOORBELL_1);
+		break;
+	case HostNormRespNotFull:
+		Rx_WRITE_ULONG(dev, MUnit.IDR,INBOUNDDOORBELL_4);
+		break;
+	case AdapNormRespQue:
+		Rx_WRITE_ULONG(dev, MUnit.IDR,INBOUNDDOORBELL_2);
+		break;
+	case HostNormCmdNotFull:
+		Rx_WRITE_ULONG(dev, MUnit.IDR,INBOUNDDOORBELL_3);
+		break;
+	case HostShutdown:
+//		RxSendSynchCommand(dev, HOST_CRASHING, 0, 0, 0, 0, &ReturnStatus);
+		break;
+	case FastIo:
+		Rx_WRITE_ULONG(dev, MUnit.IDR,INBOUNDDOORBELL_6);
+		break;
+	case AdapPrintfDone:
+		Rx_WRITE_ULONG(dev, MUnit.IDR,INBOUNDDOORBELL_5);
+		break;
+	default:
+		BUG();
+		break;
+	}
+}
+
+#if 0
+static struct aac_ops aac_rx_ops = 
+{
+	RxInterruptAdapter,
+	RxEnableInterrupt,
+	RxDisableInterrupt,
+	RxNotifyAdapter,
+};
+#endif
+
+int RxInitDevice(struct aac_dev *dev, 
+	unsigned long devNumber)
+/*++
+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
+--*/
+{
+	unsigned long StartTime, EndTime;
+	unsigned long InitStatus;
+	int instance;
+	const char * name;
+
+	dev->devNumber = devNumber;
+
+	instance = dev->id;
+	name     = dev->name;
+	//
+	// Map in the registers from the adapter, register space 0 is config space,
+	// register space 1 is the memery space.
+	//
+	if (OsMapDeviceRegisters(dev)) {
+		printk(KERN_ERR "%s%d: can't map device registers.\n",
+				dev->name, instance);
+		return FAILURE;
+	}
+	//
+	// Check to see if the board failed any self tests.
+	//
+
+	if (Rx_READ_ULONG( dev, IndexRegs.Mailbox[7]) & SELF_TEST_FAILED) {
+		printk(KERN_ERR "%s%d: adapter self-test failed.\n",
+				dev->name, instance);
+		return(FAILURE);
+	}
+	//
+	// Check to see if the board panic'd while booting.
+	//
+
+	if (Rx_READ_ULONG( dev, IndexRegs.Mailbox[7]) & KERNEL_PANIC) {
+		printk(KERN_ERR "%s%d: adapter kernel panic'd.\n",
+				dev->name, instance);
+		return(FAILURE);
+	}
+
+	StartTime = jiffies;
+	//
+	//  Wait for the adapter to be up and running. Wait up until 3 minutes.
+	//
+
+	while (!(Rx_READ_ULONG(dev, IndexRegs.Mailbox[7]) & KERNEL_UP_AND_RUNNING)) {
+		EndTime = jiffies;
+
+		if(time_after(EndTime, StartTime+30*HZ))
+		{
+			InitStatus = Rx_READ_ULONG( dev, IndexRegs.Mailbox[7]) >> 16;
+			printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %ld.\n",
+					dev->name, instance, InitStatus);
+			return(FAILURE);
+		}
+	}
+
+	if (request_irq(dev->OsDep.scsi_host_ptr->irq, aac_rx_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev)<0) {
+		printk(KERN_ERR "%s%d: Interrupt unavailable.\n", name, instance);
+		return(FAILURE);
+	}
+
+	//
+	// Fill in the function dispatch table.
+	//
+
+	dev->AdapterFuncs.InterruptAdapter = RxInterruptAdapter;
+	dev->AdapterFuncs.EnableInterrupt = RxEnableInterrupt;
+	dev->AdapterFuncs.DisableInterrupt = RxDisableInterrupt;
+	dev->AdapterFuncs.NotifyAdapter = RxNotifyAdapter;
+	dev->AdapterFuncs.InterruptHost = NULL;
+
+	dev->Dip = dev->OsDep.dip;
+
+	if (AfaCommInitNewAdapter(dev) == NULL) {
+		printk(KERN_WARNING "AfaCommInitNewAdapter failed.\n");
+		return (FAILURE);
+	}
+
+	//
+	// Start any kernel threads needed
+	//
+	OsStartKernelThreads(dev);
+
+	//
+	// Tell the adapter that all is configure, and it can start accepting requests
+	//
+
+	RxStartAdapter(dev);
+	return 0;
+}
+
+void RxStartAdapter(struct aac_dev *dev)
+{
+	unsigned long ReturnStatus;
+	PADAPTER_INIT_STRUCT InitStruct;
+
+	//
+	// Fill in the remaining pieces of the InitStruct.
+	//
+
+	InitStruct = dev->InitStruct;
+
+	InitStruct->HostElapsedSeconds = jiffies/HZ;
+
+	//
+	// Tell the adapter we are back and up and running so it will scan its command
+	// queues and enable our interrupts
+	//
+
+	dev->irq_mask = (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( dev, MUnit.OIMR, 0xff);
+	Rx_WRITE_ULONG( dev, MUnit.ODR, 0xffffffff);
+//	Rx_WRITE_UCHAR(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK);
+	Rx_WRITE_UCHAR( dev, MUnit.OIMR, 0xfb);
+
+	RxSendSynchCommand(dev, 
+		 INIT_STRUCT_BASE_ADDRESS, 
+		 (unsigned long) dev->PhysicalInitStruct,
+		 0, 0, 0, &ReturnStatus);
+}
+
+
+/*++
+
+Routine Description:
+
+	This routine will send a synchronous comamnd to the adapter and wait for its
+	completion.
+
+Arguments:
+
+	dev - 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:
+
+	u32
+
+--*/
+u32 RxSendSynchCommand(struct aac_dev *dev, unsigned long Command, unsigned long Parameter1, unsigned long Parameter2, unsigned long Parameter3, unsigned long Parameter4, unsigned long *ReturnStatus)
+{
+	unsigned long start;
+	int CommandSucceeded;
+
+	//
+	// Write the Command into Mailbox 0
+	//
+
+	Rx_WRITE_ULONG( dev, InboundMailbox0, Command);
+
+	//
+	// Write the parameters into Mailboxes 1 - 4
+	//
+
+	Rx_WRITE_ULONG( dev, InboundMailbox1, Parameter1);
+	Rx_WRITE_ULONG( dev, InboundMailbox2, Parameter2);
+	Rx_WRITE_ULONG( dev, InboundMailbox3, Parameter3);
+	Rx_WRITE_ULONG( dev, InboundMailbox4, Parameter4);
+
+	//
+	// Clear the synch command doorbell to start on a clean slate.
+	//
+		
+	Rx_WRITE_ULONG( dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
+
+	//
+	// disable doorbell interrupts
+	//
+
+	Rx_WRITE_UCHAR( dev, MUnit.OIMR, 
+					Rx_READ_UCHAR(dev, MUnit.OIMR) | 0x04);
+
+	//
+	// force the completion of the mask register write before issuing the interrupt.
+	//
+
+	Rx_READ_UCHAR ( dev, MUnit.OIMR);
+
+	//
+	// Signal that there is a new synch command
+	//
+
+	Rx_WRITE_ULONG( dev, InboundDoorbellReg, INBOUNDDOORBELL_0);
+
+	CommandSucceeded = FALSE;
+
+	start = jiffies;
+
+	while (time_before(start+30*HZ, jiffies)) 
+	{ // wait up to 30 seconds
+		udelay(5);				// delay 5 microseconds to let Mon960 get info.
+		//
+		// Mon110 will set doorbell0 bit when it has completed the command.
+		//
+		if (Rx_READ_ULONG(dev, OutboundDoorbellReg) & OUTBOUNDDOORBELL_0) {
+			//
+			// clear the doorbell.
+			//
+			Rx_WRITE_ULONG(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
+			CommandSucceeded = TRUE;
+			break;
+		}
+		// Yield the processor in case we are slow 
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+	}
+	if (CommandSucceeded != TRUE) {
+		//
+		// restore interrupt mask even though we timed out
+		//
+		Rx_WRITE_UCHAR(dev, MUnit.OIMR, 
+			 		   Rx_READ_ULONG(dev, MUnit.OIMR) & 0xfb);
+		return (STATUS_IO_TIMEOUT);
+	}
+	//
+	// Pull the synch status from Mailbox 0.
+	//
+
+	*ReturnStatus = Rx_READ_ULONG(dev, IndexRegs.Mailbox[0]);
+
+	//
+	// Clear the synch command doorbell.
+	//
+		
+	Rx_WRITE_ULONG(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
+
+	//
+	// restore interrupt mask
+	//
+
+	Rx_WRITE_UCHAR(dev, MUnit.OIMR, 
+		 		   Rx_READ_ULONG(dev, MUnit.OIMR) & 0xfb);
+	//
+	// Return SUCCESS
+	//
+	return (STATUS_SUCCESS);
+
+}
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/sap1sup.c linux.gamma/drivers/scsi/aacraid/sap1sup.c
--- linux.15p3/drivers/scsi/aacraid/sap1sup.c	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/sap1sup.c	Wed Nov 28 01:26:41 2001
@@ -0,0 +1,492 @@
+/*++
+ * 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
+ *
+ --*/
+
+#define DEFINE_PCI_IDS
+#include "os.h"
+
+#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
+//
+
+int SaInitDevice(struct aac_dev *dev, unsigned long devNumber);
+
+//
+// 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
+--*/
+
+static void aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct aac_dev *dev = dev_id;
+	unsigned short intstat, mask;
+
+	intstat = Sa_READ_USHORT( dev, 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( dev, SaDbCSR.PRISETIRQMASK));
+
+	// Check to see if this is our interrupt.  If it isn't just return FALSE.
+
+	if (intstat & mask) {
+		if (intstat & PrintfReady) {
+			unsigned long Length, MailboxValue, Level;
+			unsigned char *cp;
+			MailboxValue = Sa_READ_ULONG (dev, Mailbox5);
+			Length = MailboxValue & 0xffff;
+			Level = (MailboxValue >> 16) & 0xffff;
+			cp = dev->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) {
+				cp[Length] = 0;
+			}
+
+			if (Level == LOG_HIGH_ERROR)
+				printk(KERN_WARNING "%s:%s.\n", dev->name, (char *)dev->PrintfBufferAddress);
+			else
+				printk(KERN_INFO "%s:%s.\n", dev->name, (char *)dev->PrintfBufferAddress);
+
+			memset(dev->PrintfBufferAddress, 0, 256);
+			Sa_WRITE_USHORT( dev, DoorbellClrReg_p,PrintfReady); //clear PrintfReady
+			Sa_WRITE_USHORT( dev, DoorbellReg_s,PrintfDone);
+		} else if (intstat & DOORBELL_1) {	// dev -> Host Normal Command Ready
+			HostCommandNormDpc(&dev->CommRegion->HostNormCmdQue);
+			Sa_WRITE_USHORT( dev, DoorbellClrReg_p, DOORBELL_1);
+		} else if (intstat & DOORBELL_2) {	// dev -> Host Normal Response Ready
+			HostResponseNormalDpc(&dev->CommRegion->HostNormRespQue);
+			Sa_WRITE_USHORT( dev, DoorbellClrReg_p,DOORBELL_2);
+		} else if (intstat & DOORBELL_3) {	// dev -> Host Normal Command Not Full
+			Sa_WRITE_USHORT( dev, DoorbellClrReg_p, DOORBELL_3);
+		} else if (intstat & DOORBELL_4) {	// dev -> Host Normal Response Not Full
+			Sa_WRITE_USHORT( dev, DoorbellClrReg_p, DOORBELL_4);
+		}
+	}
+}
+
+
+/*++
+Routine Description:
+	This routine will enable the corresponding adapter event to cause an interrupt on 
+	the host.
+Arguments:
+	dev - Which adapter to enable.
+	AdapterEvent - Which adapter event.
+	AtDeviceIrq - Whether the system is in DEVICE irql
+Return Value:
+    Nothing.
+--*/
+void SaEnableInterrupt(struct aac_dev *dev, u32 AdapterEvent, int AtDeviceIrq)
+{
+	switch (AdapterEvent) {
+
+	case HostNormCmdQue:
+		Sa_WRITE_USHORT( dev,  SaDbCSR.PRICLEARIRQMASK, DOORBELL_1 );
+		break;
+
+	case HostNormRespQue:
+		Sa_WRITE_USHORT( dev,  SaDbCSR.PRICLEARIRQMASK, DOORBELL_2 );
+		break;
+
+	case AdapNormCmdNotFull:
+		Sa_WRITE_USHORT( dev,  SaDbCSR.PRICLEARIRQMASK, DOORBELL_3 );
+		break;
+
+	case AdapNormRespNotFull:
+		Sa_WRITE_USHORT( dev,  SaDbCSR.PRICLEARIRQMASK, DOORBELL_4 );
+		break;
+	}
+}
+
+/*++
+Routine Description:
+	This routine will disable the corresponding adapter event to cause an interrupt on 
+	the host.
+Arguments:
+	dev - Which adapter to enable.
+	AdapterEvent - Which adapter event.
+	AtDeviceIrq - Whether the system is in DEVICE irql
+Return Value:
+	Nothing.
+
+--*/
+void SaDisableInterrupt (struct aac_dev *dev, u32 AdapterEvent, int AtDeviceIrq)
+{
+	switch (AdapterEvent) {
+
+	case HostNormCmdQue:
+		Sa_WRITE_USHORT( dev,  SaDbCSR.PRISETIRQMASK, DOORBELL_1 );
+		break;
+
+	case HostNormRespQue:
+		Sa_WRITE_USHORT( dev,  SaDbCSR.PRISETIRQMASK, DOORBELL_2 );
+		break;
+
+	case AdapNormCmdNotFull:
+		Sa_WRITE_USHORT( dev,  SaDbCSR.PRISETIRQMASK, DOORBELL_3 );
+		break;
+
+	case AdapNormRespNotFull:
+		Sa_WRITE_USHORT( dev,  SaDbCSR.PRISETIRQMASK, DOORBELL_4 );
+		break;
+	}
+}
+
+/*++
+Routine Description:
+	The will cause the adapter to take a break point.
+Arguments:
+	None
+Return Value:
+	Nothing
+--*/
+
+void SaInterruptAdapter (struct aac_dev *dev)
+{
+	unsigned long ret;
+
+	SaSendSynchCommand(dev, 
+			   BREAKPOINT_REQUEST,
+			   0,
+			   0,
+			   0,
+			   0,
+			   &ret);
+}
+
+
+/*++
+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(struct aac_dev *dev, HOST_2_ADAP_EVENT AdapterEvent)
+{
+	switch (AdapterEvent) {
+
+	case AdapNormCmdQue:
+		Sa_WRITE_USHORT( dev, DoorbellReg_s,DOORBELL_1);
+		break;
+	case HostNormRespNotFull:
+		Sa_WRITE_USHORT( dev, DoorbellReg_s,DOORBELL_4);
+		break;
+	case AdapNormRespQue:
+		Sa_WRITE_USHORT( dev, DoorbellReg_s,DOORBELL_2);
+		break;
+	case HostNormCmdNotFull:
+		Sa_WRITE_USHORT( dev, DoorbellReg_s,DOORBELL_3);
+		break;
+	case HostShutdown:
+		//SaSendSynchCommand(dev, HOST_CRASHING, 0, 0, 0, 0, &ret);
+		break;
+	case FastIo:
+		Sa_WRITE_USHORT( dev, DoorbellReg_s,DOORBELL_6);
+		break;
+	case AdapPrintfDone:
+		Sa_WRITE_USHORT( dev, DoorbellReg_s,DOORBELL_5);
+		break;
+	default:
+		BUG();
+		break;
+	}
+}
+
+
+/*++
+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
+--*/
+#if 0
+static struct aac_ops aac_sa_ops =
+{
+	AfaPortAllocateAndMapFibSpace,
+	AfaPortUnmapAndFreeFibSpace,
+	SaInterruptAdapter,
+	SaEnableInterrupt,
+	SaDisableInterrupt,
+	SaNotifyAdapter,
+};
+#endif
+
+int SaInitDevice (struct aac_dev *dev, unsigned long devNumber)
+{
+	unsigned long StartTime;
+	unsigned long InitStatus;
+	int instance;
+	const char *name;
+
+	dev->devNumber = devNumber;
+
+	dprintk(("PREINST\n"));
+	instance = dev->id;
+	name     = dev->name;
+
+	//
+	// Map in the registers from the adapter, register space 0 is config space,
+	// register space 1 is the memery space.
+	//
+	dprintk(("PREMAP\n"));
+
+	if (OsMapDeviceRegisters(dev)){
+		printk(KERN_WARNING "%s%d SaInitDevice: failed OsMapDeviceRegisters.\n", name, instance);
+		return(FAILURE);
+	}
+	//
+	// Check to see if the board failed any self tests.
+	//
+
+	if (Sa_READ_ULONG(dev, Mailbox7) & SELF_TEST_FAILED) {
+		printk(KERN_WARNING "%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(dev, Mailbox7) & KERNEL_PANIC) {
+		printk(KERN_WARNING "%s%d: adapter kernel panic'd.\n",
+				name, instance);
+		return(FAILURE);
+	}
+
+	StartTime = jiffies;
+	//
+	//  Wait for the adapter to be up and running. Wait up until 3 minutes.
+	//
+
+	while (!(Sa_READ_ULONG(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) {
+		if (time_after(StartTime+180*HZ, jiffies)) {
+			InitStatus = Sa_READ_ULONG(dev, Mailbox7) >> 16;
+			printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %ld.\n",
+					name, instance, InitStatus);
+			return(FAILURE);
+		}
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+	}
+
+	dprintk(("ATIRQ\n"));
+	if (request_irq(dev->OsDep.scsi_host_ptr->irq, aac_sa_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev ) < 0) {
+		printk(KERN_WARNING "%s%d: Interrupt unavailable.\n", name, instance);
+		return FAILURE;
+	}
+
+	//
+	// Save the current adapter number and increment the total number.
+	//
+	dev->devNumber = FsaCommData.TotalAdapters++;
+
+	//
+	// Fill in the function dispatch table.
+	//
+
+	dev->AdapterFuncs.InterruptAdapter = SaInterruptAdapter;
+	dev->AdapterFuncs.EnableInterrupt = SaEnableInterrupt;
+	dev->AdapterFuncs.DisableInterrupt = SaDisableInterrupt;
+	dev->AdapterFuncs.NotifyAdapter = SaNotifyAdapter;
+	dev->AdapterFuncs.InterruptHost = NULL;
+
+	dprintk(("FUNCDONE\n"));
+
+	dev->Dip = dev->OsDep.dip;
+
+	if ( AfaCommInitNewAdapter(dev) == NULL) {
+		printk(KERN_WARNING "SaInitDevice: AfaCommInitNewAdapter failed.\n");
+		return FAILURE;
+	};
+
+	dprintk(("NEWADAPTDONE\n"));
+
+	//
+	// Start any kernel threads needed
+	OsStartKernelThreads(dev);
+
+	//
+	// Tell the adapter that all is configure, and it can start accepting requests
+	//
+	
+	dprintk(("STARTING\n"));
+
+	SaStartAdapter(dev);
+
+	dprintk(("STARTED\n"));
+
+	//
+	// Put this adapter into the list of Sa adapters
+	//
+	return 0;
+}
+
+
+
+void SaStartAdapter (struct aac_dev *dev)
+{
+	unsigned long ret;
+	PADAPTER_INIT_STRUCT InitStruct;
+
+	//
+	// Fill in the remaining pieces of the InitStruct.
+	//
+	InitStruct = dev->InitStruct;
+	InitStruct->HostElapsedSeconds = jiffies/HZ;
+
+	dprintk(("INIT\n"));
+	//
+	// Tell the adapter we are back and up and running so it will scan its command
+	// queues and enable our interrupts
+	//
+
+	dev->irq_mask =	(PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4);
+	//
+	// First clear out all interrupts.  Then enable the one's that we can handle.
+	//
+	dprintk(("MASK\n"));
+
+	Sa_WRITE_USHORT( dev,  SaDbCSR.PRISETIRQMASK, (unsigned short) 0xffff );
+	Sa_WRITE_USHORT( dev,  SaDbCSR.PRICLEARIRQMASK,
+					(PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4) );
+
+	dprintk(("SYNCCMD\n"));
+	SaSendSynchCommand(dev, 
+			   INIT_STRUCT_BASE_ADDRESS, 
+			   (unsigned long) dev->PhysicalInitStruct,
+			   0, 0, 0, &ret);
+
+}
+
+
+
+/*++
+Routine Description:
+	This routine will send a synchronous comamnd to the adapter and wait for its
+	completion.
+Arguments:
+	dev - Pointer to adapter structure.
+	Command - Which command to send
+	Parameter1 - 4	- Parameters for command
+	ret - return status from adapter after completion of command
+Return Value:
+	u32
+--*/
+u32 SaSendSynchCommand(struct aac_dev *dev, unsigned long Command,
+	   unsigned long Parameter1,unsigned long Parameter2,
+	   unsigned long Parameter3,unsigned long Parameter4,
+	   unsigned long *ret)
+{
+	unsigned long StartTime;
+	int CommandSucceeded;
+
+	//
+	// Write the Command into Mailbox 0
+	//
+	Sa_WRITE_ULONG( dev, Mailbox0, Command);
+
+	//
+	// Write the parameters into Mailboxes 1 - 4
+	//
+	Sa_WRITE_ULONG( dev, Mailbox1, Parameter1);
+	Sa_WRITE_ULONG( dev, Mailbox2, Parameter2);
+	Sa_WRITE_ULONG( dev, Mailbox3, Parameter3);
+	Sa_WRITE_ULONG( dev, Mailbox4, Parameter4);
+
+	//
+	// Clear the synch command doorbell to start on a clean slate.
+	//
+	Sa_WRITE_USHORT( dev, DoorbellClrReg_p, DOORBELL_0);
+
+	//
+	// Signal that there is a new synch command
+	//
+	Sa_WRITE_USHORT( dev, DoorbellReg_s, DOORBELL_0);
+
+	CommandSucceeded = FALSE;
+	StartTime = jiffies;
+
+	while(time_before(jiffies, StartTime+30*HZ))
+	{
+		// wait up to 30 seconds
+		udelay(5);				// delay 5 microseconds to let Mon960 get info.
+		//
+		// Mon110 will set doorbell0 bit when it has completed the command.
+		//
+		if( Sa_READ_USHORT( dev, DoorbellReg_p) & DOORBELL_0 )  {
+			CommandSucceeded = TRUE;
+			break;
+		}
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(1);
+	}
+
+	if (CommandSucceeded != TRUE)
+		return STATUS_IO_TIMEOUT;
+	//
+	// Clear the synch command doorbell.
+	//
+	Sa_WRITE_USHORT( dev, DoorbellClrReg_p, DOORBELL_0);
+
+	//
+	// Pull the synch status from Mailbox 0.
+	//
+	*ret = Sa_READ_ULONG( dev, Mailbox0);
+
+	//
+	// Return SUCCESS
+	//
+	return STATUS_SUCCESS;
+}
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/aacraid/zone.c linux.gamma/drivers/scsi/aacraid/zone.c
--- linux.15p3/drivers/scsi/aacraid/zone.c	Thu Jan  1 01:00:00 1970
+++ linux.gamma/drivers/scsi/aacraid/zone.c	Tue Nov 27 11:14:19 2001
@@ -0,0 +1,188 @@
+/*++
+ * 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
+ *
+ * 
+ *
+ --*/
+
+#include "osheaders.h"
+#include "aac_unix_defs.h"
+#include "os.h"
+
+
+u32 ExInitializeZone(PZONE_HEADER Zone, unsigned long BlockSize, void * InitialSegment, unsigned long 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.
+
+--*/
+
+{
+    unsigned long i;
+    char * 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 = (char *)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;
+
+    return STATUS_SUCCESS;
+}
+
+u32 ExExtendZone(PZONE_HEADER Zone, void * Segment, unsigned long 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.
+
+--*/
+
+{
+    unsigned long i;
+    char * p;
+
+
+    ((PZONE_SEGMENT_HEADER) Segment)->SegmentList.Next = Zone->SegmentList.Next;
+    Zone->SegmentList.Next = &((PZONE_SEGMENT_HEADER) Segment)->SegmentList;
+
+    p = (char *)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;
+
+    return STATUS_SUCCESS;
+}
+
+//++
+//
+// void *
+// ExFreeToZone(
+//     PZONE_HEADER Zone,
+//     void * 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.
+//
+//--
+
+void ExFreeToZone(PZONE_HEADER Zone, void *Block)
+{
+	((PSINGLE_LIST_ENTRY)(Block))->Next = (Zone)->FreeList.Next;
+	(Zone)->FreeList.Next = ((PSINGLE_LIST_ENTRY)(Block));
+}
+
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.15p3/drivers/scsi/scsi_scan.c linux.gamma/drivers/scsi/scsi_scan.c
--- linux.15p3/drivers/scsi/scsi_scan.c	Mon Nov 12 09:11:52 2001
+++ linux.gamma/drivers/scsi/scsi_scan.c	Mon Nov 19 11:42:23 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...
