@@ -2026,6 +2026,109 @@ static int refclk(int argc, char **argv)
20262026 return 0 ;
20272027}
20282028
2029+ static int convert_str_to_dwords (char * str , uint32_t * * dwords , int * num_dwords )
2030+ {
2031+ * num_dwords = 0 ;
2032+ const char * ptr = str ;
2033+ int dword_len = 0 ;
2034+ while (* ptr != '\0' ) {
2035+ if (* ptr == '0' && * (ptr + 1 ) == 'x' ) {
2036+ (* num_dwords )++ ;
2037+ ptr += 2 ;
2038+ dword_len = 0 ;
2039+ }
2040+ while (* ptr != ' ' && * ptr != '\0' ) {
2041+ ptr ++ ;
2042+ dword_len ++ ;
2043+ }
2044+ if (dword_len > 8 ) {
2045+ printf ("Entered dword longer than allowed\n" );
2046+ return -1 ;
2047+ }
2048+ if (* ptr == ' ' )
2049+ ptr ++ ;
2050+ }
2051+
2052+ * dwords = (uint32_t * )malloc (* num_dwords * sizeof (uint32_t ));
2053+ if (* dwords == NULL )
2054+ return -1 ;
2055+
2056+ ptr = str ;
2057+ for (int i = 0 ; i < * num_dwords ; i ++ ) {
2058+ char * endptr ;
2059+ (* dwords )[i ] = (uint32_t )strtoul (ptr , & endptr , 0 );
2060+ if (endptr == ptr || (* endptr != ' ' && * endptr != '\0' )) {
2061+ free (* dwords );
2062+ return -1 ;
2063+ }
2064+ ptr = endptr ;
2065+ while (* ptr == ' ' )
2066+ ptr ++ ;
2067+ }
2068+
2069+ return 0 ;
2070+ }
2071+
2072+ #define CMD_TLP_INJECT "Inject a raw TLP"
2073+
2074+ static int tlp_inject (int argc , char * * argv )
2075+ {
2076+ int ret = 0 ;
2077+ uint32_t * raw_tlp_dwords = NULL ;
2078+ int num_dwords = 0 ;
2079+ static struct {
2080+ struct switchtec_dev * dev ;
2081+ int port_id ;
2082+ int tlp_type ;
2083+ int ecrc ;
2084+ char * raw_tlp_data ;
2085+ } cfg = {
2086+ .tlp_type = 0
2087+ };
2088+
2089+ const struct argconfig_options opts [] = {
2090+ DEVICE_OPTION ,
2091+ {"port" , 'p' , "PORT_ID" , CFG_NONNEGATIVE , & cfg .port_id ,
2092+ required_argument , "destination port ID" },
2093+ {"tlp_type" , 't' , "TYPE" , CFG_NONNEGATIVE , & cfg .tlp_type ,
2094+ required_argument , "tlp type:\n0: P - Posted\n1: NP - Non-posted\n2: CP - Completion\n(default 0)" },
2095+ {"enable_ecrc" , 'e' , "" , CFG_NONE , & cfg .ecrc , no_argument ,
2096+ "Enable the ecrc to be included at the end of the input data (Default: disabled)" },
2097+ {"tlp_data" , 'd' , "\"DW0 DW1 ... DW131\"" , CFG_STRING ,
2098+ & cfg .raw_tlp_data , required_argument ,
2099+ "DWs to be sent as part of the raw TLP (Maximum 132 DWs). Every DW must start with \'0x\'" },
2100+ {NULL }
2101+ };
2102+
2103+ argconfig_parse (argc , argv , CMD_TLP_INJECT , opts , & cfg , sizeof (cfg ));
2104+
2105+ if (cfg .raw_tlp_data == NULL ) {
2106+ fprintf (stderr , "Must set tlp data --tlp_data -d \n" );
2107+ return -1 ;
2108+ }
2109+ ret = convert_str_to_dwords (cfg .raw_tlp_data , & raw_tlp_dwords ,
2110+ & num_dwords );
2111+ if (ret ) {
2112+ fprintf (stderr , "Error with tlp data provided \n" );
2113+ return -1 ;
2114+ }
2115+ if (num_dwords > SWITCHTEC_DIAG_MAX_TLP_DWORDS ) {
2116+ fprintf (stderr , "TLP data cannot exceed %d dwords \n" ,
2117+ SWITCHTEC_DIAG_MAX_TLP_DWORDS );
2118+ free (raw_tlp_dwords );
2119+ return -1 ;
2120+ }
2121+
2122+ ret = switchtec_tlp_inject (cfg .dev , cfg .port_id , cfg .tlp_type ,
2123+ num_dwords , cfg .ecrc , raw_tlp_dwords );
2124+ if (ret != 0 ) {
2125+ switchtec_perror ("tlp_inject" );
2126+ return -1 ;
2127+ }
2128+
2129+ return 0 ;
2130+ }
2131+
20292132static const struct cmd commands [] = {
20302133 CMD (crosshair , CMD_DESC_CROSS_HAIR ),
20312134 CMD (eye , CMD_DESC_EYE ),
@@ -2039,6 +2142,7 @@ static const struct cmd commands[] = {
20392142 CMD (rcvr_obj , CMD_DESC_RCVR_OBJ ),
20402143 CMD (refclk , CMD_DESC_REF_CLK ),
20412144 CMD (ltssm_log , CMD_DESC_LTSSM_LOG ),
2145+ CMD (tlp_inject , CMD_TLP_INJECT ),
20422146 {}
20432147};
20442148
0 commit comments