/* * Copyright (c) 2011-2018, Emulex * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * 3. Neither the name of the copyright holder nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * */ /** * @file * Defines the elxsdkutil command handlers. */ /** * * @defgroup cmd_handler Command Handlers * */ #include #include #include #include #include #include #include #include "version.h" #include "elxu_commands.h" #include "elxu_common.h" #include "elxu_dwnld.h" #include "elxu_device.h" #include "elxu_dump.h" #include "elxu_mgmt.h" #include "elx_pt_ioctl.h" #include #define PORTSPEED_1GFC 0x00000001 /* 1G FC */ #define PORTSPEED_2GFC 0x00000002 /* 2G FC */ #define PORTSPEED_4GFC 0x00000008 /* 4G FC */ #define PORTSPEED_8GFC 0x00000010 /* 8G FC */ #define PORTSPEED_16GFC 0x00000020 /* 16G FC */ #define PORTSPEED_32GFC 0x00000040 /* 32G FC */ #define PORTSPEED_64GFC 0x00000400 /* 64G FC*/ #define PORTSPEED_128GFC 0x00000200 /* 128G FC */ #define PORTSPEED_UNKNOWN 0x00008000 /* Unknown*/ char *supported_linkcfgs[] = { OCS_CONFIG_LINKCFG_4X10G, OCS_CONFIG_LINKCFG_1X40G, OCS_CONFIG_LINKCFG_2X16G, OCS_CONFIG_LINKCFG_4X8G, OCS_CONFIG_LINKCFG_4X1G, OCS_CONFIG_LINKCFG_2X10G, OCS_CONFIG_LINKCFG_2X10G_2X8G}; #define ETH_FC_AUTO "0" #define ETH_FC_10G "1000" #define FC_2G "2000" #define FC_4G "4000" #define FC_8G "8000" #define FC_16G "16000" #define FC_32G "32000" char *supported_linkspeed[] = { ETH_FC_AUTO, ETH_FC_10G, FC_2G, FC_4G, FC_8G, FC_16G, FC_32G}; #define AUTO "0" #define N_PORT "1" #define LOOP "2" char *supported_linktopology[] = { AUTO, N_PORT, LOOP }; #define OCS_MAX_SLI_PORTS_PER_DEVICE 4 #define OCS_FC_TRUNK_2_PORT_CONFIG 0x30 #define OCS_FC_TRUNK_2_PORT_HI_CONFIG 0xC0 #define OCS_FC_TRUNK_4_PORT_CONFIG 0xF0 #define OCS_FC_TRUNK_CONFIG_MASK 0xF0 #define OCS_FC_TRUNK_LINK_STATE_MASK 0x0F static void show_examples(); typedef struct elx_sfp_transceiver_data_A0_s { uint8_t identifier; uint8_t ext_identifier; uint8_t connector; uint8_t transceiver[8]; uint8_t encoding; uint8_t br_nominal; uint8_t rate_id; uint8_t length_9um_km; uint8_t length_9um; uint8_t length_50um; uint8_t length_62_5_um; uint8_t len_copper; uint8_t length_om3; char vendor_name[16]; uint8_t transciever; uint8_t vendor_oui[3]; char vendor_pn[16]; char vendor_rev[4]; uint8_t wavelength[2]; uint8_t unallocated; uint8_t cc_base; uint8_t options[2]; uint8_t br_max; uint8_t br_min; char vendor_sn[16]; uint8_t date_code[8]; uint8_t diag_monitor_type; uint8_t enhance_opt; uint8_t SFF_8472_compliance; uint8_t cc_ext; uint8_t vendor_specific[32]; } elx_sfp_transceiver_data_A0_t; typedef struct { char* vendor; char* vendor_pn; char* vendor_rev; /* Note: This is minimum rev number */ uint8_t length_copper; } elx_dport_sfp_table1_entry; typedef struct { char* vendor_pn; } elx_dport_sfp_table2_entry; /** * @ingroup cmd_handler * @brief Command handler for the file-info command. * * @par Description * This function processes the file-info command.

* Command: file-info
* Required Parameters:
* Optional Parameters: None
* Supported Devices: N/A
* Supported Protocols: N/A
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line * arguments. * * @return Returns 0 on success; or a non-zero error code value * on failure. */ int elxu_cmd_file_info(int argc, char **argv) { cmd_options_t options; if (argc < 3) { fprintf(stderr, "Filename is required\n"); return -1; } /* Parse arguments, to pick up a --host argument */ if (parse_arguments(argc, argv, &options, 0, 1) == -1) { return -1; } if (options.file == NULL) { fprintf(stderr, "Filename missing\n"); return -1; } printf("file: %s \n", options.file); file_handler(NULL, options.file, FW_FILE_DISPLAY_INFO); return 0; } /** * @ingroup cmd_handler * @brief Command handler for the list command. * * @par Description * This function processes the list command. * * Command: list
* Required Parameters: None
* Optional Parameters: None
* Supported Devices: N/A
* Supported Protocols: N/A
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line * arguments. * * @return Returns 0 on success; or a non-zero error code value * on failure. */ int elxu_cmd_list(int argc, char **argv) { cmd_options_t options; /* Parse arguments, to pick up a --host argument */ if (parse_arguments(argc, argv, &options, 0, 1) == -1) { return -1; } elxu_display_device_list(options.hostname); return 0; } /** * @ingroup cmd_handler * @brief Command handler for the read command. * * @par Description * This function processes the read command. * * Command: read
* Required Parameters:
* Optional Parameters: -d -f
* Supported Devices: Lancer
* Supported Protocols: N/A
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_read(int argc, char **argv) { char *objname = NULL; cmd_options_t options; if (argc < 3) { fprintf(stderr, "objname is required\n"); return -1; } objname = argv[2]; if (parse_arguments(argc, argv, &options, 1, 2) == -1) { return -1; } if (objname == NULL) { printf ("Missing object name argument\n"); return -1; } /* Read Obj only supported for Lancer */ if(!is_lancer(options.device) && !is_prism(options.device)) { fprintf(stderr, "readobj is only supported on Lancer/Prism\n"); return -1; } hba_data_object_upload (options.device, objname, options.file); return 0; } /** * @ingroup cmd_handler * @brief Command handler for the write command. * * @par Description * This function processes the write command. * * Command: write
* Required Parameters: -f
* Optional Parameters: -d
* Supported Devices: Any
* Supported Protocols: N/A
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_write(int argc, char **argv) { cmd_options_t options; if (parse_arguments(argc, argv, &options, 1, 1) == -1) { return -1; } if (options.device == NULL) { fprintf(stderr, "Unable to open device\n"); return -1; } if (options.file == NULL) { fprintf(stderr, "Filename missing\n"); return -1; } return file_handler (options.device, options.file, FW_FILE_DOWNLOAD); } /** * @ingroup cmd_handler * @brief Command handler for the version command. * * @par Description * This function processes the version command. * * Command: version
* Required Parameters: None
* Optional Parameters: None
* Supported Devices: N/A
* Supported Protocols: N/A
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_version(int argc, char **argv) { printf ("\nVersion %s\n", ELXU_VERSION); return 0; } /** * @ingroup cmd_handler * @brief Command handler for the cmp command. * * @par Description * This function processes the cmp command. * * Command: cmp
* Required Parameters: -f
* Optional Parameters: -d
* Supported Devices: Skyhawk
* Supported Protocols: N/A
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_cmp(int argc, char **argv) { cmd_options_t options; if (parse_arguments(argc, argv, &options, 1, 1) == -1) { return -1; } if (options.device == NULL) { fprintf(stderr, "Unable to open device\n"); return -1; } if (options.file == NULL) { fprintf(stderr, "Filename missing\n"); return -1; } return file_handler (options.device, options.file, FW_FILE_VERIFY); } /** * @ingroup cmd_handler * @brief Command handler for the dump command. * * @par Description * This function processes the dump command. * * Command: dump
* Required Parameters: None
* Optional Parameters: dump type (--fat, --efd, --ecd), -f , -d
* Supported Devices: Any
* Supported Protocols: N/A
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_dump(int argc, char **argv) { cmd_options_t options; data_type_req_t dump_type; int rc; if (parse_arguments(argc, argv, &options, 1, 1) == -1) { return -1; } if (options.device == NULL) { fprintf(stderr, "Unable to open device\n"); return -1; } if (is_lancer(options.device) || is_prism(options.device)) { /* No dump type option for Lancer */ if ((options.fat) || (options.efd) || (options.ecd) || (options.ecd_test)) { fprintf(stderr, "Dump type option does not apply to Lancer/Prism\n"); return -1; } dump_type = LANCER_DUMP; } else { /* Could be ecd, ecdtest, fat, or efd. Default is ecd */ dump_type = ECD_DATA; /* Verify that no more than one dump type is selected */ if ((options.fat + options.efd + options.ecd + options.ecd_test) > 1) { fprintf(stderr, "Choose no more than one of --fat, --efd, --ecd, or --ecdtest\n"); return -1; } if (options.efd) { dump_type = EFD_DATA; } else if (options.fat) { dump_type = FAT_DATA; } } switch(dump_type) { case FAT_DATA: case EFD_DATA: case LANCER_DUMP: rc = hba_data_upload (options.device, options.file, dump_type); break; case ECD_DATA: /* * Because of the way ioctls are implemented in the user space driver an ECD * is very slow (several days to get a dump.) For that reason ECD dump is * not supported with the userspace driver. */ if (is_uspace(options.device)) { fprintf(stderr, "ECD dump not supported with user space driver.\n"); return -1; } rc = elxu_core_dump(options.device, options.file, options.ecd_test); break; default: /* This shouldn't happen */ fprintf(stderr, "No dump type selected\n"); rc = -1; } return rc; } /** * @ingroup cmd_handler * @brief Command handler for the efdc command. * * @par Description * This function processes the efdc command. * * Command: efdc
* Required Parameters: None
* Optional Parameters: -f , -d
* Supported Devices: Skyhawk
* Supported Protocols: N/A
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_efdc(int argc, char **argv) { cmd_options_t options; if (parse_arguments(argc, argv, &options, 1, 1) == -1) { return -1; } if (options.device == NULL) { fprintf(stderr, "Unable to open device\n"); return -1; } if (!is_skyhawk(options.device)) { fprintf(stderr, "efdc is only supported on Skyhwawk\n"); return -1; } return ext_fat_capabilities_upld(options.device); } /** * @ingroup cmd_handler * @brief Command handler for the objenum command. * * @par Description * This function processes the objenum command. * * Command: objenum
* Required Parameters: None
* Optional Parameters: -d
* Supported Devices: Lancer
* Supported Protocols: N/A
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_objenum(int argc, char **argv) { sli4_object_t *objlist; sli4_object_t *obj; int cnt = 0; cmd_options_t options; if (parse_arguments(argc, argv, &options, 1, 1) == -1) { return -1; } if (options.device == NULL) { fprintf(stderr, "Unable to open device\n"); return -1; } if (!is_lancer(options.device) && !is_prism(options.device)) { fprintf(stderr, "objenum is only supported on Lancer/Prism\n"); return -1; } objlist = sli4_object_enumerate(options.device); for (obj = objlist; obj; obj=obj->next, cnt++) { if (obj->type != OFT_DIRECTORY_OBJECT) { printf ("[%2d] %-20s ......... %6d\n", cnt, obj->name, obj->length); } else { printf ("[%2d] %-20s \n", cnt, obj->name); } } sli4_object_free_list (objlist); return 0; } char * elxu_decode_sfp_id(uint32_t value) { char *identify = "UNKNOWN"; switch (value) { case 0x0: identify = "Unknown"; break; case 0x1: identify = "GBIC"; break; case 0x2: identify = "Module/connector soldered to motherboard "; break; case 0x3: identify = "SFP"; break; case 0x4: identify = "300 pin XBI"; break; case 0x5: identify = "XENPAK"; break; case 0x6: identify = "XFP"; break; case 0xC: identify = "QSFP"; break; default: identify = "Refer Spec"; } return identify; } char * elxu_decode_sfp_connector(uint32_t value) { char *identify = "UNKNOWN"; switch (value) { case 0x0: identify = "Unknown"; break; case 0x1: identify = "SC"; break; case 0x2: identify = "Fibre Channel Style 1 copper connector"; break; case 0x3: identify = "Fibre Channel Style 2 copper connector"; break; case 0x4: identify = "BNC/TNC"; break; case 0x5: identify = "Fibre Channel coaxial headers"; break; case 0x6: identify = "FiberJack"; break; case 0x7: identify = "LC"; break; default: identify = "Refer Spec"; } return identify; } char * elxu_decode_sfp_rate_id(uint32_t value) { char *identify; switch (value) { case 0x1: identify = "SFF-8079"; break; case 0x2: case 0x4: case 0x6: identify = "SFF-8431"; break; case 0x8: case 0xA: identify = "FC-PI-5"; break; default: identify = "Unspecified"; } return identify; } char * elxu_sfp_encoding_info(uint32_t value) { char *identify; switch (value) { case 0x0: identify = "Unspecified"; break; case 0x1: identify = "8B10B"; break; case 0x2: identify = "4B5B"; break; case 0x3: identify = "NRZ"; break; case 0x4: identify = "Manchester"; break; case 0x5: identify = "SONET Scrambled"; break; case 0x6: identify = "64B/66B"; break; default: identify = "Unspecified"; } return identify; } int elxu_device_get_lancer_temp(elxu_device_t *device) { int rc; uint32_t *resp_buff; resp_buff = malloc(OCS_DUMP_TYPE4_WKI_TAG_SAT_TEM_RESP_LEN); if (resp_buff == NULL) { perror("malloc"); return -1; } memset(resp_buff, 0, OCS_DUMP_TYPE4_WKI_TAG_SAT_TEM_RESP_LEN); rc = elxu_device_exec(device, "/ocs/driver/lancer_temp", NULL, 0, resp_buff, OCS_DUMP_TYPE4_WKI_TAG_SAT_TEM_RESP_LEN); if (rc != 0) { printf("Get board temperature failed\n"); free(resp_buff); return -1; } /* * Following is the format of resp buffer: * Word 0 - curr_temp * Word 1 - crit_temp_thrshld * Word 2 - warn_temp_thrshld * Word 3 - norm_temp_thrshld * Word 4 - fan_off_thrshld * Word 5 - fan_on_thrshld */ printf("Device %d temperature details - \n", device->deviceIndex); printf("\tCurrent temperature: \t %d degrees\n\n", resp_buff[0]); printf("\tCritical temperature threshold:\t %d degrees\n", resp_buff[1]); printf("\tWarning temperature threshold: \t %d degrees\n", resp_buff[2]); free(resp_buff); return rc; } /** * @ingroup cmd_handler * @brief Command handler for the board temperature. * * @par Description * This function processes the Dump Type 4 (Well Known Item) command for Lancer. * WKI selection ID 0x1040 (WKI_TAG_SAT_TEM) to read board temperature data. * * Command: boardtemp
* Required Parameters: None
* Optional Parameters: -d
* Supported Devices: Lancer
* Supported Protocols: N/A
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_board_temp(int argc, char **argv) { cmd_options_t options; if (parse_arguments(argc, argv, &options, 1, 1) == -1) { return -1; } /* Board temperature supported for Lancer */ if (!is_lancer(options.device)) { printf("boardtemp is only supproted on Lancer\n"); return -1; } if (is_uspace(options.device)) { printf("boardtemp is not supported with the user space driver\n"); return -1; } return elxu_device_get_lancer_temp(options.device); } /** * @ingroup cmd_handler * @brief Command handler for the sfp command. * * @par Description * This function processes the sfp command. * sfp data returned by the mgmt api is an ASCII string of hex values * but it isn't formatted nicely. This function retrives the string, * converts it to binary, then uses dump8() to display it nicely * formatted. * * Command: sfp
* Required Parameters: None
* Optional Parameters: -d
* Supported Devices: All
* Supported Protocols: N/A
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_sfp(int argc, char **argv) { uint8_t transceiver_buffer[TRANSCEIVER_INFO_PAGE_SIZE]; elx_sfp_transceiver_data_A0_t a0_page_info; cmd_options_t options; char *value; char *s; uint8_t *d; if (parse_arguments(argc, argv, &options, 1, 1) == -1) { return -1; } if (options.device == NULL) { fprintf(stderr, "Unable to open device\n"); return -1; } value = elxu_device_get_value(options.device, "/ocs/sfp_a0"); if ((strcmp(value, "no-sfp") == 0)) { printf("Warning: No SFP module present on this device.\n"); } if ((strlen(value) != 0) && (strcmp(value, "(unknown)") != 0) && (strcmp(value, "no-sfp") != 0)) { d = transceiver_buffer; s = value; while (isalnum(*s)) { *d = (uint8_t) strtoul(s, NULL, 16); ++d; s += 3; } if (!options.sfp_diag_data && !options.sfp_xceiver_data) { dump8("Hex information from page 0xA0 ---\n", transceiver_buffer, TRANSCEIVER_INFO_PAGE_SIZE); printf("\n"); } if (options.sfp_xceiver_data) { int i = 0; memcpy(&a0_page_info, transceiver_buffer, min(TRANSCEIVER_INFO_PAGE_SIZE, sizeof(a0_page_info))); printf("\n\nSFP Transceiver data\n"); printf("==============================================================================\n"); printf("Identifier : 0x%x(%s)\n", a0_page_info.identifier, elxu_decode_sfp_id(a0_page_info.identifier)); printf("Ext Identifier: : 0x%x(%s)\n", a0_page_info.ext_identifier, (a0_page_info.ext_identifier == 0x4) ? "non-custom SFP, SFP+ and GBIC module": "Unknown"); printf("Connector : 0x%x (%s)\n", a0_page_info.connector, elxu_decode_sfp_connector(a0_page_info.connector)); printf("Transceiver codes : 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", a0_page_info.transceiver[0], a0_page_info.transceiver[1],a0_page_info.transceiver[2],a0_page_info.transceiver[3], a0_page_info.transceiver[4],a0_page_info.transceiver[5],a0_page_info.transceiver[6],a0_page_info.transceiver[7]); printf("FC Transceiver Speed : "); for (i = 0; i < 8; i++) { if (a0_page_info.transceiver[7] & (1 << i)) { switch (i) { case 0: printf("100 MBytes/sec "); break; case 1: printf("Unallocated "); break; case 2: printf("200 MBytes/sec "); break; case 3: printf("3200 MBytes/sec "); break; case 4: printf("400 MBytes/sec "); break; case 5: printf("1600 MBytes/sec "); break; case 6: printf("800 MBytes/sec "); break; case 7: printf("1200 MBytes/sec "); break; default: printf("Unknown "); } } } printf("\nEncoding : 0x%x (%s)\n", a0_page_info.encoding, elxu_sfp_encoding_info(a0_page_info.encoding)); printf("BR, Nominal : 0x%x\n", a0_page_info.br_nominal); printf("Rate Id : 0x%x (%s)\n", a0_page_info.rate_id, elxu_decode_sfp_rate_id(a0_page_info.rate_id)); printf("Length(9um,km) : 0x%x\n", a0_page_info.length_9um_km); printf("Length(9um) : 0x%x\n", a0_page_info.length_9um); printf("Length(50um) : 0x%x\n", a0_page_info.length_50um); printf("Length(62.5) : 0x%x\n", a0_page_info.length_62_5_um); printf("Length(Copper) : 0x%x\n", a0_page_info.len_copper); printf("Length(OM3) : 0x%x\n", a0_page_info.length_om3); printf("Vendor name : "); for (i=0; i<16; i++) printf("%c", a0_page_info.vendor_name[i]); printf("\nVendor OUI : %x:%x:%x", a0_page_info.vendor_oui[0],a0_page_info.vendor_oui[1],a0_page_info.vendor_oui[2]); printf("\nVendor PN : "); for (i = 0; i<16; i++) printf("%c", a0_page_info.vendor_pn[i]); printf("\nVendor Revision : "); for (i = 0; i<4; i++) printf("%c", a0_page_info.vendor_rev[i]); printf("\nOption values : 0x%x 0x%x\n", a0_page_info.options[0], a0_page_info.options[1]); printf("BR margin, max : %d%s\n", a0_page_info.br_max, " %"); printf("BR margin, min : %d%s\n", a0_page_info.br_min, " %"); printf("Vendor SN : "); for (i = 0; i<16; i++) printf("%c", a0_page_info.vendor_sn[i]); printf("\nDate code : "); for (i = 0; i<8; i++) printf("%c", a0_page_info.date_code[i]); printf("\nOptical diagnostics support : %s", (a0_page_info.diag_monitor_type & 1 << 6) ? "Yes":"No"); printf("\n==============================================================================\n"); } } value = elxu_device_get_value(options.device, "/ocs/sfp_a2"); if ((strlen(value) != 0) && (strcmp(value, "(unknown)") != 0)) { d = transceiver_buffer; s = value; while (isalnum(*s)) { *d = (uint8_t) strtoul(s, NULL, 16); ++d; s += 3; } if (!options.sfp_diag_data && !options.sfp_xceiver_data) { dump8("Hex information from page 0xA2 ---\n", transceiver_buffer, TRANSCEIVER_INFO_PAGE_SIZE); printf("\n"); } else { float temp_high,temp_low,vcc_high,vcc_low,tx_bias_high,tx_bias_low; float tx_power_high,tx_power_low,rx_power_high,rx_power_low; float temp_high_warn,temp_low_warn,vcc_high_warn,vcc_low_warn,tx_bias_high_warn,tx_bias_low_warn; float tx_power_high_warn,tx_power_low_warn,rx_power_high_warn,rx_power_low_warn; float temperature,vcc,tx_bias_current,tx_power,rx_power; temp_high = ((transceiver_buffer[0] << 8) | transceiver_buffer[1])/(float)256; temp_low = ((transceiver_buffer[2] << 8) | transceiver_buffer[3])/(float)256; temp_high_warn = ((transceiver_buffer[4] << 8) | transceiver_buffer[5])/(float)256; temp_low_warn = ((transceiver_buffer[6] << 8) | transceiver_buffer[7])/(float)256; vcc_high = ((transceiver_buffer[8] << 8) | transceiver_buffer[9]) * (float)100 / 1000000; vcc_low = ((transceiver_buffer[10] << 8) | transceiver_buffer[11]) * (float)100 / 1000000; vcc_high_warn = ((transceiver_buffer[12] << 8) | transceiver_buffer[13]) * (float)100 / 1000000; vcc_low_warn = ((transceiver_buffer[14] << 8) | transceiver_buffer[15]) * (float)100 / 1000000; tx_bias_high = ((transceiver_buffer[16] << 8) | transceiver_buffer[17]) * (float)2 / 1000; tx_bias_low = ((transceiver_buffer[18] << 8) | transceiver_buffer[19]) * (float)2 / 1000; tx_bias_high_warn = ((transceiver_buffer[20] << 8) | transceiver_buffer[21]) * (float)2 / 1000; tx_bias_low_warn = ((transceiver_buffer[22] << 8) | transceiver_buffer[23]) * (float)2 / 1000; tx_power_high = ((transceiver_buffer[24] << 8) | transceiver_buffer[25]) * (float)0.1 / 1000; tx_power_low = ((transceiver_buffer[26] << 8) | transceiver_buffer[27]) * (float)0.1 / 1000; tx_power_high_warn = ((transceiver_buffer[28] << 8) | transceiver_buffer[29]) * (float)0.1 / 1000; tx_power_low_warn = ((transceiver_buffer[30] << 8) | transceiver_buffer[31]) * (float)0.1 / 1000; rx_power_high = ((transceiver_buffer[32] << 8) | transceiver_buffer[33]) * (float)0.1 / 1000; rx_power_low = ((transceiver_buffer[34] << 8) | transceiver_buffer[35]) * (float)0.1 / 1000; rx_power_high_warn = ((transceiver_buffer[36] << 8) | transceiver_buffer[37]) * (float)0.1 / 1000; rx_power_low_warn = ((transceiver_buffer[38] << 8) | transceiver_buffer[39]) * (float)0.1 / 1000; printf("== Threshold data ==\n"); printf("Temperature : -%f C(low) - %f C(high)\n", temp_low, temp_high); printf("Voltage : %f V(low) - %f V(high)\n", vcc_low, vcc_high); printf("TX Bias Current : %f mA(low) - %f mA(high)\n", tx_bias_low, tx_bias_high); printf("TX Power : %f mW(low) - %f mW(high)\n", tx_power_low, tx_power_high); printf("RX Power : %f mW(low) - %f mW(high)\n\n", rx_power_low, rx_power_high); printf("== Threshold warnings data ==\n"); printf("Temperature : %f (low) - %f (high)\n", temp_low_warn, temp_high_warn); printf("Voltage : %f V(low) - %f V(high)\n", vcc_low_warn, vcc_high_warn); printf("TX Bias Current : %f mA(low) - %f mA(high)\n", tx_bias_low_warn, tx_bias_high_warn); printf("TX Power : %f mW(low) - %f mW(high)\n", tx_power_low_warn, tx_power_high_warn); printf("RX Power : %f mW(low) - %f mW(high)\n\n", rx_power_low_warn, rx_power_high_warn); temperature = ((transceiver_buffer[96] << 8) | transceiver_buffer[97])/(float)256; vcc = ((transceiver_buffer[98] << 8) | transceiver_buffer[99]) * (float)100 / 1000000; tx_bias_current = ((transceiver_buffer[100] << 8) | transceiver_buffer[101]) * (float)2 / 1000; tx_power = ((transceiver_buffer[102] << 8) | transceiver_buffer[103]) * (float)0.1 / 1000; rx_power = ((transceiver_buffer[104] << 8) | transceiver_buffer[105]) * (float)0.1 / 1000; printf("== Current SFP diagnostic data ==\n"); printf("Temperature: %f C \nSupply Voltage: %f V\n", temperature, vcc); printf("TX Bias Current: %f mA\nTX Power: %f mW\nRX power: %f mW\n\n", tx_bias_current, tx_power, rx_power); } } return 0; } /** * @ingroup cmd_handler * @brief Command handler for the gendump command. * * @par Description * This function processes the gendump command. * * Command: gendump
* Required Parameters: None
* Optional Parameters: -d
* Supported Devices: Lancer
* Supported Protocols: N/A
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_gendump(int argc, char **argv) { cmd_options_t options; if (parse_arguments(argc, argv, &options, 1, 1) == -1) { return -1; } /* Read Obj only supported for Lancer/Prism */ if (!is_lancer(options.device) && !is_prism(options.device)) { printf ("gendump is only supported on Lancer/Prism\n"); return -1; } return lancer_gen_dump(options.device, options.fdb_dump); } /** * @ingroup cmd_handler * @brief Command handler for the fw-diag-log command. * * @par Description * This function processes the fw-diag-log command. * * Command: fw-diag-log
* Required Parameters: -d -f
* Optional Parameters: None
* Supported Devices: Lancer G6 and Prism
* Supported Protocols: FC
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_fw_diagnostic_log(int argc, char **argv) { cmd_options_t options; if (parse_arguments(argc, argv, &options, 1, 1) == -1) { return -1; } if (!is_fc(options.device)) { fprintf(stderr, "FW diagnostic logging is only supported for FC devices.\n"); return -1; } elxu_get_fw_diagnostic_log(options.device, options.file); return 0; } /** * @ingroup cmd_handler * @brief Command handler for the dump command. * * @par Description * This function processes the dump command. * * Command: dump-to-host
* Required Parameters: None
* Optional Parameters: -d -f
* Supported Devices: Lancer
* Supported Protocols: N/A
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_dump_to_host(int argc, char **argv) { cmd_options_t options; char *pci_dev; char *pci_func; if (parse_arguments(argc, argv, &options, 1, 1) == -1) { return -1; } /* Dump to host only supported for Lancer/Prism */ if (!is_lancer(options.device) && !is_prism(options.device)) { printf ("dump-to-host is only supported on Lancer/Prism\n"); return -1; } if (is_uspace(options.device)) { printf("dump-to-host is not supported with the user space driver\n"); return -1; } pci_dev = elxu_device_get_value(options.device, "/ocs/businfo"); pci_func = strrchr(pci_dev, '.') + 1; if (!options.fdb_dump && strcmp(pci_func, "0") != 0) { printf("dump-to-host is only valid for PCI function 0, "); printf("device index %d corresponds to PCI function %s of device %s\n", options.device->deviceIndex, pci_func, pci_dev); return -1; } return lancer_dump_to_host(options.device, options.file, options.fdb_dump); } /** * @ingroup cmd_handler * @brief Command handler for the read-status command. * * @par Description * This function processes the read-status command. * * Command: read-status
* Required Parameters: None
* Optional Parameters: -d --cc
* Supported Devices: Lancer
* Supported Protocols: N/A
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_read_status(int argc, char **argv) { cmd_options_t options; if (parse_arguments(argc, argv, &options, 1, 1) == -1) { return -1; } if (is_iscsi(options.device)) { printf ("iSCSI does not support this command\n"); return -1; } return mbox_read_status(options.device, options.cc); } /** * @ingroup cmd_handler * @brief Command handler for the read-link-status command. * * @par Description * This function processes the read-link-status command. * * Command: read-link-status
* Required Parameters: None
* Optional Parameters: -d
* Supported Devices: Lancer
* Supported Protocols: N/A
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_read_link_status(int argc, char **argv) { cmd_options_t options; if (parse_arguments(argc, argv, &options, 1, 1) == -1) { return -1; } if (is_iscsi(options.device)) { printf ("iSCSI does not support this command\n"); return -1; } return mbox_read_link_status(options.device, options.clof, options.clrc); } int elxu_check_sfp_dport_support(elxu_device_t *device) { uint8_t transceiver_buffer[TRANSCEIVER_INFO_PAGE_SIZE]; elx_sfp_transceiver_data_A0_t *a0_page_info; char *value, *s; uint8_t *d; int i; /* Explicitily supported SFP table */ elx_dport_sfp_table1_entry supported_table1[] = { {"HP-F", "QW923A", "", 0x0C }, // Finisar, HP branded {"HP-A", "QW923A", "", 0 }, // Avago, HP branded {"HP-A", "E7Y09A", "", 0 }, // Avago, HP branded 16G {"FINISAR CORP.", "FTLF8529P3BCV-EM", "B", 0 }, // Finisar, Emulex branded {"EMULEX", "AFBR-57F5MZ-ELX", "", 0 }, // Avago, Emulex branded {"FINISAR CORP.", "FTLF8532P4BCV-EM", "", 0 }, // Finisar, Emulex Branded for 32G SFP {"AVAGO", "AFBR-57G5MZ-ELX", "", 0 }, // Avago, Emulex Branded for 32G SFP {"HPE-F", "P9H30A", "", 0 }, // Finisar, HP Branded for 32G SFP {"HPE-A", "P9H30A", "", 0 }, // Avago(Broadcom)-FIT, HP Branded for 32G SFP {"HP-F", "E7Y10A", "", 0 }, // Finisar, HP Branded for 16G SFP {"HP-A", "E7Y10A", "", 0 }, // Avago(Broadcom)-FIT, HP Branded for 16G SFP {"AVAGO", "AFCT-57F3TMZ-ELX", "B", 0 }, // Avago(Broadcom)-FIT, (Downrev of Rev "B"), FIT 16G }; #define DPORT_SFP_TABLE1_LEN (sizeof(supported_table1) / sizeof(elx_dport_sfp_table1_entry)) /* Implicitily supported SFP table for emulex branded */ elx_dport_sfp_table2_entry supported_table2[] = { {"FTLF8529"}, // Finisar, Emulex branded {"AFBR-57F"}, // Avago, Emulex branded {"AFCT-57F"}, // Avago, Emulex Branded 16G {"AFCT-57G"}, // Avago, Emulex Branded 32G {"FTLF1429"}, // Finisar, Emulex Branded 16 {"FTLF1432"}, // Finisar, Emulex Branded 32G }; #define DPORT_SFP_TABLE2_LEN (sizeof(supported_table2) / sizeof(elx_dport_sfp_table2_entry)) value = elxu_device_get_value(device, "/ocs/sfp_a0"); if ((strcmp(value, "no-sfp") == 0)) { printf("Warning: No SFP module present on this device.\n"); } if ((strlen(value) != 0) && (strcmp(value, "(unknown)") != 0) && (strcmp(value, "no-sfp") != 0)) { d = transceiver_buffer; s = value; while (isalnum(*s)) { *d = (uint8_t) strtoul(s, NULL, 16); ++d; s += 3; } a0_page_info = (elx_sfp_transceiver_data_A0_t *)transceiver_buffer; /* Validate against first table */ for (i = 0; i < DPORT_SFP_TABLE1_LEN; i ++) { /* Validate vendor name */ if (strncmp(a0_page_info->vendor_name, supported_table1[i].vendor, strlen(supported_table1[i].vendor)) == 0) { /* Validate vendor part number */ if (strncmp(a0_page_info->vendor_pn, supported_table1[i].vendor_pn, strlen(supported_table1[i].vendor_pn)) == 0) { /* Validate revision number */ if ((strncmp(a0_page_info->vendor_rev, supported_table1[i].vendor_rev, strlen(supported_table1[i].vendor_rev)) == 0) || (a0_page_info->vendor_rev[0] > supported_table1[i].vendor_rev[0])) { return 0; /* Supported */ } } } } /* Validate against second table */ for (i = 0; i < DPORT_SFP_TABLE2_LEN; i ++) { if (strncmp(a0_page_info->vendor_pn, supported_table2[i].vendor_pn, strlen(supported_table2[i].vendor_pn)) == 0) { if ((strncmp((char *)a0_page_info->vendor_specific, "Emulex Certified", strlen("Emulex Certified")) == 0) || (strncmp((char *)a0_page_info->vendor_specific, "Emulex.Certified", strlen("Emulex.Certified")) == 0)) { return 0; /* Supported */ } } } } return -1; } /** * @ingroup cmd_handler * @brief Command handler for the get-dport-stats command. * * @par Description * This function processes the get-dport-stats command. * * Command: get-dport-stats
* Required Parameters: None
* Optional Parameters: -d
* Supported Devices: Lancer
* Supported Protocols: FC
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_get_dport_stats(int argc, char **argv) { cmd_options_t options; if (parse_arguments(argc, argv, &options, 1, 1) == -1) { return -1; } if (is_iscsi(options.device)) { printf ("iSCSI does not support this command\n"); return -1; } if (elxu_check_sfp_dport_support(options.device) != 0) { printf ("SFP is not supported for Dport tests\n"); return -1; } return mbox_get_dport_stats(options.device); } int elxu_cmd_set_dport_dynamic_mode(int argc, char **argv) { cmd_options_t options; char *value; if (argc < 3) { fprintf(stderr, "Value (enable or disable) is required\n"); return -1; } value = argv[2]; if ((strcasecmp(value, "enable") != 0) && (strcasecmp(value, "disable") != 0)) { fprintf(stderr, "Unexpected value '%s' - should be 'enable' or 'disable'\n", value); return -1; } if (parse_arguments(argc, argv, &options, 1, 2) == -1) { return -1; } if(is_iscsi(options.device)) { printf("iSCSI does not support this command\n"); return -1; } return mbox_set_dynamic_dport(options.device, value); } int elxu_cmd_get_dynamic_dport_status(int argc, char **argv) { cmd_options_t options; if (parse_arguments(argc, argv, &options, 1, 1) == -1) { return -1; } if (is_iscsi(options.device)) { printf ("iSCSI does not support this command\n"); return -1; } return mbox_query_dynamic_dport_status(options.device); } int elxu_cmd_diag_loopback_tests(int argc, char **argv) { cmd_options_t options; if (parse_arguments(argc, argv, &options, 1, 1) == -1) { return -1; } if (!is_lancer(options.device) && !is_prism(options.device)) { printf (" Command supports only to lancer/Prism\n"); return -1; } return mbox_diag_loopback_tests(options.device, options.loopback_type, options.retry_count); } /** * @ingroup cmd_handler * @brief Command handler for the read-rev command. * * @par Description * This function processes the read-rev command. * * Command: read-rev
* Required Parameters: None
* Optional Parameters: -d
* Supported Devices: Lancer, Skyhawk
* Supported Protocols: N/A
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_read_rev(int argc, char **argv) { cmd_options_t options; if (parse_arguments(argc, argv, &options, 1, 1) == -1) { return -1; } return mbox_read_rev(options.device); } /** * @ingroup cmd_handler * @brief Command handler for the ack-frequency command. * * @par Description * This function processes the ack-frequency command. * * Command: ack-frequency
* Required Parameters:
* Optional Parameters: -d
* Supported Devices: Skyhawk
* Supported Protocols: iSCSI
* * @param argc The number of command line arguments. * @param argv An array of pointers to the command line arguments. * * @return Returns 0 on success; or a non-zero error code value on failure. */ int elxu_cmd_ack_frequency(int argc, char **argv) { uint32_t freq; cmd_options_t options; if (argc < 3) { fprintf(stderr, "ACK frequency is required\n"); return -1; } freq = strtoul(argv[2], NULL, 0); if (parse_arguments(argc, argv, &options, 1, 2) == -1) { return -1; } if (!is_skyhawk(options.device)) { printf("Setting TCP parameters is only supported on Skyhawk\n"); return -1; } return mbox_tcp_parameters(options.device, ISCSI_UPDATE_ACK_FREQUENCY, freq, 0); } /** * @ingroup cmd_handler * @brief Command handler for the delayed-ack-timer command. * * @par Description * This function processes the delayed-ack-timer command. * * Command: delayed-ack-timer
* Required Parameters: