diff usr/src/uts/common/io/sata/impl/sata.c @ 4836:7e0fe47fd304

PSARC/2007/422 Acoustic Management support under SATA module 6556577 Need to support Advanced Acoustic Management Feature (AAM
author ls24207
date Thu, 09 Aug 2007 06:29:28 -0700
parents c3ede552abd1
children fe2f53c9eb50
line wrap: on
line diff
--- a/usr/src/uts/common/io/sata/impl/sata.c	Thu Aug 09 01:08:41 2007 -0700
+++ b/usr/src/uts/common/io/sata/impl/sata.c	Thu Aug 09 06:29:28 2007 -0700
@@ -206,6 +206,10 @@
     struct mode_cache_scsi3 *, int, int *, int *, int *);
 static	int sata_mode_select_page_1c(sata_pkt_txlate_t *,
     struct mode_info_excpt_page *, int, int *, int *, int *);
+static	int sata_build_msense_page_30(sata_drive_info_t *, int, uint8_t *);
+static	int sata_mode_select_page_30(sata_pkt_txlate_t *,
+    struct mode_acoustic_management *, int, int *, int *, int *);
+
 static	int sata_build_lsense_page_0(sata_drive_info_t *, uint8_t *);
 static	int sata_build_lsense_page_10(sata_drive_info_t *, uint8_t *,
     sata_hba_inst_t *);
@@ -270,7 +274,7 @@
 
 static struct modlmisc modlmisc = {
 	&mod_miscops,			/* Type of module */
-	"SATA Module v%I%"		/* module name */
+	"SATA Module v1.23"		/* module name */
 };
 
 
@@ -4510,6 +4514,11 @@
 			/* power condition */
 			len += sata_build_msense_page_1a(sdinfo, pc, buf+len);
 			break;
+
+		case MODEPAGE_ACOUSTIC_MANAG:
+			/* acoustic management */
+			len += sata_build_msense_page_30(sdinfo, pc, buf+len);
+			break;
 		case MODEPAGE_ALLPAGES:
 			/* all pages */
 			len += sata_build_msense_page_1(sdinfo, pc, buf+len);
@@ -4519,6 +4528,7 @@
 				len += sata_build_msense_page_1c(sdinfo, pc,
 				    buf+len);
 			}
+			len += sata_build_msense_page_30(sdinfo, pc, buf+len);
 			break;
 		default:
 		err:
@@ -4757,6 +4767,31 @@
 				}
 				break;
 
+			case MODEPAGE_ACOUSTIC_MANAG:
+				stat = sata_mode_select_page_30(spx,
+				    (struct mode_acoustic_management *)
+				    &buf[len], pllen, &pagelen, &rval, &dmod);
+				/*
+				 * The pagelen value indicates the number of
+				 * parameter bytes already processed.
+				 * The rval is the return value from
+				 * sata_tran_start().
+				 * The stat indicates the overall status of
+				 * the operation(s).
+				 */
+				if (stat != SATA_SUCCESS)
+					/*
+					 * Page processing did not succeed -
+					 * all error info is already set-up,
+					 * just return
+					 */
+					pllen = 0; /* this breaks the loop */
+				else {
+					len += pagelen;
+					pllen -= pagelen;
+				}
+
+				break;
 			default:
 				*scsipkt->pkt_scbp = STATUS_CHECK;
 				sense = sata_arq_sense(spx);
@@ -6784,6 +6819,74 @@
 }
 
 
+static int
+sata_build_msense_page_30(sata_drive_info_t *sdinfo, int pcntrl, uint8_t *buf)
+{
+	struct mode_acoustic_management *page =
+	    (struct mode_acoustic_management *)buf;
+	sata_id_t *sata_id = &sdinfo->satadrv_id;
+
+	/*
+	 * Most of the fields are set to 0, being not supported and/or disabled
+	 */
+	bzero(buf, PAGELENGTH_DAD_MODE_ACOUSTIC_MANAGEMENT);
+
+	switch (pcntrl) {
+	case P_CNTRL_DEFAULT:
+		/*  default paramters not supported */
+		return (0);
+
+	case P_CNTRL_CURRENT:
+	case P_CNTRL_SAVED:
+		/* Saved and current are supported and are identical */
+		page->mode_page.code = MODEPAGE_ACOUSTIC_MANAG;
+		page->mode_page.length =
+		    PAGELENGTH_DAD_MODE_ACOUSTIC_MANAGEMENT;
+		page->mode_page.ps = 1;
+
+		/* Word 83 indicates if feature is supported */
+		/* If feature is not supported */
+		if (!(sata_id->ai_cmdset83 & SATA_ACOUSTIC_MGMT)) {
+			page->acoustic_manag_enable =
+			    ACOUSTIC_DISABLED;
+		} else {
+			page->acoustic_manag_enable =
+			    (sata_id->ai_features86 & SATA_ACOUSTIC_MGMT
+			    != 0);
+			/* Word 94 inidicates the value */
+#ifdef	_LITTLE_ENDIAN
+			page->acoustic_manag_level =
+			    (uchar_t)sata_id->ai_acoustic;
+			page->vendor_recommended_value =
+			    sata_id->ai_acoustic >> 8;
+#else
+			page->acoustic_manag_level =
+			    sata_id->ai_acoustic >> 8;
+			page->vendor_recommended_value =
+			    (uchar_t)sata_id->ai_acoustic;
+#endif
+		}
+		break;
+
+	case P_CNTRL_CHANGEABLE:
+		page->mode_page.code = MODEPAGE_ACOUSTIC_MANAG;
+		page->mode_page.length =
+		    PAGELENGTH_DAD_MODE_ACOUSTIC_MANAGEMENT;
+		page->mode_page.ps = 1;
+
+		/* Word 83 indicates if the feature is supported */
+		if (sata_id->ai_cmdset83 & SATA_ACOUSTIC_MGMT) {
+			page->acoustic_manag_enable =
+			    ACOUSTIC_ENABLED;
+			page->acoustic_manag_level = 0xff;
+		}
+		break;
+	}
+	return (PAGELENGTH_DAD_MODE_ACOUSTIC_MANAGEMENT +
+	    sizeof (struct mode_page));
+}
+
+
 /*
  * Build Mode sense power condition page
  * NOT IMPLEMENTED.
@@ -7065,6 +7168,80 @@
 	return (SATA_FAILURE);
 }
 
+int
+sata_mode_select_page_30(sata_pkt_txlate_t *spx, struct
+    mode_acoustic_management *page, int parmlen, int *pagelen,
+    int *rval, int *dmod)
+{
+	struct scsi_pkt *scsipkt = spx->txlt_scsi_pkt;
+	sata_drive_info_t *sdinfo;
+	sata_cmd_t *scmd = &spx->txlt_sata_pkt->satapkt_cmd;
+	sata_id_t *sata_id;
+	struct scsi_extended_sense *sense;
+
+	sdinfo = sata_get_device_info(spx->txlt_sata_hba_inst,
+	    &spx->txlt_sata_pkt->satapkt_device);
+	sata_id = &sdinfo->satadrv_id;
+	*dmod = 0;
+
+	/* If parmlen is too short or the feature is not supported, drop it */
+	if (((PAGELENGTH_DAD_MODE_ACOUSTIC_MANAGEMENT +
+	    sizeof (struct mode_page)) < parmlen) ||
+	    (! (sata_id->ai_cmdset83 & SATA_ACOUSTIC_MGMT))) {
+		*scsipkt->pkt_scbp = STATUS_CHECK;
+		sense = sata_arq_sense(spx);
+		sense->es_key = KEY_ILLEGAL_REQUEST;
+		sense->es_add_code = SD_SCSI_INVALID_FIELD_IN_PARAMETER_LIST;
+		*pagelen = parmlen;
+		*rval = TRAN_ACCEPT;
+		return (SATA_FAILURE);
+	}
+
+	*pagelen = PAGELENGTH_DAD_MODE_ACOUSTIC_MANAGEMENT +
+	    sizeof (struct mode_page);
+
+	/*
+	 * We can enable and disable acoustice management and
+	 * set the acoustic management level.
+	 */
+
+	/*
+	 * Set-up Internal SET FEATURES command(s)
+	 */
+	scmd->satacmd_flags.sata_data_direction = SATA_DIR_NODATA_XFER;
+	scmd->satacmd_addr_type = 0;
+	scmd->satacmd_device_reg = 0;
+	scmd->satacmd_status_reg = 0;
+	scmd->satacmd_error_reg = 0;
+	scmd->satacmd_cmd_reg = SATAC_SET_FEATURES;
+	if (page->acoustic_manag_enable) {
+		scmd->satacmd_features_reg = SATAC_SF_ENABLE_ACOUSTIC;
+		scmd->satacmd_sec_count_lsb = page->acoustic_manag_level;
+	} else {	/* disabling acoustic management */
+		scmd->satacmd_features_reg = SATAC_SF_DISABLE_ACOUSTIC;
+	}
+
+	/* Transfer command to HBA */
+	if (sata_hba_start(spx, rval) != 0)
+		/*
+		 * Pkt not accepted for execution.
+		 */
+		return (SATA_FAILURE);
+
+	/* Now process return */
+	if (spx->txlt_sata_pkt->satapkt_reason != SATA_PKT_COMPLETED) {
+		sata_xlate_errors(spx);
+		return (SATA_FAILURE);
+	}
+
+	*dmod = 1;
+
+	return (SATA_SUCCESS);
+}
+
+
+
+
 /*
  * sata_build_lsense_page0() is used to create the
  * SCSI LOG SENSE page 0 (supported log pages)