aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gilbert <dgilbert@interlog.com>2009-02-23 23:51:42 +0000
committerDouglas Gilbert <dgilbert@interlog.com>2009-02-23 23:51:42 +0000
commit451e0b0c3cc8f78a47ca471719f1a9971d592515 (patch)
tree0d9d6f131fd4a50ddc297a24bd6befab98afced4
parent5a7139e9760cb772fdb7a2ca7ebe2fb00e92943a (diff)
downloadsg3_utils-451e0b0c3cc8f78a47ca471719f1a9971d592515.tar.gz
Power Condition VPD page + mode page expansion, sync with spc4r18
git-svn-id: https://svn.bingwo.ca/repos/sg3_utils/trunk@218 6180dd3e-e324-4e3e-922d-17de1ae2f315
-rw-r--r--ChangeLog6
-rw-r--r--lib/sg_lib_data.c26
-rw-r--r--src/sg_inq.c69
-rw-r--r--src/sg_inq_data.c6
-rw-r--r--src/sg_logs.c10
-rw-r--r--src/sg_scan.c.win3248
-rw-r--r--src/sg_vpd.c85
7 files changed, 204 insertions, 46 deletions
diff --git a/ChangeLog b/ChangeLog
index 904e289c..e68040d9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,8 +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.27 [20090215] [svn: r214]
- - sg_inq: sync version descriptors with spc4r17
+Changelog for sg3_utils-1.27 [20090223] [svn: r218]
+ - sg_inq: sync version descriptors with spc4r18
+ - add power condition VPD page
+ - sg_vpd: add power condition VPD page
- sg_map26: fix for lk 2.6.26 when CONFIG_SYSFS_DEPRECATED_V2
is not defined
- output cdb when verbose option given
diff --git a/lib/sg_lib_data.c b/lib/sg_lib_data.c
index 4f3cd44e..746d057f 100644
--- a/lib/sg_lib_data.c
+++ b/lib/sg_lib_data.c
@@ -33,7 +33,7 @@
#include "sg_lib_data.h"
-const char * sg_lib_version_str = "1.47 20090201"; /* spc-4 rev 15 */
+const char * sg_lib_version_str = "1.47 20090223"; /* spc-4 rev 18 */
struct sg_lib_value_name_t sg_lib_normal_opcodes[] = {
{0, 0, "Test Unit Ready"},
@@ -110,14 +110,15 @@ struct sg_lib_value_name_t sg_lib_normal_opcodes[] = {
{0x3f, 0, "Write long(10)"},
{0x40, 0, "Change definition"}, /* obsolete in SPC-4 r11 */
{0x41, 0, "Write same(10)"},
- {0x42, 0, "Read sub-channel"},
- {0x43, 0, "Read TOC/PMA/ATIP"},
+ {0x42, 0, "Unmap"}, /* added SPC-4 rev 18 */
+ {0x42, PDT_MMC, "Read sub-channel"},
+ {0x43, PDT_MMC, "Read TOC/PMA/ATIP"},
{0x44, 0, "Report density support"},
- {0x45, 0, "Play audio(10)"},
- {0x46, 0, "Get configuration"},
- {0x47, 0, "Play audio msf"},
- {0x4a, 0, "Get event status notification"},
- {0x4b, 0, "Pause/resume"},
+ {0x45, PDT_MMC, "Play audio(10)"},
+ {0x46, PDT_MMC, "Get configuration"},
+ {0x47, PDT_MMC, "Play audio msf"},
+ {0x4a, PDT_MMC, "Get event status notification"},
+ {0x4b, PDT_MMC, "Pause/resume"},
{0x4c, 0, "Log select"},
{0x4d, 0, "Log sense"},
{0x4e, 0, "Stop play/scan"},
@@ -403,6 +404,7 @@ struct sg_lib_asc_ascq_t sg_lib_asc_ascq[] =
"notify (enable spinup) required"},
{0x04,0x12,"Logical unit not ready, offline"},
{0x04,0x13,"Logical unit not ready, SA creation in progress"},
+ {0x04,0x14,"Logical unit not ready, space allocation in progress"},
{0x05,0x00,"Logical unit does not respond to selection"},
{0x06,0x00,"No reference position found"},
{0x07,0x00,"Multiple peripheral devices selected"},
@@ -425,6 +427,7 @@ struct sg_lib_asc_ascq_t sg_lib_asc_ascq[] =
{0x0B,0x05,"Warning - background medium scan detected medium error"},
{0x0B,0x06,"Warning - non-volatile cache now volatile"},
{0x0B,0x07,"Warning - degraded power to non-volatile cache"},
+ {0x0B,0x08,"Warning - power loss expected"},
{0x0C,0x00,"Write error"},
{0x0C,0x01,"Write error - recovered with auto reallocation"},
{0x0C,0x02,"Write error - auto reallocation failed"},
@@ -577,6 +580,7 @@ struct sg_lib_asc_ascq_t sg_lib_asc_ascq[] =
{0x27,0x04,"Persistent write protect"},
{0x27,0x05,"Permanent write protect"},
{0x27,0x06,"Conditional write protect"},
+ {0x27,0x07,"Space allocation failed write protect"},
{0x28,0x00,"Not ready to ready change, medium may have changed"},
{0x28,0x01,"Import or export element accessed"},
{0x28,0x02,"Format-layer may have changed"},
@@ -888,6 +892,12 @@ struct sg_lib_asc_ascq_t sg_lib_asc_ascq[] =
{0x5E,0x02,"Standby condition activated by timer"},
{0x5E,0x03,"Idle condition activated by command"},
{0x5E,0x04,"Standby condition activated by command"},
+ {0x5E,0x05,"Idle_b condition activated by timer"},
+ {0x5E,0x06,"Idle_b condition activated by command"},
+ {0x5E,0x07,"Idle_c condition activated by timer"},
+ {0x5E,0x08,"Idle_c condition activated by command"},
+ {0x5E,0x09,"Standby_y condition activated by timer"},
+ {0x5E,0x0a,"Standby_y condition activated by command"},
{0x5E,0x41,"Power state change to active"},
{0x5E,0x42,"Power state change to idle"},
{0x5E,0x43,"Power state change to standby"},
diff --git a/src/sg_inq.c b/src/sg_inq.c
index d909a45c..83931365 100644
--- a/src/sg_inq.c
+++ b/src/sg_inq.c
@@ -23,7 +23,7 @@
#include "sg_cmds_basic.h"
/* A utility program originally written for the Linux OS SCSI subsystem.
-* Copyright (C) 2000-2008 D. Gilbert
+* Copyright (C) 2000-2009 D. Gilbert
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
@@ -66,7 +66,7 @@
* information [MAINTENANCE IN, service action = 0xc]; see sg_opcodes.
*/
-static char * version_str = "0.79 20081125"; /* spc-4 rev 17 */
+static char * version_str = "0.79 20090223"; /* SPC-4 rev 18 */
#define VPD_SUPPORTED_VPDS 0x0
@@ -78,6 +78,7 @@ static char * version_str = "0.79 20081125"; /* spc-4 rev 17 */
#define VPD_MODE_PG_POLICY 0x87
#define VPD_SCSI_PORTS 0x88
#define VPD_ATA_INFO 0x89
+#define VPD_POWER_CONDITION 0x8a
#define VPD_PROTO_LU 0x90
#define VPD_PROTO_PORT 0x91
#define VPD_BLOCK_LIMITS 0xb0
@@ -144,6 +145,7 @@ static struct svpd_values_name_t vpd_pg[] = {
{VPD_EXT_INQ, 0, -1, 0, "ei", "Extended inquiry data"},
{VPD_MAN_NET_ADDR, 0, -1, 0, "mna", "Management network addresses"},
{VPD_MODE_PG_POLICY, 0, -1, 0, "mpp", "Mode page policy"},
+ {VPD_POWER_CONDITION, 0, -1, 0, "po", "Power condition"},
{VPD_PROTO_LU, 0, 0x0, 0, "pslu", "Protocol-specific logical unit "
"information"},
{VPD_PROTO_PORT, 0, 0x0, 0, "pspo", "Protocol-specific port information"},
@@ -644,6 +646,7 @@ static struct vpd_name vpd_name_arr[] = {
{VPD_MODE_PG_POLICY, 0, "Mode page policy"},
{VPD_SCSI_PORTS, 0, "SCSI ports"},
{VPD_ATA_INFO, 0, "ATA information"},
+ {VPD_POWER_CONDITION, 0, "Power condition"},
{VPD_BLOCK_LIMITS, 0, "Block limits (sbc2)"},
{VPD_BLOCK_DEV_CHARS, 0, "Block device characteristics (sbc3)"},
{0xb0, PDT_TAPE, "Sequential access device capabilities (ssc3)"},
@@ -1260,9 +1263,11 @@ decode_x_inq_vpd(unsigned char * buff, int len, int do_hex)
"SIMPSUP=%d\n", !!(buff[5] & 0x20), !!(buff[5] & 0x10),
!!(buff[5] & 0x8), !!(buff[5] & 0x4), !!(buff[5] & 0x2),
!!(buff[5] & 0x1));
- printf(" WU_SUP=%d CRD_SUP=%d NV_SUP=%d V_SUP=%d LUICLR=%d\n",
+ printf(" WU_SUP=%d CRD_SUP=%d NV_SUP=%d V_SUP=%d\n",
!!(buff[6] & 0x8), !!(buff[6] & 0x4), !!(buff[6] & 0x2),
- !!(buff[6] & 0x1), !!(buff[7] & 0x1));
+ !!(buff[6] & 0x1));
+ printf(" P_I_I_SUP=%d LUICLR=%d CBCS=%d\n",
+ !!(buff[7] & 0x10), !!(buff[7] & 0x1), !!(buff[8] & 0x1));
printf(" Multi I_T nexus microcode download=%d\n", buff[9] & 0xf);
}
@@ -1345,6 +1350,35 @@ decode_ata_info_vpd(unsigned char * buff, int len, int do_hex)
}
static void
+decode_power_condition(unsigned char * buff, int len, int do_hex)
+{
+ if (len < 18) {
+ fprintf(stderr, "Power condition VPD page length too short=%d\n",
+ len);
+ return;
+ }
+ if (do_hex) {
+ dStrHex((const char *)buff, len, 0);
+ return;
+ }
+ printf(" Standby_y=%d Standby_z=%d Idle_c=%d Idle_b=%d Idle_a=%d\n",
+ !!(buff[4] & 0x2), !!(buff[4] & 0x1),
+ !!(buff[5] & 0x4), !!(buff[5] & 0x2), !!(buff[5] & 0x1));
+ printf(" Stopped condition recovery time (ms) %d\n",
+ (buff[6] << 8) + buff[7]);
+ printf(" Standby_z condition recovery time (ms) %d\n",
+ (buff[8] << 8) + buff[9]);
+ printf(" Standby_y condition recovery time (ms) %d\n",
+ (buff[10] << 8) + buff[11]);
+ printf(" Idle_a condition recovery time (ms) %d\n",
+ (buff[12] << 8) + buff[13]);
+ printf(" Idle_b condition recovery time (ms) %d\n",
+ (buff[14] << 8) + buff[15]);
+ printf(" Idle_c condition recovery time (ms) %d\n",
+ (buff[16] << 8) + buff[17]);
+}
+
+static void
decode_b0_vpd(unsigned char * buff, int len, int do_hex, int pdt)
{
unsigned int u;
@@ -2234,6 +2268,33 @@ decode_vpd(int sg_fd, const struct opts_t * optsp)
decode_ata_info_vpd(rsp_buff, len, optsp->do_hex);
}
break;
+ case VPD_POWER_CONDITION:
+ if (!optsp->do_raw)
+ printf("VPD INQUIRY: Power condition page\n");
+ res = sg_ll_inquiry(sg_fd, 0, 1, VPD_POWER_CONDITION, rsp_buff,
+ DEF_ALLOC_LEN, 1, optsp->do_verbose);
+ if (0 == res) {
+ len = ((rsp_buff[2] << 8) + rsp_buff[3]) + 4;
+ if (VPD_POWER_CONDITION != rsp_buff[1]) {
+ fprintf(stderr, "invalid VPD response; probably a STANDARD "
+ "INQUIRY response\n");
+ return SG_LIB_CAT_MALFORMED;
+ }
+ if (len > MX_ALLOC_LEN) {
+ fprintf(stderr, "response length too long: %d > %d\n", len,
+ MX_ALLOC_LEN);
+ return SG_LIB_CAT_MALFORMED;
+ } else if (len > DEF_ALLOC_LEN) {
+ if (sg_ll_inquiry(sg_fd, 0, 1, VPD_POWER_CONDITION, rsp_buff,
+ len, 1, optsp->do_verbose))
+ return SG_LIB_CAT_OTHER;
+ }
+ if (optsp->do_raw)
+ dStrRaw((const char *)rsp_buff, len);
+ else
+ decode_power_condition(rsp_buff, len, optsp->do_hex);
+ }
+ break;
case 0xb0: /* could be BLOCK LIMITS but need to know pdt to find out */
res = sg_ll_inquiry(sg_fd, 0, 1, 0xb0, rsp_buff,
DEF_ALLOC_LEN, 1, optsp->do_verbose);
diff --git a/src/sg_inq_data.c b/src/sg_inq_data.c
index 89b311b9..9605c6d9 100644
--- a/src/sg_inq_data.c
+++ b/src/sg_inq_data.c
@@ -23,7 +23,7 @@
#include "sg_cmds_basic.h"
/* A utility program originally written for the Linux OS SCSI subsystem.
-* Copyright (C) 2000-2008 D. Gilbert
+* Copyright (C) 2000-2009 D. Gilbert
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
@@ -53,7 +53,7 @@ struct sg_version_descriptor {
const char * name;
};
-/* table from SPC-4 revision 15 [sorted numerically (from Annex D.8)] */
+/* table from SPC-4 revision 18 [sorted numerically (from Annex D.8)] */
struct sg_version_descriptor sg_version_descriptor_arr[] = {
{0x0, "Version Descriptor not supported or No standard identified"},
{0x20, "SAM (no version claimed)"},
@@ -174,6 +174,7 @@ struct sg_version_descriptor sg_version_descriptor_arr[] = {
{0x434, "MMC-5 ANSI INCITS 430-2007"},
{0x440, "OSD-2 (no version claimed)"},
{0x444, "OSD-2 T10/1729-D revision 4"},
+ {0x446, "OSD-2 T10/1729-D revision 5"},
{0x460, "SPC-4 (no version claimed)"},
{0x461, "SPC-4 T10/1713-D revision 16"},
{0x480, "SMC-3 (no version claimed)"},
@@ -185,6 +186,7 @@ struct sg_version_descriptor sg_version_descriptor_arr[] = {
{0x500, "ADC-3 (no version claimed)"},
{0x520, "SSC-4 (no version claimed)"},
{0x560, "OSD-3 (no version claimed)"},
+ {0x580, "SES-3 (no version claimed)"},
{0x820, "SSA-TL2 (no version claimed)"},
{0x83b, "SSA-TL2 T10/1147-D revision 05b"},
{0x83c, "SSA-TL2 ANSI INCITS 308-1998"},
diff --git a/src/sg_logs.c b/src/sg_logs.c
index fc048c5a..d73f3e0b 100644
--- a/src/sg_logs.c
+++ b/src/sg_logs.c
@@ -25,7 +25,8 @@
*/
-static char * version_str = "0.82 20090205"; /* SPC-4 revision 17 */
+static char * version_str = "0.83 20090223"; /* SPC-4 revision 18 */
+/* TODO: define Power Condition transition log page */
#define MX_ALLOC_LEN (0xfffc)
#define SHORT_RESP_LEN 128
@@ -45,6 +46,7 @@ static char * version_str = "0.82 20090205"; /* SPC-4 revision 17 */
#define SELF_TEST_LPAGE 0x10
#define PORT_SPECIFIC_LPAGE 0x18
#define GSP_LPAGE 0x19
+#define PCT_LPAGE 0x1a
#define TAPE_ALERT_LPAGE 0x2e
#define IE_LPAGE 0x2f
#define NOT_SUBPG_LOG 0x0
@@ -149,6 +151,7 @@ usage()
"output\n");
printf(" --ppc|-Q set the Parameter Pointer Control (PPC) bit "
"(def: 0)\n"
+ " the PPC bit made obsolete in SPC-4 rev 18\n"
" --raw|-r output response in binary to stdout\n"
" --reset|-R reset log parameters (takes PC and SP into "
"account)\n"
@@ -316,7 +319,7 @@ process_cl_new(struct opts_t * optsp, int argc, char * argv[])
case 'q':
++optsp->do_pcb;
break;
- case 'Q':
+ case 'Q': /* N.B. PPC bit obsoleted in SPC-4 rev 18 */
++optsp->do_ppc;
break;
case 'r':
@@ -657,6 +660,9 @@ show_page_name(int pg_code, int subpg_code,
case GSP_LPAGE:
printf("%sGeneral statistics and performance", b);
break;
+ case PCT_LPAGE:
+ printf("%sPower condition transition", b);
+ break;
case IE_LPAGE: printf("%sInformational exceptions (SMART)", b); break;
default : done = 0; break;
}
diff --git a/src/sg_scan.c.win32 b/src/sg_scan.c.win32
index 7e41d4d9..6f441f5b 100644
--- a/src/sg_scan.c.win32
+++ b/src/sg_scan.c.win32
@@ -198,19 +198,19 @@ union STORAGE_DEVICE_DESCRIPTOR_DATA {
static int
storage_query_property_ioctl(HANDLE hdevice,
- union STORAGE_DEVICE_DESCRIPTOR_DATA * data)
+ union STORAGE_DEVICE_DESCRIPTOR_DATA * data)
{
DWORD num_out;
STORAGE_PROPERTY_QUERY query = {StorageDeviceProperty, PropertyStandardQuery, {0} };
memset(data, 0, sizeof(*data));
if (! DeviceIoControl(hdevice, IOCTL_STORAGE_QUERY_PROPERTY,
- &query, sizeof(query), data, sizeof(*data),
- &num_out, NULL)) {
+ &query, sizeof(query), data, sizeof(*data),
+ &num_out, NULL)) {
#if 0
if (verbose > 1)
fprintf(stderr, " IOCTL_STORAGE_QUERY_PROPERTY failed, "
- "Error=%ld\n", GetLastError());
+ "Error=%ld\n", GetLastError());
#endif
return -ENOSYS;
}
@@ -223,13 +223,13 @@ storage_query_property_ioctl(HANDLE hdevice,
" Removable: %s\n"
" BusType: 0x%02x\n",
(data->desc.VendorIdOffset ?
- data->raw+data->desc.VendorIdOffset : ""),
+ data->raw+data->desc.VendorIdOffset : ""),
(data->desc.ProductIdOffset ?
- data->raw+data->desc.ProductIdOffset : ""),
+ data->raw+data->desc.ProductIdOffset : ""),
(data->desc.ProductRevisionOffset ?
- data->raw+data->desc.ProductRevisionOffset : ""),
+ data->raw+data->desc.ProductRevisionOffset : ""),
(data->desc.RemovableMedia ? "Yes":"No"),
- data->desc.BusType);
+ data->desc.BusType);
}
return 0;
}
@@ -358,15 +358,15 @@ iter_scsi_adapters(void)
OPEN_EXISTING, 0, NULL);
if (fh != INVALID_HANDLE_VALUE) {
#if 0
- union STORAGE_DEVICE_DESCRIPTOR_DATA sdda;
+ union STORAGE_DEVICE_DESCRIPTOR_DATA sdda;
- if (storage_query_property_ioctl(fh, &sdda) < 0) {
- err = GetLastError();
+ if (storage_query_property_ioctl(fh, &sdda) < 0) {
+ err = GetLastError();
fprintf(stderr, "%s: IOCTL_STORAGE_QUERY_PROPERTY failed "
"err=%lu\n\t%s",
adapter_name, err, get_err_str(err, sizeof(b), b));
- }
- // fprintf(stderr, "%s: failed\n", __FUNCTION__ );
+ }
+ // fprintf(stderr, "%s: failed\n", __FUNCTION__ );
#endif
hole_count = 0;
success = DeviceIoControl(fh, IOCTL_SCSI_GET_INQUIRY_DATA,
@@ -468,10 +468,10 @@ iter_volumes(int letter)
OPEN_EXISTING, 0, NULL);
if (fh != INVALID_HANDLE_VALUE) {
#if 1
- union STORAGE_DEVICE_DESCRIPTOR_DATA sdda;
+ union STORAGE_DEVICE_DESCRIPTOR_DATA sdda;
- if (storage_query_property_ioctl(fh, &sdda) < 0)
- fprintf(stderr, "%s: failed\n", __FUNCTION__ );
+ if (storage_query_property_ioctl(fh, &sdda) < 0)
+ fprintf(stderr, "%s: failed\n", __FUNCTION__ );
#endif
success = DeviceIoControl(fh, IOCTL_SCSI_GET_ADDRESS,
NULL, 0, inqDataBuff,
@@ -585,10 +585,10 @@ iter_pds(void)
OPEN_EXISTING, 0, NULL);
if (fh != INVALID_HANDLE_VALUE) {
#if 1
- union STORAGE_DEVICE_DESCRIPTOR_DATA sdda;
+ union STORAGE_DEVICE_DESCRIPTOR_DATA sdda;
- if (storage_query_property_ioctl(fh, &sdda) < 0)
- fprintf(stderr, "%s: failed\n", __FUNCTION__ );
+ if (storage_query_property_ioctl(fh, &sdda) < 0)
+ fprintf(stderr, "%s: failed\n", __FUNCTION__ );
#endif
hole_count = 0;
success = DeviceIoControl(fh, IOCTL_SCSI_GET_ADDRESS,
@@ -914,19 +914,19 @@ sg_do_wscan(char letter)
memset(w_scsi_arr, 0, sizeof(w_scsi_arr));
k = iter_scsi_adapters();
if (k)
- return k;
+ return k;
k = iter_volumes(letter);
if (k)
- return k;
+ return k;
k = iter_pds();
if (k)
- return k;
+ return k;
k = iter_cdroms();
if (k)
- return k;
+ return k;
k = iter_tapes();
if (k)
- return k;
+ return k;
for (k = 0; k < MAX_SCSI_ELEMS; ++k) {
sep = w_scsi_arr + k;
diff --git a/src/sg_vpd.c b/src/sg_vpd.c
index d8343a8e..47291d61 100644
--- a/src/sg_vpd.c
+++ b/src/sg_vpd.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006-2008 Douglas Gilbert.
+ * Copyright (c) 2006-2009 Douglas Gilbert.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -52,7 +52,7 @@
*/
-static char * version_str = "0.29 20080513"; /* spc4r14 */
+static char * version_str = "0.30 20090223"; /* spc4r18 */
extern void svpd_enumerate_vendor(void);
extern int svpd_decode_vendor(int sg_fd, int num_vpd, int subvalue,
@@ -74,6 +74,7 @@ extern const struct svpd_values_name_t *
#define VPD_MODE_PG_POLICY 0x87
#define VPD_SCSI_PORTS 0x88
#define VPD_ATA_INFO 0x89
+#define VPD_POWER_CONDITION 0x8a
#define VPD_PROTO_LU 0x90
#define VPD_PROTO_PORT 0x91
#define VPD_BLOCK_LIMITS 0xb0 /* SBC-3 */
@@ -166,6 +167,7 @@ static struct svpd_values_name_t standard_vpd_pg[] = {
{VPD_MAN_NET_ADDR, 0, -1, 0, "mna", "Management network addresses"},
{VPD_MODE_PG_POLICY, 0, -1, 0, "mpp", "Mode page policy"},
{VPD_OSD_INFO, 0, 0x11, 0, "oi", "OSD information"},
+ {VPD_POWER_CONDITION, 0, -1, 0, "po", "Power condition"},
{VPD_PROTO_LU, 0, 0x0, 0, "pslu", "Protocol-specific logical unit "
"information"},
{VPD_PROTO_PORT, 0, 0x0, 0, "pspo", "Protocol-specific port information"},
@@ -1063,9 +1065,11 @@ decode_x_inq_vpd(unsigned char * buff, int len, int do_hex)
"SIMPSUP=%d\n", !!(buff[5] & 0x20), !!(buff[5] & 0x10),
!!(buff[5] & 0x8), !!(buff[5] & 0x4), !!(buff[5] & 0x2),
!!(buff[5] & 0x1));
- printf(" WU_SUP=%d CRD_SUP=%d NV_SUP=%d V_SUP=%d LUICLR=%d\n",
+ printf(" WU_SUP=%d CRD_SUP=%d NV_SUP=%d V_SUP=%d\n",
!!(buff[6] & 0x8), !!(buff[6] & 0x4), !!(buff[6] & 0x2),
- !!(buff[6] & 0x1), !!(buff[7] & 0x1));
+ !!(buff[6] & 0x1));
+ printf(" P_I_I_SUP=%d LUICLR=%d CBCS=%d\n",
+ !!(buff[7] & 0x10), !!(buff[7] & 0x1), !!(buff[8] & 0x1));
printf(" Multi I_T nexus microcode download=%d\n", buff[9] & 0xf);
}
@@ -1151,6 +1155,35 @@ decode_ata_info_vpd(unsigned char * buff, int len, int do_long, int do_hex)
}
static void
+decode_power_condition(unsigned char * buff, int len, int do_hex)
+{
+ if (len < 18) {
+ fprintf(stderr, "Power condition VPD page length too short=%d\n",
+ len);
+ return;
+ }
+ if (do_hex) {
+ dStrHex((const char *)buff, len, 0);
+ return;
+ }
+ printf(" Standby_y=%d Standby_z=%d Idle_c=%d Idle_b=%d Idle_a=%d\n",
+ !!(buff[4] & 0x2), !!(buff[4] & 0x1),
+ !!(buff[5] & 0x4), !!(buff[5] & 0x2), !!(buff[5] & 0x1));
+ printf(" Stopped condition recovery time (ms) %d\n",
+ (buff[6] << 8) + buff[7]);
+ printf(" Standby_z condition recovery time (ms) %d\n",
+ (buff[8] << 8) + buff[9]);
+ printf(" Standby_y condition recovery time (ms) %d\n",
+ (buff[10] << 8) + buff[11]);
+ printf(" Idle_a condition recovery time (ms) %d\n",
+ (buff[12] << 8) + buff[13]);
+ printf(" Idle_b condition recovery time (ms) %d\n",
+ (buff[14] << 8) + buff[15]);
+ printf(" Idle_c condition recovery time (ms) %d\n",
+ (buff[16] << 8) + buff[17]);
+}
+
+static void
decode_proto_lu_vpd(unsigned char * buff, int len, int do_hex)
{
int k, bump, rel_port, desc_len, proto;
@@ -1844,6 +1877,50 @@ svpd_decode_standard(int sg_fd, int num_vpd, int subvalue, int maxlen,
return 0;
}
break;
+ case VPD_POWER_CONDITION: /* 0x8a */
+ if ((! do_raw) && (3 != do_hex) && (! do_quiet))
+ printf("Power condition VPD page:\n");
+ res = sg_ll_inquiry(sg_fd, 0, 1, num_vpd, rsp_buff, alloc_len, 1,
+ verbose);
+ if (0 == res) {
+ len = ((rsp_buff[2] << 8) + rsp_buff[3]) + 4;
+ if (num_vpd != rsp_buff[1]) {
+ fprintf(stderr, "invalid VPD response; probably a STANDARD "
+ "INQUIRY response\n");
+ if (verbose) {
+ fprintf(stderr, "First 32 bytes of bad response\n");
+ dStrHex((const char *)rsp_buff, 32, 0);
+ }
+ return SG_LIB_CAT_MALFORMED;
+ }
+ if (len > alloc_len) {
+ if ((0 == maxlen) && (len < MX_ALLOC_LEN)) {
+ res = sg_ll_inquiry(sg_fd, 0, 1, num_vpd, rsp_buff, len,
+ 1, verbose);
+ if (res) {
+ fprintf(stderr, "fetching ATA info page "
+ "(alloc_len=%d) failed\n", len);
+ return res;
+ }
+ } else {
+ fprintf(stderr, ">>> warning: response length (%d) "
+ "longer than requested (%d)\n", len, alloc_len);
+ len = alloc_len;
+ }
+ }
+ if (do_raw)
+ dStrRaw((const char *)rsp_buff, len);
+ else {
+ pdt = rsp_buff[0] & 0x1f;
+ if (verbose || do_long)
+ printf(" [PQual=%d Peripheral device type: %s]\n",
+ (rsp_buff[0] & 0xe0) >> 5,
+ sg_get_pdt_str(pdt, sizeof(buff), buff));
+ decode_power_condition(rsp_buff, len, do_hex);
+ }
+ return 0;
+ }
+ break;
case VPD_PROTO_LU: /* 0x90 */
if ((! do_raw) && (! do_quiet))
printf("Protocol-specific logical unit information:\n");