[SCSI] aacraid: add Voodoo Lite class of cards.

The cards being added are supported in a limited sense already through
family matching, but we needed to add some functionality to the driver
to expose selectively the physical drives. These Physical drives are
specifically marked to not be part of any array and thus are declared
JBODs (Just a Bunch Of Drives) for generic SCSI access.

We report that this is the second patch in a set of two, but merely
depends on the stand-alone functionality of the first patch which adds
in that case the ability to report a driver feature flag via sysfs. We
leverage that functionality by reporting that this driver now supports
this new JBOD feature for the controller so that the array management
applications may react accordingly and guide the user as they manage
the controller.

Signed-off-by: Mark Salyzyn <aacraid@adaptec.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 8d7b770..d7235f4 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -1339,6 +1339,8 @@
 	}
 
 	dev->cache_protected = 0;
+	dev->jbod = ((dev->supplement_adapter_info.FeatureBits &
+		AAC_FEATURE_JBOD) != 0);
 	dev->nondasd_support = 0;
 	dev->raid_scsi_mode = 0;
 	if(dev->adapter_info.options & AAC_OPT_NONDASD)
@@ -1923,7 +1925,8 @@
 				}
 			}
 		} else {  /* check for physical non-dasd devices */
-			if ((dev->nondasd_support == 1) || expose_physicals) {
+			if (dev->nondasd_support || expose_physicals ||
+					dev->jbod) {
 				if (dev->in_reset)
 					return -1;
 				return aac_send_srb_fib(scsicmd);
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 8a5b9c8..3195d29 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -12,7 +12,7 @@
  *----------------------------------------------------------------------------*/
 
 #ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 2454
+# define AAC_DRIVER_BUILD 2455
 # define AAC_DRIVER_BRANCH "-ms"
 #endif
 #define MAXIMUM_NUM_CONTAINERS	32
@@ -866,6 +866,7 @@
 	__le32	ReservedGrowth[1];
 };
 #define AAC_FEATURE_FALCON	cpu_to_le32(0x00000010)
+#define AAC_FEATURE_JBOD	cpu_to_le32(0x08000000)
 #define AAC_OPTION_MU_RESET	cpu_to_le32(0x00000001)
 #define AAC_OPTION_IGNORE_RESET	cpu_to_le32(0x00000002)
 #define AAC_SIS_VERSION_V3	3
@@ -1012,6 +1013,7 @@
 	 * lets break them out so we don't have to do an AND to check them
 	 */
 	u8			nondasd_support;
+	u8			jbod;
 	u8			cache_protected;
 	u8			dac_support;
 	u8			raid_scsi_mode;
@@ -1777,6 +1779,8 @@
 #define			AifEnExpEvent		23	/* Firmware Event Log */
 #define			AifExeFirmwarePanic	3	/* Firmware Event Panic */
 #define			AifHighPriority		3	/* Highest Priority Event */
+#define			AifEnAddJBOD		30	/* JBOD created */
+#define			AifEnDeleteJBOD		31	/* JBOD deleted */
 
 #define		AifCmdJobProgress	2	/* Progress report */
 #define			AifJobCtrZero	101	/* Array Zero progress */
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 1dd2e57..81b3692 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -901,7 +901,31 @@
 		case AifEnConfigChange:
 			break;
 
+		case AifEnAddJBOD:
+		case AifEnDeleteJBOD:
+			container = le32_to_cpu(((__le32 *)aifcmd->data)[1]);
+			if ((container >> 28))
+				break;
+			channel = (container >> 24) & 0xF;
+			if (channel >= dev->maximum_num_channels)
+				break;
+			id = container & 0xFFFF;
+			if (id >= dev->maximum_num_physicals)
+				break;
+			lun = (container >> 16) & 0xFF;
+			channel = aac_phys_to_logical(channel);
+			device_config_needed =
+			  (((__le32 *)aifcmd->data)[0] ==
+			    cpu_to_le32(AifEnAddJBOD)) ? ADD : DELETE;
+			break;
+
 		case AifEnEnclosureManagement:
+			/*
+			 * If in JBOD mode, automatic exposure of new
+			 * physical target to be suppressed until configured.
+			 */
+			if (dev->jbod)
+				break;
 			switch (le32_to_cpu(((__le32 *)aifcmd->data)[3])) {
 			case EM_DRIVE_INSERTION:
 			case EM_DRIVE_REMOVAL:
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 5ab733d..61be227 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -404,6 +404,7 @@
 	struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata;
 	if ((sdev->type == TYPE_DISK) &&
 			(sdev_channel(sdev) != CONTAINER_CHANNEL) &&
+			(!aac->jbod || sdev->inq_periph_qual) &&
 			(!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))) {
 		if (expose_physicals == 0)
 			return -ENXIO;
@@ -411,7 +412,8 @@
 			sdev->no_uld_attach = 1;
 	}
 	if (sdev->tagged_supported && (sdev->type == TYPE_DISK) &&
-			(sdev_channel(sdev) == CONTAINER_CHANNEL)) {
+			(!aac->raid_scsi_mode || (sdev_channel(sdev) != 2)) &&
+			!sdev->no_uld_attach) {
 		struct scsi_device * dev;
 		struct Scsi_Host *host = sdev->host;
 		unsigned num_lsu = 0;
@@ -430,8 +432,11 @@
 				++num_lsu;
 		__shost_for_each_device(dev, host) {
 			if (dev->tagged_supported && (dev->type == TYPE_DISK) &&
-				(sdev_channel(dev) == CONTAINER_CHANNEL)) {
-				if (!aac->fsa_dev[sdev_id(dev)].valid)
+					(!aac->raid_scsi_mode ||
+						(sdev_channel(sdev) != 2)) &&
+					!dev->no_uld_attach) {
+				if ((sdev_channel(dev) != CONTAINER_CHANNEL)
+				 || !aac->fsa_dev[sdev_id(dev)].valid)
 					++num_lsu;
 			} else
 				++num_one;
@@ -804,6 +809,8 @@
 	if (dev->raw_io_interface && dev->raw_io_64)
 		len += snprintf(buf + len, PAGE_SIZE - len,
 				"SAI_READ_CAPACITY_16\n");
+	if (dev->jbod)
+		len += snprintf(buf + len, PAGE_SIZE - len, "SUPPORTED_JBOD\n");
 	return len;
 }
 
@@ -1157,7 +1164,7 @@
 	 * all containers are on the virtual channel 0 (CONTAINER_CHANNEL)
 	 * physical channels are address by their actual physical number+1
 	 */
-	if ((aac->nondasd_support == 1) || expose_physicals)
+	if (aac->nondasd_support || expose_physicals || aac->jbod)
 		shost->max_channel = aac->maximum_num_channels;
 	else
 		shost->max_channel = 0;