summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/cmd/scsi/smp/common/smp.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/usr/src/cmd/scsi/smp/common/smp.c b/usr/src/cmd/scsi/smp/common/smp.c
index 374049b845..00dd414c67 100644
--- a/usr/src/cmd/scsi/smp/common/smp.c
+++ b/usr/src/cmd/scsi/smp/common/smp.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2015 PALO, Richard
+ * Copyright 2019, Joyent, Inc.
*/
#include <sys/types.h>
#include <sys/scsi/generic/smp_frames.h>
@@ -70,6 +71,31 @@ fatal(int err, const char *fmt, ...)
_exit(err);
}
+/*
+ * Print out a buffer of SMP character array data. The data in str is guaranteed
+ * to be at most len bytes long. While it is supposed to be ascii, we should not
+ * assume as such.
+ */
+static void
+smp_print_ascii(const char *header, const char *str, size_t len)
+{
+ size_t i, last = len;
+
+ while (last > 0 && str[last - 1] == ' ')
+ last--;
+
+ (void) printf("%s: ", header);
+ for (i = 0; i < last; i++) {
+ if (isascii(str[i]) != 0 && isalnum(str[i]) != 0) {
+ (void) putchar(str[i]);
+ } else {
+ (void) printf("\\x%x", str[i]);
+ }
+ }
+
+ (void) putchar('\n');
+}
+
static char *
smp_get_result(smp_result_t result)
{
@@ -431,6 +457,12 @@ smp_validate_args(int argc, char *argv[])
fatal(-1, "Usage: %s <device> <function> ...\n", argv[0]);
switch (func) {
+ case SMP_FUNC_REPORT_GENERAL:
+ case SMP_FUNC_REPORT_MANUFACTURER_INFO:
+ if (argc != 3) {
+ fatal(-1, "Usage: %s <device> 0x%x\n", argv[0], func);
+ }
+ break;
case SMP_FUNC_DISCOVER:
case SMP_FUNC_REPORT_PHY_EVENT:
case SMP_FUNC_REPORT_PHY_ERROR_LOG: {
@@ -540,6 +572,13 @@ main(int argc, char *argv[])
}
switch (func) {
+ case SMP_FUNC_REPORT_GENERAL:
+ case SMP_FUNC_REPORT_MANUFACTURER_INFO:
+ /*
+ * These functions have no additional request bytes. therefore
+ * there is nothing for us to get and fill in here.
+ */
+ break;
case SMP_FUNC_DISCOVER: {
smp_discover_req_t *dp;
@@ -615,6 +654,150 @@ main(int argc, char *argv[])
smp_get_response(B_TRUE);
switch (func) {
+ case SMP_FUNC_REPORT_GENERAL: {
+ smp_report_general_resp_t *gr =
+ (smp_report_general_resp_t *)smp_resp;
+
+ (void) printf("Expander Route Indexes: %u\n",
+ SCSI_READ16(&gr->srgr_exp_route_indexes));
+ (void) printf("Long Responses: %s\n",
+ gr->srgr_long_response != 0 ? "Supported" : "Unsupported");
+ (void) printf("Phys: %d\n", gr->srgr_number_of_phys);
+ (void) printf("Features:\n");
+ if (gr->srgr_externally_configurable_route_table != 0) {
+ (void) printf("\tExternally Configurable Route "
+ "Table\n");
+ }
+ if (gr->srgr_configuring != 0) {
+ (void) printf("\tConfiguring\n");
+ }
+ if (gr->srgr_configures_others != 0) {
+ (void) printf("\tConfigures Others\n");
+ }
+ if (gr->srgr_open_reject_retry_supported != 0) {
+ (void) printf("\tOpen Reject Retry\n");
+ }
+ if (gr->srgr_stp_continue_awt != 0) {
+ (void) printf("\tSTP Continue AWT\n");
+ }
+ if (gr->srgr_table_to_table_supported != 0) {
+ (void) printf("\tTable to Table\n");
+ }
+
+ (void) printf("Logical Identify: %016llx\n",
+ SCSI_READ64(&gr->srgr_enclosure_logical_identifier));
+
+ (void) printf("STP Bus Inactivity Time Limit: %u us\n",
+ SCSI_READ16(&gr->srgr_stp_bus_inactivity_time_limit) * 100);
+ (void) printf("STP Maximum Connect Time Limit: %u us\n",
+ SCSI_READ16(&gr->srgr_stp_maximum_connect_time_limit) *
+ 100);
+ (void) printf("STP SMP I_T Nexus Loss Time: ");
+ if (gr->srgr_stp_smp_nexus_loss_time == 0) {
+ (void) printf("Vendor Specific\n");
+ } else if (gr->srgr_stp_smp_nexus_loss_time == UINT16_MAX) {
+ (void) printf("Retries Forever\n");
+ } else {
+ (void) printf("%u ms\n",
+ SCSI_READ16(&gr->srgr_stp_smp_nexus_loss_time));
+ }
+
+ (void) printf("Physical Presence: %s, %s\n",
+ gr->srgr_physical_presence_supported ? "Supported" :
+ "Unsupported",
+ gr->srgr_physical_presence_asserted ? "Enabled" :
+ "Disabled");
+
+ (void) printf("Zoning:\n");
+ if (gr->srgr_zoning_supported != 0) {
+ (void) printf("\tSupported\n");
+ } else {
+ (void) printf("\tUnsupported\n");
+ }
+ if (gr->srgr_zoning_enabled != 0) {
+ (void) printf("\tEnabled\n");
+ } else {
+ (void) printf("\tDisabled\n");
+ }
+ if (gr->srgr_zone_locked != 0) {
+ (void) printf("\tLocked\n");
+ } else {
+ (void) printf("\tUnlocked\n");
+ }
+ if (gr->srgr_saving_zoning_enabled_supported != 0) {
+ (void) printf("\tSaving Zoning Enabled Supported\n");
+ }
+ if (gr->srgr_saving_zone_perm_table_supported != 0) {
+ (void) printf("\tSaving Zone Perm Table Supported\n");
+ }
+ if (gr->srgr_saving_zone_phy_info_supported != 0) {
+ (void) printf("\tSaving Zone Phy Info Supported\n");
+ }
+ if (gr->srgr_saving != 0) {
+ (void) printf("\tSaving\n");
+ }
+ (void) printf("\tActive Zone Manager SAS Address: %016llx\n",
+ SCSI_READ64(&gr->srgr_active_zm_sas_addr));
+ (void) printf("\tZone Lock Inactivity Limit: %u ms\n",
+ SCSI_READ16(&gr->srgr_zone_lock_inactivity_limit) * 100);
+
+ (void) printf("Maximum Routed SAS Addresses: %u\n",
+ SCSI_READ16(&gr->srgr_max_routed_sas_addrs));
+
+ (void) printf("First Enclosure Connector Element Index: %u\n",
+ gr->srgr_first_encl_conn_elem_idx);
+ (void) printf("Number of Enclosure Connector Elements: %u\n",
+ gr->srgr_number_encl_conn_elem_idxs);
+
+ if (gr->srgr_reduced_functionality != 0) {
+ (void) printf("Time to Reduced Functionality: %u ms\n",
+ gr->srgr_time_to_reduced_functionality * 100);
+ }
+ (void) printf("Initial Time to Reduced Functionality: %u ms\n",
+ gr->srgr_initial_time_to_reduced_functionality * 100);
+ (void) printf("Maximum Time to Reduced Functionality: %u ms\n",
+ gr->srgr_max_reduced_functionality_time * 100);
+ (void) printf("Last Self-configuration Status Index: %u\n",
+ SCSI_READ16(&gr->srgr_last_self_conf_status_descr_idx));
+ (void) printf("Maximum Stored Self-configuration Statuses: "
+ "%u\n", SCSI_READ16(
+ &gr->srgr_max_stored_self_config_status_descrs));
+ (void) printf("Last Phy Event List Descriptor Index: %u\n",
+ SCSI_READ16(&gr->srgr_last_phy_event_list_descr_idx));
+ (void) printf("Maximum Stored Phy Event List Descriptors: "
+ "%u\n", SCSI_READ16(
+ &gr->srgr_max_stored_phy_event_list_descrs));
+ (void) printf("STP Reject to Open Limit: %u us\n",
+ SCSI_READ16(&gr->srgr_stp_reject_to_open_limit) * 10);
+ break;
+ }
+ case SMP_FUNC_REPORT_MANUFACTURER_INFO: {
+ smp_report_manufacturer_info_resp_t *mir =
+ (smp_report_manufacturer_info_resp_t *)smp_resp;
+
+ smp_print_ascii("Vendor", mir->srmir_vendor_identification,
+ sizeof (mir->srmir_vendor_identification));
+ smp_print_ascii("Product", mir->srmir_product_identification,
+ sizeof (mir->srmir_product_identification));
+ smp_print_ascii("Revision", mir->srmir_product_revision_level,
+ sizeof (mir->srmir_product_revision_level));
+ /*
+ * The format of the following section was changed in the SAS
+ * 1.1 specification. If this bit is not present, it is vendor
+ * specific and therefore we don't print them.
+ */
+ if (mir->srmir_sas_1_1_format == 0) {
+ break;
+ }
+ smp_print_ascii("Component Vendor",
+ mir->srmir_component_vendor_identification,
+ sizeof (mir->srmir_component_vendor_identification));
+ (void) printf("Component ID: 0x%x\n",
+ SCSI_READ16(&mir->srmir_component_id));
+ (void) printf("Component Revision: 0x%x\n",
+ mir->srmir_component_revision_level);
+ break;
+ }
case SMP_FUNC_DISCOVER: {
smp_discover_resp_t *rp = (smp_discover_resp_t *)smp_resp;
(void) printf("Addr: %016llx Phy: %02x\n",