Skip to content

Commit 2f980a4

Browse files
Chetana2791BenReed161
authored andcommitted
Add support for Gen5 Eye capture
Updated eye command gen5 mrpc. Add gen5 eye mrpc calls to original switchtec user eye command and added gen5 detection as part of the function.
1 parent a9979d2 commit 2f980a4

File tree

7 files changed

+300
-40
lines changed

7 files changed

+300
-40
lines changed

cli/diag.c

Lines changed: 165 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
#include <switchtec/switchtec.h>
3333
#include <switchtec/utils.h>
34+
#include <switchtec/endian.h>
3435

3536
#include <limits.h>
3637
#include <locale.h>
@@ -325,7 +326,9 @@ static void print_eye_csv(FILE *f, struct range *X, struct range *Y,
325326
int x, y, i, j = 0;
326327

327328
fprintf(f, "%s\n", title);
328-
fprintf(f, "interval_ms, %d\n", interval);
329+
330+
if (interval > -1)
331+
fprintf(f, "interval_ms, %d\n", interval);
329332

330333
for_range(x, X)
331334
fprintf(f, ", %d", x);
@@ -1190,7 +1193,7 @@ static double *eye_observe_dev(struct switchtec_dev *dev, int port_id,
11901193
goto out_err;
11911194
}
11921195

1193-
ret = switchtec_diag_eye_start(dev, lane_mask, X, Y, interval);
1196+
ret = switchtec_diag_eye_start(dev, lane_mask, X, Y, interval, 0);
11941197
if (ret) {
11951198
switchtec_perror("eye_start");
11961199
goto out_err;
@@ -1249,7 +1252,8 @@ static double *eye_observe_dev(struct switchtec_dev *dev, int port_id,
12491252

12501253
static int eye_graph(enum output_format fmt, struct range *X, struct range *Y,
12511254
double *pixels, const char *title,
1252-
struct switchtec_diag_cross_hair *ch)
1255+
struct switchtec_diag_cross_hair *ch,
1256+
struct switchtec_dev *dev)
12531257
{
12541258
size_t pixel_cnt = RANGE_CNT(X) * RANGE_CNT(Y);
12551259
int data[pixel_cnt], shades[pixel_cnt];
@@ -1277,14 +1281,131 @@ static int eye_graph(enum output_format fmt, struct range *X, struct range *Y,
12771281
}
12781282

12791283
if (fmt == FMT_TEXT) {
1280-
graph_draw_text(X, Y, data, title, 'T', 'V');
1284+
if (switchtec_is_gen5(dev))
1285+
graph_draw_text_no_invert(X, Y, data, title, 'P', 'B');
1286+
else
1287+
graph_draw_text(X, Y, data, title, 'T', 'V');
12811288
if (status_ptr)
12821289
printf("\n %s\n", status_ptr);
12831290
return 0;
12841291
}
12851292

1286-
return graph_draw_win(X, Y, data, shades, title, 'T', 'V',
1287-
status_ptr, NULL, NULL);
1293+
if (switchtec_is_gen5(dev))
1294+
return graph_draw_win(X, Y, data, shades, title, 'P', 'B',
1295+
status_ptr, NULL, NULL);
1296+
else
1297+
return graph_draw_win(X, Y, data, shades, title, 'T', 'V',
1298+
status_ptr, NULL, NULL);
1299+
}
1300+
1301+
static int switchtec_gen5_diag_eye_read(struct switchtec_dev *dev, int lane_id,
1302+
int bin, int* num_phases, double* ber_data)
1303+
{
1304+
struct switchtec_gen5_diag_eye_read_in in = {
1305+
.sub_cmd = MRPC_EYE_CAP_READ_GEN5,
1306+
.lane_id = lane_id,
1307+
.bin = bin,
1308+
};
1309+
struct switchtec_gen5_diag_eye_read_out out;
1310+
int i, ret;
1311+
1312+
ret = switchtec_cmd(dev, MRPC_GEN5_EYE_CAPTURE, &in, sizeof(in),
1313+
&out, sizeof(out));
1314+
if (ret)
1315+
return ret;
1316+
1317+
*num_phases = out.num_phases;
1318+
1319+
for(i = 0; i < out.num_phases; i++) {
1320+
ber_data[i] = le64toh(out.ber_data[i]) / 281474976710656.;
1321+
}
1322+
1323+
return ret;
1324+
}
1325+
1326+
static double *eye_capture_dev_gen5(struct switchtec_dev *dev,
1327+
int port_id, int lane_id, int num_lanes,
1328+
int capture_depth, int* num_phases, int* gen)
1329+
{
1330+
int bin, j, ret, eye_status, first_lane, num_phases_l, stride;
1331+
int lane_mask[4] = {};
1332+
struct switchtec_status sw_status;
1333+
double tmp[60];
1334+
double* ber_data = NULL;
1335+
struct switchtec_gen5_diag_eye_status_in in = {
1336+
.sub_cmd = MRPC_EYE_CAP_STATUS_GEN5,
1337+
};
1338+
struct switchtec_gen5_diag_eye_status_out out;
1339+
1340+
ret = switchtec_calc_lane_mask(dev, port_id, lane_id, num_lanes,
1341+
lane_mask, &sw_status);
1342+
if (ret < 0) {
1343+
switchtec_perror("Invalid lane");
1344+
return NULL;
1345+
}
1346+
1347+
ret = switchtec_diag_eye_start(dev, lane_mask, NULL, NULL, 0,
1348+
capture_depth);
1349+
if (ret) {
1350+
switchtec_perror("eye_run");
1351+
return NULL;
1352+
}
1353+
1354+
do {
1355+
ret = switchtec_cmd(dev, MRPC_GEN5_EYE_CAPTURE, &in, sizeof(in),
1356+
&out, sizeof(out));
1357+
if (ret) {
1358+
switchtec_perror("eye_status");
1359+
return NULL;
1360+
}
1361+
eye_status = out.status;
1362+
usleep(200000);
1363+
} while (eye_status == SWITCHTEC_GEN5_DIAG_EYE_STATUS_IN_PROGRESS ||
1364+
eye_status == SWITCHTEC_GEN5_DIAG_EYE_STATUS_PENDING);
1365+
1366+
switch (eye_status) {
1367+
case SWITCHTEC_GEN5_DIAG_EYE_STATUS_IDLE:
1368+
switchtec_perror("Eye capture idle");
1369+
case SWITCHTEC_GEN5_DIAG_EYE_STATUS_DONE:
1370+
break;
1371+
case SWITCHTEC_GEN5_DIAG_EYE_STATUS_TIMEOUT:
1372+
switchtec_perror("Eye capture timeout");
1373+
case SWITCHTEC_GEN5_DIAG_EYE_STATUS_ERROR:
1374+
switchtec_perror("Eye capture error");
1375+
return NULL;
1376+
}
1377+
1378+
first_lane = switchtec_calc_lane_id(dev, port_id, lane_id, NULL);
1379+
for (j = 0; j < num_lanes; j++) {
1380+
for (bin = 0; bin < 64; bin++) {
1381+
ret = switchtec_gen5_diag_eye_read(dev, first_lane + j,
1382+
bin, &num_phases_l,
1383+
tmp);
1384+
if (ret) {
1385+
switchtec_perror("eye_read");
1386+
if (ber_data)
1387+
free(ber_data);
1388+
return NULL;
1389+
}
1390+
1391+
if (!ber_data) {
1392+
stride = 64 * num_phases_l;
1393+
ber_data = calloc(num_lanes * stride,
1394+
sizeof(double));
1395+
if (!ber_data) {
1396+
perror("allocating BER data");
1397+
return NULL;
1398+
}
1399+
}
1400+
1401+
memcpy(&ber_data[(j * stride) + (bin * num_phases_l)],
1402+
tmp, num_phases_l * sizeof(double));
1403+
}
1404+
}
1405+
1406+
*gen = sw_status.link_rate;
1407+
*num_phases = num_phases_l;
1408+
return ber_data;
12881409
}
12891410

12901411
#define CMD_DESC_EYE "Capture PCIe Eye Errors"
@@ -1294,13 +1415,14 @@ static int eye(int argc, char **argv)
12941415
struct switchtec_diag_cross_hair ch = {}, *ch_ptr = NULL;
12951416
char title[128], subtitle[50];
12961417
double *pixels = NULL;
1297-
int ret, gen;
1418+
int num_phases, ret, gen;
12981419

12991420
static struct {
13001421
struct switchtec_dev *dev;
13011422
int fmt;
13021423
int port_id;
13031424
int lane_id;
1425+
int capture_depth;
13041426
int num_lanes;
13051427
int mode;
13061428
struct range x_range, y_range;
@@ -1313,6 +1435,7 @@ static int eye(int argc, char **argv)
13131435
.fmt = FMT_DEFAULT,
13141436
.port_id = -1,
13151437
.lane_id = 0,
1438+
.capture_depth = 24,
13161439
.num_lanes = 1,
13171440
.mode = SWITCHTEC_DIAG_EYE_RAW,
13181441
.x_range.start = 0,
@@ -1327,7 +1450,7 @@ static int eye(int argc, char **argv)
13271450
DEVICE_OPTION_OPTIONAL,
13281451
{"crosshair", 'C', "FILE", CFG_FILE_R, &cfg.crosshair_file,
13291452
required_argument,
1330-
"optionally, superimpose a crosshair CSV onto the result"},
1453+
"optionally, superimpose a crosshair CSV onto the result (Not supported in Gen 5)"},
13311454
{"format", 'f', "FMT", CFG_CHOICES, &cfg.fmt, required_argument,
13321455
"output format (default: " FMT_DEFAULT_STR ")",
13331456
.choices=output_fmt_choices},
@@ -1357,12 +1480,24 @@ static int eye(int argc, char **argv)
13571480
required_argument, "voltage step (default: 5)"},
13581481
{"interval", 'i', "NUM", CFG_NONNEGATIVE, &cfg.step_interval,
13591482
required_argument, "step interval in ms (default: 1ms)"},
1483+
{"capture-depth", 'd', "NUM", CFG_POSITIVE, &cfg.capture_depth,
1484+
required_argument, "capture depth (6 to 40; default: 24)"},
13601485
{NULL}};
13611486

13621487
argconfig_parse(argc, argv, CMD_DESC_EYE, opts, &cfg,
13631488
sizeof(cfg));
13641489

1490+
if (cfg.dev != NULL && switchtec_is_gen5(cfg.dev)) {
1491+
cfg.y_range.start = 0;
1492+
cfg.y_range.end = 63;
1493+
cfg.y_range.step = 1;
1494+
}
1495+
13651496
if (cfg.crosshair_file) {
1497+
if (switchtec_is_gen5(cfg.dev)) {
1498+
fprintf(stderr, "Crosshair superimpose not suppored in Gen 5\n");
1499+
return -1;
1500+
}
13661501
ret = load_crosshair_csv(cfg.crosshair_file, &ch, subtitle,
13671502
sizeof(subtitle));
13681503
if (ret) {
@@ -1373,11 +1508,11 @@ static int eye(int argc, char **argv)
13731508

13741509
ch_ptr = &ch;
13751510
}
1376-
1511+
13771512
if (cfg.plot_file) {
13781513
pixels = load_eye_csv(cfg.plot_file, &cfg.x_range,
1379-
&cfg.y_range, subtitle, sizeof(subtitle),
1380-
&cfg.step_interval);
1514+
&cfg.y_range, subtitle, sizeof(subtitle),
1515+
&cfg.step_interval);
13811516
if (!pixels) {
13821517
fprintf(stderr, "Unable to parse CSV file: %s\n",
13831518
cfg.plot_filename);
@@ -1433,12 +1568,25 @@ static int eye(int argc, char **argv)
14331568
}
14341569

14351570
if (!pixels) {
1436-
pixels = eye_observe_dev(cfg.dev, cfg.port_id, cfg.lane_id,
1437-
cfg.num_lanes, cfg.mode, cfg.step_interval,
1438-
&cfg.x_range, &cfg.y_range, &gen);
1439-
if (!pixels)
1440-
return -1;
1571+
if (switchtec_is_gen5(cfg.dev)) {
1572+
pixels = eye_capture_dev_gen5(cfg.dev, cfg.port_id,
1573+
cfg.lane_id, cfg.num_lanes,
1574+
cfg.capture_depth,
1575+
&num_phases, &gen);
1576+
if (!pixels)
1577+
return -1;
14411578

1579+
cfg.x_range.end = num_phases - 1;
1580+
}
1581+
else {
1582+
pixels = eye_observe_dev(cfg.dev, cfg.port_id,
1583+
cfg.lane_id, cfg.num_lanes,
1584+
cfg.mode, cfg.step_interval,
1585+
&cfg.x_range, &cfg.y_range,
1586+
&gen);
1587+
if (!pixels)
1588+
return -1;
1589+
}
14421590
eye_set_title(title, cfg.port_id, cfg.lane_id, gen);
14431591
}
14441592

@@ -1451,7 +1599,7 @@ static int eye(int argc, char **argv)
14511599
}
14521600

14531601
ret = eye_graph(cfg.fmt, &cfg.x_range, &cfg.y_range, pixels, title,
1454-
ch_ptr);
1602+
ch_ptr, cfg.dev);
14551603

14561604
free(pixels);
14571605
return ret;

cli/graph.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,15 @@ void graph_init(void)
390390

391391
#endif /* defined(HAVE_LIBCURSES) || defined(HAVE_LIBNCURSES) */
392392

393+
int graph_draw_win_no_invert(struct range *X, struct range *Y, int *data,
394+
int *shades, const char *title, char x_title, char y_title,
395+
char *status, graph_anim_fn *anim, void *opaque)
396+
{
397+
graph_draw_text_no_invert(X, Y, data, title, x_title, y_title);
398+
return 0;
399+
}
400+
401+
393402
void graph_draw_text(struct range *X, struct range *Y, int *data,
394403
const char *title, char x_title, char y_title)
395404
{
@@ -428,3 +437,43 @@ void graph_draw_text(struct range *X, struct range *Y, int *data,
428437
j--;
429438
}
430439
}
440+
441+
void graph_draw_text_no_invert(struct range *X, struct range *Y,
442+
int *data, const char *title, char x_title, char y_title)
443+
{
444+
int stride = RANGE_CNT(X);
445+
int x, y, i = RANGE_CNT(Y) - 1;
446+
int j = Y->start;
447+
int space_ch;
448+
449+
printf(" %s\n\n", title);
450+
451+
printf(" ");
452+
for_range(x, X)
453+
printf("%d ", x / 10);
454+
printf("\n");
455+
456+
printf(" ");
457+
for_range(x, X)
458+
printf("%d ", x % 10);
459+
printf("\n\n");
460+
461+
for_range(y, Y) {
462+
printf("%5d ", y);
463+
i = 0;
464+
for_range(x, X) {
465+
space_ch = ' ';
466+
if (data[j * stride + i] == GRAPH_TEXT_HLINE ||
467+
data[j * stride + i] == GRAPH_TEXT_PLUS)
468+
space_ch = GRAPH_TEXT_HLINE;
469+
else if (data[j * stride + i] == '-' ||
470+
data[j * stride + i] == '+')
471+
space_ch = '-';
472+
473+
printf("%lc%lc", data[j * stride + i], space_ch);
474+
i++;
475+
}
476+
printf("\n");
477+
j++;
478+
}
479+
}

cli/graph.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,5 +68,9 @@ void graph_draw_text(struct range *X, struct range *Y, int *data,
6868
int graph_draw_win(struct range *X, struct range *Y, int *data, int *shades,
6969
const char *title, char x_title, char y_title, char *status,
7070
graph_anim_fn *anim, void *opaque);
71-
71+
void graph_draw_text_no_invert(struct range *X, struct range *Y,
72+
int *data, const char *title, char x_title, char y_title);
73+
int graph_draw_win_no_invert(struct range *X, struct range *Y, int *data,
74+
int *shades, const char *title, char x_title, char y_title,
75+
char *status, graph_anim_fn *anim, void *opaque);
7276
#endif

inc/switchtec/diag.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,15 @@ struct switchtec_diag_port_eye_fetch {
242242
};
243243
};
244244

245+
246+
struct switchtec_gen5_diag_eye_run_in {
247+
uint8_t sub_cmd;
248+
uint8_t capture_depth;
249+
uint8_t timeout_disable;
250+
uint8_t resvd1;
251+
uint32_t lane_mask[4];
252+
};
253+
245254
struct switchtec_diag_cross_hair_in {
246255
uint8_t sub_cmd;
247256
uint8_t lane_id;

inc/switchtec/mrpc.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,8 @@ enum mrpc_cmd {
124124
MRPC_SN_VER_GET_GEN5 = 0x119,
125125
MRPC_DBG_UNLOCK_GEN5 = 0x11A,
126126
MRPC_BOOTUP_RESUME_GEN5 = 0x11B,
127+
MRPC_GEN5_EYE_CAPTURE = 0x142,
127128
MRPC_FTDC_LOG_DUMP = 0x147,
128-
129129
MRPC_MAX_ID = 0x148,
130130
};
131131

@@ -280,6 +280,10 @@ enum mrpc_sub_cmd {
280280
MRPC_EYE_OBSERVE_SET_DATA_MODE = 3,
281281
MRPC_EYE_OBSERVE_GET_DATA_MODE = 4,
282282

283+
MRPC_EYE_CAP_RUN_GEN5 = 0,
284+
MRPC_EYE_CAP_STATUS_GEN5 = 1,
285+
MRPC_EYE_CAP_READ_GEN5 = 2,
286+
283287
MRPC_CROSS_HAIR_ENABLE = 0,
284288
MRPC_CROSS_HAIR_DISABLE = 1,
285289
MRPC_CROSS_HAIR_GET = 2,

0 commit comments

Comments
 (0)