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
12501253static 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,77 @@ 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 double * eye_capture_dev_gen5 (struct switchtec_dev * dev ,
1302+ int port_id , int lane_id , int num_lanes ,
1303+ int capture_depth , int * num_phases , int * gen )
1304+ {
1305+ int bin , j , ret , first_lane , num_phases_l , stride ;
1306+ int lane_mask [4 ] = {};
1307+ struct switchtec_status sw_status ;
1308+ double tmp [60 ];
1309+ double * ber_data = NULL ;
1310+
1311+ ret = switchtec_calc_lane_mask (dev , port_id , lane_id , num_lanes ,
1312+ lane_mask , & sw_status );
1313+ if (ret < 0 ) {
1314+ switchtec_perror ("Invalid lane" );
1315+ return NULL ;
1316+ }
1317+
1318+ ret = switchtec_diag_eye_start (dev , lane_mask , NULL , NULL , 0 ,
1319+ capture_depth );
1320+ if (ret ) {
1321+ switchtec_perror ("eye_run" );
1322+ return NULL ;
1323+ }
1324+
1325+ first_lane = switchtec_calc_lane_id (dev , port_id , lane_id , NULL );
1326+ for (j = 0 ; j < num_lanes ; j ++ ) {
1327+ for (bin = 0 ; bin < 64 ; bin ++ ) {
1328+ ret = switchtec_diag_eye_read (dev , first_lane + j , bin ,
1329+ & num_phases_l , tmp );
1330+ if (ret ) {
1331+ switchtec_perror ("eye_read" );
1332+ if (ber_data )
1333+ free (ber_data );
1334+ return NULL ;
1335+ }
1336+
1337+ if (!ber_data ) {
1338+ stride = 64 * num_phases_l ;
1339+ ber_data = calloc (num_lanes * stride ,
1340+ sizeof (double ));
1341+ if (!ber_data ) {
1342+ perror ("allocating BER data" );
1343+ return NULL ;
1344+ }
1345+ }
1346+
1347+ memcpy (& ber_data [(j * stride ) + (bin * num_phases_l )],
1348+ tmp , num_phases_l * sizeof (double ));
1349+ }
1350+ }
1351+
1352+ * gen = sw_status .link_rate ;
1353+ * num_phases = num_phases_l ;
1354+ return ber_data ;
12881355}
12891356
12901357#define CMD_DESC_EYE "Capture PCIe Eye Errors"
@@ -1294,13 +1361,14 @@ static int eye(int argc, char **argv)
12941361 struct switchtec_diag_cross_hair ch = {}, * ch_ptr = NULL ;
12951362 char title [128 ], subtitle [50 ];
12961363 double * pixels = NULL ;
1297- int ret , gen ;
1364+ int num_phases , ret , gen ;
12981365
12991366 static struct {
13001367 struct switchtec_dev * dev ;
13011368 int fmt ;
13021369 int port_id ;
13031370 int lane_id ;
1371+ int capture_depth ;
13041372 int num_lanes ;
13051373 int mode ;
13061374 struct range x_range , y_range ;
@@ -1313,6 +1381,7 @@ static int eye(int argc, char **argv)
13131381 .fmt = FMT_DEFAULT ,
13141382 .port_id = -1 ,
13151383 .lane_id = 0 ,
1384+ .capture_depth = 24 ,
13161385 .num_lanes = 1 ,
13171386 .mode = SWITCHTEC_DIAG_EYE_RAW ,
13181387 .x_range .start = 0 ,
@@ -1327,7 +1396,7 @@ static int eye(int argc, char **argv)
13271396 DEVICE_OPTION_OPTIONAL ,
13281397 {"crosshair" , 'C' , "FILE" , CFG_FILE_R , & cfg .crosshair_file ,
13291398 required_argument ,
1330- "optionally, superimpose a crosshair CSV onto the result" },
1399+ "optionally, superimpose a crosshair CSV onto the result (Not supported in Gen 5) " },
13311400 {"format" , 'f' , "FMT" , CFG_CHOICES , & cfg .fmt , required_argument ,
13321401 "output format (default: " FMT_DEFAULT_STR ")" ,
13331402 .choices = output_fmt_choices },
@@ -1357,12 +1426,24 @@ static int eye(int argc, char **argv)
13571426 required_argument , "voltage step (default: 5)" },
13581427 {"interval" , 'i' , "NUM" , CFG_NONNEGATIVE , & cfg .step_interval ,
13591428 required_argument , "step interval in ms (default: 1ms)" },
1429+ {"capture-depth" , 'd' , "NUM" , CFG_POSITIVE , & cfg .capture_depth ,
1430+ required_argument , "capture depth (6 to 40; default: 24)" },
13601431 {NULL }};
13611432
13621433 argconfig_parse (argc , argv , CMD_DESC_EYE , opts , & cfg ,
13631434 sizeof (cfg ));
13641435
1436+ if (cfg .dev != NULL && switchtec_is_gen5 (cfg .dev )) {
1437+ cfg .y_range .start = 0 ;
1438+ cfg .y_range .end = 63 ;
1439+ cfg .y_range .step = 1 ;
1440+ }
1441+
13651442 if (cfg .crosshair_file ) {
1443+ if (switchtec_is_gen5 (cfg .dev )) {
1444+ fprintf (stderr , "Crosshair superimpose not suppored in Gen 5\n" );
1445+ return -1 ;
1446+ }
13661447 ret = load_crosshair_csv (cfg .crosshair_file , & ch , subtitle ,
13671448 sizeof (subtitle ));
13681449 if (ret ) {
@@ -1373,11 +1454,11 @@ static int eye(int argc, char **argv)
13731454
13741455 ch_ptr = & ch ;
13751456 }
1376-
1457+
13771458 if (cfg .plot_file ) {
13781459 pixels = load_eye_csv (cfg .plot_file , & cfg .x_range ,
1379- & cfg .y_range , subtitle , sizeof (subtitle ),
1380- & cfg .step_interval );
1460+ & cfg .y_range , subtitle , sizeof (subtitle ),
1461+ & cfg .step_interval );
13811462 if (!pixels ) {
13821463 fprintf (stderr , "Unable to parse CSV file: %s\n" ,
13831464 cfg .plot_filename );
@@ -1433,12 +1514,25 @@ static int eye(int argc, char **argv)
14331514 }
14341515
14351516 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 ;
1517+ if (switchtec_is_gen5 (cfg .dev )) {
1518+ pixels = eye_capture_dev_gen5 (cfg .dev , cfg .port_id ,
1519+ cfg .lane_id , cfg .num_lanes ,
1520+ cfg .capture_depth ,
1521+ & num_phases , & gen );
1522+ if (!pixels )
1523+ return -1 ;
14411524
1525+ cfg .x_range .end = num_phases - 1 ;
1526+ }
1527+ else {
1528+ pixels = eye_observe_dev (cfg .dev , cfg .port_id ,
1529+ cfg .lane_id , cfg .num_lanes ,
1530+ cfg .mode , cfg .step_interval ,
1531+ & cfg .x_range , & cfg .y_range ,
1532+ & gen );
1533+ if (!pixels )
1534+ return -1 ;
1535+ }
14421536 eye_set_title (title , cfg .port_id , cfg .lane_id , gen );
14431537 }
14441538
@@ -1451,7 +1545,7 @@ static int eye(int argc, char **argv)
14511545 }
14521546
14531547 ret = eye_graph (cfg .fmt , & cfg .x_range , & cfg .y_range , pixels , title ,
1454- ch_ptr );
1548+ ch_ptr , cfg . dev );
14551549
14561550 free (pixels );
14571551 return ret ;
0 commit comments