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,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 ;
0 commit comments