30#define SWITCHTEC_LIB_CORE
32#include "switchtec_priv.h"
35#include "switchtec/mrpc.h"
36#include "switchtec/errors.h"
37#include "switchtec/log.h"
38#include "switchtec/endian.h"
39#include "switchtec/utils.h"
81 unsigned short device_id;
90 {0x8531, SWITCHTEC_GEN3, SWITCHTEC_PFX},
91 {0x8532, SWITCHTEC_GEN3, SWITCHTEC_PFX},
92 {0x8533, SWITCHTEC_GEN3, SWITCHTEC_PFX},
93 {0x8534, SWITCHTEC_GEN3, SWITCHTEC_PFX},
94 {0x8535, SWITCHTEC_GEN3, SWITCHTEC_PFX},
95 {0x8536, SWITCHTEC_GEN3, SWITCHTEC_PFX},
96 {0x8541, SWITCHTEC_GEN3, SWITCHTEC_PSX},
97 {0x8542, SWITCHTEC_GEN3, SWITCHTEC_PSX},
98 {0x8543, SWITCHTEC_GEN3, SWITCHTEC_PSX},
99 {0x8544, SWITCHTEC_GEN3, SWITCHTEC_PSX},
100 {0x8545, SWITCHTEC_GEN3, SWITCHTEC_PSX},
101 {0x8546, SWITCHTEC_GEN3, SWITCHTEC_PSX},
102 {0x8551, SWITCHTEC_GEN3, SWITCHTEC_PAX},
103 {0x8552, SWITCHTEC_GEN3, SWITCHTEC_PAX},
104 {0x8553, SWITCHTEC_GEN3, SWITCHTEC_PAX},
105 {0x8554, SWITCHTEC_GEN3, SWITCHTEC_PAX},
106 {0x8555, SWITCHTEC_GEN3, SWITCHTEC_PAX},
107 {0x8556, SWITCHTEC_GEN3, SWITCHTEC_PAX},
108 {0x8561, SWITCHTEC_GEN3, SWITCHTEC_PFXL},
109 {0x8562, SWITCHTEC_GEN3, SWITCHTEC_PFXL},
110 {0x8563, SWITCHTEC_GEN3, SWITCHTEC_PFXL},
111 {0x8564, SWITCHTEC_GEN3, SWITCHTEC_PFXL},
112 {0x8565, SWITCHTEC_GEN3, SWITCHTEC_PFXL},
113 {0x8566, SWITCHTEC_GEN3, SWITCHTEC_PFXL},
114 {0x8571, SWITCHTEC_GEN3, SWITCHTEC_PFXI},
115 {0x8572, SWITCHTEC_GEN3, SWITCHTEC_PFXI},
116 {0x8573, SWITCHTEC_GEN3, SWITCHTEC_PFXI},
117 {0x8574, SWITCHTEC_GEN3, SWITCHTEC_PFXI},
118 {0x8575, SWITCHTEC_GEN3, SWITCHTEC_PFXI},
119 {0x8576, SWITCHTEC_GEN3, SWITCHTEC_PFXI},
120 {0x4000, SWITCHTEC_GEN4, SWITCHTEC_PFX},
121 {0x4084, SWITCHTEC_GEN4, SWITCHTEC_PFX},
122 {0x4068, SWITCHTEC_GEN4, SWITCHTEC_PFX},
123 {0x4052, SWITCHTEC_GEN4, SWITCHTEC_PFX},
124 {0x4036, SWITCHTEC_GEN4, SWITCHTEC_PFX},
125 {0x4028, SWITCHTEC_GEN4, SWITCHTEC_PFX},
126 {0x4100, SWITCHTEC_GEN4, SWITCHTEC_PSX},
127 {0x4184, SWITCHTEC_GEN4, SWITCHTEC_PSX},
128 {0x4168, SWITCHTEC_GEN4, SWITCHTEC_PSX},
129 {0x4152, SWITCHTEC_GEN4, SWITCHTEC_PSX},
130 {0x4136, SWITCHTEC_GEN4, SWITCHTEC_PSX},
131 {0x4128, SWITCHTEC_GEN4, SWITCHTEC_PSX},
132 {0x4200, SWITCHTEC_GEN4, SWITCHTEC_PAX},
133 {0x4284, SWITCHTEC_GEN4, SWITCHTEC_PAX},
134 {0x4268, SWITCHTEC_GEN4, SWITCHTEC_PAX},
135 {0x4252, SWITCHTEC_GEN4, SWITCHTEC_PAX},
136 {0x4236, SWITCHTEC_GEN4, SWITCHTEC_PAX},
137 {0x4352, SWITCHTEC_GEN4, SWITCHTEC_PFXA},
138 {0x4336, SWITCHTEC_GEN4, SWITCHTEC_PFXA},
139 {0x4328, SWITCHTEC_GEN4, SWITCHTEC_PFXA},
140 {0x4452, SWITCHTEC_GEN4, SWITCHTEC_PSXA},
141 {0x4436, SWITCHTEC_GEN4, SWITCHTEC_PSXA},
142 {0x4428, SWITCHTEC_GEN4, SWITCHTEC_PSXA},
143 {0x4552, SWITCHTEC_GEN4, SWITCHTEC_PAXA},
144 {0x4536, SWITCHTEC_GEN4, SWITCHTEC_PAXA},
145 {0x4528, SWITCHTEC_GEN4, SWITCHTEC_PAXA},
146 {0x4228, SWITCHTEC_GEN4, SWITCHTEC_PAX},
147 {0x5000, SWITCHTEC_GEN5, SWITCHTEC_PFX},
148 {0x5084, SWITCHTEC_GEN5, SWITCHTEC_PFX},
149 {0x5068, SWITCHTEC_GEN5, SWITCHTEC_PFX},
150 {0x5052, SWITCHTEC_GEN5, SWITCHTEC_PFX},
151 {0x5036, SWITCHTEC_GEN5, SWITCHTEC_PFX},
152 {0x5028, SWITCHTEC_GEN5, SWITCHTEC_PFX},
153 {0x5100, SWITCHTEC_GEN5, SWITCHTEC_PSX},
154 {0x5184, SWITCHTEC_GEN5, SWITCHTEC_PSX},
155 {0x5168, SWITCHTEC_GEN5, SWITCHTEC_PSX},
156 {0x5152, SWITCHTEC_GEN5, SWITCHTEC_PSX},
157 {0x5136, SWITCHTEC_GEN5, SWITCHTEC_PSX},
158 {0x5128, SWITCHTEC_GEN5, SWITCHTEC_PSX},
159 {0x5200, SWITCHTEC_GEN5, SWITCHTEC_PAX},
160 {0x5284, SWITCHTEC_GEN5, SWITCHTEC_PAX},
161 {0x5268, SWITCHTEC_GEN5, SWITCHTEC_PAX},
162 {0x5252, SWITCHTEC_GEN5, SWITCHTEC_PAX},
163 {0x5236, SWITCHTEC_GEN5, SWITCHTEC_PAX},
164 {0x5228, SWITCHTEC_GEN5, SWITCHTEC_PAX},
165 {0x5300, SWITCHTEC_GEN5, SWITCHTEC_PFXA},
166 {0x5384, SWITCHTEC_GEN5, SWITCHTEC_PFXA},
167 {0x5368, SWITCHTEC_GEN5, SWITCHTEC_PFXA},
168 {0x5352, SWITCHTEC_GEN5, SWITCHTEC_PFXA},
169 {0x5336, SWITCHTEC_GEN5, SWITCHTEC_PFXA},
170 {0x5328, SWITCHTEC_GEN5, SWITCHTEC_PFXA},
171 {0x5400, SWITCHTEC_GEN5, SWITCHTEC_PSXA},
172 {0x5484, SWITCHTEC_GEN5, SWITCHTEC_PSXA},
173 {0x5468, SWITCHTEC_GEN5, SWITCHTEC_PSXA},
174 {0x5452, SWITCHTEC_GEN5, SWITCHTEC_PSXA},
175 {0x5436, SWITCHTEC_GEN5, SWITCHTEC_PSXA},
176 {0x5428, SWITCHTEC_GEN5, SWITCHTEC_PSXA},
177 {0x5500, SWITCHTEC_GEN5, SWITCHTEC_PAXA},
178 {0x5584, SWITCHTEC_GEN5, SWITCHTEC_PAXA},
179 {0x5568, SWITCHTEC_GEN5, SWITCHTEC_PAXA},
180 {0x5552, SWITCHTEC_GEN5, SWITCHTEC_PAXA},
181 {0x5536, SWITCHTEC_GEN5, SWITCHTEC_PAXA},
182 {0x5528, SWITCHTEC_GEN5, SWITCHTEC_PAXA},
183 {0x6048, SWITCHTEC_GEN6, SWITCHTEC_PFX},
184 {0x6064, SWITCHTEC_GEN6, SWITCHTEC_PFX},
185 {0x6044, SWITCHTEC_GEN6, SWITCHTEC_PFX},
186 {0x6060, SWITCHTEC_GEN6, SWITCHTEC_PFX},
187 {0x6148, SWITCHTEC_GEN6, SWITCHTEC_PSX},
188 {0x6164, SWITCHTEC_GEN6, SWITCHTEC_PSX},
189 {0x6144, SWITCHTEC_GEN6, SWITCHTEC_PSX},
190 {0x6160, SWITCHTEC_GEN6, SWITCHTEC_PSX},
191 {0x6248, SWITCHTEC_GEN6, SWITCHTEC_PFX},
192 {0x6264, SWITCHTEC_GEN6, SWITCHTEC_PFX},
193 {0x6244, SWITCHTEC_GEN6, SWITCHTEC_PFX},
194 {0x6260, SWITCHTEC_GEN6, SWITCHTEC_PFX},
195 {0x6348, SWITCHTEC_GEN6, SWITCHTEC_PSX},
196 {0x6364, SWITCHTEC_GEN6, SWITCHTEC_PSX},
197 {0x6344, SWITCHTEC_GEN6, SWITCHTEC_PSX},
198 {0x6360, SWITCHTEC_GEN6, SWITCHTEC_PSX},
202static int set_gen_variant(
struct switchtec_dev * dev)
207 dev->boot_phase = SWITCHTEC_BOOT_PHASE_FW;
208 dev->gen = SWITCHTEC_GEN_UNKNOWN;
209 dev->var = SWITCHTEC_VAR_UNKNOWN;
210 dev->device_id = dev->ops->get_device_id(dev);
212 switchtec_get_device_id_bl2(dev,
213 (
unsigned short *)&dev->device_id);
215 while (id->device_id) {
216 if (id->device_id == dev->device_id) {
226 dev->pax_id = SWITCHTEC_PAX_ID_LOCAL;
234static int set_local_pax_id(
struct switchtec_dev *dev)
236 unsigned char local_pax_id;
239 dev->local_pax_id = -1;
245 &local_pax_id,
sizeof(local_pax_id));
249 dev->local_pax_id = local_pax_id;
287 struct switchtec_dev *ret;
289 if (sscanf(device,
"%i@%i", &bus, &dev) == 2) {
290 ret = switchtec_open_i2c_by_adapter(bus, dev);
294 if (sscanf(device,
"%2049[^@]@%i", path, &dev) == 2) {
299 if (device[0] ==
'/' &&
300 sscanf(device,
"%2049[^:]:%i", path, &dev) == 2) {
305 if (strchr(device,
'/') || strchr(device,
'\\')) {
310 if (sscanf(device,
"%x:%x.%x", &bus, &dev, &func) == 3) {
315 if (sscanf(device,
"%x:%x:%x.%x", &domain, &bus, &dev, &func) == 4) {
320 if (sscanf(device,
"%2049[^:]:%i", path, &inst) == 2) {
326 idx = strtol(device, &endptr, 0);
327 if (!errno && endptr != device) {
332 if (sscanf(device,
"switchtec%d", &idx) == 1) {
346 snprintf(ret->name,
sizeof(ret->name),
"%s", device);
348 if (set_gen_variant(ret))
351 if (set_local_pax_id(ret))
366 return dev->device_id;
402 return dev->boot_phase;
424 return dev->partition;
427int switchtec_set_pax_id(
struct switchtec_dev *dev,
int pax_id)
432 if (pax_id == SWITCHTEC_PAX_ID_LOCAL)
433 dev->pax_id = dev->local_pax_id;
435 dev->pax_id = pax_id;
440static int compare_port_id(
const void *aa,
const void *bb)
448 return a->
log_id - b->log_id;
451static int compare_status(
const void *aa,
const void *bb)
455 return compare_port_id(&a->
port, &b->port);
465 case 0:
return "Normal Lane Ordering";
466 case 1:
return "x16 (Full) Lane Reversal";
467 case 2:
return "x2 Lane Reversal";
468 case 4:
return "x4 Lane Reversal";
469 case 8:
return "x8 Lane Reversal";
470 default:
return "Unknown Lane Ordering";
474static const char *lane_reversal_str_gen6(
int link_up,
481 case 0:
return "Normal Lane Ordering";
482 case 1:
return "Lane Reversal in effect";
483 default:
return "Unknown Lane Ordering";
507 s->lanes[l] =
'0' + i;
509 s->lanes[l] =
'a' + i - 10;
515static int switchtec_status_gen345(
struct switchtec_dev *dev,
518 uint64_t port_bitmap = 0;
533 uint8_t phys_port_id;
540 uint8_t linkup_linkrate;
546 ret =
switchtec_cmd(dev, MRPC_LNKSTAT, &port_bitmap,
sizeof(port_bitmap),
547 ports,
sizeof(ports));
552 for (i = 0; i < max_ports; i++) {
553 if ((ports[i].stk_id >> 4) > SWITCHTEC_MAX_STACKS)
558 s = *status = calloc(nr_ports,
sizeof(*s));
562 for (i = 0, p = 0; i < max_ports && p < nr_ports; i++) {
563 if ((ports[i].stk_id >> 4) > SWITCHTEC_MAX_STACKS)
575 s[p].
link_up = ports[i].linkup_linkrate >> 7;
576 s[p].
link_rate = ports[i].linkup_linkrate & 0x7F;
577 s[p].
ltssm = le16toh(ports[i].LTSSM);
578 s[p].
ltssm_str = switchtec_ltssm_str(s[p].ltssm, 1, dev);
584 generate_lane_str(&s[p]);
589 qsort(s, nr_ports,
sizeof(*s), compare_status);
594static int switchtec_status_gen6(
struct switchtec_dev *dev,
621 uint8_t phys_port_id;
628 uint8_t linkup_linkrate;
635 ret =
switchtec_cmd(dev, MRPC_LNKSTAT, &port_bitmap,
sizeof(port_bitmap),
636 ports,
sizeof(ports));
641 for (i = 0; i < max_ports; i++) {
642 if ((ports[i].stk_id >> 4) > SWITCHTEC_MAX_STACKS)
647 s = *status = calloc(nr_ports,
sizeof(*s));
651 for (i = 0, p = 0; i < max_ports && p < nr_ports; i++) {
652 if ((ports[i].stk_id >> 4) > SWITCHTEC_MAX_STACKS)
664 s[p].
link_up = ports[i].linkup_linkrate >> 7;
665 s[p].
link_rate = ports[i].linkup_linkrate & 0x7F;
666 s[p].
ltssm = le16toh(ports[i].ltssm_major);
667 s[p].
ltssm_str = switchtec_ltssm_str(s[p].ltssm, 1, dev);
673 generate_lane_str(&s[p]);
678 qsort(s, nr_ports,
sizeof(*s), compare_status);
698 return switchtec_status_gen6(dev, status);
700 return switchtec_status_gen345(dev, status);
713 for (i = 0; i < ports; i++) {
714 if (status[i].pci_bdf)
715 free(status[i].pci_bdf);
717 if (status[i].pci_bdf_path)
718 free(status[i].pci_bdf_path);
720 if (status[i].pci_dev)
721 free(status[i].pci_dev);
723 if (status[i].class_devices)
724 free(status[i].class_devices);
750 const char *msg =
"Unknown MRPC error";
753 if ((errno & (SWITCHTEC_ERRNO_MRPC_FLAG_BIT |
754 SWITCHTEC_ERRNO_GENERAL_FLAG_BIT)) == 0) {
756 return strerror(errno);
758 return platform_strerror();
761 if (errno & SWITCHTEC_ERRNO_GENERAL_FLAG_BIT) {
763 case SWITCHTEC_ERR_LOG_DEF_READ_ERROR:
764 msg =
"Error reading log definition file";
break;
765 case SWITCHTEC_ERR_BIN_LOG_READ_ERROR:
766 msg =
"Error reading binary log file";
break;
767 case SWITCHTEC_ERR_PARSED_LOG_WRITE_ERROR:
768 msg =
"Error writing parsed log file";
break;
769 case SWITCHTEC_ERR_LOG_DEF_DATA_INVAL:
770 msg =
"Invalid log definition data";
break;
771 case SWITCHTEC_ERR_INVALID_PORT:
772 msg =
"Invalid port specified";
break;
773 case SWITCHTEC_ERR_INVALID_LANE:
774 msg =
"Invalid lane specified";
break;
776 msg =
"Unknown Switchtec error";
break;
782 err = errno & ~SWITCHTEC_ERRNO_MRPC_FLAG_BIT;
785 case ERR_NO_AVAIL_MRPC_THREAD:
786 msg =
"No available MRPC handler thread";
break;
787 case ERR_HANDLER_THREAD_NOT_IDLE:
788 msg =
"The handler thread is not idle";
break;
789 case ERR_NO_BG_THREAD:
790 msg =
"No background thread run for the command";
break;
792 case ERR_REFCLK_SUBCMD_INVALID:
793 case ERR_STACKBIF_SUBCMD_INVALID:
794 case ERR_SUBCMD_INVALID: msg =
"Invalid subcommand";
break;
795 case ERR_CMD_INVALID: msg =
"Invalid command";
break;
796 case ERR_PARAM_INVALID: msg =
"Invalid parameter";
break;
797 case ERR_BAD_FW_STATE: msg =
"Bad firmware state";
break;
798 case ERR_MRPC_DENIED: msg =
"MRPC request denied";
break;
799 case ERR_MRPC_NO_PREV_DATA:
800 msg =
"No previous adaptation object data";
802 case ERR_REFCLK_STACK_ID_INVALID:
803 case ERR_STACKBIF_STACK_ID_INVALID:
804 case ERR_STACK_INVALID: msg =
"Invalid Stack";
break;
805 case ERR_LOOPBACK_PORT_INVALID:
806 case ERR_PORT_INVALID: msg =
"Invalid Port";
break;
807 case ERR_EVENT_INVALID: msg =
"Invalid Event";
break;
808 case ERR_RST_RULE_FAILED: msg =
"Reset rule search failed";
break;
809 case ERR_UART_NOT_SUPPORTED:
810 msg =
"UART interface not supported for this command";
break;
811 case ERR_XML_VERSION_MISMATCH:
812 msg =
"XML version mismatch between MAIN and CFG partition";
814 case ERR_ACCESS_REFUSED: msg =
"Access Refused";
break;
816 case ERR_STACKBIF_CODE_INVALID:
817 msg =
"Stack bifurcation code invalid";
break;
819 case ERR_STACKBIF_PORT_BOUND:
820 msg =
"Port already bound";
break;
827 case MRPC_PORTPARTP2P:
829 case ERR_PHYC_PORT_ARDY_BIND:
830 msg =
"Physical port already bound";
break;
831 case ERR_LOGC_PORT_ARDY_BIND:
832 msg =
"Logical bridge instance already bound";
break;
833 case ERR_BIND_PRTT_NOT_EXIST:
834 msg =
"Partition does not exist";
break;
835 case ERR_PHYC_PORT_NOT_EXIST:
836 msg =
"Physical port does not exist";
break;
837 case ERR_PHYC_PORT_DIS:
838 msg =
"Physical port disabled";
break;
839 case ERR_NO_LOGC_PORT:
840 msg =
"No logical bridge instance";
break;
841 case ERR_BIND_IN_PROGRESS:
842 msg =
"Bind/unbind in progress";
break;
843 case ERR_BIND_TGT_IS_USP:
844 msg =
"Bind/unbind target is USP";
break;
845 case ERR_BIND_SUBCMD_INVALID:
846 msg =
"Sub-command does not exist";
break;
847 case ERR_PHYC_PORT_LINK_ACT:
848 msg =
"Physical port link active";
break;
849 case ERR_LOGC_PORT_NOT_BIND_PHYC_PORT:
850 msg =
"Logical bridge not bind to physical port";
break;
851 case ERR_UNBIND_OPT_INVALID:
852 msg =
"Invalid unbind option";
break;
853 case ERR_BIND_CHECK_FAIL:
854 msg =
"Port bind checking failed";
break;
874 int is_mrpc = errno & SWITCHTEC_ERRNO_MRPC_FLAG_BIT;
875 int err = errno & ~SWITCHTEC_ERRNO_MRPC_FLAG_BIT;
878 fprintf(stderr,
"%s: %s (MRPC: 0x%x, error: 0x%x)\n",
881 fprintf(stderr,
"%s: %s\n", str, msg);
906 output,
sizeof(*output));
922 return switchtec_cmd(dev, MRPC_RESET, &subcmd,
sizeof(subcmd),
967 for (i = defs->
num_alloc; i < num_modules; i++)
987 *val = strtol(str, &endptr, 0);
989 if ((endptr == str) || (*endptr !=
'\0') || (errno != 0))
1016 while (fgets(line,
sizeof(line), log_def_file)) {
1023 line[strcspn(line,
"\r\n")] =
'\0';
1029 tok = strtok(line,
" \t");
1033 tok = strtok(NULL,
" \t");
1038 errno = SWITCHTEC_ERR_LOG_DEF_DATA_INVAL;
1039 goto err_free_log_defs;
1051 tok = strtok(NULL,
" \t");
1056 errno = SWITCHTEC_ERR_LOG_DEF_DATA_INVAL;
1057 goto err_free_log_defs;
1066 if (!fgets(line,
sizeof(line),
1078 goto err_free_log_defs;
1081 if (fgets(line,
sizeof(line), log_def_file) == NULL) {
1082 errno = SWITCHTEC_ERR_LOG_DEF_READ_ERROR;
1083 goto err_free_log_defs;
1086 mod_defs->
entries[i] = strdup(line);
1088 goto err_free_log_defs;
1092 if (ferror(log_def_file)) {
1093 errno = SWITCHTEC_ERR_LOG_DEF_READ_ERROR;
1094 goto err_free_log_defs;
1115 int num_entries_alloc;
1129 num_entries_alloc = 100;
1130 mod_defs->
entries = calloc(num_entries_alloc,
1133 goto err_free_log_defs;
1135 while (fgets(line,
sizeof(line), log_def_file)) {
1142 num_entries_alloc *= 2;
1144 (num_entries_alloc *
1147 goto err_free_log_defs;
1152 goto err_free_log_defs;
1157 if (ferror(log_def_file)) {
1158 errno = SWITCHTEC_ERR_LOG_DEF_READ_ERROR;
1159 goto err_free_log_defs;
1181 size_t count,
int init_entry_idx,
1184 FILE *log_file,
int ts_factor)
1188 int entry_idx = init_entry_idx;
1189 unsigned long long time;
1190 unsigned int nanos, micros, millis, secs, mins, hours, days;
1191 unsigned int entry_num;
1192 unsigned int mod_id;
1193 unsigned int log_sev = 0;
1194 const char *log_sev_strs[] = {
"DISABLED",
"HIGHEST",
"HIGH",
"MEDIUM",
1199 if (entry_idx == 0) {
1200 if (log_type == SWITCHTEC_LOG_PARSE_TYPE_APP || log_type == SWITCHTEC_LOG_PARSE_TYPE_FTDC)
1201 fputs(
" #|Timestamp |Module |Severity |Event ID |Event\n",
1204 fputs(
" #|Timestamp |Source |Event ID |Event\n",
1208 for (i = 0; i < count; i ++) {
1210 time = (((
unsigned long long)log_data[i].data[0] << 32) |
1211 log_data[i].data[1]) * ts_factor/100;
1212 nanos = time % 1000;
1214 micros = time % 1000;
1216 millis = time % 1000;
1225 if (log_type == SWITCHTEC_LOG_PARSE_TYPE_APP || log_type == SWITCHTEC_LOG_PARSE_TYPE_FTDC) {
1230 mod_id = (log_data[i].data[2] >> 16) & 0xFFF;
1231 log_sev = (log_data[i].data[2] >> 28) & 0xF;
1236 if (fprintf(log_file,
"(Invalid module ID: 0x%x)\n",
1238 goto ret_print_error;
1242 if (log_sev >= ARRAY_SIZE(log_sev_strs)) {
1243 if (fprintf(log_file,
"(Invalid log severity: %d)\n",
1245 goto ret_print_error;
1253 is_bl1 = (((log_data[i].data[2] >> 27) & 1) == 0);
1262 entry_num = log_data[i].data[2] & 0x0000FFFF;
1265 if (fprintf(log_file,
1266 "(Invalid log entry number: %d (module 0x%x))\n",
1267 entry_num, mod_id) < 0)
1268 goto ret_print_error;
1274 ret = fprintf(log_file,
1275 "%04d|xxxd xx:xx:xx.xxx,xxx,xxx|",
1278 ret = fprintf(log_file,
1279 "%04d|%03dd %02d:%02d:%02d.%03d,%03d,%03d|",
1280 entry_idx, days, hours, mins, secs,
1281 millis, micros, nanos);
1284 goto ret_print_error;
1286 if (log_type == SWITCHTEC_LOG_PARSE_TYPE_APP || log_type == SWITCHTEC_LOG_PARSE_TYPE_FTDC) {
1288 if (fprintf(log_file,
"%-12s |%-8s |0x%04x |",
1289 mod_defs->
mod_name, log_sev_strs[log_sev],
1291 goto ret_print_error;
1294 if (fprintf(log_file,
"%-6s |0x%04x |",
1295 (is_bl1 ?
"BL1" :
"BL2"), entry_num) < 0)
1296 goto ret_print_error;
1300 if (fprintf(log_file, mod_defs->
entries[entry_num],
1301 log_data[i].data[3], log_data[i].data[4],
1302 log_data[i].data[5], log_data[i].data[6],
1303 log_data[i].data[7]) < 0)
1304 goto ret_print_error;
1309 if (fflush(log_file) != 0)
1315 errno = SWITCHTEC_ERR_PARSED_LOG_WRITE_ERROR;
1319static int parse_def_header(FILE *log_def_file, uint32_t *fw_version,
1320 uint32_t *sdk_version)
1327 while (fgets(line,
sizeof(line), log_def_file)) {
1332 while (line[i] ==
' ' || line[i] ==
'#') i++;
1334 if (strncasecmp(line + i,
"SDK Version:", 12) == 0) {
1336 while (line[i] ==
' ') i++;
1337 sscanf(line + i,
"%i", (
int*)sdk_version);
1339 else if (strncasecmp(line + i,
"FW Version:", 11) == 0) {
1341 while (line[i] ==
' ') i++;
1342 sscanf(line + i,
"%i", (
int*)fw_version);
1346 rewind(log_def_file);
1350static int append_ftdc_log_header(
int fd, uint32_t sdk_def_version,
1351 uint32_t fw_def_version)
1354 char hdr_str_fmt[] =
"##########################################\n"
1355 "## Parsed with FTDC log file from definition:\n"
1356 "## FW def version %08x\n"
1357 "## SDK def version %08x\n"
1358 "##########################################\n\n";
1361 snprintf(hdr_str, 512, hdr_str_fmt, fw_def_version, sdk_def_version);
1362 ret = write(fd, hdr_str, strlen(hdr_str));
1367static int append_log_header(
int fd, uint32_t sdk_version,
1368 uint32_t fw_version,
int binary)
1373 uint32_t fw_version;
1374 uint32_t sdk_version;
1378 .magic = {
'S',
'W',
'M',
'C',
'L',
'O',
'G',
'F'},
1379 .fw_version = fw_version,
1380 .sdk_version = sdk_version
1382 char hdr_str_fmt[] =
"####################################\n"
1383 "## Parsed with definition file for\n"
1384 "## FW version %08x\n"
1385 "## SDK version %08x\n"
1386 "####################################\n\n";
1390 ret = write(fd, &header,
sizeof(header));
1392 snprintf(hdr_str, 512, hdr_str_fmt, fw_version, sdk_version);
1393 ret = write(fd, hdr_str, strlen(hdr_str));
1401 if (gen == SWITCHTEC_GEN_UNKNOWN)
1403 else if (gen == SWITCHTEC_GEN3)
1409static int log_a_to_file(
struct switchtec_dev *dev,
int sub_cmd_id,
1410 int fd, FILE *log_def_file,
1417 .sub_cmd_id = sub_cmd_id,
1421 .module_defs = NULL,
1425 uint32_t fw_version = 0;
1426 uint32_t sdk_version = 0;
1428 if (log_def_file != NULL) {
1429 ret = parse_def_header(log_def_file, &fw_version,
1441 while (res.hdr.remain) {
1445 goto ret_free_log_defs;
1446 if (res.hdr.overflow && info)
1449 if (dev->gen < SWITCHTEC_GEN5) {
1450 res.hdr.sdk_version = 0;
1451 res.hdr.fw_version = 0;
1455 info->def_fw_version = fw_version;
1456 info->def_sdk_version = sdk_version;
1457 info->log_fw_version = res.hdr.fw_version;
1458 info->log_sdk_version = res.hdr.sdk_version;
1461 if (res.hdr.sdk_version != sdk_version ||
1462 res.hdr.fw_version != fw_version) {
1463 if (info && log_def_file)
1464 info->version_mismatch =
true;
1468 append_log_header(fd, res.hdr.sdk_version,
1470 log_def_file == NULL? 1 : 0);
1473 if (log_def_file == NULL) {
1475 ret = write(fd, res.data,
1476 sizeof(*res.data) * res.hdr.count);
1480 log_file = fdopen(fd,
"w");
1482 goto ret_free_log_defs;
1487 SWITCHTEC_LOG_PARSE_TYPE_APP,
1489 get_ts_factor(dev->gen));
1491 goto ret_free_log_defs;
1493 entry_idx += res.hdr.count;
1496 read += le32toh(res.hdr.count);
1497 cmd.start = res.hdr.next_start;
1507static int log_b_to_file(
struct switchtec_dev *dev,
int sub_cmd_id,
int fd)
1513 .sub_cmd_id = sub_cmd_id,
1515 .length = htole32(
sizeof(res.data)),
1518 res.hdr.remain =
sizeof(res.data);
1520 while (res.hdr.remain) {
1526 ret = write(fd, res.data, res.hdr.length);
1530 read += le32toh(res.hdr.length);
1531 cmd.offset = htole32(read);
1537static int log_c_to_file(
struct switchtec_dev *dev,
int sub_cmd_id,
int fd)
1548 uint32_t nvlog_version;
1549 uint32_t thread_handle;
1550 uint32_t fw_version;
1551 uint32_t timestamp1;
1552 uint32_t timestamp2;
1555 cmd.subcmd = sub_cmd_id;
1558 &reply,
sizeof(reply));
1562 ret = write(fd, &reply,
sizeof(reply));
1569static int log_d_to_file(
struct switchtec_dev *dev,
int sub_cmd_id,
int fd)
1576 .sub_cmd_id = sub_cmd_id,
1580 uint32_t length =
sizeof(res.data);
1585 while ( !(res.data[1]) ) {
1586 ret =
switchtec_cmd(dev, MRPC_FTDC_LOG_DUMP, &cmd,
sizeof(cmd),
1591 ret = write(fd, res.data, (res.data[0]+1)*4);
1602static int log_ram_flash_to_file(
struct switchtec_dev *dev,
1603 int gen5_cmd,
int gen4_cmd,
int gen4_cmd_lgcy,
1604 int fd, FILE *log_def_file,
1610 return log_a_to_file(dev, gen5_cmd, fd, log_def_file,
1613 ret = log_a_to_file(dev, gen4_cmd, fd, log_def_file,
1622 (ERRNO_MRPC(errno) == ERR_LOGC_PORT_ARDY_BIND ||
1623 ERRNO_MRPC(errno) == ERR_SUBCMD_INVALID))
1624 ret = log_a_to_file(dev, gen4_cmd_lgcy, fd,
1625 log_def_file, info);
1645 memset(info, 0,
sizeof(*info));
1648 case SWITCHTEC_LOG_RAM:
1649 return log_ram_flash_to_file(dev,
1650 MRPC_FWLOGRD_RAM_GEN5,
1651 MRPC_FWLOGRD_RAM_WITH_FLAG,
1653 fd, log_def_file, info);
1654 case SWITCHTEC_LOG_FLASH:
1655 return log_ram_flash_to_file(dev,
1656 MRPC_FWLOGRD_FLASH_GEN5,
1657 MRPC_FWLOGRD_FLASH_WITH_FLAG,
1659 fd, log_def_file, info);
1660 case SWITCHTEC_LOG_FTDC:
1661 return log_d_to_file(dev, MRPC_FWLOGRD_RAM, fd);
1662 case SWITCHTEC_LOG_MEMLOG:
1663 return log_b_to_file(dev, MRPC_FWLOGRD_MEMLOG, fd);
1664 case SWITCHTEC_LOG_REGS:
1665 return log_b_to_file(dev, MRPC_FWLOGRD_REGS, fd);
1666 case SWITCHTEC_LOG_THRD_STACK:
1667 return log_b_to_file(dev, MRPC_FWLOGRD_THRD_STACK, fd);
1668 case SWITCHTEC_LOG_SYS_STACK:
1669 return log_b_to_file(dev, MRPC_FWLOGRD_SYS_STACK, fd);
1670 case SWITCHTEC_LOG_THRD:
1671 return log_b_to_file(dev, MRPC_FWLOGRD_THRD, fd);
1672 case SWITCHTEC_LOG_NVHDR:
1673 return log_c_to_file(dev, MRPC_FWLOGRD_NVHDR, fd);
1680static int parse_log_header(FILE *bin_log_file, uint32_t *fw_version,
1681 uint32_t *sdk_version)
1685 uint32_t fw_version;
1686 uint32_t sdk_version;
1691 char sig[8] = {
'S',
'W',
'M',
'C',
'L',
'O',
'G',
'F'};
1694 ret = fread(&header,
sizeof(header), 1, bin_log_file);
1700 if (memcmp(sig, header.magic, 8)) {
1701 rewind(bin_log_file);
1707 *fw_version = header.fw_version;
1708 *sdk_version = header.sdk_version;
1724 FILE *parsed_log_file,
1732 .module_defs = NULL,
1735 uint32_t fw_version_log = 0;
1736 uint32_t sdk_version_log = 0;
1737 uint32_t fw_version_def;
1738 uint32_t sdk_version_def;
1742 memset(info, 0,
sizeof(*info));
1744 if ((log_type != SWITCHTEC_LOG_PARSE_TYPE_APP) &&
1745 (log_type != SWITCHTEC_LOG_PARSE_TYPE_MAILBOX) &&
1746 (log_type != SWITCHTEC_LOG_PARSE_TYPE_FTDC)) {
1751 if (log_type != SWITCHTEC_LOG_PARSE_TYPE_FTDC)
1753 ret = parse_log_header(bin_log_file, &fw_version_log,
1759 ret = parse_def_header(log_def_file, &fw_version_def,
1764 if (log_type == SWITCHTEC_LOG_PARSE_TYPE_MAILBOX) {
1765 fw_version_log = fw_version_def;
1766 sdk_version_log = sdk_version_def;
1770 info->def_fw_version = fw_version_def;
1771 info->def_sdk_version = sdk_version_def;
1773 info->log_fw_version = fw_version_log;
1774 info->log_sdk_version = sdk_version_log;
1777 if (log_type == SWITCHTEC_LOG_PARSE_TYPE_APP || log_type == SWITCHTEC_LOG_PARSE_TYPE_FTDC)
1785 if (log_type != SWITCHTEC_LOG_PARSE_TYPE_FTDC)
1786 ret = append_log_header(fileno(parsed_log_file), sdk_version_log,
1789 ret = append_ftdc_log_header(fileno(parsed_log_file), sdk_version_def,
1796 while (fread(&log_data,
sizeof(
struct log_a_data), 1,
1797 bin_log_file) == 1) {
1803 if (gen_file != SWITCHTEC_GEN_UNKNOWN &&
1804 gen != SWITCHTEC_GEN_UNKNOWN) {
1806 info->gen_ignored =
true;
1807 }
else if (gen_file == SWITCHTEC_GEN_UNKNOWN &&
1808 gen == SWITCHTEC_GEN_UNKNOWN) {
1810 info->gen_unknown =
true;
1811 }
else if (gen != SWITCHTEC_GEN_UNKNOWN) {
1816 log_type, parsed_log_file,
1817 get_ts_factor(gen_file));
1819 goto ret_free_log_defs;
1824 if (ferror(bin_log_file)) {
1825 errno = SWITCHTEC_ERR_BIN_LOG_READ_ERROR;
1829 if (fw_version_def != fw_version_log ||
1830 sdk_version_def != sdk_version_log) {
1832 info->version_mismatch =
true;
1861 uint16_t end_of_data;
1864 uint16_t next_mod_id;
1865 uint8_t data[MRPC_MAX_DATA_LEN - 16];
1869 case SWITCHTEC_LOG_DEF_TYPE_APP:
1870 cmd.subcmd = MRPC_LOG_DEF_APP;
1873 case SWITCHTEC_LOG_DEF_TYPE_MAILBOX:
1874 cmd.subcmd = MRPC_LOG_DEF_MAILBOX;
1883 ret =
switchtec_cmd(dev, MRPC_LOG_DEF_GET, &cmd,
sizeof(cmd),
1884 &reply,
sizeof(reply));
1888 ret = fwrite(reply.data, reply.data_len, 1, file);
1892 cmd.idx = reply.next_idx;
1893 cmd.mod_id = reply.next_mod_id;
1894 }
while (!reply.end_of_data);
1905 ret = SWITCHTEC_GEN4;
1908 ret = SWITCHTEC_GEN5;
1911 ret = SWITCHTEC_GEN6;
1914 ret = SWITCHTEC_GEN_UNKNOWN;
1935 uint32_t ping_dw = 0;
1937 struct get_dev_info_reply {
1939 uint32_t ping_reply;
1942 ping_dw = time(NULL);
1950 &reply,
sizeof(reply));
1952 if (ping_dw != ~reply.ping_reply)
1955 dev_info = le32toh(reply.dev_info);
1957 *phase = dev_info & 0xff;
1959 *rev = (dev_info >> 8) & 0x0f;
1961 *gen = map_to_gen((dev_info >> 12) & 0x0f);
1962 }
else if (errno == EBADMSG || ERRNO_MRPC(errno) == ERR_CMD_INVALID) {
1964 *phase = SWITCHTEC_BOOT_PHASE_FW;
1966 *gen = SWITCHTEC_GEN3;
1968 *rev = SWITCHTEC_REV_UNKNOWN;
1987 uint32_t sub_cmd_id;
1991 sub_cmd_id = MRPC_DIETEMP_SET_MEAS;
1993 sizeof(sub_cmd_id), NULL, 0);
1997 sub_cmd_id = MRPC_DIETEMP_GET;
1999 sizeof(sub_cmd_id), &temp,
sizeof(temp));
2003 sub_cmd_id = MRPC_DIETEMP_GET_GEN4;
2005 sizeof(sub_cmd_id), &temp,
sizeof(temp));
2009 sub_cmd_id = MRPC_DIETEMP_GET_GEN5;
2012 sizeof(sub_cmd_id), temps,
sizeof(temps));
2015 temp = (temps[0] + temps[1] + temps[2] + temps[3]) / 4;
2018 return le32toh(temp) / 100.;
2029 float *sensor_readings)
2032 uint32_t sub_cmd_id;
2035 if (nr_sensor <= 0 || !sensor_readings)
2039 sub_cmd_id = MRPC_DIETEMP_SET_MEAS;
2041 sizeof(sub_cmd_id), NULL, 0);
2045 sub_cmd_id = MRPC_DIETEMP_GET;
2047 sizeof(sub_cmd_id), &temp,
sizeof(temp));
2051 sensor_readings[0] = le32toh(temp) / 100.;
2054 sub_cmd_id = MRPC_DIETEMP_GET_GEN4;
2056 sizeof(sub_cmd_id), &temp,
sizeof(temp));
2060 sensor_readings[0] = le32toh(temp) / 100.;
2063 sub_cmd_id = MRPC_DIETEMP_GET_GEN5;
2068 sizeof(sub_cmd_id), temps,
sizeof(temps));
2072 for (i = 0; i < nr_sensor && i < 4; i++)
2073 sensor_readings[i] = le32toh(temps[i]) / 100.;
2079int switchtec_bind_info(
struct switchtec_dev *dev,
2083 .sub_cmd = MRPC_PORT_INFO,
2084 .phys_port_id = phy_port
2088 sizeof(sub_cmd_id), status,
sizeof(*status));
2091int switchtec_bind(
struct switchtec_dev *dev,
int par_id,
int log_port,
2097 .sub_cmd = MRPC_PORT_BIND,
2099 .log_port_id = log_port,
2100 .phys_port_id = phy_port
2104 sizeof(sub_cmd_id), &output,
sizeof(output));
2107int switchtec_unbind(
struct switchtec_dev *dev,
int par_id,
int log_port)
2112 .sub_cmd = MRPC_PORT_UNBIND,
2114 .log_port_id = log_port,
2119 sizeof(sub_cmd_id), &output,
sizeof(output));
2122static int __switchtec_calc_lane_id(
struct switchtec_status *port,
int lane_id)
2127 errno = SWITCHTEC_ERR_INVALID_LANE;
2148 default:
return lane;
2171 for (i = 0; i < ports; i++)
2176 errno = SWITCHTEC_ERR_INVALID_PORT;
2184 rc = __switchtec_calc_lane_id(&status[i], lane_id);
2201 int *phys_port_id,
int *port_lane_id,
2205 int ports, i, p, lane;
2212 if (lane_id >= 96) {
2213 if (dev->gen < SWITCHTEC_GEN5)
2214 p = lane_id - 96 + 48;
2216 p = lane_id - 96 + 56;
2218 for (i = 0; i < ports; i++)
2222 for (i = 0; i < ports; i++) {
2230 errno = SWITCHTEC_ERR_INVALID_PORT;
2242 if (
port->lane_reversal)
2246 *port_lane_id = lane;
2265 int lane_id,
int num_lanes,
int *lane_mask,
2269 int ports, i, l, lane;
2276 for (i = 0; i < ports; i++)
2281 errno = SWITCHTEC_ERR_INVALID_PORT;
2289 for (l = lane_id; l < lane_id + num_lanes; l++) {
2290 lane = __switchtec_calc_lane_id(&status[i], l);
2296 lane_mask[lane >> 5] |= 1 << (lane & 0x1F);
2314 if (dev->gen == SWITCHTEC_GEN4)
2315 return stack_id * 8 + port_id < 52;
2333 if (port_bif != 1 && port_bif != 2 && port_bif != 4 && port_bif != 8 &&
2339 if (dev->gen == SWITCHTEC_GEN4 && stack_id == 6)
2342 return (port_bif + 1) / 2;
2353 int port_bif[SWITCHTEC_PORTS_PER_STACK])
2356 .sub_cmd = MRPC_STACKBIF_GET,
2357 .stack_id = stack_id,
2361 ret =
switchtec_cmd(dev, MRPC_STACKBIF, &in,
sizeof(in), &out,
2366 for (i = 0; i < SWITCHTEC_PORTS_PER_STACK; i++) {
2372 switch (out.code & 0xF) {
2373 case 0x0: port_bif[i] = 0;
break;
2374 case 0x1: port_bif[i] = 2;
break;
2375 case 0x2: port_bif[i] = 4;
break;
2376 case 0x4: port_bif[i] = 8;
break;
2377 case 0x8: port_bif[i] = 16;
break;
2378 case 0xf: port_bif[i] = 1;
break;
2397 int port_bif[SWITCHTEC_PORTS_PER_STACK])
2400 .sub_cmd = MRPC_STACKBIF_SET,
2401 .stack_id = stack_id,
2405 for (i = 0; i < SWITCHTEC_PORTS_PER_STACK; i++) {
2406 switch (port_bif[i]) {
2407 case 0: in.code |= 0x0 << (i * 4);
break;
2408 case 1: in.code |= 0xf << (i * 4);
break;
2409 case 2: in.code |= 0x1 << (i * 4);
break;
2410 case 4: in.code |= 0x2 << (i * 4);
break;
2411 case 8: in.code |= 0x4 << (i * 4);
break;
2412 case 16: in.code |= 0x8 << (i * 4);
break;
2419 return switchtec_cmd(dev, MRPC_STACKBIF, &in,
sizeof(in), &out,
2435 .sub_cmd = MRPC_VGPIO_GET_VAL,
2436 .log_gpio_id = pin_id,
2444 *gpio_val = out.data;
2460 .sub_cmd = MRPC_VGPIO_SET_VAL,
2461 .log_gpio_id = pin_id,
2465 return switchtec_cmd(dev, MRPC_VGPIO, &in,
sizeof(in), NULL, 0);
2480 .sub_cmd = MRPC_VGPIO_GET_DIR,
2481 .log_gpio_id = pin_id,
2489 *direction = out.data;
2506 .sub_cmd = MRPC_VGPIO_GET_POL,
2507 .log_gpio_id = pin_id,
2515 *polarity = out.data;
2530 .sub_cmd = MRPC_VGPIO_DIS_INT,
2531 .log_gpio_id = pin_id,
2535 in.sub_cmd = MRPC_VGPIO_EN_INT;
2537 return switchtec_cmd(dev, MRPC_VGPIO, &in,
sizeof(in), NULL, 0);
2550 .sub_cmd = MRPC_VPGIO_GET_PIN_STS,
2554 ret =
switchtec_cmd(dev, MRPC_VGPIO, &in,
sizeof(in), &out,
sizeof(out));
2558 memcpy(values, out.pin_values,
sizeof(out.pin_values));
2572 in.sub_cmd = MRPC_RTC_RESET;
2575 ret =
switchtec_cmd(dev, MRPC_RTC, &in,
sizeof(in), &out,
sizeof(out));
2593 in.sub_cmd = MRPC_RTC_SET;
2594 in.rtc_counter = *rtc_counter;
2596 ret =
switchtec_cmd(dev, MRPC_RTC, &in,
sizeof(in), &out,
sizeof(out));
2614 in.sub_cmd = MRPC_RTC_GET;
2616 ret =
switchtec_cmd(dev, MRPC_RTC, &in,
sizeof(in), &out,
sizeof(out));
2620 *rtc_counter = out.rtc_counter;
2638 uint16_t slave_addr, uint32_t offset,
2639 uint8_t offset_size, uint8_t slave_addr_size,
2640 uint16_t num_bytes, uint32_t *data)
2645 memset(&input, 0,
sizeof(input));
2646 input.sub_cmd = TWI_ACCESS_WRITE;
2647 input.twi_port = twi_port;
2648 input.slave_addr = slave_addr;
2649 input.offset = offset;
2650 input.offset_size = offset_size;
2651 input.slave_addr_size = slave_addr_size;
2652 input.num_of_bytes = num_bytes;
2654 if (data && num_bytes > 0) {
2655 int num_dwords = (num_bytes + 3) / 4;
2656 if (num_dwords > 253)
2658 memcpy(input.data, data, num_dwords *
sizeof(uint32_t));
2661 ret =
switchtec_cmd(dev, MRPC_TWI, &input,
sizeof(input), NULL, 0);
2684 uint16_t slave_addr, uint32_t offset,
2685 uint8_t offset_size, uint8_t slave_addr_size,
2686 uint16_t num_bytes, uint32_t *output)
2690 uint32_t output_buf[256] = {0};
2692 memset(&input, 0,
sizeof(input));
2693 input.sub_cmd = TWI_ACCESS_READ;
2694 input.twi_port = twi_port;
2695 input.slave_addr = slave_addr;
2696 input.offset = offset;
2697 input.offset_size = offset_size;
2698 input.slave_addr_size = slave_addr_size;
2699 input.num_of_bytes = num_bytes;
2702 output_buf,
sizeof(output_buf));
2710 memcpy(output, output_buf,
sizeof(output_buf));
2725 uint8_t twi_port, uint32_t duration_ms)
2729 input.duration_ms = duration_ms;
2730 input.master_recov = master_recov;
2731 input.twi_port = twi_port;
2732 input.sub_cmd = TWI_ACCESS_RESET;
2734 ret =
switchtec_cmd(dev, MRPC_TWI, &input,
sizeof(input), NULL, 0);
struct switchtec_dev * switchtec_open(const char *device)
Open a Switchtec device by string.
void switchtec_list_free(struct switchtec_device_info *devlist)
Free a list of device info structures allocated by switchtec_list().
struct switchtec_dev * switchtec_open_by_index(int index)
Open a switchtec device by index.
int switchtec_cmd(struct switchtec_dev *dev, uint32_t cmd, const void *payload, size_t payload_len, void *resp, size_t resp_len)
Execute an MRPC command.
void switchtec_perror(const char *str)
Print an error string to stdout.
int mrpc_error_cmd
The MRPC command ID when errno is set.
struct switchtec_dev * switchtec_open_i2c(const char *path, int i2c_addr)
Open a switchtec device behind an I2C device.
void switchtec_status_free(struct switchtec_status *status, int ports)
Free a list of status structures allocated by switchtec_status().
int switchtec_status(struct switchtec_dev *dev, struct switchtec_status **status)
Get the status of all the ports on a switchtec device.
struct switchtec_dev * switchtec_open_by_path(const char *path)
Open a switchtec device by path.
_PURE const char * switchtec_name(struct switchtec_dev *dev)
Get the string that was used to open the deviec.
const char * switchtec_strerror(void)
Return a message coresponding to the last error.
static const struct switchtec_device_id switchtec_device_id_tbl[]
Supported Switchtec device id table.
_PURE int switchtec_device_id(struct switchtec_dev *dev)
Get the device id of the device.
struct switchtec_dev * switchtec_open_eth(const char *ip, const int inst)
Open a switchtec device over ethernet.
_PURE enum switchtec_gen switchtec_gen(struct switchtec_dev *dev)
Get the generation of the device.
_PURE enum switchtec_variant switchtec_variant(struct switchtec_dev *dev)
Get the variant type of the device.
_PURE int switchtec_partition(struct switchtec_dev *dev)
Get the partiton number of the device that was opened.
struct switchtec_dev * switchtec_open_by_pci_addr(int domain, int bus, int device, int func)
Open a switchtec device by PCI address (BDF).
enum switchtec_gen switchtec_fw_version_to_gen(unsigned int version)
Extract generation information from FW version number.
int switchtec_stack_bif_width(struct switchtec_dev *dev, int stack_id, int port_bif)
Return the number of stack ports used for a given bifurcation.
int switchtec_calc_lane_mask(struct switchtec_dev *dev, int phys_port_id, int lane_id, int num_lanes, int *lane_mask, struct switchtec_status *port)
Calculate the lane mask for lanes within a physical port.
int switchtec_get_gpio(struct switchtec_dev *dev, int pin_id, int *gpio_val)
Get the GPIO pin value.
int switchtec_log_to_file(struct switchtec_dev *dev, enum switchtec_log_type type, int fd, FILE *log_def_file, struct switchtec_log_file_info *info)
Dump the Switchtec log data to a file.
int switchtec_twi_access_reset(struct switchtec_dev *dev, uint8_t master_recov, uint8_t twi_port, uint32_t duration_ms)
Reset the TWI bus using TWI Access MRPC.
int switchtec_set_gpio(struct switchtec_dev *dev, int pin_id, int gpio_val)
Set the GPIO pin value.
static int read_mailbox_log_defs(FILE *log_def_file, struct log_defs *defs)
Read a mailbox log definition file and store the definitions.
int switchtec_get_gpio_polarity_cfg(struct switchtec_dev *dev, int pin_id, int *polarity)
Get the GPIO pin polarity.
int switchtec_parse_log(FILE *bin_log_file, FILE *log_def_file, FILE *parsed_log_file, enum switchtec_log_parse_type log_type, enum switchtec_gen gen, struct switchtec_log_file_info *info)
Parse a binary app log or mailbox log to a text file.
float switchtec_die_temp(struct switchtec_dev *dev)
Get the die temperature of the switchtec device.
int switchtec_die_temps(struct switchtec_dev *dev, int nr_sensor, float *sensor_readings)
Get the die temperature sensor readings of the switchtec device.
int switchtec_rtc_counter_set(struct switchtec_dev *dev, uint64_t *rtc_counter)
Set the RTC counter.
int switchtec_get_stack_bif(struct switchtec_dev *dev, int stack_id, int port_bif[SWITCHTEC_PORTS_PER_STACK])
Get the bifurcation of ports in a stack.
static void free_log_defs(struct log_defs *defs)
Free log definition data.
int switchtec_twi_access_write(struct switchtec_dev *dev, uint8_t twi_port, uint16_t slave_addr, uint32_t offset, uint8_t offset_size, uint8_t slave_addr_size, uint16_t num_bytes, uint32_t *data)
Write to the TWI bus using TWI Access MRPC.
bool switchtec_stack_bif_port_valid(struct switchtec_dev *dev, int stack_id, int port_id)
Return true if a port within a stack is valid.
int switchtec_hard_reset(struct switchtec_dev *dev)
Perform an MRPC hard reset command.
int switchtec_log_def_to_file(struct switchtec_dev *dev, enum switchtec_log_def_type type, FILE *file)
Dump the Switchtec log definition data to a file.
int switchtec_get_device_info(struct switchtec_dev *dev, enum switchtec_boot_phase *phase, enum switchtec_gen *gen, enum switchtec_rev *rev)
Get device generation, revision, and boot phase info.
static int read_app_log_defs(FILE *log_def_file, struct log_defs *defs)
Read an app log definition file and store the definitions.
static int realloc_log_defs(struct log_defs *defs, int num_modules)
Allocate / reallocate log definition data.
int switchtec_twi_access_read(struct switchtec_dev *dev, uint8_t twi_port, uint16_t slave_addr, uint32_t offset, uint8_t offset_size, uint8_t slave_addr_size, uint16_t num_bytes, uint32_t *output)
Read from the TWI bus using TWI Access MRPC.
int switchtec_en_dis_interrupt(struct switchtec_dev *dev, int pin_id, int en)
Enable/Disable the GPIO pin interrupt.
int switchtec_rtc_counter_reset(struct switchtec_dev *dev)
Perform a reset operation on the RTC counter.
int switchtec_echo(struct switchtec_dev *dev, uint32_t input, uint32_t *output)
Perform an MRPC echo command.
static bool parse_int(char *str, int *val)
Parse an integer from a string.
int switchtec_get_all_pin_sts(struct switchtec_dev *dev, uint32_t *values)
Get all GPIO pin status.
int switchtec_set_stack_bif(struct switchtec_dev *dev, int stack_id, int port_bif[SWITCHTEC_PORTS_PER_STACK])
Set the bifurcation of ports in a stack.
int switchtec_rtc_counter_get(struct switchtec_dev *dev, uint64_t *rtc_counter)
Get the RTC counter.
int switchtec_calc_lane_id(struct switchtec_dev *dev, int phys_port_id, int lane_id, struct switchtec_status *port)
Calculate the global lane ID for a lane within a physical port.
int switchtec_get_gpio_direction_cfg(struct switchtec_dev *dev, int pin_id, int *direction)
Get the GPIO pin direction.
int switchtec_calc_port_lane(struct switchtec_dev *dev, int lane_id, int *phys_port_id, int *port_lane_id, struct switchtec_status *port)
Calculate the port and lane within the port from a global lane ID.
static int write_parsed_log(struct log_a_data log_data[], size_t count, int init_entry_idx, struct log_defs *defs, enum switchtec_log_parse_type log_type, FILE *log_file, int ts_factor)
Parse an app log or mailbox log and write the results to a file.
Log definitions for all modules.
struct module_log_defs * module_defs
per-module log definitions
int num_alloc
number of modules allocated
Module-specific log definitions.
char * mod_name
module name
int num_entries
number of log entries
char ** entries
log entry array
Switchtec device id to generation/variant mapping.
Represents a Switchtec device in the switchtec_list() function.
Information about log file and log definition file.
unsigned char upstream
1 if this is an upstream port
unsigned char partition
Partition the port is in.
unsigned char stk_id
Port number within the stack.
unsigned char log_id
Logical port number.
unsigned char phys_id
Physical port number.
unsigned char stack
Stack number.
struct switchtec_port_id port
Port ID.
unsigned char link_up
1 if the link is up
unsigned char lane_reversal
Lane reversal.
unsigned int acs_ctrl
ACS Setting of the Port.
const char * lane_reversal_str
Lane reversal as a string.
unsigned char cfg_lnk_width
Configured link width.
unsigned char link_rate
Link rate/gen.
unsigned char first_act_lane
First active lane.
unsigned char neg_lnk_width
Negotiated link width.
uint16_t ltssm
Link state.
const char * ltssm_str
Link state as a string.
switchtec_log_parse_type
Log types to parse.
switchtec_rev
Device hardware revision.
switchtec_gen
The PCIe generations.
switchtec_log_def_type
Log definition data types.
switchtec_variant
The variant types of Switchtec device.
static int switchtec_is_gen6(struct switchtec_dev *dev)
Return whether a Switchtec device is a Gen 6 device.
switchtec_log_type
Describe the type of logs too dump.
switchtec_boot_phase
Device boot phase.
static int switchtec_is_gen4(struct switchtec_dev *dev)
Return whether a Switchtec device is a Gen 4 device.
static int switchtec_max_supported_ports(struct switchtec_dev *dev)
Return the max number of ports of a Switchtec device.
static int switchtec_is_gen5(struct switchtec_dev *dev)
Return whether a Switchtec device is a Gen 5 device.
static int switchtec_is_pax_all(struct switchtec_dev *dev)
Return whether a Switchtec device is PAX(A).
static int switchtec_is_gen3(struct switchtec_dev *dev)
Return whether a Switchtec device is a Gen 3 device.