--- 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);