diff --git a/cli/diag.c b/cli/diag.c index 7b7d7b6c..68c225bd 100644 --- a/cli/diag.c +++ b/cli/diag.c @@ -81,6 +81,11 @@ static const struct argconfig_choice port_eq_prev_speeds[] = { .choices=port_eq_prev_speeds \ } +#define OSA_STACK_ID_OPTION { \ + "stack_id", 's', "STACK_ID", CFG_INT, &cfg.stack_id, \ + required_argument,"ID of the stack (0-5), 7 for mangement stack (Gen5). ID of the stack (0-9) (Gen6)", \ +} + static int get_port(struct switchtec_dev *dev, int port_id, struct switchtec_status *port) { @@ -216,6 +221,33 @@ static int ltssm_log(int argc, char **argv) { return ret; } +static const struct argconfig_choice data_mode_choices[] = { + {"ADC", SWITCHTEC_DIAG_EYE_ADC, + "ADC data mode"}, + {"FFE", SWITCHTEC_DIAG_EYE_FFE, + "FFE eye data mode"}, + {"DFE", SWITCHTEC_DIAG_EYE_DFE, + "enumated DFE data eye data mode"}, + {} +}; + +static const struct argconfig_choice eye_modes_gen6[] = { + {"FULL", SWITCHTEC_DIAG_EYE_FULL, + "the full eye diagram"}, + {"INTERLEAVE", SWITCHTEC_DIAG_EYE_INTERLEAVE, + "interleaver eye diagram"}, + {"SAR", SWITCHTEC_DIAG_EYE_SAR, + "interleaver eye diagram"}, + {} +}; + +static const struct argconfig_choice hstep_choices[] = { + {"ultra-fine", SWITCHTEC_DIAG_EYE_ULTRA_FINE, "ultra-fine"}, + {"fine", SWITCHTEC_DIAG_EYE_FINE, "fine"}, + {"medium", SWITCHTEC_DIAG_EYE_MEDIUM, "medium"}, + {"coarse", SWITCHTEC_DIAG_EYE_COARSE, "coarse"}, +}; + static const struct argconfig_choice eye_modes[] = { {"RAW", SWITCHTEC_DIAG_EYE_RAW, "raw data mode (slow, more accurate)"}, @@ -1243,7 +1275,8 @@ static double *eye_observe_dev(struct switchtec_dev *dev, int port_id, goto out_err; } - ret = switchtec_diag_eye_start(dev, lane_mask, X, Y, interval, 0); + ret = switchtec_diag_eye_start(dev, lane_mask, X, Y, interval, + 0, 0, 0, 0, 0, 0, 0, 0); if (ret) { switchtec_perror("eye_start"); goto out_err; @@ -1350,7 +1383,10 @@ static int eye_graph(enum output_format fmt, struct range *X, struct range *Y, static double *eye_capture_dev_gen5(struct switchtec_dev *dev, int port_id, int lane_id, int num_lanes, - int capture_depth, int* num_phases, int* gen) + int capture_depth, int* num_phases, int* gen, + int sar_sel, int intleav_sel, int hstep, + int data_mode, int eye_mode, uint64_t refclk, + int vstep) { int bin, j, ret, first_lane, num_phases_l, stride; int lane_mask[4] = {}; @@ -1366,7 +1402,8 @@ static double *eye_capture_dev_gen5(struct switchtec_dev *dev, } ret = switchtec_diag_eye_start(dev, lane_mask, NULL, NULL, 0, - capture_depth); + capture_depth, sar_sel, intleav_sel, hstep, + data_mode, eye_mode, refclk, vstep); if (ret) { switchtec_perror("eye_run"); return NULL; @@ -1427,6 +1464,12 @@ static int eye(int argc, char **argv) const char *plot_filename; FILE *crosshair_file; const char *crosshair_filename; + int eye_modes_gen6; + int hstep; + int sar_sel; + int intleav_sel; + uint64_t refclk; + int data_mode; } cfg = { .fmt = FMT_DEFAULT, .port_id = -1, @@ -1441,6 +1484,12 @@ static int eye(int argc, char **argv) .y_range.end = 255, .y_range.step = 5, .step_interval = 1, + .hstep = 1, + .sar_sel = 10, + .intleav_sel = 0, + .refclk = 0, + .data_mode = SWITCHTEC_DIAG_EYE_ADC, + .eye_modes_gen6 = SWITCHTEC_DIAG_EYE_FULL, }; const struct argconfig_options opts[] = { DEVICE_OPTION_OPTIONAL, @@ -1455,6 +1504,12 @@ static int eye(int argc, char **argv) {"mode", 'm', "MODE", CFG_CHOICES, &cfg.mode, required_argument, "data mode for the capture", .choices=eye_modes}, + {"mode-gen6", 'M', "MODE", CFG_CHOICES, &cfg.mode, + required_argument, "eye mode for the capture for gen6", + .choices=eye_modes_gen6}, + {"data-mode", 'd', "MODE", CFG_CHOICES, &cfg.data_mode, + required_argument, "data mode for the eye capture gen6", + .choices=data_mode_choices}, {"num-lanes", 'n', "NUM", CFG_POSITIVE, &cfg.num_lanes, required_argument, "number of lanes to capture, if greater than one, format must be csv (default: 1)"}, @@ -1478,6 +1533,15 @@ static int eye(int argc, char **argv) required_argument, "step interval in ms (default: 1ms)"}, {"capture-depth", 'd', "NUM", CFG_POSITIVE, &cfg.capture_depth, required_argument, "capture depth (6 to 40; default: 24)"}, + {"h-step", 'H', "NUM", CFG_CHOICES, &cfg.hstep, + required_argument, "Granularity of the X-axis Gen 6 only", + .choices=hstep_choices}, + {"sar-sel", 'e', "NUM", CFG_NONNEGATIVE, &cfg.sar_sel, + required_argument, "Eye scan for a particular slice (10 to 15) Gen 6 only"}, + {"intleav-sel", 'I', "NUM", CFG_NONNEGATIVE, &cfg.intleav_sel, + required_argument, "Eye scan for a particular interleave (0 to 3) Gen6 only"}, + {"refclk", 'r', "NUM", CFG_NONNEGATIVE, &cfg.refclk, required_argument, + "Configures the number of ref clk cycles used to sample the data (0 to 48 bit num max) Gen 6 only"}, {NULL}}; argconfig_parse(argc, argv, CMD_DESC_EYE, opts, &cfg, @@ -1564,11 +1628,14 @@ static int eye(int argc, char **argv) } if (!pixels) { - if (switchtec_is_gen5(cfg.dev)) { + if (switchtec_is_gen5(cfg.dev) || switchtec_is_gen6(cfg.dev)) { pixels = eye_capture_dev_gen5(cfg.dev, cfg.port_id, cfg.lane_id, cfg.num_lanes, cfg.capture_depth, - &num_phases, &gen); + &num_phases, &gen, cfg.sar_sel, + cfg.intleav_sel, cfg.hstep, + cfg.data_mode, cfg.eye_modes_gen6, + cfg.refclk, cfg.y_range.step); if (!pixels) return -1; @@ -1762,6 +1829,20 @@ static int loopback(int argc, char **argv) return print_loopback_mode(cfg.dev, cfg.port_id); } +static const struct argconfig_choice all_pattern_types[] = { + {"PRBS7", SWITCHTEC_DIAG_PATTERN_PRBS_7, "PRBS 7"}, + {"PRBS11", SWITCHTEC_DIAG_PATTERN_PRBS_11, "PRBS 11"}, + {"PRBS23", SWITCHTEC_DIAG_PATTERN_PRBS_23, "PRBS 23"}, + {"PRBS31", SWITCHTEC_DIAG_PATTERN_PRBS_31, "PRBS 31"}, + {"PRBS9", SWITCHTEC_DIAG_PATTERN_PRBS_9, "PRBS 9"}, + {"PRBS15", SWITCHTEC_DIAG_PATTERN_PRBS_15, "PRBS 15"}, + {"PRBS5", SWITCHTEC_DIAG_GEN_5_PATTERN_PRBS_5, "PRBS 5 (Gen 5)"}, + {"PRBS20", SWITCHTEC_DIAG_GEN_5_PATTERN_PRBS_20, "PRBS 20 (Gen 5)"}, + {"PRBS13", SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_13, "PRBS 13 (Gen 6)"}, + {"52UI", SWITCHTEC_DIAG_GEN_6_PATTERN_PCIE_52_UI_JIT, "PCIe 52UI Jitter (Gen 6)"}, + {} +}; + static const struct argconfig_choice pattern_types[] = { {"PRBS7", SWITCHTEC_DIAG_PATTERN_PRBS_7, "PRBS 7"}, {"PRBS11", SWITCHTEC_DIAG_PATTERN_PRBS_11, "PRBS 11"}, @@ -1774,12 +1855,25 @@ static const struct argconfig_choice pattern_types[] = { {} }; +static const struct argconfig_choice pattern_types_gen6[] = { + {"PRBS7", SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_7, "PRBS 7"}, + {"PRBS11", SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_9, "PRBS 9"}, + {"PRBS23", SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_11, "PRBS 11"}, + {"PRBS31", SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_13, "PRBS 13"}, + {"PRBS9", SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_15, "PRBS 15"}, + {"PRBS15", SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_23, "PRBS 23"}, + {"PRBS5", SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_31, "PRBS 31"}, + {"PRBS20", SWITCHTEC_DIAG_GEN_6_PATTERN_PCIE_52_UI_JIT, "PCIe 52UI Jitter"}, + {} +}; + static const struct argconfig_choice pat_gen_link_speeds[] = { {"GEN1", SWITCHTEC_DIAG_PAT_LINK_GEN1, "GEN1 Pattern Generator Speed"}, {"GEN2", SWITCHTEC_DIAG_PAT_LINK_GEN2, "GEN2 Pattern Generator Speed"}, {"GEN3", SWITCHTEC_DIAG_PAT_LINK_GEN3, "GEN3 Pattern Generator Speed"}, {"GEN4", SWITCHTEC_DIAG_PAT_LINK_GEN4, "GEN4 Pattern Generator Speed"}, {"GEN5", SWITCHTEC_DIAG_PAT_LINK_GEN5, "GEN5 Pattern Generator Speed"}, + {"GEN6", SWITCHTEC_DIAG_PAT_LINK_GEN6, "GEN6 Pattern Generator Speed"}, }; static const char *pattern_to_str(enum switchtec_diag_pattern type) @@ -1794,6 +1888,18 @@ static const char *pattern_to_str(enum switchtec_diag_pattern type) return "UNKNOWN"; } +static const char *pattern_to_str_gen6(enum switchtec_diag_pattern_gen6 type) +{ + const struct argconfig_choice *s; + + for (s = pattern_types_gen6; s->name; s++) { + if (s->value == type) + return s->name; + } + + return "UNKNOWN"; +} + static const char *link_speed_to_str(enum switchtec_diag_pattern_link_rate type) { const struct argconfig_choice *s; @@ -1811,6 +1917,7 @@ static int print_pattern_mode(struct switchtec_dev *dev, { enum switchtec_diag_pattern gen_pat, mon_pat; int gen_pat_gen5, mon_pat_gen5; + enum switchtec_diag_pattern_gen6 mon_pat_gen6, gen_pat_gen6; unsigned long long err_cnt; int ret, lane_id; int err = 0; @@ -1821,6 +1928,7 @@ static int print_pattern_mode(struct switchtec_dev *dev, return -1; } gen_pat_gen5 = gen_pat; + gen_pat_gen6 = gen_pat; if (gen_pat_gen5 == SWITCHTEC_DIAG_GEN_5_PATTERN_PRBS_DISABLED) { fprintf(stderr, "!! The pattern generator is disabled on either the TX or RX port\n"); err = 1; @@ -1829,6 +1937,7 @@ static int print_pattern_mode(struct switchtec_dev *dev, ret = switchtec_diag_pattern_mon_get(dev, port_id, 0, &mon_pat, &err_cnt); mon_pat_gen5 = mon_pat; + mon_pat_gen6 = mon_pat; if (ret == ERR_PAT_MON_IS_DISABLED || mon_pat_gen5 == SWITCHTEC_DIAG_GEN_5_PATTERN_PRBS_DISABLED) { fprintf(stderr, "!! The pattern monitor is disabled on either the TX or RX port\n"); err = 1; @@ -1844,15 +1953,22 @@ static int print_pattern_mode(struct switchtec_dev *dev, } printf("Port: %d\n", port_id); - if (gen_pat == SWITCHTEC_DIAG_PATTERN_PRBS_DISABLED && switchtec_is_gen4(dev)) + if (gen_pat == SWITCHTEC_DIAG_PATTERN_PRBS_DISABLED && switchtec_is_gen4(dev)) { printf(" Generator: Disabled\n"); - else - printf(" Generator: %s\n", pattern_to_str(gen_pat)); + } else { + if (switchtec_is_gen6(dev)) + printf(" Generator: %s\n", pattern_to_str_gen6(gen_pat_gen6)); + else + printf(" Generator: %s\n", pattern_to_str(gen_pat)); + } if (mon_pat == SWITCHTEC_DIAG_PATTERN_PRBS_DISABLED && switchtec_is_gen4(dev)) { printf(" Monitor: Disabled\n"); } else { - printf(" Monitor: %-20s\n", pattern_to_str(mon_pat)); + if (switchtec_is_gen6(dev)) + printf(" Monitor: %-20s\n", pattern_to_str_gen6(mon_pat_gen6)); + else + printf(" Monitor: %-20s\n", pattern_to_str(mon_pat)); printf(" Lane %-2d Errors: 0x%llx\n", 0, err_cnt); for (lane_id = 1; lane_id < port->cfg_lnk_width; lane_id++) { ret = switchtec_diag_pattern_mon_get(dev, port_id, @@ -1891,7 +2007,7 @@ static int pattern(int argc, char **argv) int link_speed; } cfg = { .port_id = -1, - .pattern = SWITCHTEC_DIAG_PATTERN_PRBS_31, + .pattern = SWITCHTEC_DIAG_PATTERN_PRBS_7, }; const struct argconfig_options opts[] = { @@ -1910,8 +2026,8 @@ static int pattern(int argc, char **argv) "Enable Pattern Monitor on specified port"}, {"pattern", 't', "PATTERN", CFG_CHOICES, &cfg.pattern, required_argument, - "pattern to generate or monitor for (default: PRBS31)", - .choices = pattern_types}, + "pattern to generate or monitor for (default: PRBS7)", + .choices = all_pattern_types}, {"speed", 's', "SPEED", CFG_CHOICES, &cfg.link_speed, required_argument, "link speed that applies to the pattern generator (default: GEN1)", @@ -1925,6 +2041,26 @@ static int pattern(int argc, char **argv) "Cannot enable link speed -s / --speed on pattern monitor\n"); return -1; } + + if (cfg.pattern == SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_13 && !switchtec_is_gen6(cfg.dev)) { + fprintf(stderr, "Cannot set PRBS 13 pattern for non Gen6 Switchtec device.\n"); + return -1; + } + + if (cfg.pattern == SWITCHTEC_DIAG_GEN_6_PATTERN_PCIE_52_UI_JIT && !switchtec_is_gen6(cfg.dev)) { + fprintf(stderr, "Cannot set PCIe 52 UI Jitter pattern for non Gen6 Switchtec device.\n"); + return -1; + } + + if (cfg.pattern == SWITCHTEC_DIAG_GEN_5_PATTERN_PRBS_5 && !switchtec_is_gen5(cfg.dev)) { + fprintf(stderr, "Cannot set PRBS 5 pattern for non Gen6 Switchtec device.\n"); + return -1; + } + + if (cfg.pattern == SWITCHTEC_DIAG_GEN_5_PATTERN_PRBS_20 && !switchtec_is_gen5(cfg.dev)) { + fprintf(stderr, "Cannot set PRBS 20 pattern for non Gen6 Switchtec device.\n"); + return -1; + } if (!cfg.link_speed) { if (switchtec_is_gen5(cfg.dev)) @@ -1960,12 +2096,17 @@ static int pattern(int argc, char **argv) switchtec_perror("pattern_mon_set"); return -1; } - if (cfg.disable) + if (cfg.disable) { printf("Disabled pattern monitor on port %d\n", cfg.port_id); - else - printf("Pattern monitor set for port %d with pattern type %s\n", - cfg.port_id, pattern_to_str(cfg.pattern)); + } else { + if (switchtec_is_gen6(cfg.dev)) + printf("Pattern monitor set for port %d with pattern type %s\n", + cfg.port_id, pattern_to_str_gen6(cfg.pattern)); + else + printf("Pattern monitor set for port %d with pattern type %s\n", + cfg.port_id, pattern_to_str(cfg.pattern)); + } } if (cfg.generate) { @@ -2653,6 +2794,22 @@ static int linkerr_inject(int argc, char ** argv) return ret; } +static int stack_id_check(struct switchtec_dev *dev, int stack_id) +{ + if (switchtec_is_gen6(dev)) { + if (stack_id < 0 || stack_id > 9) + goto invalid_stack; + } else { + if (stack_id < 0 || (stack_id > 5 && stack_id != 7)) + goto invalid_stack; + } + return 0; + +invalid_stack: + fprintf(stderr, "Invalid stack ID.\n"); + return -1; +} + #define CMD_ORDERED_SET_ANALYZER "Ordered set analyzer" static int osa(int argc, char **argv) @@ -2665,8 +2822,7 @@ static int osa(int argc, char **argv) } cfg; const struct argconfig_options opts[] = { DEVICE_OPTION, - {"stack_id", 's', "STACK_ID", CFG_INT, &cfg.stack_id, - required_argument,"ID of the stack (0-5), 7 for mangement stack"}, + OSA_STACK_ID_OPTION, {"operation", 'o', "0/1/2/3/4/5", CFG_INT, &cfg.operation, required_argument,"operations:\n- stop:0\n- start:1\n- trigger:2\n- reset:3\n- release:4\n- status:5"}, {NULL}}; @@ -2674,10 +2830,9 @@ static int osa(int argc, char **argv) argconfig_parse(argc, argv, CMD_ORDERED_SET_ANALYZER, opts, &cfg, sizeof(cfg)); - if (cfg.stack_id < 0 || (cfg.stack_id > 5 && cfg.stack_id != 7)) { - fprintf(stderr, "Invalid stack ID.\n"); - return -1; - } + ret = stack_id_check(cfg.dev, cfg.stack_id); + if (ret) + return ret; if (cfg.operation > 5 || cfg.operation < 0) { printf("Invalid operation!\n"); @@ -2712,8 +2867,7 @@ static int osa_config_type(int argc, char **argv) } cfg; const struct argconfig_options opts[] = { DEVICE_OPTION, - {"stack_id", 's', "STACK_ID", CFG_INT, &cfg.stack_id, - required_argument,"ID of the stack (0-5), 7 for mangement stack"}, + OSA_STACK_ID_OPTION, {"lane_mask", 'm', "LANE_MASK", CFG_STRING, &cfg.lane_mask, required_argument, "16 bit lane mask, 1 enables the triggering for that specified lane. " \ @@ -2724,23 +2878,22 @@ static int osa_config_type(int argc, char **argv) "(If left blank defaults to all bits set to 0). Input as a hexidecimal value prefixed with 0x\nBit 0 : tx\nBit 1 : rx"}, {"link_rate", 'r', "LINK_RATE", CFG_STRING, &cfg.link_rate, required_argument, - "5 bit mask for link rate, 1 enables the corrisponding link rate. " \ + "6 bit mask for link rate, 1 enables the corrisponding link rate. " \ "(If left blank defaults to all bits set to 0). Input as a hexidecimal value prefixed with " \ - "0x\nBit 0 : Gen1\nBit 1 : Gen2\nBit 2 : Gen3\nBit 3 : Gen4\nBit 4 : Gen5"}, + "0x\nBit 0 : Gen1\nBit 1 : Gen2\nBit 2 : Gen3\nBit 3 : Gen4\nBit 4 : Gen5\nBit 5 : Gen6"}, {"os_types", 't', "OS_TYPES", CFG_STRING, &cfg.os_types, required_argument, - "4 bit mask for OS types, 1 enables the corrisponding OS type. "\ - "(If left blank defaults to all bits set to 0). Input as a hexidecimal value prefixed with "\ - "0x\nBit 0 : TS1\nBit 1 : TS2\nBit 2 : FTS\nBit 3 : CTL_SKP"}, + "4 bit mask for OS types, 5 bit mask Gen6 only. 1 enables the corrisponding OS type. "\ + "(If left blank defaults to all bits set to 0). Input as a hexidecimal value prefixed with 0x."\ + "\n\t\tGen5\tGen6\nBit 0\tTS1\tTS0\nBit 1\tTS2\tTS1\nBit 2\tFTS\tTS2\nBit 3\tCTL_SKP\tFTS\nBit 4\t----\tCTL_SKP"}, {NULL}}; argconfig_parse(argc, argv, CMD_ORDERED_SET_ANALYZER_CONF, opts, &cfg, sizeof(cfg)); - if (cfg.stack_id < 0 || (cfg.stack_id > 5 && cfg.stack_id != 7)) { - fprintf(stderr, "Invalid stack ID.\n"); - return -1; - } + ret = stack_id_check(cfg.dev, cfg.stack_id); + if (ret) + return ret; if (cfg.lane_mask) { ret = convert_hex_str(cfg.lane_mask, &lane_mask, &num_dwords, 4); @@ -2770,8 +2923,14 @@ static int osa_config_type(int argc, char **argv) fprintf(stderr, "Error with link rate mask.\n"); return -1; } - if (*link_rate_mask > 31) { - fprintf(stderr, "Link rate cannot be greater than 0x1F.\n"); + if ((*link_rate_mask > 31 || (*link_rate_mask | 0x20)) && switchtec_is_gen5(cfg.dev)) { + fprintf(stderr, "Cannot enable Gen6 link rate or mask greater than 0x1F (Gen5 Switchtec devices).\n"); + free(lane_mask); + free(direction_mask); + free(link_rate_mask); + return -1; + } else if (*link_rate_mask > 63 && switchtec_is_gen6(cfg.dev)) { + fprintf(stderr, "Link rate cannot be greater than 0x3F (Gen6 Switchtec devices).\n"); free(lane_mask); free(direction_mask); free(link_rate_mask); @@ -2842,9 +3001,9 @@ static int osa_config_pat(int argc, char **argv) "(If left blank defaults to all bits set to 0). Input as a hexidecimal value prefixed with 0x\nBit 0 : tx\nBit 1 : rx"}, {"link_rate", 'r', "LINK_RATE", CFG_STRING, &cfg.link_rate, required_argument, - "5 bit mask for link rate, 1 enables the corrisponding link rate. "\ + "6 bit mask for link rate, 1 enables the corrisponding link rate. "\ "(If left blank defaults to all bits set to 0). Input as a hexidecimal value "\ - "prefixed with 0x\nBit 0 : Gen1\nBit 1 : Gen2\nBit 2 : Gen3\nBit 3 : Gen4\nBit 4 : Gen5"}, + "prefixed with 0x\nBit 0 : Gen1\nBit 1 : Gen2\nBit 2 : Gen3\nBit 3 : Gen4\nBit 4 : Gen5\nBit 5 : Gen6"}, {"dwords_value", 'V', "\"val_dword0 val_dword1 etc.\"", CFG_STRING, &cfg.value_dwords, required_argument, "(Maximum 4 DWs) Dwords should be surrounded by quotations, each "\ @@ -2858,10 +3017,9 @@ static int osa_config_pat(int argc, char **argv) argconfig_parse(argc, argv, CMD_ORDERED_SET_ANALYZER_CONF, opts, &cfg, sizeof(cfg)); - if (cfg.stack_id < 0 || (cfg.stack_id > 5 && cfg.stack_id != 7)) { - fprintf(stderr, "Invalid stack ID.\n"); - return -1; - } + ret = stack_id_check(cfg.dev, cfg.stack_id); + if (ret) + return ret; if (cfg.lane_mask) { ret = convert_hex_str(cfg.lane_mask, &lane_mask, &num_dwords, 4); @@ -2891,8 +3049,14 @@ static int osa_config_pat(int argc, char **argv) fprintf(stderr, "Error with link rate mask.\n"); return -1; } - if (*link_rate_mask > 31) { - fprintf(stderr, "Link rate cannot be greater than 0x1F.\n"); + if ((*link_rate_mask > 31 || (*link_rate_mask | 0x20)) && switchtec_is_gen5(cfg.dev)) { + fprintf(stderr, "Cannot enable Gen6 link rate or mask greater than 0x1F (Gen5 Switchtec devices).\n"); + free(lane_mask); + free(direction_mask); + free(link_rate_mask); + return -1; + } else if (*link_rate_mask > 63 && switchtec_is_gen6(cfg.dev)) { + fprintf(stderr, "Link rate cannot be greater than 0x3F (Gen6 Switchtec devices).\n"); free(lane_mask); free(direction_mask); free(link_rate_mask); @@ -2961,8 +3125,7 @@ static int osa_config_misc(int argc, char **argv) } cfg; const struct argconfig_options opts[] = { DEVICE_OPTION, - {"stack_id", 's', "STACK_ID", CFG_INT, &cfg.stack_id, - required_argument,"ID of the stack (0-5), 7 for mangement stack"}, + OSA_STACK_ID_OPTION, {"trigger_en", 't', "ENABLED", CFG_STRING, &cfg.trigger_en, required_argument, "3 bit mask for trigger enable, 1 enables the correisponding trigger. "\ @@ -2973,10 +3136,9 @@ static int osa_config_misc(int argc, char **argv) argconfig_parse(argc, argv, CMD_ORDERED_SET_ANALYZER_MISC_CONF, opts, &cfg, sizeof(cfg)); - if (cfg.stack_id < 0 || (cfg.stack_id > 5 && cfg.stack_id != 7)) { - fprintf(stderr, "Invalid stack ID.\n"); - return -1; - } + ret = stack_id_check(cfg.dev, cfg.stack_id); + if (ret) + return ret; if (cfg.trigger_en) { ret = convert_hex_str(cfg.trigger_en, &trigger_mask, @@ -3003,7 +3165,7 @@ static int osa_config_misc(int argc, char **argv) #define CMD_ORDERED_SET_ANALYZER_CAP_CTRL "Ordered set analyzer capture control" -static int osa_capture_contol(int argc, char **argv) +static int osa_capture_control(int argc, char **argv) { int ret = 0; uint32_t * os_type_mask = NULL; @@ -3029,8 +3191,7 @@ static int osa_capture_contol(int argc, char **argv) const struct argconfig_options opts[] = { DEVICE_OPTION, - {"stack_id", 's', "STACK_ID", CFG_INT, &cfg.stack_id, - required_argument,"ID of the stack (0-5), 7 for mangement stack"}, + OSA_STACK_ID_OPTION, {"lane_mask", 'm', "LANE_MASK", CFG_STRING, &cfg.lane_mask, required_argument, "16 bit lane mask, 1 enables the triggering for that specified lane. "\ @@ -3041,7 +3202,7 @@ static int osa_capture_contol(int argc, char **argv) "(If left blank defaults to all bits set to 0). Input as a hexidecimal value prefixed with 0x\nBit 0 : tx\nBit 1 : rx"}, {"drop_single_os", 'o', "", CFG_NONE, &cfg.drop_single_os, no_argument, - "When set to 1, the single TS1, TS2, FTS, and CTL_SKP OS's are excluded from the capture."}, + "When set to 1, the single TS0(Gen6), TS1, TS2, FTS, and CTL_SKP OS's are excluded from the capture."}, {"stop_mode", 'S', "", CFG_NONE, &cfg.stop_mode, no_argument, "Controls when the OSA stops capturing. disabled: any lane has stopped, enabled: all lanes have stopped. (Default: disabled)"}, @@ -3055,17 +3216,17 @@ static int osa_capture_contol(int argc, char **argv) "Max 256 entries.\n(Required if disabling --snapshot_mode -s)"}, {"os_types", 't', "OS_TYPES", CFG_STRING, &cfg.os_types, required_argument, - "8 bit mask for OS types, 1 enables the corrisponding OS type. "\ - "(If left blank defaults to all bits set to 0). Input as a hexidecimal value prefixed "\ - "with 0x\nBit 0 : TS1\nBit 1 : TS2\nBit 2 : FTS\nBit 3 : CTL_SKP\nBit 4 : SKP\nBit 5 : EIEOS\nBit 6 : EIOS\nBit 7 : ERR_OS"}, + "4 bit mask for OS types, 5 bit mask Gen6 only. 1 enables the corrisponding OS type. "\ + "(If left blank defaults to all bits set to 0). Input as a hexidecimal value prefixed with 0x."\ + "\n\t\tGen5\tGen6\nBit 0\tTS1\tTS0\nBit 1\tTS2\tTS1\nBit 2\tFTS\tTS2\nBit 3\tCTL_SKP\tFTS\n" \ + "Bit 4\tSKP\tCTL_SKP\nBit 5\tEIEOS\tSKP\nBit 6\tEIOS\tEIEOS\nBit 7\tERR_OS\tEIOS\nBit 8\t----\tERR_OS"}, {NULL}}; argconfig_parse(argc, argv, CMD_ORDERED_SET_ANALYZER_CAP_CTRL, opts, &cfg, sizeof(cfg)); - if (cfg.stack_id < 0 || (cfg.stack_id > 5 && cfg.stack_id != 7)) { - fprintf(stderr, "Invalid stack ID.\n"); - return -1; - } + ret = stack_id_check(cfg.dev, cfg.stack_id); + if (ret) + return ret; if (cfg.post_trig_entries && cfg.snapshot_mode) { fprintf(stderr, "Cannot enable snapshot mode and set the number of post trigger entries.\n"); @@ -3134,17 +3295,15 @@ static int osa_dump_config(int argc, char **argv) } cfg; const struct argconfig_options opts[] = { DEVICE_OPTION, - {"stack_id", 's', "STACK_ID", CFG_INT, &cfg.stack_id, - required_argument,"ID of the stack (0-5), 7 for mangement stack"}, + OSA_STACK_ID_OPTION, {NULL}}; argconfig_parse(argc, argv, CMD_ORDERED_SET_ANALYZER, opts, &cfg, sizeof(cfg)); - if (cfg.stack_id < 0 || (cfg.stack_id > 5 && cfg.stack_id != 7)) { - fprintf(stderr, "Invalid stack ID.\n"); - return -1; - } + ret = stack_id_check(cfg.dev, cfg.stack_id); + if (ret) + return ret; ret = switchtec_osa_dump_conf(cfg.dev, cfg.stack_id); if (ret) { @@ -3167,8 +3326,7 @@ static int osa_dump_data(int argc, char **argv) } cfg; const struct argconfig_options opts[] = { DEVICE_OPTION, - {"stack_id", 's', "STACK_ID", CFG_INT, &cfg.stack_id, - required_argument,"ID of the stack (0-5), 7 for mangement stack"}, + OSA_STACK_ID_OPTION, {"lane", 'l', "lane", CFG_INT, &cfg.lane, required_argument,"lane ID"}, {"direction", 'd', "0/1", CFG_INT, &cfg.direction, @@ -3178,10 +3336,9 @@ static int osa_dump_data(int argc, char **argv) argconfig_parse(argc, argv, CMD_ORDERED_SET_ANALYZER, opts, &cfg, sizeof(cfg)); - if (cfg.stack_id < 0 || (cfg.stack_id > 5 && cfg.stack_id != 7)) { - fprintf(stderr, "Invalid stack ID.\n"); - return -1; - } + ret = stack_id_check(cfg.dev, cfg.stack_id); + if (ret) + return ret; if (cfg.direction > 1) { fprintf(stderr, "Direction must be either 0 or 1\n"); @@ -3217,7 +3374,7 @@ static const struct cmd commands[] = { CMD(osa_config_type, CMD_ORDERED_SET_ANALYZER_CONF), CMD(osa_config_pat, CMD_ORDERED_SET_ANALYZER_PAT_CONF), CMD(osa_config_misc, CMD_ORDERED_SET_ANALYZER_MISC_CONF), - CMD(osa_capture_contol, CMD_ORDERED_SET_ANALYZER_CAP_CTRL), + CMD(osa_capture_control, CMD_ORDERED_SET_ANALYZER_CAP_CTRL), CMD(osa_dump_config, CMD_ORDERED_SET_ANALYZER_DUMP_CONF), CMD(osa_dump_data, CMD_ORDERED_SET_ANALYZER_DUMP_DATA), {} diff --git a/cli/main.c b/cli/main.c index 13782f13..a0f4ea05 100644 --- a/cli/main.c +++ b/cli/main.c @@ -1856,8 +1856,10 @@ enum switchtec_fw_type check_and_print_fw_image(int img_fd, fprintf(stderr, "%s: Invalid image file format\n", img_filename); return ret; + } else if (ret > 0) { + return SWITCHTEC_FW_TYPE_BL2; } - + printf("File: %s\n", get_basename(img_filename)); printf("Gen: %s\n", switchtec_fw_image_gen_str(&info)); printf("Type: %s\n", switchtec_fw_image_type(&info)); @@ -2242,8 +2244,8 @@ static int fw_redundant(int argc, char **argv) argconfig_parse(argc, argv, CMD_DESC_FW_REDUNDANT, opts, &cfg, sizeof(cfg)); - if (!switchtec_is_gen5(cfg.dev)) { - fprintf(stderr, "Setting the redundant flag is only supported on Gen5 switches\n"); + if (!switchtec_is_gen5(cfg.dev) && !switchtec_is_gen6(cfg.dev)) { + fprintf(stderr, "Setting the redundant flag is only supported on Gen5/6 switches\n"); return 1; } if (!cfg.bl2 && !cfg.key && !cfg.firmware && !cfg.config && !cfg.riotcore) { @@ -2254,6 +2256,10 @@ static int fw_redundant(int argc, char **argv) fprintf(stderr, "Set redundant flag to either set - 1 or unset - 0\n"); return 1; } + if (switchtec_is_gen6(cfg.dev) && cfg.riotcore) { + fprintf(stderr, "Setting riotcore partition is not supported on Gen6 switches\n"); + return 1; + } ret = switchtec_fw_set_redundant_flag(cfg.dev, cfg.key, cfg.riotcore, cfg.bl2, @@ -2270,7 +2276,7 @@ static int fw_redundant(int argc, char **argv) return ret; } -#define CMD_DESC_FW_READ "read a firmware image from flash" +#define CMD_DESC_FW_READ "read a firmware image from flash, default(no args) reads main firmware image" static int fw_read(int argc, char **argv) { @@ -2302,8 +2308,6 @@ static int fw_read(int argc, char **argv) "assume yes when prompted"}, {"inactive", 'i', "", CFG_NONE, &cfg.inactive, no_argument, "read the inactive partition"}, - {"data", 'd', "", CFG_NONE, &cfg.data, no_argument, - "read the data/config partiton instead of the main firmware"}, {"config", 'c', "", CFG_NONE, &cfg.data, no_argument, "read the data/config partiton instead of the main firmware"}, {"bl2", 'b', "", CFG_NONE, &cfg.bl2, no_argument, diff --git a/cli/mfg.c b/cli/mfg.c index 879d8c8b..023f3055 100644 --- a/cli/mfg.c +++ b/cli/mfg.c @@ -475,21 +475,23 @@ static int info(int argc, char **argv) printf("----------------- UID info --------------------------------\n"); printf("Device Unique ID: \t\t\t0x"); - for (int i = 0; i < SWITCHTEC_UID_DWORD_S; i++) { - printf("%08X", *sn_info.UID); + printf("%08X\n", *sn_info.UID); + sn_info.UID++; + for (int i = 1; i < SWITCHTEC_UID_DWORD_S; i++) { + printf("\t\t\t\t\t %08X\n", *sn_info.UID); sn_info.UID++; } - printf("\n"); printf("Status: \t\t\t\t%s\n", status[(sn_info.PSID_UID_valid_flags >> 4) & 0x3]); printf("Mask Read Mask Enable: \t\t\t0x%0x\n", (sn_info.PSID_UID_valid_flags >> 6) & 0x1); printf("Read Mask Request Enable: \t\t0x%0x\n", (sn_info.PSID_UID_valid_flags >> 7) & 0x1); printf("----------------- PSID info -------------------------------\n"); printf("Device PSID: \t\t\t\t0x"); - for (int i = 0; i < SWITCHTEC_PSID_DWORD_S; i++) { - printf("%08X", *sn_info.PSID0); + printf("%08X\n", *sn_info.PSID0); + sn_info.PSID0++; + for (int i = 1; i < SWITCHTEC_PSID_DWORD_S; i++) { + printf("\t\t\t\t\t %08X\n", *sn_info.PSID0); sn_info.PSID0++; } - printf("\n"); printf("Status: \t\t\t\t%s\n", status[(sn_info.PSID_UID_valid_flags) & 0x3]); printf("Read Mask Enable: \t\t\t0x%0x\n", (sn_info.PSID_UID_valid_flags >> 2) & 0x1); printf("Read Mask Request Enable: \t\t0x%0x\n", (sn_info.PSID_UID_valid_flags >> 3) & 0x1); diff --git a/inc/switchtec/diag.h b/inc/switchtec/diag.h index 7c657156..f82212bf 100644 --- a/inc/switchtec/diag.h +++ b/inc/switchtec/diag.h @@ -252,6 +252,23 @@ struct switchtec_gen5_diag_eye_run_in { uint32_t lane_mask[4]; }; +struct switchtec_gen6_diag_eye_run_in { + uint8_t sub_cmd; + uint8_t resvd1; + uint8_t timeout_disable; + uint8_t resvd2; + uint32_t lane_mask[4]; + uint8_t sar_sel; + uint8_t intleav_sel; + uint8_t vstep; + int8_t hstep; + uint8_t data_mode; + uint8_t eye_mode; + uint16_t resvd3; + uint32_t ref_timer_lwr; + uint32_t ref_timer_upp; +}; + struct switchtec_diag_cross_hair_in { uint8_t sub_cmd; uint8_t lane_id; diff --git a/inc/switchtec/mrpc.h b/inc/switchtec/mrpc.h index 84e7e403..d7d1b744 100644 --- a/inc/switchtec/mrpc.h +++ b/inc/switchtec/mrpc.h @@ -313,6 +313,9 @@ enum mrpc_sub_cmd { MRPC_EYE_CAP_STATUS_GEN5 = 1, MRPC_EYE_CAP_READ_GEN5 = 2, + MRPC_EYE_CAP_RUN_GEN6 = 3, + MRPC_EYE_CAP_READ_GEN6 = 4, + MRPC_CROSS_HAIR_ENABLE = 0, MRPC_CROSS_HAIR_DISABLE = 1, MRPC_CROSS_HAIR_GET = 2, diff --git a/inc/switchtec/switchtec.h b/inc/switchtec/switchtec.h index 0fded978..a021b34f 100644 --- a/inc/switchtec/switchtec.h +++ b/inc/switchtec/switchtec.h @@ -932,42 +932,42 @@ static inline const char *switchtec_ltssm_str_gen5(int ltssm, int show_minor) static inline const char *switchtec_ltssm_str_gen6(int ltssm_major) { switch(ltssm_major) { - case 0x00: return "DETECT_QUIET"; - case 0x01: return "DETECT_ACTIVE"; - case 0x02: return "POLL_ACTIVE"; - case 0x03: return "POLL_COMPLIANCE"; - case 0x04: return "POLL_CONFIG"; - case 0x05: return "PRE_DETECT_QUIET"; - case 0x06: return "DETECT_WAIT"; - case 0x07: return "CFG_LINKWD_START"; - case 0x08: return "CFG_LINKWD_ACEPT"; - case 0x09: return "CFG_LANENUM_WAI"; - case 0x0A: return "CFG_LANENUM_ACEPT"; - case 0x0B: return "CFG_COMPLETE"; - case 0x0C: return "CFG_IDLE"; - case 0x0D: return "RCVRY_LOCK"; - case 0x0E: return "RCVRY_SPEED"; - case 0x0F: return "RCVRY_RCVRCFG"; - case 0x10: return "RCVRY_IDLE"; - case 0x11: return "L0"; - case 0x12: return "L0S"; - case 0x13: return "L123_SEND_EIDLE"; - case 0x14: return "L1_IDLE"; - case 0x15: return "L2_IDLE"; - case 0x16: return "L2_WAKE"; - case 0x17: return "DISABLED_ENTRY"; - case 0x18: return "DISABLED_IDLE"; - case 0x19: return "DISABLED"; - case 0x1A: return "LPBK_ENTRY"; - case 0x1B: return "LPBK_ACTIVE"; - case 0x1C: return "LPBK_EXIT"; - case 0x1D: return "LPBK_EXIT_TIMEOUT"; - case 0x1E: return "HOT_RESET_ENTRY"; - case 0x1F: return "HOT_RESET"; - case 0x20: return "RCVRY_EQ0"; - case 0x21: return "RCVRY_EQ1"; - case 0x22: return "RCVRY_EQ2"; - case 0x23: return "RCVRY_EQ3"; + case 0x00: return "Detect (QUIET)"; + case 0x01: return "Detect (ACTIVE)"; + case 0x02: return "Polling (ACTIVE)"; + case 0x03: return "Polling (COMPLIANCE)"; + case 0x04: return "Polling (CONFIG)"; + case 0x05: return "Detect (PRE_DETECT_QUIET)"; + case 0x06: return "Detect (DETECT_WAIT)"; + case 0x07: return "Configuration (LINKWD_START)"; + case 0x08: return "Configuration (LINKWD_ACCEPT)"; + case 0x09: return "Configuration (LANENUM_WAIT)"; + case 0x0A: return "Configuration (LANENUM_ACCEPT)"; + case 0x0B: return "Configuration (COMPLETE)"; + case 0x0C: return "Configuration (IDLE)"; + case 0x0D: return "Recovery (LOCK)"; + case 0x0E: return "Recovery (SPEED)"; + case 0x0F: return "Recovery (RCVRCFG)"; + case 0x10: return "Recovery (IDLE)"; + case 0x11: return "L0 (ACTIVE)"; + case 0x12: return "L0s (IDLE)"; + case 0x13: return "L1/L2/L3 (SEND_EIDLE)"; + case 0x14: return "L1 (IDLE)"; + case 0x15: return "L2 (IDLE)"; + case 0x16: return "L2 (WAKE)"; + case 0x17: return "Disabled (ENTRY)"; + case 0x18: return "Disabled (IDLE)"; + case 0x19: return "Disabled"; + case 0x1A: return "Loopback (ENTRY)"; + case 0x1B: return "Loopback (ACTIVE)"; + case 0x1C: return "Loopback (EXIT)"; + case 0x1D: return "Loopback (EXIT_TIMEOUT)"; + case 0x1E: return "Hot Reset (ENTRY)"; + case 0x1F: return "Hot Reset"; + case 0x20: return "Recovery (EQ0)"; + case 0x21: return "Recovery (EQ1)"; + case 0x22: return "Recovery (EQ2)"; + case 0x23: return "Recovery (EQ3)"; default: return "UNKNOWN"; } } @@ -1519,6 +1519,25 @@ enum switchtec_diag_eye_data_mode { SWITCHTEC_DIAG_EYE_RATIO, }; +enum switchtec_diag_eye_data_mode_gen6 { + SWITCHTEC_DIAG_EYE_ADC, + SWITCHTEC_DIAG_EYE_FFE, + SWITCHTEC_DIAG_EYE_DFE, +}; + +enum switchtec_diag_eye_mode_gen6 { + SWITCHTEC_DIAG_EYE_FULL, + SWITCHTEC_DIAG_EYE_INTERLEAVE, + SWITCHTEC_DIAG_EYE_SAR, +}; + +enum switchtec_diag_eye_h_step { + SWITCHTEC_DIAG_EYE_ULTRA_FINE = 1, + SWITCHTEC_DIAG_EYE_FINE = 2, + SWITCHTEC_DIAG_EYE_MEDIUM = 3, + SWITCHTEC_DIAG_EYE_COARSE = 4, +}; + struct switchtec_gen5_diag_eye_status_in { uint8_t sub_cmd; uint8_t resvd1[3]; @@ -1574,6 +1593,18 @@ enum switchtec_diag_pattern_gen5 { SWITCHTEC_DIAG_GEN_5_PATTERN_PRBS_DISABLED, }; +enum switchtec_diag_pattern_gen6 { + SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_7, + SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_9, + SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_11, + SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_13, + SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_15, + SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_23, + SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_31, + SWITCHTEC_DIAG_GEN_6_PATTERN_PCIE_52_UI_JIT = 0x19, + SWITCHTEC_DIAG_GEN_6_PATTERN_PRBS_DISABLED = 0x1A, +}; + enum switchtec_diag_pattern_link_rate { SWITCHTEC_DIAG_PAT_LINK_DISABLED = 0, SWITCHTEC_DIAG_PAT_LINK_GEN1 = 1, @@ -1581,6 +1612,7 @@ enum switchtec_diag_pattern_link_rate { SWITCHTEC_DIAG_PAT_LINK_GEN3 = 3, SWITCHTEC_DIAG_PAT_LINK_GEN4 = 4, SWITCHTEC_DIAG_PAT_LINK_GEN5 = 5, + SWITCHTEC_DIAG_PAT_LINK_GEN6 = 6, }; enum switchtec_diag_ltssm_speed { @@ -1632,7 +1664,9 @@ int switchtec_diag_eye_read(struct switchtec_dev *dev, int lane_id, int bin, int* num_phases, double* ber_data); int switchtec_diag_eye_start(struct switchtec_dev *dev, int lane_mask[4], struct range *x_range, struct range *y_range, - int step_interval, int capture_depth); + int step_interval, int capture_depth, int sar_sel, + int intleav_sel, int hstep, int data_mode, + int eye_mode, uint64_t refclk, int vstep); int switchtec_diag_eye_fetch(struct switchtec_dev *dev, double *pixels, size_t pixel_cnt, int *lane_id); int switchtec_diag_eye_cancel(struct switchtec_dev *dev); diff --git a/lib/diag.c b/lib/diag.c index 354ff381..19e8a284 100644 --- a/lib/diag.c +++ b/lib/diag.c @@ -281,7 +281,9 @@ int switchtec_diag_eye_read(struct switchtec_dev *dev, int lane_id, */ int switchtec_diag_eye_start(struct switchtec_dev *dev, int lane_mask[4], struct range *x_range, struct range *y_range, - int step_interval, int capture_depth) + int step_interval, int capture_depth, int sar_sel, + int intleav_sel, int hstep, int data_mode, + int eye_mode, uint64_t refclk, int vstep) { int err, ret; if (switchtec_is_gen5(dev)) { @@ -295,6 +297,27 @@ int switchtec_diag_eye_start(struct switchtec_dev *dev, int lane_mask[4], .lane_mask[3] = lane_mask[3], }; + ret = switchtec_diag_eye_cmd_gen5(dev, &in, sizeof(in)); + err = errno; + errno = err; + return ret; + } else if (switchtec_is_gen6(dev)) { + struct switchtec_gen6_diag_eye_run_in in = { + .sub_cmd = MRPC_EYE_CAP_RUN_GEN6, + .timeout_disable = 1, + .lane_mask[0] = lane_mask[0], + .lane_mask[1] = lane_mask[1], + .lane_mask[2] = lane_mask[2], + .lane_mask[3] = lane_mask[3], + .sar_sel = sar_sel, + .intleav_sel = intleav_sel, + .vstep = vstep, + .data_mode = data_mode, + .eye_mode = eye_mode, + .ref_timer_lwr = refclk & 0xFFFFFFFF, + .ref_timer_upp = refclk >> 32, + }; + ret = switchtec_diag_eye_cmd_gen5(dev, &in, sizeof(in)); err = errno; errno = err; @@ -2481,12 +2504,23 @@ int switchtec_osa_dump_conf(struct switchtec_dev *dev, int stack_id) printf("%s", (osa_dmp_out.os_type_trig_link_rate >> 2) & 1 ? "GEN3," : ""); printf("%s", (osa_dmp_out.os_type_trig_link_rate >> 3) & 1 ? "GEN4," : ""); printf("%s\n", (osa_dmp_out.os_type_trig_link_rate >> 4) & 1 ? "GEN5" : ""); - - printf("os types: \t\t%s", osa_dmp_out.os_type_trig_os_types & 1 ? "TS1," : ""); - printf("%s", (osa_dmp_out.os_type_trig_os_types >> 1) & 1 ? "TS2," : ""); - printf("%s", (osa_dmp_out.os_type_trig_os_types >> 2) & 1 ? "FTS," : ""); - printf("%s\n", (osa_dmp_out.os_type_trig_os_types >> 3) & 1 ? "CTL_SKP" : ""); - + if (switchtec_is_gen6(dev)) + printf("%s\n", (osa_dmp_out.os_type_trig_link_rate >> 5) & 1 ? "GEN6" : ""); + + printf("os types: \t\t"); + if (switchtec_is_gen6(dev)) { + printf("%s", osa_dmp_out.os_type_trig_os_types & 1 ? "TS0," : ""); + printf("%s", (osa_dmp_out.os_type_trig_os_types >> 1) & 1 ? "TS1," : ""); + printf("%s", (osa_dmp_out.os_type_trig_os_types >> 2) & 1 ? "TS2," : ""); + printf("%s\n", (osa_dmp_out.os_type_trig_os_types >> 3) & 1 ? "FTS" : ""); + printf("%s\n", (osa_dmp_out.os_type_trig_os_types >> 4) & 1 ? "CTL_SKP" : ""); + } else { + printf("%s", osa_dmp_out.os_type_trig_os_types & 1 ? "TS1," : ""); + printf("%s", (osa_dmp_out.os_type_trig_os_types >> 1) & 1 ? "TS2," : ""); + printf("%s", (osa_dmp_out.os_type_trig_os_types >> 2) & 1 ? "FTS," : ""); + printf("%s\n", (osa_dmp_out.os_type_trig_os_types >> 3) & 1 ? "CTL_SKP" : ""); + } + printf("------- OS Pattern ---------------------\n"); printf("lanes: \t\t\t%s", osa_dmp_out.os_pat_trig_lane_mask & 1 ? "0," : ""); for (int i = 1; i < 16; i++) { @@ -2506,6 +2540,8 @@ int switchtec_osa_dump_conf(struct switchtec_dev *dev, int stack_id) printf("%s", (osa_dmp_out.os_pat_trig_link_rate >> 2) & 1 ? "GEN3," : ""); printf("%s", (osa_dmp_out.os_pat_trig_link_rate >> 3) & 1 ? "GEN4," : ""); printf("%s\n", (osa_dmp_out.os_pat_trig_link_rate >> 4) & 1 ? "GEN5" : ""); + if (switchtec_is_gen6(dev)) + printf("%s\n", (osa_dmp_out.os_type_trig_link_rate >> 5) & 1 ? "GEN6" : ""); printf("patttern: \t\t0x%08x %08x %08x %08x\n", osa_dmp_out.os_pat_trig_val_dw0, osa_dmp_out.os_pat_trig_val_dw1, osa_dmp_out.os_pat_trig_val_dw2, @@ -2536,9 +2572,15 @@ int switchtec_osa_dump_conf(struct switchtec_dev *dev, int stack_id) printf("direciton: \t\t%s", osa_dmp_out.capture_dir & 1 ? "RX," : ""); printf("%s\n", (osa_dmp_out.capture_dir >> 1) & 1 ? "TX" : ""); - printf("drop single os: \t%d: Single TS1, TS2, FTS and CTL_SKP OS's %s in the capture\n", - osa_dmp_out.capture_drop_os, - osa_dmp_out.capture_drop_os ? " excluded" : "included"); + if (switchtec_is_gen6(dev)) + printf("drop single os: \t%d: Single TS0, TS1, TS2, FTS and CTL_SKP OS's %s in the capture\n", + osa_dmp_out.capture_drop_os, + osa_dmp_out.capture_drop_os ? " excluded" : "included"); + else + printf("drop single os: \t%d: Single TS1, TS2, FTS and CTL_SKP OS's %s in the capture\n", + osa_dmp_out.capture_drop_os, + osa_dmp_out.capture_drop_os ? " excluded" : "included"); + printf("stop mode: \t\t%d: OSA will stop capturing after %s lane has stopped writing into %s allocated RAMs\n", osa_dmp_out.capture_stop_mode, osa_dmp_out.capture_stop_mode ? "all" : "any", @@ -2548,14 +2590,27 @@ int switchtec_osa_dump_conf(struct switchtec_dev *dev, int stack_id) osa_dmp_out.capture_snap_mode ? "until the RAM is full" : "according to the Post-Trigger Entries value"); printf("post-trigger entries: \t%d\n", osa_dmp_out.capture_post_trig_entries); - printf("os types: \t\t%s", (osa_dmp_out.capture_os_types & 1) ? "TS1," : ""); - printf("%s", (osa_dmp_out.capture_os_types >> 1) & 1 ? "TS2," : ""); - printf("%s", (osa_dmp_out.capture_os_types >> 2) & 1 ? "FTS," : ""); - printf("%s", (osa_dmp_out.capture_os_types >> 3) & 1 ? "CTL_SKP," : ""); - printf("%s", (osa_dmp_out.capture_os_types >> 4) & 1 ? "SKP," : ""); - printf("%s", (osa_dmp_out.capture_os_types >> 5) & 1 ? "EIEOS," : ""); - printf("%s", (osa_dmp_out.capture_os_types >> 6) & 1 ? "EIOS," : ""); - printf("%s", (osa_dmp_out.capture_os_types >> 7) & 1 ? "ERR_OS," : ""); + printf("os types: \t\t"); + if (switchtec_is_gen6(dev)) { + printf("%s", (osa_dmp_out.capture_os_types & 1) ? "TS0," : ""); + printf("%s", (osa_dmp_out.capture_os_types >> 1) & 1 ? "TS2," : ""); + printf("%s", (osa_dmp_out.capture_os_types >> 2) & 1 ? "TS2," : ""); + printf("%s", (osa_dmp_out.capture_os_types >> 3) & 1 ? "FTS," : ""); + printf("%s", (osa_dmp_out.capture_os_types >> 4) & 1 ? "CTL_SKP," : ""); + printf("%s", (osa_dmp_out.capture_os_types >> 5) & 1 ? "SKP," : ""); + printf("%s", (osa_dmp_out.capture_os_types >> 6) & 1 ? "EIEOS," : ""); + printf("%s", (osa_dmp_out.capture_os_types >> 7) & 1 ? "EIOS," : ""); + printf("%s", (osa_dmp_out.capture_os_types >> 8) & 1 ? "ERR_OS," : ""); + } else { + printf("%s", (osa_dmp_out.capture_os_types & 1) ? "TS1," : ""); + printf("%s", (osa_dmp_out.capture_os_types >> 1) & 1 ? "TS2," : ""); + printf("%s", (osa_dmp_out.capture_os_types >> 2) & 1 ? "FTS," : ""); + printf("%s", (osa_dmp_out.capture_os_types >> 3) & 1 ? "CTL_SKP," : ""); + printf("%s", (osa_dmp_out.capture_os_types >> 4) & 1 ? "SKP," : ""); + printf("%s", (osa_dmp_out.capture_os_types >> 5) & 1 ? "EIEOS," : ""); + printf("%s", (osa_dmp_out.capture_os_types >> 6) & 1 ? "EIOS," : ""); + printf("%s", (osa_dmp_out.capture_os_types >> 7) & 1 ? "ERR_OS," : ""); + } printf("\n"); return ret; } diff --git a/lib/fw.c b/lib/fw.c index d5e227de..33dbb790 100644 --- a/lib/fw.c +++ b/lib/fw.c @@ -306,7 +306,10 @@ static int set_redundant(struct switchtec_dev *dev, int type, int set) cmd.subcmd = MRPC_FWDNLD_SET_RDNDNT; cmd.redundant_val = set; - cmd.part_type = type; + if (switchtec_is_gen6(dev) && type != 1) + cmd.part_type = type - 1; + else + cmd.part_type = type; printf("%s redundant flag \t(%s)\n", set ? "Checking" : "Un-checking", part_types[type-1]); @@ -456,6 +459,7 @@ int switchtec_fw_toggle_active_partition(struct switchtec_dev *dev, { uint32_t cmd_id; size_t cmd_size; + int ret; struct { uint8_t subcmd; uint8_t toggle_fw; @@ -463,26 +467,40 @@ int switchtec_fw_toggle_active_partition(struct switchtec_dev *dev, uint8_t toggle_bl2; uint8_t toggle_key; uint8_t toggle_riotcore; + uint16_t reserved; } cmd; if (switchtec_boot_phase(dev) == SWITCHTEC_BOOT_PHASE_BL2) { + cmd_size = sizeof(cmd); cmd_id = get_fw_tx_id(dev); cmd.subcmd = MRPC_FW_TX_TOGGLE; - } else { - cmd_id = MRPC_FWDNLD; - cmd.subcmd = MRPC_FWDNLD_TOGGLE; + cmd.toggle_bl2 = !!toggle_bl2; + ret = switchtec_cmd(dev, cmd_id, &cmd, cmd_size, NULL, 0); + if (ret) + return ret; + cmd.toggle_bl2 = 0; + cmd.toggle_fw = !!toggle_fw; + ret = switchtec_cmd(dev, cmd_id, &cmd, cmd_size, NULL, 0); + if (ret) + return ret; + cmd.toggle_fw = 0; + cmd.toggle_cfg = !!toggle_cfg; + ret = switchtec_cmd(dev, cmd_id, &cmd, cmd_size, NULL, 0); + if (ret) + return ret; + + return 0; } - + + cmd_id = MRPC_FWDNLD; + cmd.subcmd = MRPC_FWDNLD_TOGGLE; cmd.toggle_bl2 = !!toggle_bl2; cmd.toggle_key = !!toggle_key; cmd.toggle_fw = !!toggle_fw; cmd.toggle_cfg = !!toggle_cfg; - if (switchtec_is_gen5(dev)) { + if (switchtec_is_gen5(dev)) cmd.toggle_riotcore = !!toggle_riotcore; - cmd_size = sizeof(cmd); - } else { - cmd_size = sizeof(cmd) - 1; - } + cmd_size = sizeof(cmd); return switchtec_cmd(dev, cmd_id, &cmd, cmd_size, NULL, 0); @@ -1056,6 +1074,8 @@ int switchtec_fw_file_info(int fd, struct switchtec_fw_image_info *info) return switchtec_fw_file_info_gen3(fd, info); } else if (!strncmp(magic, "MSCC", sizeof(magic))) { return switchtec_fw_file_info_gen45(fd, info); + } else if (!strncmp(magic, "DCBI", sizeof(magic))) { + return 1; } else { errno = ENOEXEC; return -1; @@ -1443,12 +1463,12 @@ struct switchtec_flash_info_gen6 { uint8_t running_cfg_flag; uint8_t running_img_flag; uint8_t running_key_flag; - uint8_t rsvd2[3]; + uint8_t rsvd2[4]; uint8_t key_redundant_flag; uint8_t bl2_redundant_flag; uint8_t cfg_redundant_flag; uint8_t img_redundant_flag; - uint8_t rsvd3[3]; + uint8_t rsvd3[2]; uint32_t rsvd4[9]; struct switchtec_flash_part_info_gen4 map0, map1, keyman0, keyman1, bl20, bl21, cfg0, cfg1, img0, img1, @@ -1629,27 +1649,35 @@ static int switchtec_fw_part_info_gen6(struct switchtec_dev *dev, part_info = &all->map1; break; case SWITCHTEC_FW_PART_ID_G6_KEY0: + inf->redundant = all->key_redundant_flag; part_info = &all->keyman0; break; case SWITCHTEC_FW_PART_ID_G6_KEY1: + inf->redundant = all->key_redundant_flag; part_info = &all->keyman1; break; case SWITCHTEC_FW_PART_ID_G6_BL20: + inf->redundant = all->bl2_redundant_flag; part_info = &all->bl20; break; case SWITCHTEC_FW_PART_ID_G6_BL21: + inf->redundant = all->bl2_redundant_flag; part_info = &all->bl21; break; case SWITCHTEC_FW_PART_ID_G6_IMG0: + inf->redundant = all->img_redundant_flag; part_info = &all->img0; break; case SWITCHTEC_FW_PART_ID_G6_IMG1: + inf->redundant = all->img_redundant_flag; part_info = &all->img1; break; case SWITCHTEC_FW_PART_ID_G6_CFG0: + inf->redundant = all->cfg_redundant_flag; part_info = &all->cfg0; break; case SWITCHTEC_FW_PART_ID_G6_CFG1: + inf->redundant = all->cfg_redundant_flag; part_info = &all->cfg1; break; case SWITCHTEC_FW_PART_ID_G6_NVLOG: diff --git a/lib/switchtec.c b/lib/switchtec.c index 0ba402b0..4f93dc1a 100644 --- a/lib/switchtec.c +++ b/lib/switchtec.c @@ -471,6 +471,20 @@ static const char *lane_reversal_str(int link_up, } } +static const char *lane_reversal_str_gen6(int link_up, + int lane_reversal) +{ + if (!link_up) + return "N/A"; + + switch(lane_reversal) { + case 0: return "Normal Lane Ordering"; + case 1: return "Lane Reversal in effect"; + default: return "Unknown Lane Ordering"; + } +} + + static void generate_lane_str(struct switchtec_status *s) { int i, l; @@ -498,19 +512,8 @@ static void generate_lane_str(struct switchtec_status *s) } } -/** - * @brief Get the status of all the ports on a switchtec device - * @param[in] dev Switchtec device handle - * @param[out] status A pointer to an allocated list of port statuses - * @return The number of ports in the status list or a negative value - * on failure - * - * This function a allocates memory for the number of ports in the - * system. The returned \p status structure should be freed with the - * switchtec_status_free() function. - */ -int switchtec_status(struct switchtec_dev *dev, - struct switchtec_status **status) +static int switchtec_status_gen345(struct switchtec_dev *dev, + struct switchtec_status **status) { uint64_t port_bitmap = 0; int ret; @@ -588,6 +591,115 @@ int switchtec_status(struct switchtec_dev *dev, return nr_ports; } +static int switchtec_status_gen6(struct switchtec_dev *dev, + struct switchtec_status **status) +{ + struct { + uint64_t map1; + uint16_t map2; + uint16_t rsvrd1; + uint32_t rsvrd2; + } port_bitmap = { + .map1 = 0, + .map2 = 0 + }; + + int ret; + int i, p; + int nr_ports = 0; + struct switchtec_status *s; + int max_ports; + + if (!status) { + errno = EINVAL; + return -errno; + } + + max_ports = switchtec_max_supported_ports(dev); + + struct { + uint8_t phys_port_id; + uint8_t par_id; + uint8_t log_port_id; + uint8_t stk_id; + uint8_t cfg_lnk_width; + uint8_t neg_lnk_width; + uint8_t usp_flag; + uint8_t linkup_linkrate; + uint8_t ltssm_major; + uint8_t ltssm_minor; + uint8_t lane_reversal; + uint8_t first_act_lane; + } ports[max_ports]; + + ret = switchtec_cmd(dev, MRPC_LNKSTAT, &port_bitmap, sizeof(port_bitmap), + ports, sizeof(ports)); + if (ret) + return -1; + + + for (i = 0; i < max_ports; i++) { + if ((ports[i].stk_id >> 4) > SWITCHTEC_MAX_STACKS) + continue; + nr_ports++; + } + + s = *status = calloc(nr_ports, sizeof(*s)); + if (!s) + return -ENOMEM; + + for (i = 0, p = 0; i < max_ports && p < nr_ports; i++) { + if ((ports[i].stk_id >> 4) > SWITCHTEC_MAX_STACKS) + continue; + + s[p].port.partition = ports[i].par_id; + s[p].port.stack = ports[i].stk_id >> 4; + s[p].port.upstream = ports[i].usp_flag; + s[p].port.stk_id = ports[i].stk_id & 0xF; + s[p].port.phys_id = ports[i].phys_port_id; + s[p].port.log_id = ports[i].log_port_id; + + s[p].cfg_lnk_width = ports[i].cfg_lnk_width; + s[p].neg_lnk_width = ports[i].neg_lnk_width; + s[p].link_up = ports[i].linkup_linkrate >> 7; + s[p].link_rate = ports[i].linkup_linkrate & 0x7F; + s[p].ltssm = le16toh(ports[i].ltssm_major); + s[p].ltssm_str = switchtec_ltssm_str(s[p].ltssm, 1, dev); + s[p].lane_reversal = ports[i].lane_reversal; + s[p].lane_reversal_str = lane_reversal_str_gen6(s[p].link_up, + s[p].lane_reversal); + s[p].first_act_lane = ports[i].first_act_lane & 0xF; + s[p].acs_ctrl = -1; + generate_lane_str(&s[p]); + + p++; + } + + qsort(s, nr_ports, sizeof(*s), compare_status); + + return nr_ports; +} + +/** + * @brief Get the status of all the ports on a switchtec device + * @param[in] dev Switchtec device handle + * @param[out] status A pointer to an allocated list of port statuses + * @return The number of ports in the status list or a negative value + * on failure + * + * This function a allocates memory for the number of ports in the + * system. The returned \p status structure should be freed with the + * switchtec_status_free() function. + */ +int switchtec_status(struct switchtec_dev *dev, + struct switchtec_status **status) +{ + if (switchtec_is_gen6(dev)) + return switchtec_status_gen6(dev, status); + else + return switchtec_status_gen345(dev, status); +} + /** * @brief Free a list of status structures allocated by switchtec_status() * @param[in] status Status structure list