usr/src/uts/common/io/sata/impl/sata.c
changeset 10247 27d5d7e9cd70
parent 10131 7fe254ca5fe8
child 10318 811db323512d
--- a/usr/src/uts/common/io/sata/impl/sata.c	Mon Aug 03 11:56:44 2009 -0700
+++ b/usr/src/uts/common/io/sata/impl/sata.c	Mon Aug 03 12:46:12 2009 -0700
@@ -4019,6 +4019,8 @@
  * Returns TRAN_ACCEPT and appropriate values in scsi_pkt fields.
  */
 
+#define	LLBAA	0x10	/* Long LBA Accepted */
+
 static int
 sata_txlt_mode_sense(sata_pkt_txlate_t *spx)
 {
@@ -4067,7 +4069,7 @@
 		bdlen = 0;
 		if (!(scsipkt->pkt_cdbp[1] & 8)) {
 			if (scsipkt->pkt_cdbp[0] == SCMD_MODE_SENSE_G1 &&
-			    (scsipkt->pkt_cdbp[0] & 0x10))
+			    (scsipkt->pkt_cdbp[1] & LLBAA))
 				bdlen = 16;
 			else
 				bdlen = 8;
@@ -6478,7 +6480,7 @@
 	else
 		page->dexcpt = 1;	/* Only changeable parameter */
 
-	return (PAGELENGTH_INFO_EXCPT + sizeof (struct mode_info_excpt_page));
+	return (PAGELENGTH_INFO_EXCPT + sizeof (struct mode_page));
 }
 
 
@@ -6586,7 +6588,7 @@
  * Process mode select caching page 8 (scsi3 format only).
  * Read Ahead (same as read cache) and Write Cache may be turned on and off
  * if these features are supported by the device. If these features are not
- * supported, quietly ignore them.
+ * supported, the command will be terminated with STATUS_CHECK.
  * This function fails only if the SET FEATURE command sent to
  * the device fails. The page format is not varified, assuming that the
  * target driver operates correctly - if parameters length is too short,
@@ -6632,8 +6634,8 @@
 	*dmod = 0;
 
 	/* Verify parameters length. If too short, drop it */
-	if (PAGELENGTH_DAD_MODE_CACHE_SCSI3 +
-	    sizeof (struct mode_page) < parmlen) {
+	if ((PAGELENGTH_DAD_MODE_CACHE_SCSI3 +
+	    sizeof (struct mode_page)) > parmlen) {
 		*scsipkt->pkt_scbp = STATUS_CHECK;
 		sense = sata_arq_sense(spx);
 		sense->es_key = KEY_ILLEGAL_REQUEST;
@@ -6645,19 +6647,6 @@
 
 	*pagelen = PAGELENGTH_DAD_MODE_CACHE_SCSI3 + sizeof (struct mode_page);
 
-	/*
-	 * We can manipulate only write cache and read ahead
-	 * (read cache) setting.
-	 */
-	if (!SATA_READ_AHEAD_SUPPORTED(*sata_id) &&
-	    !SATA_WRITE_CACHE_SUPPORTED(*sata_id)) {
-		/*
-		 * None of the features is supported - ignore
-		 */
-		*rval = TRAN_ACCEPT;
-		return (SATA_SUCCESS);
-	}
-
 	/* Current setting of Read Ahead (and Read Cache) */
 	if (SATA_READ_AHEAD_ENABLED(*sata_id))
 		dra = 0;	/* 0 == not disabled */
@@ -6686,57 +6675,79 @@
 	scmd->satacmd_error_reg = 0;
 	scmd->satacmd_cmd_reg = SATAC_SET_FEATURES;
 	if (page->dra != dra || page->rcd != dra) {
-		/* Need to flip read ahead setting */
-		if (dra == 0)
-			/* Disable read ahead / read cache */
-			scmd->satacmd_features_reg =
-			    SATAC_SF_DISABLE_READ_AHEAD;
-		else
-			/* Enable read ahead  / read cache */
-			scmd->satacmd_features_reg =
-			    SATAC_SF_ENABLE_READ_AHEAD;
-
-		/* Transfer command to HBA */
-		if (sata_hba_start(spx, rval) != 0)
-			/*
-			 * Pkt not accepted for execution.
-			 */
+		if (SATA_READ_AHEAD_SUPPORTED(*sata_id)) {
+			/* Need to flip read ahead setting */
+			if (dra == 0)
+				/* Disable read ahead / read cache */
+				scmd->satacmd_features_reg =
+				    SATAC_SF_DISABLE_READ_AHEAD;
+			else
+				/* Enable read ahead  / read cache */
+				scmd->satacmd_features_reg =
+				    SATAC_SF_ENABLE_READ_AHEAD;
+
+			/* Transfer command to HBA */
+			if (sata_hba_start(spx, rval) != 0)
+				/*
+				 * Pkt not accepted for execution.
+				 */
+				return (SATA_FAILURE);
+
+			*dmod = 1;
+
+			/* Now process return */
+			if (spx->txlt_sata_pkt->satapkt_reason !=
+			    SATA_PKT_COMPLETED) {
+				goto failure;	/* Terminate */
+			}
+		} else {
+			*scsipkt->pkt_scbp = STATUS_CHECK;
+			sense = sata_arq_sense(spx);
+			sense->es_key = KEY_ILLEGAL_REQUEST;
+			sense->es_add_code =
+			    SD_SCSI_ASC_INVALID_FIELD_IN_PARAMS_LIST;
+			*pagelen = parmlen;
+			*rval = TRAN_ACCEPT;
 			return (SATA_FAILURE);
-
-		*dmod = 1;
-
-		/* Now process return */
-		if (spx->txlt_sata_pkt->satapkt_reason !=
-		    SATA_PKT_COMPLETED) {
-			goto failure;	/* Terminate */
 		}
 	}
 
 	/* Note that the packet is not removed, so it could be re-used */
 	if (page->wce != wce) {
-		/* Need to flip Write Cache setting */
-		if (page->wce == 1)
-			/* Enable write cache */
-			scmd->satacmd_features_reg =
-			    SATAC_SF_ENABLE_WRITE_CACHE;
-		else
-			/* Disable write cache */
-			scmd->satacmd_features_reg =
-			    SATAC_SF_DISABLE_WRITE_CACHE;
-
-		/* Transfer command to HBA */
-		if (sata_hba_start(spx, rval) != 0)
-			/*
-			 * Pkt not accepted for execution.
-			 */
+		if (SATA_WRITE_CACHE_SUPPORTED(*sata_id)) {
+			/* Need to flip Write Cache setting */
+			if (page->wce == 1)
+				/* Enable write cache */
+				scmd->satacmd_features_reg =
+				    SATAC_SF_ENABLE_WRITE_CACHE;
+			else
+				/* Disable write cache */
+				scmd->satacmd_features_reg =
+				    SATAC_SF_DISABLE_WRITE_CACHE;
+
+			/* Transfer command to HBA */
+			if (sata_hba_start(spx, rval) != 0)
+				/*
+				 * Pkt not accepted for execution.
+				 */
+				return (SATA_FAILURE);
+
+			*dmod = 1;
+
+			/* Now process return */
+			if (spx->txlt_sata_pkt->satapkt_reason !=
+			    SATA_PKT_COMPLETED) {
+				goto failure;
+			}
+		} else {
+			*scsipkt->pkt_scbp = STATUS_CHECK;
+			sense = sata_arq_sense(spx);
+			sense->es_key = KEY_ILLEGAL_REQUEST;
+			sense->es_add_code =
+			    SD_SCSI_ASC_INVALID_FIELD_IN_PARAMS_LIST;
+			*pagelen = parmlen;
+			*rval = TRAN_ACCEPT;
 			return (SATA_FAILURE);
-
-		*dmod = 1;
-
-		/* Now process return */
-		if (spx->txlt_sata_pkt->satapkt_reason !=
-		    SATA_PKT_COMPLETED) {
-			goto failure;
 		}
 	}
 	return (SATA_SUCCESS);
@@ -6797,7 +6808,7 @@
 	*dmod = 0;
 
 	/* Verify parameters length. If too short, drop it */
-	if (((PAGELENGTH_INFO_EXCPT + sizeof (struct mode_page)) < parmlen) ||
+	if (((PAGELENGTH_INFO_EXCPT + sizeof (struct mode_page)) > parmlen) ||
 	    page->perf || page->test || (page->mrie != MRIE_ONLY_ON_REQUEST)) {
 		*scsipkt->pkt_scbp = STATUS_CHECK;
 		sense = sata_arq_sense(spx);
@@ -6885,7 +6896,7 @@
 
 	/* If parmlen is too short or the feature is not supported, drop it */
 	if (((PAGELENGTH_DAD_MODE_ACOUSTIC_MANAGEMENT +
-	    sizeof (struct mode_page)) < parmlen) ||
+	    sizeof (struct mode_page)) > parmlen) ||
 	    (! (sata_id->ai_cmdset83 & SATA_ACOUSTIC_MGMT))) {
 		*scsipkt->pkt_scbp = STATUS_CHECK;
 		sense = sata_arq_sense(spx);