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 +* 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 +* Re-diff'd against 2.4.11 and released patch + +2001-10-09 Matt Domsch +* Added two new PCI IDs + +2001-09-25 Matt Domsch +* 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 +* 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 +* 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 +* 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 +* 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 +* 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: .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 + +// +// 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 +//#include +#include // 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 // 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 + +/*------------------------------------------------------------------------------ + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 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 + +#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 // definition of FSAFID; includes fsatypes.h +#include // 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= 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 +#include +#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 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// + * @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 + +#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... .