Mercurial > illumos > illumos-gate
changeset 13106:efddb0166961
6962613 REPORT GENERAL structure definition includes extra bit
6970613 Updates to smp headers and the smp utility
author | David Hollister <david.hollister@oracle.com> |
---|---|
date | Thu, 12 Aug 2010 15:59:36 -0600 |
parents | 48f2dbca79a2 |
children | eb7af425d949 |
files | usr/src/cmd/scsi/smp/common/smp.c usr/src/lib/scsi/libsmp/common/libsmp.h usr/src/lib/scsi/libsmp/common/smp_engine.c usr/src/lib/scsi/libsmp/mapfile-vers usr/src/lib/scsi/plugins/smp/sas2/common/sas2_functions.c usr/src/uts/common/sys/scsi/generic/smp_frames.h |
diffstat | 6 files changed, 768 insertions(+), 105 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/scsi/smp/common/smp.c Thu Aug 12 14:55:22 2010 -0700 +++ b/usr/src/cmd/scsi/smp/common/smp.c Thu Aug 12 15:59:36 2010 -0600 @@ -27,6 +27,7 @@ #include <sys/scsi/generic/commands.h> #include <sys/scsi/impl/commands.h> #include <sys/ccompile.h> +#include <sys/byteorder.h> #include <stdarg.h> #include <stdio.h> @@ -40,8 +41,19 @@ #include <scsi/libsmp.h> #include <scsi/libsmp_plugin.h> +static char *yes = "Yes"; +static char *no = "No"; + static void fatal(int, const char *, ...) __NORETURN; +static smp_target_t *tp = NULL; +static smp_action_t *ap = NULL; +static smp_function_t func; +static smp_result_t result; +static smp_target_def_t tdef; +static uint8_t *smp_resp; +static size_t smp_resp_len; + static void fatal(int err, const char *fmt, ...) { @@ -57,31 +69,444 @@ _exit(err); } -int -main(int argc, char *argv[]) +static char * +smp_get_result(smp_result_t result) +{ + switch (result) { + case SMP_RES_FUNCTION_ACCEPTED: + return ("Function accepted"); + break; + case SMP_RES_UNKNOWN_FUNCTION: + return ("Unknown function"); + break; + case SMP_RES_FUNCTION_FAILED: + return ("Function failed"); + break; + case SMP_RES_INVALID_REQUEST_FRAME_LENGTH: + return ("Invalid request frame length"); + break; + case SMP_RES_INVALID_EXPANDER_CHANGE_COUNT: + return ("Invalid expander change count"); + break; + case SMP_RES_BUSY: + return ("Busy"); + break; + case SMP_RES_INCOMPLETE_DESCRIPTOR_LIST: + return ("Incomplete descriptor list"); + break; + case SMP_RES_PHY_DOES_NOT_EXIST: + return ("PHY does not exist"); + break; + case SMP_RES_INDEX_DOES_NOT_EXIST: + return ("Index does not exist"); + break; + case SMP_RES_PHY_DOES_NOT_SUPPORT_SATA: + return ("PHY does not support SATA"); + break; + case SMP_RES_UNKNOWN_PHY_OPERATION: + return ("Unknown PHY operation"); + break; + case SMP_RES_UNKNOWN_PHY_TEST_FUNCTION: + return ("Unknown PHY test function"); + break; + case SMP_RES_PHY_TEST_IN_PROGRESS: + return ("PHY test in progress"); + break; + case SMP_RES_PHY_VACANT: + return ("PHY vacant"); + break; + case SMP_RES_UNKNOWN_PHY_EVENT_SOURCE: + return ("Unknown PHY event source"); + break; + case SMP_RES_UNKNOWN_DESCRIPTOR_TYPE: + return ("Unknown descriptor type"); + break; + case SMP_RES_UNKNOWN_PHY_FILTER: + return ("Unknown PHY filter"); + break; + case SMP_RES_AFFILIATION_VIOLATION: + return ("Affiliation violation"); + break; + case SMP_RES_ZONE_VIOLATION: + return ("Zone violation"); + break; + case SMP_RES_NO_MANAGEMENT_ACCESS_RIGHTS: + return ("No management access rights"); + break; + case SMP_RES_UNKNOWN_ENABLE_DISABLE_ZONING: + return ("Unknown enable/disable zoning value"); + break; + case SMP_RES_ZONE_LOCK_VIOLATION: + return ("Zone lock violation"); + break; + case SMP_RES_NOT_ACTIVATED: + return ("Not activated"); + break; + case SMP_RES_ZONE_GROUP_OUT_OF_RANGE: + return ("Zone group out of range"); + break; + case SMP_RES_NO_PHYSICAL_PRESENCE: + return ("No physical presence"); + break; + case SMP_RES_SAVING_NOT_SUPPORTED: + return ("Saving not supported"); + break; + case SMP_RES_SOURCE_ZONE_GROUP_DNE: + return ("Source zone group does not exist"); + break; + case SMP_RES_DISABLED_PW_NOT_SUPPORTED: + return ("Disabled password not supported"); + break; + default: + break; + } + + return (NULL); +} + +static void +smp_execute() +{ + if (smp_exec(ap, tp) != 0) { + smp_close(tp); + smp_action_free(ap); + smp_fini(); + fatal(-4, "exec failed: %s", smp_errmsg()); + } +} + +static void +smp_cmd_failed(smp_result_t result) +{ + char *smp_result_str = smp_get_result(result); + + if (result == NULL) { + fatal(-5, "Command failed: Unknown result (0x%x)", + result); + } else { + fatal(-5, "Command failed: %s", smp_result_str); + } +} + +static void +smp_get_response(boolean_t close_on_fail) +{ + smp_action_get_response(ap, &result, (void **)&smp_resp, &smp_resp_len); + + if (close_on_fail && (result != SMP_RES_FUNCTION_ACCEPTED)) { + smp_close(tp); + smp_action_free(ap); + smp_fini(); + smp_cmd_failed(result); + } +} + +static void +smp_cleanup() +{ + if (tp) { + smp_close(tp); + tp = NULL; + } + smp_action_free(ap); + smp_fini(); +} + +static void +smp_handle_report_route_info(int argc, char *argv[]) { - smp_target_t *tp; - smp_action_t *ap; - smp_errno_t err; - smp_function_t func; - smp_result_t result; - smp_target_def_t tdef; - smp_discover_resp_t *rp; - smp_report_manufacturer_info_resp_t *ip; - uint8_t *resp; - size_t len; - uint_t cap; - void *x; - uint_t i, j; + smp_report_route_info_req_t *rp; + smp_report_route_info_resp_t *rirp; + uint16_t route_indexes = smp_target_get_exp_route_indexes(tp); + uint8_t num_phys = smp_target_get_number_of_phys(tp); + uint16_t rt_idx_req, ri_idx, ri_end; + uint8_t phy_id_req, pi_idx, pi_end; + boolean_t enabled_entries = B_FALSE; + + /* + * Verify the expander supports the PHY-based expander route table + */ + if (route_indexes == 0) { + smp_cleanup(); + fatal(-6, "Expander does not support PHY-based route table\n"); + } + + rt_idx_req = strtol(argv[3], NULL, 0); + phy_id_req = strtol(argv[4], NULL, 0); + + if (((int16_t)rt_idx_req == -1) && ((int8_t)phy_id_req == -1)) { + ri_idx = 0; + ri_end = route_indexes - 1; + pi_idx = 0; + pi_end = num_phys - 1; + } else if (((int16_t)rt_idx_req < 0) || (rt_idx_req >= route_indexes) || + ((int8_t)phy_id_req < 0) || (phy_id_req >= num_phys)) { + smp_cleanup(); + fatal(-1, "Invalid route index (%d) or PHY ID (%d)\n", + rt_idx_req, phy_id_req); + } else { + ri_end = ri_idx = rt_idx_req; + pi_end = pi_idx = phy_id_req; + } + + (void) printf("%6s %6s %3s %14s\n", + "RT Idx", "PHY ID", "DIS", "Routed SASAddr"); + + smp_action_get_request(ap, (void **)&rp, NULL); + + while (ri_idx <= ri_end) { + while (pi_idx <= pi_end) { + rp->srrir_phy_identifier = pi_idx; + rp->srrir_exp_route_index = ri_idx; + + smp_execute(); + smp_get_response(B_FALSE); + + if (result != SMP_RES_FUNCTION_ACCEPTED) { + pi_idx++; + continue; + } + + rirp = (smp_report_route_info_resp_t *)smp_resp; + + if (rirp->srrir_exp_route_entry_disabled == 0) { + enabled_entries = B_TRUE; + (void) printf("%6d %6d %3d %016llx\n", + rirp->srrir_exp_route_index, + rirp->srrir_phy_identifier, + rirp->srrir_exp_route_entry_disabled, + BE_64(rirp->srrir_routed_sas_addr)); + } + + pi_idx++; + } + + ri_idx++; + pi_idx = 0; + } + + if (!enabled_entries) { + (void) printf("No enabled entries in the table.\n"); + } + + smp_cleanup(); + exit(0); +} + +static char * +smp_phy_event_src_str(smp_phy_event_source_t src, boolean_t *peak_detector) +{ + char *src_str; + + *peak_detector = B_FALSE; + + switch (src) { + case SMP_PHY_EVENT_NO_EVENT: + src_str = "No event"; + break; + case SMP_PHY_EVENT_INVALID_DWORD_COUNT: + src_str = "Invalid DWORD count"; + break; + case SMP_PHY_EVENT_RUNNING_DISPARITY_ERROR_COUNT: + src_str = "Running disparity error count"; + break; + case SMP_PHY_EVENT_LOSS_OF_DWORD_SYNC_COUNT: + src_str = "Loss of DWORD sync count"; + break; + case SMP_PHY_EVENT_PHY_RESET_PROBLEM_COUNT: + src_str = "PHY reset problem count"; + break; + case SMP_PHY_EVENT_ELASTICITY_BUFFER_OVERFLOW_COUNT: + src_str = "Elasticity buffer overflow count"; + break; + case SMP_PHY_EVENT_RX_ERROR_COUNT: + src_str = "Received ERROR count"; + break; + case SMP_PHY_EVENT_RX_ADDR_FRAME_ERROR_COUNT: + src_str = "Received address frame error count"; + break; + case SMP_PHY_EVENT_TX_ABANDON_CLASS_OPEN_REJ_COUNT: + src_str = "Transmitted abandon-class OPEN_REJECT count"; + break; + case SMP_PHY_EVENT_RX_ABANDON_CLASS_OPEN_REJ_COUNT: + src_str = "Received abandon-class OPEN_REJECT count"; + break; + case SMP_PHY_EVENT_TX_RETRY_CLASS_OPEN_REJ_COUNT: + src_str = "Transmitted retry-class OPEN_REJECT count"; + break; + case SMP_PHY_EVENT_RX_RETRY_CLASS_OPEN_REJ_COUNT: + src_str = "Received retry-class OPEN_REJECT count"; + break; + case SMP_PHY_EVENT_RX_AIP_W_O_PARTIAL_COUNT: + src_str = "Received AIP (WAITING ON PARTIAL) count"; + break; + case SMP_PHY_EVENT_RX_AIP_W_O_CONN_COUNT: + src_str = "Received AIP (WAITING ON CONNECTION) count"; + break; + case SMP_PHY_EVENT_TX_BREAK_COUNT: + src_str = "Transmitted BREAK count"; + break; + case SMP_PHY_EVENT_RX_BREAK_COUNT: + src_str = "Received BREAK count"; + break; + case SMP_PHY_EVENT_BREAK_TIMEOUT_COUNT: + src_str = "BREAK timeout count"; + break; + case SMP_PHY_EVENT_CONNECTION_COUNT: + src_str = "Connection count"; + break; + case SMP_PHY_EVENT_PEAK_TX_PATHWAY_BLOCKED_COUNT: + src_str = "Peak transmitted pathway blocked count"; + *peak_detector = B_TRUE; + break; + case SMP_PHY_EVENT_PEAK_TX_ARB_WAIT_TIME: + src_str = "Peak transmitted arbitration wait time"; + *peak_detector = B_TRUE; + break; + case SMP_PHY_EVENT_PEAK_ARB_TIME: + src_str = "Peak arbitration time"; + *peak_detector = B_TRUE; + break; + case SMP_PHY_EVENT_PEAK_CONNECTION_TIME: + src_str = "Peak connection time"; + *peak_detector = B_TRUE; + break; + case SMP_PHY_EVENT_TX_SSP_FRAME_COUNT: + src_str = "Transmitted SSP frame count"; + break; + case SMP_PHY_EVENT_RX_SSP_FRAME_COUNT: + src_str = "Received SSP frame count"; + break; + case SMP_PHY_EVENT_TX_SSP_FRAME_ERROR_COUNT: + src_str = "Transmitted SSP frame error count"; + break; + case SMP_PHY_EVENT_RX_SSP_FRAME_ERROR_COUNT: + src_str = "Received SSP frame error count"; + break; + case SMP_PHY_EVENT_TX_CREDIT_BLOCKED_COUNT: + src_str = "Transmitted CREDIT_BLOCKED count"; + break; + case SMP_PHY_EVENT_RX_CREDIT_BLOCKED_COUNT: + src_str = "Received CREDIT_BLOCKED count"; + break; + case SMP_PHY_EVENT_TX_SATA_FRAME_COUNT: + src_str = "Transmitted SATA frame count"; + break; + case SMP_PHY_EVENT_RX_SATA_FRAME_COUNT: + src_str = "Received SATA frame count"; + break; + case SMP_PHY_EVENT_SATA_FLOW_CTRL_BUF_OVERFLOW_COUNT: + src_str = "SATA flow control buffer overflow count"; + break; + case SMP_PHY_EVENT_TX_SMP_FRAME_COUNT: + src_str = "Transmitted SMP frame count"; + break; + case SMP_PHY_EVENT_RX_SMP_FRAME_COUNT: + src_str = "Received SMP frame count"; + break; + case SMP_PHY_EVENT_RX_SMP_FRAME_ERROR_COUNT: + src_str = "Received SMP frame error count"; + break; + default: + src_str = "<Unknown>"; + break; + } + + return (src_str); +} + +static void +smp_validate_args(int argc, char *argv[]) +{ + errno = 0; if (argc < 3) fatal(-1, "Usage: %s <device> <function> ...\n", argv[0]); - errno = 0; func = strtoul(argv[2], NULL, 0); + if (errno != 0) fatal(-1, "Usage: %s <device> <function> ...\n", argv[0]); + switch (func) { + case SMP_FUNC_DISCOVER: + case SMP_FUNC_REPORT_PHY_EVENT: + case SMP_FUNC_REPORT_PHY_ERROR_LOG: { + if (argc != 4) { + fatal(-1, + "Usage: %s <device> 0x%x <phy identifier>\n", + argv[0], func); + } + break; + } + case SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST: { + if (argc < 4) { + fatal(-1, + "Usage: %s <device> 0x%x <SAS Address Index>\n", + argv[0], func); + } + break; + } + case SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD: { + if (argc < 4) { + fatal(-1, + "Usage: %s <device> 0x%x <report type>\n", + argv[0], func); + } + break; + } + case SMP_FUNC_ENABLE_DISABLE_ZONING: { + if (argc != 4) { + fatal(-1, + "Usage: %s <device> 0x%x " + "[0(no change) | 1(enable)| 2(disable)]\n", + argv[0], func); + } + break; + } + case SMP_FUNC_REPORT_BROADCAST: { + if (argc != 4) { + fatal(-1, "Usage: %s <device> 0x%x <bcast type>\n", + argv[0], func); + } + break; + } + case SMP_FUNC_REPORT_ROUTE_INFO: { + if (argc != 5) { + fatal(-1, + "Usage: %s <device> 0x%x <exp_route_idx> " + "<phy_identifier>\n", argv[0], func); + } + break; + } + case SMP_FUNC_PHY_CONTROL: { + if (argc != 5) { + fatal(-1, + "Usage: %s <device> 0x%x <phy identifier> " + " <phy operation>\n", + argv[0], func); + } + break; + } + default: { + fatal(-1, "Usage: %s <device> <function> ...\n", argv[0]); + break; + } + } +} + +int +main(int argc, char *argv[]) +{ + uint_t i, j; + char *yesorno; + uint16_t exp_change_count; + + /* + * If the arguments are invalid, this function will not return. + */ + smp_validate_args(argc, argv); + if (smp_init(LIBSMP_VERSION) != 0) fatal(-1, "libsmp initialization failed: %s", smp_errmsg()); @@ -93,7 +518,18 @@ fatal(-2, "failed to open %s: %s", argv[1], smp_errmsg()); } - cap = smp_target_getcap(tp); + exp_change_count = smp_target_get_change_count(tp); + + (void) printf("%s\n", argv[0]); + (void) printf("\tSAS Address: %016llx\n", smp_target_addr(tp)); + (void) printf("\tVendor/Product/Revision: %s/%s/%s\n", + smp_target_vendor(tp), smp_target_product(tp), + smp_target_revision(tp)); + (void) printf("\tExp Vendor/ID/Rev: %s/%04x/%02x\n", + smp_target_component_vendor(tp), smp_target_component_id(tp), + smp_target_component_revision(tp)); + (void) printf("\tExpander change count: 0x%04x\n", exp_change_count); + ap = smp_action_alloc(func, tp, 0); if (ap == NULL) { smp_close(tp); @@ -101,104 +537,84 @@ fatal(-3, "failed to allocate action: %s", smp_errmsg()); } - if (func == SMP_FUNC_DISCOVER) { + switch (func) { + case SMP_FUNC_DISCOVER: { smp_discover_req_t *dp; - if (argc < 4) - fatal(-1, - "Usage: %s <device> 0x10 <phy identifier>\n", - argv[0]); smp_action_get_request(ap, (void **)&dp, NULL); dp->sdr_phy_identifier = strtoul(argv[3], NULL, 0); - } else if (func == SMP_FUNC_REPORT_ROUTE_INFO) { - smp_report_route_info_req_t *rp; - if (argc < 5) - fatal(-1, "Usage: %s <device> 0x13 <expander route " - "index> <phy identifier>\n", - argv[0]); - - smp_action_get_request(ap, (void **)&rp, NULL); - rp->srrir_exp_route_index = strtoul(argv[3], NULL, 0); - rp->srrir_phy_identifier = strtoul(argv[4], NULL, 0); - } else if (func == SMP_FUNC_ENABLE_DISABLE_ZONING) { + break; + } + case SMP_FUNC_REPORT_ROUTE_INFO: { + smp_handle_report_route_info(argc, argv); + break; + } + case SMP_FUNC_ENABLE_DISABLE_ZONING: { smp_enable_disable_zoning_req_t *rp; - if (argc < 4) - fatal(-1, - "Usage: %s <device> 0x81 " - "[0(no change) | 1(enable)| 2(disable)]\n", - argv[0]); smp_action_get_request(ap, (void **)&rp, NULL); rp->sedzr_enable_disable_zoning = strtoul(argv[3], NULL, 0); - } else if (func == SMP_FUNC_PHY_CONTROL) { + break; + } + case SMP_FUNC_PHY_CONTROL: { smp_phy_control_req_t *rp; - if (argc < 5) - fatal(-1, - "Usage: %s <device> 0x91 <phy identifier> " - " <phy operation>\n", - argv[0]); - - smp_action_get_request(ap, (void **)&rp, NULL); smp_action_get_request(ap, (void **)&rp, NULL); rp->spcr_phy_identifier = strtoul(argv[3], NULL, 0); rp->spcr_phy_operation = strtoul(argv[4], NULL, 0); - } else if (func == SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST) { + break; + } + case SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST: { smp_report_exp_route_table_list_req_t *rp; - if (argc < 4) - fatal(-1, - "Usage: %s <device> 0x22 <SAS Address Index> \n", - argv[0]); smp_action_get_request(ap, (void **)&rp, NULL); SCSI_WRITE16(&rp->srertlr_max_descrs, 64); SCSI_WRITE16(&rp->srertlr_starting_routed_sas_addr_index, strtoull(argv[3], NULL, 0)); rp->srertlr_starting_phy_identifier = 0; + break; } + case SMP_FUNC_REPORT_PHY_ERROR_LOG: { + smp_report_phy_error_log_req_t *pelp; + + smp_action_get_request(ap, (void **)&pelp, NULL); + pelp->srpelr_phy_identifier = strtoul(argv[3], NULL, 0); + break; + } + case SMP_FUNC_REPORT_PHY_EVENT: { + smp_report_phy_event_req_t *rpep; - (void) printf("%s\n", argv[0]); - (void) printf("\tSAS Address: %016llx\n", smp_target_addr(tp)); - (void) printf("\tVendor: %s\n", smp_target_vendor(tp)); - (void) printf("\tProduct: %s\n", smp_target_product(tp)); - (void) printf("\tRevision: %s\n", smp_target_revision(tp)); - (void) printf("\tExp Vendor: %s\n", smp_target_component_vendor(tp)); - (void) printf("\tExp ID: %04x\n", smp_target_component_id(tp)); - (void) printf("\tExp Rev: %02x\n", smp_target_component_revision(tp)); + smp_action_get_request(ap, (void **)&rpep, NULL); + rpep->srper_phy_identifier = strtoul(argv[3], NULL, 0); + break; + } + case SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD: { + smp_report_zone_mgr_password_req_t *rzmprp; - if (smp_exec(ap, tp) != 0) { + smp_action_get_request(ap, (void **)&rzmprp, NULL); + rzmprp->srzmpr_rpt_type = strtoul(argv[3], NULL, 0); + break; + } + case SMP_FUNC_REPORT_BROADCAST: { + smp_report_broadcast_req_t *rbrp; + + smp_action_get_request(ap, (void **)&rbrp, NULL); + rbrp->srbr_broadcast_type = strtoul(argv[3], NULL, 0); + break; + } + default: smp_close(tp); smp_action_free(ap); smp_fini(); - fatal(-4, "exec failed: %s", smp_errmsg()); - } - - smp_close(tp); - smp_action_get_response(ap, &result, (void **)&resp, &len); - - if (result != SMP_RES_FUNCTION_ACCEPTED) { - smp_action_free(ap); - smp_fini(); - fatal(-5, "command failed with status code %d", result); + smp_cmd_failed(result); } - (void) printf("Response: (len %d)\n", len); - for (i = 0; i < len; i += 8) { - (void) printf("%02x: ", i); - for (j = i; j < i + 8; j++) - if (j < len) - (void) printf("%02x ", resp[j]); - else - (void) printf(" "); - for (j = i; j < i + 8; j++) - (void) printf("%c", - j < len && isprint(resp[j]) ? resp[j] : - j < len ? '.' : '\0'); - (void) printf("\n"); - } + smp_execute(); + smp_get_response(B_TRUE); - if (func == SMP_FUNC_DISCOVER) { - rp = (smp_discover_resp_t *)resp; + switch (func) { + case SMP_FUNC_DISCOVER: { + smp_discover_resp_t *rp = (smp_discover_resp_t *)smp_resp; (void) printf("Addr: %016llx Phy: %02x\n", SCSI_READ64(&rp->sdr_sas_addr), rp->sdr_phy_identifier); (void) printf("Peer: %016llx Phy: %02x\n", @@ -206,10 +622,172 @@ rp->sdr_attached_phy_identifier); (void) printf("Device type: %01x\n", rp->sdr_attached_device_type); + break; + } + case SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD: { + smp_report_zone_mgr_password_resp_t *rp = + (smp_report_zone_mgr_password_resp_t *)smp_resp; + char *rpt_type = NULL; + int idx; + switch (rp->srzmpr_rpt_type) { + case SMP_ZMP_TYPE_CURRENT: + rpt_type = "Current"; + break; + case SMP_ZMP_TYPE_SAVED: + rpt_type = "Saved"; + break; + case SMP_ZMP_TYPE_DEFAULT: + rpt_type = "Default"; + break; + default: + rpt_type = "(Unknown Type)"; + break; + } + (void) printf("%s zone manager password: 0x", rpt_type); + for (idx = 0; idx < 32; idx++) { + (void) printf("%02x", + rp->srzmpr_zone_mgr_password[idx]); + } + (void) printf("\n"); + break; + } + case SMP_FUNC_REPORT_EXP_ROUTE_TABLE_LIST: { + smp_report_exp_route_table_list_resp_t *rtlr = + (smp_report_exp_route_table_list_resp_t *)smp_resp; + smp_route_table_descr_t *descp = &rtlr->srertlr_descrs[0]; + int idx, idxx, ndescrs, zoning, startnum; + + (void) printf("Expander change count: 0x%04x\n", + BE_16(rtlr->srertlr_exp_change_count)); + (void) printf("Expander route table change count: 0x%04x\n", + BE_16(rtlr->srertlr_route_table_change_count)); + + if (rtlr->srertlr_zoning_enabled) { + yesorno = yes; + zoning = 1; + } else { + yesorno = no; + zoning = 0; + } + (void) printf("Zoning enabled: %s\n", yesorno); + + if (rtlr->srertlr_configuring) { + yesorno = yes; + } else { + yesorno = no; + } + (void) printf("Configuring: %s\n", yesorno); + + ndescrs = rtlr->srertlr_n_descrs; + (void) printf("Number of descriptors: %d\n", ndescrs); + startnum = BE_16(rtlr->srertlr_first_routed_sas_addr_index); + (void) printf("First/Last routed SAS address index: %d/%d\n", + startnum, BE_16(rtlr->srertlr_last_routed_sas_addr_index)); + (void) printf("Starting PHY identifier: %d\n", + rtlr->srertlr_starting_phy_identifier); + + for (idx = 0; idx < ndescrs; idx++, descp++) { + (void) printf("#%03d: Routed SAS addr: %016llx ", + idx + startnum, BE_64(descp->srtd_routed_sas_addr)); + (void) printf("PHY bitmap: 0x"); + for (idxx = 0; idxx < 6; idxx++) { + (void) printf("%02x", + descp->srtd_phy_bitmap[idxx]); + } + (void) printf("\n"); + if (zoning) { + (void) printf("\tZone group: %d\n", + descp->srtd_zone_group); + } + } + + (void) printf("\n"); + break; + } + case SMP_FUNC_REPORT_PHY_ERROR_LOG: { + smp_report_phy_error_log_resp_t *pelr = + (smp_report_phy_error_log_resp_t *)smp_resp; + (void) printf("PHY error log for PHY %d:\n", + pelr->srpelr_phy_identifier); + (void) printf("\tInvalid DWORD count: %d\n", + BE_32(pelr->srpelr_invalid_dword_count)); + (void) printf("\tRunning disparity error count: %d\n", + BE_32(pelr->srpelr_running_disparity_error_count)); + (void) printf("\tLoss of DWORD sync count: %d\n", + BE_32(pelr->srpelr_loss_dword_sync_count)); + (void) printf("\tPHY reset problem count: %d\n", + BE_32(pelr->srpelr_phy_reset_problem_count)); + break; + } + case SMP_FUNC_REPORT_PHY_EVENT: { + smp_report_phy_event_resp_t *rper = + (smp_report_phy_event_resp_t *)smp_resp; + smp_phy_event_report_descr_t *perd = + &rper->srper_phy_event_descrs[0]; + boolean_t peak; + int idx; + + (void) printf("PHY event for PHY %d:\n", + rper->srper_phy_identifier); + (void) printf("Number of PHY event descriptors: %d\n", + rper->srper_n_phy_event_descrs); + + for (idx = 0; idx < rper->srper_n_phy_event_descrs; idx++) { + (void) printf("%50s : %d\n", + smp_phy_event_src_str(perd->sped_phy_event_source, + &peak), BE_32(perd->sped_phy_event)); + if (peak) { + (void) printf("\tPeak value detector " + "threshold: %d\n", + BE_32(perd->sped_peak_detector_threshold)); + } + perd++; + } + + break; + } + case SMP_FUNC_REPORT_BROADCAST: { + smp_report_broadcast_resp_t *brp = + (smp_report_broadcast_resp_t *)smp_resp; + smp_broadcast_descr_t *bdp = &brp->srbr_descrs[0]; + uint16_t bcount, idx; + uint8_t bctype; + + bcount = brp->srbr_number_broadcast_descrs; + + (void) printf("\tNumber of broadcast descriptors: %d\n", + bcount); + (void) printf("\t%7s %5s %5s %8s\n", + "BCType", "PhyID", "BCRsn", "BC Count"); + for (idx = 0; idx < bcount; idx++) { + (void) printf("\t%7s %5s %5s %8s\n", + bdp->sbd_broadcast_type, bdp->sbd_phy_identifier, + bdp->sbd_broadcast_reason, + bdp->sbd_broadcast_count); + bdp++; + } + + break; + } + default: + (void) printf("Response: (len %d)\n", smp_resp_len); + for (i = 0; i < smp_resp_len; i += 8) { + (void) printf("%02x: ", i); + for (j = i; j < i + 8; j++) + if (j < smp_resp_len) + (void) printf("%02x ", smp_resp[j]); + else + (void) printf(" "); + for (j = i; j < i + 8; j++) + (void) printf("%c", + j < smp_resp_len && isprint(smp_resp[j]) ? + smp_resp[j] : j < smp_resp_len ? '.' : + '\0'); + (void) printf("\n"); + } + break; } - smp_action_free(ap); - smp_fini(); - + smp_cleanup(); return (0); }
--- a/usr/src/lib/scsi/libsmp/common/libsmp.h Thu Aug 12 14:55:22 2010 -0700 +++ b/usr/src/lib/scsi/libsmp/common/libsmp.h Thu Aug 12 15:59:36 2010 -0600 @@ -86,6 +86,8 @@ extern uint_t smp_target_getcap(const smp_target_t *); extern uint16_t smp_target_get_change_count(const smp_target_t *); extern void smp_target_set_change_count(smp_target_t *, uint16_t); +extern uint8_t smp_target_get_number_of_phys(const smp_target_t *); +extern uint16_t smp_target_get_exp_route_indexes(const smp_target_t *); extern const char *smp_target_vendor(const smp_target_t *); extern const char *smp_target_product(const smp_target_t *); extern const char *smp_target_revision(const smp_target_t *);
--- a/usr/src/lib/scsi/libsmp/common/smp_engine.c Thu Aug 12 14:55:22 2010 -0700 +++ b/usr/src/lib/scsi/libsmp/common/smp_engine.c Thu Aug 12 15:59:36 2010 -0600 @@ -378,6 +378,18 @@ return (tp->st_change_count); } +uint8_t +smp_target_get_number_of_phys(const smp_target_t *tp) +{ + return (tp->st_repgen.srgr_number_of_phys); +} + +uint16_t +smp_target_get_exp_route_indexes(const smp_target_t *tp) +{ + return (tp->st_repgen.srgr_exp_route_indexes); +} + void smp_close(smp_target_t *tp) {
--- a/usr/src/lib/scsi/libsmp/mapfile-vers Thu Aug 12 14:55:22 2010 -0700 +++ b/usr/src/lib/scsi/libsmp/mapfile-vers Thu Aug 12 15:59:36 2010 -0600 @@ -78,6 +78,8 @@ smp_plugin_register; smp_plugin_setspecific; smp_plugin_getspecific; + smp_target_get_number_of_phys; + smp_target_get_exp_route_indexes; smp_alloc; smp_zalloc;
--- a/usr/src/lib/scsi/plugins/smp/sas2/common/sas2_functions.c Thu Aug 12 14:55:22 2010 -0700 +++ b/usr/src/lib/scsi/plugins/smp/sas2/common/sas2_functions.c Thu Aug 12 15:59:36 2010 -0600 @@ -236,6 +236,18 @@ /*ARGSUSED*/ static size_t +sas2_report_zone_mgr_password_rq_len(size_t user, smp_target_t *tp) +{ + if (user != 0) { + (void) smp_set_errno(ESMP_RANGE); + return (0); + } + + return (SMP_REQ_MINLEN + sizeof (smp_report_zone_perm_table_req_t)); +} + +/*ARGSUSED*/ +static size_t sas2_report_broadcast_rq_len(size_t user, smp_target_t *tp) { if (user != 0) { @@ -658,7 +670,7 @@ { .sfd_function = SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD, .sfd_flags = SMP_FD_F_READ | SMP_FD_F_PROVIDES_CHANGE_COUNT, - .sfd_rq_len = sas2_rq_len, + .sfd_rq_len = sas2_report_zone_mgr_password_rq_len, .sfd_rq_dataoff = sas2_rq_dataoff, .sfd_rq_setframe = sas2_rq_setframe, .sfd_rs_datalen = sas2_rs_datalen, @@ -916,9 +928,10 @@ switch (fn) { case SMP_FUNC_REPORT_GENERAL: case SMP_FUNC_REPORT_MANUFACTURER_INFO: + return (SMP_REQ_MINLEN); case SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD: - return (SMP_REQ_MINLEN); - + return (SMP_REQ_MINLEN + + sizeof (smp_report_zone_mgr_password_req_t)); case SMP_FUNC_REPORT_SELF_CONFIG_STATUS: if (cap & SMP_TARGET_C_LONG_RESP) return (SMP_REQ_MINLEN + @@ -1023,7 +1036,6 @@ switch (fn) { case SMP_FUNC_REPORT_SELF_CONFIG_STATUS: case SMP_FUNC_REPORT_ZONE_PERM_TABLE: - case SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD: case SMP_FUNC_REPORT_BROADCAST: case SMP_FUNC_REPORT_PHY_EVENT: case SMP_FUNC_DISCOVER_LIST: @@ -1043,7 +1055,9 @@ case SMP_FUNC_PHY_TEST_FUNCTION: case SMP_FUNC_CONFIG_PHY_EVENT: return (SMP_RESP_MINLEN); - + case SMP_FUNC_REPORT_ZONE_MANAGER_PASSWORD: + return (SMP_RESP_MINLEN + + sizeof (smp_report_zone_mgr_password_resp_t)); case SMP_FUNC_REPORT_GENERAL: return (SMP_RESP_MINLEN + 24); case SMP_FUNC_REPORT_MANUFACTURER_INFO:
--- a/usr/src/uts/common/sys/scsi/generic/smp_frames.h Thu Aug 12 14:55:22 2010 -0700 +++ b/usr/src/uts/common/sys/scsi/generic/smp_frames.h Thu Aug 12 15:59:36 2010 -0600 @@ -18,10 +18,8 @@ * * CDDL HEADER END */ - /* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. */ #ifndef _SYS_SCSI_GENERIC_SMP_FRAMES_H @@ -104,6 +102,7 @@ SMP_RES_NO_PHYSICAL_PRESENCE = 0x26, SMP_RES_SAVING_NOT_SUPPORTED = 0x27, SMP_RES_SOURCE_ZONE_GROUP_DNE = 0x28, + SMP_RES_DISABLED_PW_NOT_SUPPORTED = 0x29, SMP_RES_NONE = -1 } smp_result_t; @@ -179,7 +178,7 @@ srgr_saving_zone_phy_info_supported :1, srgr_saving_zone_mgr_password_supported :1, srgr_saving :1, - _reserved7 :4); + _reserved7 :3); uint16_t srgr_max_routed_sas_addrs; uint64_t srgr_active_zm_sas_addr; uint16_t srgr_zone_lock_inactivity_limit; @@ -336,11 +335,27 @@ ((__d)[31 - ((__z) >> 3)] &= ~(1 << ((__z) & 7))) /* - * SAS-2 10.4.3.8 REPORT ZONE MANAGER PASSWORD (no additional request bytes) + * SAS-2 10.4.3.8 REPORT ZONE MANAGER PASSWORD */ +typedef enum smp_report_zmp_report_type { + SMP_ZMP_TYPE_CURRENT = 0x0, + SMP_ZMP_TYPE_SAVED = 0x2, + SMP_ZMP_TYPE_DEFAULT = 0x3 +} smp_report_zmp_report_type_t; + +typedef struct smp_report_zone_mgr_password_req { + DECL_BITFIELD2( + srzmpr_rpt_type :2, + _reserved1 :6); + uint8_t _reserved2[2]; +} smp_report_zone_mgr_password_req_t; + typedef struct smp_report_zone_mgr_password_resp { uint16_t srzmpr_exp_change_count; - uint8_t _reserved1[2]; + DECL_BITFIELD2( + srzmpr_rpt_type :2, + _reserved1 :6); + uint8_t _reserved2; uint8_t srzmpr_zone_mgr_password[32]; } smp_report_zone_mgr_password_resp_t; @@ -638,6 +653,43 @@ /* * SAS-2 10.4.3.14 SAS-2 REPORT PHY EVENT */ +typedef enum smp_phy_event_source { + SMP_PHY_EVENT_NO_EVENT = 0x00, + SMP_PHY_EVENT_INVALID_DWORD_COUNT = 0x01, + SMP_PHY_EVENT_RUNNING_DISPARITY_ERROR_COUNT = 0x02, + SMP_PHY_EVENT_LOSS_OF_DWORD_SYNC_COUNT = 0x03, + SMP_PHY_EVENT_PHY_RESET_PROBLEM_COUNT = 0x04, + SMP_PHY_EVENT_ELASTICITY_BUFFER_OVERFLOW_COUNT = 0x05, + SMP_PHY_EVENT_RX_ERROR_COUNT = 0x06, + SMP_PHY_EVENT_RX_ADDR_FRAME_ERROR_COUNT = 0x20, + SMP_PHY_EVENT_TX_ABANDON_CLASS_OPEN_REJ_COUNT = 0x21, + SMP_PHY_EVENT_RX_ABANDON_CLASS_OPEN_REJ_COUNT = 0x22, + SMP_PHY_EVENT_TX_RETRY_CLASS_OPEN_REJ_COUNT = 0x23, + SMP_PHY_EVENT_RX_RETRY_CLASS_OPEN_REJ_COUNT = 0x24, + SMP_PHY_EVENT_RX_AIP_W_O_PARTIAL_COUNT = 0x25, + SMP_PHY_EVENT_RX_AIP_W_O_CONN_COUNT = 0x26, + SMP_PHY_EVENT_TX_BREAK_COUNT = 0x27, + SMP_PHY_EVENT_RX_BREAK_COUNT = 0x28, + SMP_PHY_EVENT_BREAK_TIMEOUT_COUNT = 0x29, + SMP_PHY_EVENT_CONNECTION_COUNT = 0x2A, + SMP_PHY_EVENT_PEAK_TX_PATHWAY_BLOCKED_COUNT = 0x2B, + SMP_PHY_EVENT_PEAK_TX_ARB_WAIT_TIME = 0x2C, + SMP_PHY_EVENT_PEAK_ARB_TIME = 0x2D, + SMP_PHY_EVENT_PEAK_CONNECTION_TIME = 0x2E, + SMP_PHY_EVENT_TX_SSP_FRAME_COUNT = 0x40, + SMP_PHY_EVENT_RX_SSP_FRAME_COUNT = 0x41, + SMP_PHY_EVENT_TX_SSP_FRAME_ERROR_COUNT = 0x42, + SMP_PHY_EVENT_RX_SSP_FRAME_ERROR_COUNT = 0x43, + SMP_PHY_EVENT_TX_CREDIT_BLOCKED_COUNT = 0x44, + SMP_PHY_EVENT_RX_CREDIT_BLOCKED_COUNT = 0x45, + SMP_PHY_EVENT_TX_SATA_FRAME_COUNT = 0x50, + SMP_PHY_EVENT_RX_SATA_FRAME_COUNT = 0x51, + SMP_PHY_EVENT_SATA_FLOW_CTRL_BUF_OVERFLOW_COUNT = 0x52, + SMP_PHY_EVENT_TX_SMP_FRAME_COUNT = 0x60, + SMP_PHY_EVENT_RX_SMP_FRAME_COUNT = 0x61, + SMP_PHY_EVENT_RX_SMP_FRAME_ERROR_COUNT = 0x63 +} smp_phy_event_source_t; + typedef struct smp_report_phy_event_req { uint8_t _reserved1; uint8_t _reserved2[4]; @@ -818,12 +870,15 @@ typedef struct smp_report_exp_route_table_list_resp { uint16_t srertlr_exp_change_count; uint16_t srertlr_route_table_change_count; - DECL_BITFIELD3( - _reserved1 :1, - srertlr_configuring :1, - _reserved2 :6); + DECL_BITFIELD5( + srertlr_zoning_enabled :1, + srertlr_configuring :1, + srertlr_zone_configuring :1, + srertlr_self_configuring :1, + _reserved2 :4); uint8_t _reserved3; - uint16_t srertlr_n_descrs; + uint8_t srertlr_descr_length; + uint8_t srertlr_n_descrs; uint16_t srertlr_first_routed_sas_addr_index; uint16_t srertlr_last_routed_sas_addr_index; uint8_t _reserved4[3];