aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--README2
-rw-r--r--debian/changelog2
-rw-r--r--include/sg_cmds_extra.h19
-rw-r--r--lib/sg_cmds_extra.c206
-rw-r--r--sg3_utils.spec2
6 files changed, 205 insertions, 31 deletions
diff --git a/ChangeLog b/ChangeLog
index 59370721..c3c03773 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,9 +2,10 @@ Each utility has its own version number, date of last change and
some description at the top of its ".c" file. All utilities in the main
directory have their own "man" pages. There is also a sg3_utils man page.
-Changelog for sg3_utils-1.26 [20071102]
+Changelog for sg3_utils-1.26 [20071107]
- sg_get_config: sync with mmc6r01
- - sg_cmds_extra: sg_ll_verify10() add vrprotect argument
+ - sg_cmds_extra: add vrprotect argument to sg_ll_verify10()
+ - add sg_ll_get_performance() and sg_ll_set_cd_speed()
- sg_verify: add --vrprotect= option
Changelog for sg3_utils-1.25 [20071016]
diff --git a/README b/README
index 650d9b5e..6e79f281 100644
--- a/README
+++ b/README
@@ -327,4 +327,4 @@ See http://www.torque.net/sg/tools.html
Doug Gilbert
-2nd November 2007
+7th November 2007
diff --git a/debian/changelog b/debian/changelog
index daf88a27..2795c8a2 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -2,7 +2,7 @@ sg3-utils (1.26-0.1) unstable; urgency=low
* New upstream version
- -- Doug Gilbert <dgilbert@interlog.com> Fri, 02 Nov 2007 10:00:00 +0100
+ -- Doug Gilbert <dgilbert@interlog.com> Wed, 07 Nov 2007 08:00:00 -0500
sg3-utils (1.25-0.1) unstable; urgency=low
diff --git a/include/sg_cmds_extra.h b/include/sg_cmds_extra.h
index 7c300892..ef4b5afe 100644
--- a/include/sg_cmds_extra.h
+++ b/include/sg_cmds_extra.h
@@ -69,13 +69,22 @@ extern int sg_ll_format_unit(int sg_fd, int fmtpinfo, int rto_req,
void * paramp, int param_len, int noisy,
int verbose);
-/* Invokes a SCSI GET CONFIGURATION command (MMC-3,4,5).
+/* Invokes a SCSI GET CONFIGURATION command (MMC-3...6).
* Returns 0 when successful, SG_LIB_CAT_INVALID_OP if command not
* supported, SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported,
* SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */
extern int sg_ll_get_config(int sg_fd, int rt, int starting, void * resp,
int mx_resp_len, int noisy, int verbose);
+/* Invokes a SCSI GET PERFORMANCE command (MMC-3...6).
+ * Returns 0 when successful, SG_LIB_CAT_INVALID_OP if command not
+ * supported, SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported,
+ * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */
+extern int sg_ll_get_performance(int sg_fd, int data_type,
+ unsigned long starting_lba, int max_num_desc,
+ int type, void * resp, int mx_resp_len,
+ int noisy, int verbose);
+
/* Invokes a SCSI PERSISTENT RESERVE IN command (SPC). Returns 0
* when successful, SG_LIB_CAT_INVALID_OP if command not supported,
* SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported,
@@ -195,6 +204,14 @@ extern int sg_ll_send_diag(int sg_fd, int sf_code, int pf_bit, int sf_bit,
void * paramp, int param_len, int noisy,
int verbose);
+/* Invokes a SCSI SET CD SPEED command (MMC).
+ * Return of 0 -> success, SG_LIB_CAT_INVALID_OP -> command not supported,
+ * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION,
+ * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND,
+ * -1 -> other failure */
+extern int sg_ll_set_cd_speed(int sg_fd, int rot_control, int drv_read_speed,
+ int drv_write_speed, int noisy, int verbose);
+
/* Invokes a SCSI SET IDENTIFYING INFORMATION command. This command was
* called SET DEVICE IDENTIFIER prior to spc4r07. Return of 0 -> success,
* SG_LIB_CAT_INVALID_OP -> Set identifying information not supported,
diff --git a/lib/sg_cmds_extra.c b/lib/sg_cmds_extra.c
index 3685088c..de6569d6 100644
--- a/lib/sg_cmds_extra.c
+++ b/lib/sg_cmds_extra.c
@@ -50,50 +50,55 @@
#define SERVICE_ACTION_IN_16_CMDLEN 16
#define SERVICE_ACTION_OUT_16_CMD 0x9f
#define SERVICE_ACTION_OUT_16_CMDLEN 16
-#define READ_LONG_16_SA 0x11
-#define WRITE_LONG_16_SA 0x11
#define MAINTENANCE_IN_CMD 0xa3
#define MAINTENANCE_IN_CMDLEN 12
-#define REPORT_TGT_PRT_GRP_SA 0xa
-#define REPORT_IDENTIFYING_INFORMATION_SA 0x5
#define MAINTENANCE_OUT_CMD 0xa4
#define MAINTENANCE_OUT_CMDLEN 12
-#define SET_IDENTIFYING_INFORMATION_SA 0x6
-#define SET_TGT_PRT_GRP_SA 0xa
-#define SEND_DIAGNOSTIC_CMD 0x1d
-#define SEND_DIAGNOSTIC_CMDLEN 6
-#define RECEIVE_DIAGNOSTICS_CMD 0x1c
-#define RECEIVE_DIAGNOSTICS_CMDLEN 6
-#define READ_DEFECT10_CMD 0x37
-#define READ_DEFECT10_CMDLEN 10
-#define SERVICE_ACTION_IN_12_CMD 0xab
-#define SERVICE_ACTION_IN_12_CMDLEN 12
-#define READ_MEDIA_SERIAL_NUM_SA 0x1
+
+#define ATA_PT_12_CMD 0xa1
+#define ATA_PT_12_CMDLEN 12
+#define ATA_PT_16_CMD 0x85
+#define ATA_PT_16_CMDLEN 16
#define FORMAT_UNIT_CMD 0x4
#define FORMAT_UNIT_CMDLEN 6
-#define REASSIGN_BLKS_CMD 0x7
-#define REASSIGN_BLKS_CMDLEN 6
#define GET_CONFIG_CMD 0x46
#define GET_CONFIG_CMD_LEN 10
+#define GET_PERFORMANCE_CMD 0xac
+#define GET_PERFORMANCE_CMD_LEN 12
#define PERSISTENT_RESERVE_IN_CMD 0x5e
#define PERSISTENT_RESERVE_IN_CMDLEN 10
#define PERSISTENT_RESERVE_OUT_CMD 0x5f
#define PERSISTENT_RESERVE_OUT_CMDLEN 10
+#define READ_BUFFER_CMD 0x3c
+#define READ_BUFFER_CMDLEN 10
+#define READ_DEFECT10_CMD 0x37
+#define READ_DEFECT10_CMDLEN 10
+#define REASSIGN_BLKS_CMD 0x7
+#define REASSIGN_BLKS_CMDLEN 6
+#define RECEIVE_DIAGNOSTICS_CMD 0x1c
+#define RECEIVE_DIAGNOSTICS_CMDLEN 6
+#define SEND_DIAGNOSTIC_CMD 0x1d
+#define SEND_DIAGNOSTIC_CMDLEN 6
+#define SERVICE_ACTION_IN_12_CMD 0xab
+#define SERVICE_ACTION_IN_12_CMDLEN 12
+#define SET_CD_SPEED_CMD 0xbb
+#define SET_CD_SPEED_CMDLEN 12
#define READ_LONG10_CMD 0x3e
#define READ_LONG10_CMDLEN 10
#define WRITE_LONG10_CMD 0x3f
#define WRITE_LONG10_CMDLEN 10
-#define VERIFY10_CMD 0x2f
-#define VERIFY10_CMDLEN 10
-#define ATA_PT_12_CMD 0xa1
-#define ATA_PT_12_CMDLEN 12
-#define ATA_PT_16_CMD 0x85
-#define ATA_PT_16_CMDLEN 16
-#define READ_BUFFER_CMD 0x3c
-#define READ_BUFFER_CMDLEN 10
#define WRITE_BUFFER_CMD 0x3b
#define WRITE_BUFFER_CMDLEN 10
+#define VERIFY10_CMD 0x2f
+#define VERIFY10_CMDLEN 10
+#define READ_LONG_16_SA 0x11
+#define READ_MEDIA_SERIAL_NUM_SA 0x1
+#define REPORT_IDENTIFYING_INFORMATION_SA 0x5
+#define REPORT_TGT_PRT_GRP_SA 0xa
+#define SET_IDENTIFYING_INFORMATION_SA 0x6
+#define SET_TGT_PRT_GRP_SA 0xa
+#define WRITE_LONG_16_SA 0x11
/* Invokes a SCSI REPORT TARGET PORT GROUPS command. Return of 0 -> success,
@@ -161,6 +166,71 @@ sg_ll_report_tgt_prt_grp(int sg_fd, void * resp, int mx_resp_len, int noisy,
return ret;
}
+/* Invokes a SCSI SET CD SPEED command (MMC).
+ * Return of 0 -> success, SG_LIB_CAT_INVALID_OP -> command not supported,
+ * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION,
+ * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND,
+ * -1 -> other failure */
+int
+sg_ll_set_cd_speed(int sg_fd, int rot_control, int drv_read_speed,
+ int drv_write_speed, int noisy, int verbose)
+{
+ int res, ret, k, sense_cat;
+ unsigned char scsCmdBlk[SET_CD_SPEED_CMDLEN] = {SET_CD_SPEED_CMD, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0};
+ unsigned char sense_b[SENSE_BUFF_LEN];
+ struct sg_pt_base * ptvp;
+
+ if (NULL == sg_warnings_strm)
+ sg_warnings_strm = stderr;
+ scsCmdBlk[1] |= (rot_control & 0x3);
+ scsCmdBlk[2] = (drv_read_speed >> 8) & 0xff;
+ scsCmdBlk[3] = drv_read_speed & 0xff;
+ scsCmdBlk[4] = (drv_write_speed >> 8) & 0xff;
+ scsCmdBlk[5] = drv_write_speed & 0xff;
+
+ if (verbose) {
+ fprintf(sg_warnings_strm, " set cd speed cdb: ");
+ for (k = 0; k < SET_CD_SPEED_CMDLEN; ++k)
+ fprintf(sg_warnings_strm, "%02x ", scsCmdBlk[k]);
+ fprintf(sg_warnings_strm, "\n");
+ }
+ ptvp = construct_scsi_pt_obj();
+ if (NULL == ptvp) {
+ fprintf(sg_warnings_strm, "set cd speed: out of memory\n");
+ return -1;
+ }
+ set_scsi_pt_cdb(ptvp, scsCmdBlk, sizeof(scsCmdBlk));
+ set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
+ ret = sg_cmds_process_resp(ptvp, "set cd speed", res, 0,
+ sense_b, noisy, verbose, &sense_cat);
+ if (-1 == ret)
+ ;
+ else if (-2 == ret) {
+ switch (sense_cat) {
+ case SG_LIB_CAT_NOT_READY:
+ case SG_LIB_CAT_UNIT_ATTENTION:
+ case SG_LIB_CAT_INVALID_OP:
+ case SG_LIB_CAT_ILLEGAL_REQ:
+ case SG_LIB_CAT_ABORTED_COMMAND:
+ ret = sense_cat;
+ break;
+ case SG_LIB_CAT_RECOVERED:
+ case SG_LIB_CAT_NO_SENSE:
+ ret = 0;
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ } else
+ ret = 0;
+
+ destruct_scsi_pt_obj(ptvp);
+ return ret;
+}
+
/* Invokes a SCSI SET TARGET PORT GROUPS command. Return of 0 -> success,
* SG_LIB_CAT_INVALID_OP -> Set Target Port Groups not supported,
* SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND,
@@ -896,6 +966,92 @@ sg_ll_get_config(int sg_fd, int rt, int starting, void * resp,
return ret;
}
+/* Invokes a SCSI GET PERFORMANCE command (MMC-3...6).
+ * Returns 0 when successful, SG_LIB_CAT_INVALID_OP if command not
+ * supported, SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported,
+ * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */
+int
+sg_ll_get_performance(int sg_fd, int data_type, unsigned long starting_lba,
+ int max_num_desc, int ttype, void * resp,
+ int mx_resp_len, int noisy, int verbose)
+{
+ int res, k, ret, sense_cat;
+ unsigned char gpCmdBlk[GET_PERFORMANCE_CMD_LEN] = {GET_PERFORMANCE_CMD, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ unsigned char sense_b[SENSE_BUFF_LEN];
+ struct sg_pt_base * ptvp;
+
+ if (NULL == sg_warnings_strm)
+ sg_warnings_strm = stderr;
+ if ((data_type < 0) || (data_type > 0x1f)) {
+ fprintf(sg_warnings_strm, "Bad data_type value: %d\n", data_type);
+ return -1;
+ }
+ gpCmdBlk[1] = (data_type & 0x1f);
+ gpCmdBlk[2] = (unsigned char)((starting_lba >> 24) & 0xff);
+ gpCmdBlk[3] = (unsigned char)((starting_lba >> 16) & 0xff);
+ gpCmdBlk[4] = (unsigned char)((starting_lba >> 8) & 0xff);
+ gpCmdBlk[3] = (unsigned char)(starting_lba & 0xff);
+ if ((max_num_desc < 0) || (max_num_desc > 0xffff)) {
+ fprintf(sg_warnings_strm, "Bad max_num_desc: 0x%x\n", max_num_desc);
+ return -1;
+ }
+ gpCmdBlk[8] = (unsigned char)((max_num_desc >> 8) & 0xff);
+ gpCmdBlk[9] = (unsigned char)(max_num_desc & 0xff);
+ if ((ttype < 0) || (ttype > 0xff)) {
+ fprintf(sg_warnings_strm, "Bad type: 0x%x\n", ttype);
+ return -1;
+ }
+ gpCmdBlk[10] = (unsigned char)ttype;
+
+ if (verbose) {
+ fprintf(sg_warnings_strm, " Get Performance cdb: ");
+ for (k = 0; k < GET_PERFORMANCE_CMD_LEN; ++k)
+ fprintf(sg_warnings_strm, "%02x ", gpCmdBlk[k]);
+ fprintf(sg_warnings_strm, "\n");
+ }
+
+ ptvp = construct_scsi_pt_obj();
+ if (NULL == ptvp) {
+ fprintf(sg_warnings_strm, "get performance: out of memory\n");
+ return -1;
+ }
+ set_scsi_pt_cdb(ptvp, gpCmdBlk, sizeof(gpCmdBlk));
+ set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
+ set_scsi_pt_data_in(ptvp, (unsigned char *)resp, mx_resp_len);
+ res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
+ ret = sg_cmds_process_resp(ptvp, "get performance", res, mx_resp_len,
+ sense_b, noisy, verbose, &sense_cat);
+ if (-1 == ret)
+ ;
+ else if (-2 == ret) {
+ switch (sense_cat) {
+ case SG_LIB_CAT_INVALID_OP:
+ case SG_LIB_CAT_ILLEGAL_REQ:
+ case SG_LIB_CAT_UNIT_ATTENTION:
+ case SG_LIB_CAT_ABORTED_COMMAND:
+ ret = sense_cat;
+ break;
+ case SG_LIB_CAT_RECOVERED:
+ case SG_LIB_CAT_NO_SENSE:
+ ret = 0;
+ break;
+ default:
+ ret = -1;
+ break;
+ }
+ } else {
+ if ((verbose > 2) && (ret > 0)) {
+ fprintf(sg_warnings_strm, " get performance: response%s\n",
+ (ret > 256 ? ", first 256 bytes" : ""));
+ dStrHex((const char *)resp, (ret > 256 ? 256 : ret), -1);
+ }
+ ret = 0;
+ }
+ destruct_scsi_pt_obj(ptvp);
+ return ret;
+}
+
/* Invokes a SCSI PERSISTENT RESERVE IN command (SPC). Returns 0
* when successful, SG_LIB_CAT_INVALID_OP if command not supported,
* SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported,
diff --git a/sg3_utils.spec b/sg3_utils.spec
index 962baac3..836b4581 100644
--- a/sg3_utils.spec
+++ b/sg3_utils.spec
@@ -79,7 +79,7 @@ fi
%{_libdir}/*.la
%changelog
-* Fri Nov 02 2007 - dgilbert at interlog dot com
+* Wed Nov 07 2007 - dgilbert at interlog dot com
- sg_get_config sync with mmc6r01
* sg3_utils-1.26