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_PAXA},
166 {0x5384, SWITCHTEC_GEN5, SWITCHTEC_PAXA},
167 {0x5368, SWITCHTEC_GEN5, SWITCHTEC_PAXA},
168 {0x5352, SWITCHTEC_GEN5, SWITCHTEC_PAXA},
169 {0x5336, SWITCHTEC_GEN5, SWITCHTEC_PAXA},
170 {0x5328, SWITCHTEC_GEN5, SWITCHTEC_PAXA},
171 {0x5400, SWITCHTEC_GEN5, SWITCHTEC_PFXA},
172 {0x5484, SWITCHTEC_GEN5, SWITCHTEC_PFXA},
173 {0x5468, SWITCHTEC_GEN5, SWITCHTEC_PFXA},
174 {0x5452, SWITCHTEC_GEN5, SWITCHTEC_PFXA},
175 {0x5436, SWITCHTEC_GEN5, SWITCHTEC_PFXA},
176 {0x5428, SWITCHTEC_GEN5, SWITCHTEC_PFXA},
180 static int set_gen_variant(
struct switchtec_dev * dev)
185 dev->boot_phase = SWITCHTEC_BOOT_PHASE_FW;
186 dev->gen = SWITCHTEC_GEN_UNKNOWN;
187 dev->var = SWITCHTEC_VAR_UNKNOWN;
188 dev->device_id = dev->ops->get_device_id(dev);
190 switchtec_get_device_id_bl2(dev,
191 (
unsigned short *)&dev->device_id);
193 while (id->device_id) {
194 if (id->device_id == dev->device_id) {
213 unsigned char local_pax_id;
218 dev->local_pax_id = 0;
224 &local_pax_id,
sizeof(local_pax_id));
228 dev->local_pax_id = local_pax_id;
266 struct switchtec_dev *ret;
268 if (sscanf(device,
"%i@%i", &bus, &dev) == 2) {
269 ret = switchtec_open_i2c_by_adapter(bus, dev);
273 if (sscanf(device,
"%2049[^@]@%i", path, &dev) == 2) {
278 if (device[0] ==
'/' &&
279 sscanf(device,
"%2049[^:]:%i", path, &dev) == 2) {
284 if (strchr(device,
'/') || strchr(device,
'\\')) {
289 if (sscanf(device,
"%x:%x.%x", &bus, &dev, &func) == 3) {
294 if (sscanf(device,
"%x:%x:%x.%x", &domain, &bus, &dev, &func) == 4) {
299 if (sscanf(device,
"%2049[^:]:%i", path, &inst) == 2) {
305 idx = strtol(device, &endptr, 0);
306 if (!errno && endptr != device) {
311 if (sscanf(device,
"switchtec%d", &idx) == 1) {
325 snprintf(ret->name,
sizeof(ret->name),
"%s", device);
327 if (set_gen_variant(ret))
345 return dev->device_id;
381 return dev->boot_phase;
403 return dev->partition;
406 int switchtec_set_pax_id(
struct switchtec_dev *dev,
int pax_id)
411 if (pax_id == SWITCHTEC_PAX_ID_LOCAL)
412 dev->pax_id = dev->local_pax_id;
414 dev->pax_id = pax_id;
419 static int compare_port_id(
const void *aa,
const void *bb)
427 return a->
log_id - b->log_id;
430 static int compare_status(
const void *aa,
const void *bb)
434 return compare_port_id(&a->
port, &b->port);
444 case 0:
return "Normal Lane Ordering";
445 case 1:
return "x16 (Full) Lane Reversal";
446 case 2:
return "x2 Lane Reversal";
447 case 4:
return "x4 Lane Reversal";
448 case 8:
return "x8 Lane Reversal";
449 default:
return "Unknown Lane Ordering";
472 s->lanes[l] =
'0' + i;
474 s->lanes[l] =
'a' + i - 10;
494 uint64_t port_bitmap = 0;
509 uint8_t phys_port_id;
516 uint8_t linkup_linkrate;
522 ret =
switchtec_cmd(dev, MRPC_LNKSTAT, &port_bitmap,
sizeof(port_bitmap),
523 ports,
sizeof(ports));
528 for (i = 0; i < max_ports; i++) {
529 if ((ports[i].stk_id >> 4) > SWITCHTEC_MAX_STACKS)
534 s = *status = calloc(nr_ports,
sizeof(*s));
538 for (i = 0, p = 0; i < max_ports && p < nr_ports; i++) {
539 if ((ports[i].stk_id >> 4) > SWITCHTEC_MAX_STACKS)
551 s[p].
link_up = ports[i].linkup_linkrate >> 7;
552 s[p].
link_rate = ports[i].linkup_linkrate & 0x7F;
553 s[p].
ltssm = le16toh(ports[i].LTSSM);
554 s[p].
ltssm_str = switchtec_ltssm_str(s[p].ltssm, 1);
560 generate_lane_str(&s[p]);
565 qsort(s, nr_ports,
sizeof(*s), compare_status);
580 for (i = 0; i < ports; i++) {
581 if (status[i].pci_bdf)
582 free(status[i].pci_bdf);
584 if (status[i].pci_bdf_path)
585 free(status[i].pci_bdf_path);
587 if (status[i].pci_dev)
588 free(status[i].pci_dev);
590 if (status[i].class_devices)
591 free(status[i].class_devices);
617 const char *msg =
"Unknown MRPC error";
620 if ((errno & (SWITCHTEC_ERRNO_MRPC_FLAG_BIT |
621 SWITCHTEC_ERRNO_GENERAL_FLAG_BIT)) == 0) {
623 return strerror(errno);
625 return platform_strerror();
628 if (errno & SWITCHTEC_ERRNO_GENERAL_FLAG_BIT) {
630 case SWITCHTEC_ERR_LOG_DEF_READ_ERROR:
631 msg =
"Error reading log definition file";
633 case SWITCHTEC_ERR_BIN_LOG_READ_ERROR:
634 msg =
"Error reading binary log file";
636 case SWITCHTEC_ERR_PARSED_LOG_WRITE_ERROR:
637 msg =
"Error writing parsed log file";
639 case SWITCHTEC_ERR_LOG_DEF_DATA_INVAL:
640 msg =
"Invalid log definition data";
642 case SWITCHTEC_ERR_INVALID_PORT:
643 msg =
"Invalid port specified";
645 case SWITCHTEC_ERR_INVALID_LANE:
646 msg =
"Invalid lane specified";
649 msg =
"Unknown Switchtec error";
656 err = errno & ~SWITCHTEC_ERRNO_MRPC_FLAG_BIT;
659 case ERR_NO_AVAIL_MRPC_THREAD:
660 msg =
"No available MRPC handler thread";
662 case ERR_HANDLER_THREAD_NOT_IDLE:
663 msg =
"The handler thread is not idle";
665 case ERR_NO_BG_THREAD:
666 msg =
"No background thread run for the command";
669 case ERR_REFCLK_SUBCMD_INVALID:
670 case ERR_STACKBIF_SUBCMD_INVALID:
671 case ERR_SUBCMD_INVALID:
672 msg =
"Invalid subcommand";
674 case ERR_CMD_INVALID:
675 msg =
"Invalid command";
677 case ERR_PARAM_INVALID:
678 msg =
"Invalid parameter";
680 case ERR_BAD_FW_STATE:
681 msg =
"Bad firmware state";
683 case ERR_MRPC_DENIED:
684 msg =
"MRPC request denied";
686 case ERR_MRPC_NO_PREV_DATA:
687 msg =
"No previous adaptation object data";
689 case ERR_REFCLK_STACK_ID_INVALID:
690 case ERR_STACKBIF_STACK_ID_INVALID:
691 case ERR_STACK_INVALID:
692 msg =
"Invalid Stack";
694 case ERR_LOOPBACK_PORT_INVALID:
695 case ERR_PORT_INVALID:
696 msg =
"Invalid Port";
698 case ERR_EVENT_INVALID:
699 msg =
"Invalid Event";
701 case ERR_RST_RULE_FAILED:
702 msg =
"Reset rule search failed";
704 case ERR_UART_NOT_SUPPORTED:
705 msg =
"UART interface not supported for this command";
707 case ERR_XML_VERSION_MISMATCH:
708 msg =
"XML version mismatch between MAIN and CFG partition";
710 case ERR_ACCESS_REFUSED:
711 msg =
"Access Refused";
714 case ERR_STACKBIF_CODE_INVALID:
715 msg =
"Stack bifurcation code invalid";
717 case ERR_STACKBIF_PORT_BOUND:
718 msg =
"Port already bound";
720 case ERR_FLM_NOT_INITIALIZED:
721 msg =
"MRPC command not Supported as flash is not initialized";
728 case MRPC_PORTPARTP2P:
730 case ERR_PHYC_PORT_ARDY_BIND:
731 msg =
"Physical port already bound";
733 case ERR_LOGC_PORT_ARDY_BIND:
734 msg =
"Logical bridge instance already bound";
736 case ERR_BIND_PRTT_NOT_EXIST:
737 msg =
"Partition does not exist";
739 case ERR_PHYC_PORT_NOT_EXIST:
740 msg =
"Physical port does not exist";
742 case ERR_PHYC_PORT_DIS:
743 msg =
"Physical port disabled";
745 case ERR_NO_LOGC_PORT:
746 msg =
"No logical bridge instance";
748 case ERR_BIND_IN_PROGRESS:
749 msg =
"Bind/unbind in progress";
751 case ERR_BIND_TGT_IS_USP:
752 msg =
"Bind/unbind target is USP";
754 case ERR_BIND_SUBCMD_INVALID:
755 msg =
"Sub-command does not exist";
757 case ERR_PHYC_PORT_LINK_ACT:
758 msg =
"Physical port link active";
760 case ERR_LOGC_PORT_NOT_BIND_PHYC_PORT:
761 msg =
"Logical bridge not bind to physical port";
763 case ERR_UNBIND_OPT_INVALID:
764 msg =
"Invalid unbind option";
766 case ERR_BIND_CHECK_FAIL:
767 msg =
"Port bind checking failed";
790 int is_mrpc = errno & SWITCHTEC_ERRNO_MRPC_FLAG_BIT;
791 int err = errno & ~SWITCHTEC_ERRNO_MRPC_FLAG_BIT;
794 fprintf(stderr,
"%s: %s (MRPC: 0x%x, error: 0x%x)\n",
797 fprintf(stderr,
"%s: %s\n", str, msg);
822 output,
sizeof(*output));
838 return switchtec_cmd(dev, MRPC_RESET, &subcmd,
sizeof(subcmd),
883 for (i = defs->
num_alloc; i < num_modules; i++)
903 *val = strtol(str, &endptr, 0);
905 if ((endptr == str) || (*endptr !=
'\0') || (errno != 0))
932 while (fgets(line,
sizeof(line), log_def_file)) {
939 line[strcspn(line,
"\r\n")] =
'\0';
945 tok = strtok(line,
" \t");
949 tok = strtok(NULL,
" \t");
954 errno = SWITCHTEC_ERR_LOG_DEF_DATA_INVAL;
955 goto err_free_log_defs;
967 tok = strtok(NULL,
" \t");
972 errno = SWITCHTEC_ERR_LOG_DEF_DATA_INVAL;
973 goto err_free_log_defs;
982 if (!fgets(line,
sizeof(line),
994 goto err_free_log_defs;
997 if (fgets(line,
sizeof(line), log_def_file) == NULL) {
998 errno = SWITCHTEC_ERR_LOG_DEF_READ_ERROR;
999 goto err_free_log_defs;
1002 mod_defs->
entries[i] = strdup(line);
1004 goto err_free_log_defs;
1008 if (ferror(log_def_file)) {
1009 errno = SWITCHTEC_ERR_LOG_DEF_READ_ERROR;
1010 goto err_free_log_defs;
1031 int num_entries_alloc;
1045 num_entries_alloc = 100;
1046 mod_defs->
entries = calloc(num_entries_alloc,
1049 goto err_free_log_defs;
1051 while (fgets(line,
sizeof(line), log_def_file)) {
1058 num_entries_alloc *= 2;
1060 (num_entries_alloc *
1063 goto err_free_log_defs;
1068 goto err_free_log_defs;
1073 if (ferror(log_def_file)) {
1074 errno = SWITCHTEC_ERR_LOG_DEF_READ_ERROR;
1075 goto err_free_log_defs;
1097 size_t count,
int init_entry_idx,
1100 FILE *log_file,
int ts_factor)
1104 int entry_idx = init_entry_idx;
1105 unsigned long long time;
1106 unsigned int nanos, micros, millis, secs, mins, hours, days;
1107 unsigned int entry_num;
1108 unsigned int mod_id;
1109 unsigned int log_sev = 0;
1110 const char *log_sev_strs[] = {
"DISABLED",
"HIGHEST",
"HIGH",
"MEDIUM",
1115 if (entry_idx == 0) {
1116 if (log_type == SWITCHTEC_LOG_PARSE_TYPE_APP)
1117 fputs(
" #|Timestamp |Module |Severity |Event ID |Event\n",
1120 fputs(
" #|Timestamp |Source |Event ID |Event\n",
1124 for (i = 0; i < count; i ++) {
1126 time = (((
unsigned long long)log_data[i].data[0] << 32) |
1127 log_data[i].data[1]) * ts_factor/100;
1128 nanos = time % 1000;
1130 micros = time % 1000;
1132 millis = time % 1000;
1141 if (log_type == SWITCHTEC_LOG_PARSE_TYPE_APP) {
1146 mod_id = (log_data[i].data[2] >> 16) & 0xFFF;
1147 log_sev = (log_data[i].data[2] >> 28) & 0xF;
1152 if (fprintf(log_file,
"(Invalid module ID: 0x%x)\n",
1154 goto ret_print_error;
1158 if (log_sev >= ARRAY_SIZE(log_sev_strs)) {
1159 if (fprintf(log_file,
"(Invalid log severity: %d)\n",
1161 goto ret_print_error;
1169 is_bl1 = (((log_data[i].data[2] >> 27) & 1) == 0);
1178 entry_num = log_data[i].data[2] & 0x0000FFFF;
1181 if (fprintf(log_file,
1182 "(Invalid log entry number: %d (module 0x%x))\n",
1183 entry_num, mod_id) < 0)
1184 goto ret_print_error;
1190 ret = fprintf(log_file,
1191 "%04d|xxxd xx:xx:xx.xxx,xxx,xxx|",
1194 ret = fprintf(log_file,
1195 "%04d|%03dd %02d:%02d:%02d.%03d,%03d,%03d|",
1196 entry_idx, days, hours, mins, secs,
1197 millis, micros, nanos);
1200 goto ret_print_error;
1202 if (log_type == SWITCHTEC_LOG_PARSE_TYPE_APP) {
1204 if (fprintf(log_file,
"%-12s |%-8s |0x%04x |",
1205 mod_defs->
mod_name, log_sev_strs[log_sev],
1207 goto ret_print_error;
1210 if (fprintf(log_file,
"%-6s |0x%04x |",
1211 (is_bl1 ?
"BL1" :
"BL2"), entry_num) < 0)
1212 goto ret_print_error;
1216 if (fprintf(log_file, mod_defs->
entries[entry_num],
1217 log_data[i].data[3], log_data[i].data[4],
1218 log_data[i].data[5], log_data[i].data[6],
1219 log_data[i].data[7]) < 0)
1220 goto ret_print_error;
1225 if (fflush(log_file) != 0)
1231 errno = SWITCHTEC_ERR_PARSED_LOG_WRITE_ERROR;
1235 static int parse_def_header(FILE *log_def_file, uint32_t *fw_version,
1236 uint32_t *sdk_version)
1243 while (fgets(line,
sizeof(line), log_def_file)) {
1248 while (line[i] ==
' ' || line[i] ==
'#') i++;
1250 if (strncasecmp(line + i,
"SDK Version:", 12) == 0) {
1252 while (line[i] ==
' ') i++;
1253 sscanf(line + i,
"%i", (
int*)sdk_version);
1255 else if (strncasecmp(line + i,
"FW Version:", 11) == 0) {
1257 while (line[i] ==
' ') i++;
1258 sscanf(line + i,
"%i", (
int*)fw_version);
1262 rewind(log_def_file);
1266 static int append_log_header(
int fd, uint32_t sdk_version,
1267 uint32_t fw_version,
int binary)
1272 uint32_t fw_version;
1273 uint32_t sdk_version;
1277 .magic = {
'S',
'W',
'M',
'C',
'L',
'O',
'G',
'F'},
1278 .fw_version = fw_version,
1279 .sdk_version = sdk_version
1281 char hdr_str_fmt[] =
"#########################\n"
1282 "## FW version %08x\n"
1283 "## SDK version %08x\n"
1284 "#########################\n\n";
1288 ret = write(fd, &header,
sizeof(header));
1290 snprintf(hdr_str, 512, hdr_str_fmt, fw_version, sdk_version);
1291 ret = write(fd, hdr_str, strlen(hdr_str));
1299 if (gen == SWITCHTEC_GEN_UNKNOWN)
1301 else if (gen == SWITCHTEC_GEN3)
1307 static int log_a_to_file(
struct switchtec_dev *dev,
int sub_cmd_id,
1308 int fd, FILE *log_def_file,
1315 .sub_cmd_id = sub_cmd_id,
1323 uint32_t fw_version = 0;
1324 uint32_t sdk_version = 0;
1326 if (log_def_file != NULL) {
1327 ret = parse_def_header(log_def_file, &fw_version,
1339 while (res.hdr.remain) {
1343 goto ret_free_log_defs;
1344 if (res.hdr.overflow && info)
1347 if (dev->gen < SWITCHTEC_GEN5) {
1348 res.hdr.sdk_version = 0;
1349 res.hdr.fw_version = 0;
1353 info->def_fw_version = fw_version;
1354 info->def_sdk_version = sdk_version;
1355 info->log_fw_version = res.hdr.fw_version;
1356 info->log_sdk_version = res.hdr.sdk_version;
1359 if (res.hdr.sdk_version != sdk_version ||
1360 res.hdr.fw_version != fw_version) {
1361 if (info && log_def_file)
1362 info->version_mismatch =
true;
1366 append_log_header(fd, res.hdr.sdk_version,
1368 log_def_file == NULL? 1 : 0);
1371 if (log_def_file == NULL) {
1373 ret = write(fd, res.data,
1374 sizeof(*res.data) * res.hdr.count);
1378 log_file = fdopen(fd,
"w");
1380 goto ret_free_log_defs;
1385 SWITCHTEC_LOG_PARSE_TYPE_APP,
1387 get_ts_factor(dev->gen));
1389 goto ret_free_log_defs;
1391 entry_idx += res.hdr.count;
1394 read += le32toh(res.hdr.count);
1395 cmd.start = res.hdr.next_start;
1405 static int log_b_to_file(
struct switchtec_dev *dev,
int sub_cmd_id,
int fd)
1411 .sub_cmd_id = sub_cmd_id,
1413 .length = htole32(
sizeof(res.data)),
1416 res.hdr.remain =
sizeof(res.data);
1418 while (res.hdr.remain) {
1424 ret = write(fd, res.data, res.hdr.length);
1428 read += le32toh(res.hdr.length);
1429 cmd.offset = htole32(read);
1435 static int log_c_to_file(
struct switchtec_dev *dev,
int sub_cmd_id,
int fd)
1446 uint32_t nvlog_version;
1447 uint32_t thread_handle;
1448 uint32_t fw_version;
1449 uint32_t timestamp1;
1450 uint32_t timestamp2;
1453 cmd.subcmd = sub_cmd_id;
1456 &reply,
sizeof(reply));
1460 ret = write(fd, &reply,
sizeof(reply));
1467 static int log_ram_flash_to_file(
struct switchtec_dev *dev,
1468 int gen5_cmd,
int gen4_cmd,
int gen4_cmd_lgcy,
1469 int fd, FILE *log_def_file,
1475 return log_a_to_file(dev, gen5_cmd, fd, log_def_file,
1478 ret = log_a_to_file(dev, gen4_cmd, fd, log_def_file,
1487 (ERRNO_MRPC(errno) == ERR_LOGC_PORT_ARDY_BIND ||
1488 ERRNO_MRPC(errno) == ERR_SUBCMD_INVALID))
1489 ret = log_a_to_file(dev, gen4_cmd_lgcy, fd,
1490 log_def_file, info);
1510 memset(info, 0,
sizeof(*info));
1513 case SWITCHTEC_LOG_RAM:
1514 return log_ram_flash_to_file(dev,
1515 MRPC_FWLOGRD_RAM_GEN5,
1516 MRPC_FWLOGRD_RAM_WITH_FLAG,
1518 fd, log_def_file, info);
1519 case SWITCHTEC_LOG_FLASH:
1520 return log_ram_flash_to_file(dev,
1521 MRPC_FWLOGRD_FLASH_GEN5,
1522 MRPC_FWLOGRD_FLASH_WITH_FLAG,
1524 fd, log_def_file, info);
1525 case SWITCHTEC_LOG_MEMLOG:
1526 return log_b_to_file(dev, MRPC_FWLOGRD_MEMLOG, fd);
1527 case SWITCHTEC_LOG_REGS:
1528 return log_b_to_file(dev, MRPC_FWLOGRD_REGS, fd);
1529 case SWITCHTEC_LOG_THRD_STACK:
1530 return log_b_to_file(dev, MRPC_FWLOGRD_THRD_STACK, fd);
1531 case SWITCHTEC_LOG_SYS_STACK:
1532 return log_b_to_file(dev, MRPC_FWLOGRD_SYS_STACK, fd);
1533 case SWITCHTEC_LOG_THRD:
1534 return log_b_to_file(dev, MRPC_FWLOGRD_THRD, fd);
1535 case SWITCHTEC_LOG_NVHDR:
1536 return log_c_to_file(dev, MRPC_FWLOGRD_NVHDR, fd);
1543 static int parse_log_header(FILE *bin_log_file, uint32_t *fw_version,
1544 uint32_t *sdk_version)
1548 uint32_t fw_version;
1549 uint32_t sdk_version;
1554 char sig[8] = {
'S',
'W',
'M',
'C',
'L',
'O',
'G',
'F'};
1557 ret = fread(&header,
sizeof(header), 1, bin_log_file);
1563 if (memcmp(sig, header.magic, 8)) {
1564 rewind(bin_log_file);
1570 *fw_version = header.fw_version;
1571 *sdk_version = header.sdk_version;
1587 FILE *parsed_log_file,
1598 uint32_t fw_version_log;
1599 uint32_t sdk_version_log;
1600 uint32_t fw_version_def;
1601 uint32_t sdk_version_def;
1605 memset(info, 0,
sizeof(*info));
1607 if ((log_type != SWITCHTEC_LOG_PARSE_TYPE_APP) &&
1608 (log_type != SWITCHTEC_LOG_PARSE_TYPE_MAILBOX)) {
1613 ret = parse_log_header(bin_log_file, &fw_version_log,
1617 ret = parse_def_header(log_def_file, &fw_version_def,
1622 if (log_type == SWITCHTEC_LOG_PARSE_TYPE_MAILBOX) {
1623 fw_version_log = fw_version_def;
1624 sdk_version_log = sdk_version_def;
1628 info->def_fw_version = fw_version_def;
1629 info->def_sdk_version = sdk_version_def;
1631 info->log_fw_version = fw_version_log;
1632 info->log_sdk_version = sdk_version_log;
1635 if (log_type == SWITCHTEC_LOG_PARSE_TYPE_APP)
1640 ret = append_log_header(fileno(parsed_log_file), sdk_version_log,
1646 while (fread(&log_data,
sizeof(
struct log_a_data), 1,
1647 bin_log_file) == 1) {
1653 if (gen_file != SWITCHTEC_GEN_UNKNOWN &&
1654 gen != SWITCHTEC_GEN_UNKNOWN) {
1656 info->gen_ignored =
true;
1657 }
else if (gen_file == SWITCHTEC_GEN_UNKNOWN &&
1658 gen == SWITCHTEC_GEN_UNKNOWN) {
1660 info->gen_unknown =
true;
1661 }
else if (gen != SWITCHTEC_GEN_UNKNOWN) {
1666 log_type, parsed_log_file,
1667 get_ts_factor(gen_file));
1669 goto ret_free_log_defs;
1674 if (ferror(bin_log_file)) {
1675 errno = SWITCHTEC_ERR_BIN_LOG_READ_ERROR;
1679 if (fw_version_def != fw_version_log ||
1680 sdk_version_def != sdk_version_log) {
1682 info->version_mismatch =
true;
1711 uint16_t end_of_data;
1714 uint16_t next_mod_id;
1715 uint8_t data[MRPC_MAX_DATA_LEN - 16];
1719 case SWITCHTEC_LOG_DEF_TYPE_APP:
1720 cmd.subcmd = MRPC_LOG_DEF_APP;
1723 case SWITCHTEC_LOG_DEF_TYPE_MAILBOX:
1724 cmd.subcmd = MRPC_LOG_DEF_MAILBOX;
1733 ret =
switchtec_cmd(dev, MRPC_LOG_DEF_GET, &cmd,
sizeof(cmd),
1734 &reply,
sizeof(reply));
1738 ret = fwrite(reply.data, reply.data_len, 1, file);
1742 cmd.idx = reply.next_idx;
1743 cmd.mod_id = reply.next_mod_id;
1744 }
while (!reply.end_of_data);
1755 ret = SWITCHTEC_GEN4;
1758 ret = SWITCHTEC_GEN5;
1761 ret = SWITCHTEC_GEN_UNKNOWN;
1774 case STMFD_RCVRY_BL1_STRAP:
1775 case STMFD_RCVRY_BL1_ASSERT:
1776 boot_phase = SWITCHTEC_BOOT_PHASE_BL1;
1778 case STMFD_RCVRY_BL2_STRAP:
1779 case STMFD_RCVRY_BL2_ASSERT:
1780 case STMFD_RCVRY_BL2_EXEC:
1781 boot_phase = SWITCHTEC_BOOT_PHASE_BL2;
1783 case STMFD_RCVRY_MAINFW:
1784 boot_phase = SWITCHTEC_BOOT_PHASE_FW;
1787 boot_phase = SWITCHTEC_BOOT_PHASE_UNKNOWN;
1809 uint32_t ping_dw = 0;
1811 struct get_dev_info_reply {
1813 uint32_t ping_reply;
1814 uint32_t strap_stat;
1815 uint32_t fw_version;
1820 ping_dw = time(NULL);
1828 &reply,
sizeof(reply));
1830 if (ping_dw != ~reply.ping_reply)
1833 dev_info = le32toh(reply.dev_info);
1835 revision = (dev_info >> 20) & 0x0f;
1840 *phase = dev_info & 0xff;
1842 *phase = parse_boot_phase_ping(dev_info & 0xff);
1846 *rev = (dev_info >> 8) & 0x0f;
1849 *gen = map_to_gen((dev_info >> 12) & 0x0f);
1855 ping_info->rcvry_entry_reason = dev_info & 0xff;
1856 ping_info->ping_rev = revision;
1857 ping_info->hw_rev = (dev_info >> 8) & 0x0f;
1858 ping_info->strap_stat = le32toh(reply.strap_stat);
1859 ping_info->fw_version = reply.fw_version;
1860 ping_info->spi_freq = reply.spi_freq;
1861 ping_info->dev_family = (dev_info >> 16) & 0x0f;
1865 }
else if (errno == EBADMSG || ERRNO_MRPC(errno) == ERR_CMD_INVALID) {
1867 *phase = SWITCHTEC_BOOT_PHASE_FW;
1869 *gen = SWITCHTEC_GEN3;
1871 *rev = SWITCHTEC_REV_UNKNOWN;
1890 uint32_t sub_cmd_id;
1894 sub_cmd_id = MRPC_DIETEMP_SET_MEAS;
1896 sizeof(sub_cmd_id), NULL, 0);
1900 sub_cmd_id = MRPC_DIETEMP_GET;
1902 sizeof(sub_cmd_id), &temp,
sizeof(temp));
1906 sub_cmd_id = MRPC_DIETEMP_GET_GEN4;
1908 sizeof(sub_cmd_id), &temp,
sizeof(temp));
1913 return le32toh(temp) / 100.;
1916 int switchtec_bind_info(
struct switchtec_dev *dev,
1920 .sub_cmd = MRPC_PORT_INFO,
1921 .phys_port_id = phy_port
1925 sizeof(sub_cmd_id), status,
sizeof(*status));
1928 int switchtec_bind(
struct switchtec_dev *dev,
int par_id,
int log_port,
1934 .sub_cmd = MRPC_PORT_BIND,
1936 .log_port_id = log_port,
1937 .phys_port_id = phy_port
1941 sizeof(sub_cmd_id), &output,
sizeof(output));
1944 int switchtec_unbind(
struct switchtec_dev *dev,
int par_id,
int log_port)
1949 .sub_cmd = MRPC_PORT_UNBIND,
1951 .log_port_id = log_port,
1956 sizeof(sub_cmd_id), &output,
sizeof(output));
1959 static int __switchtec_calc_lane_id(
struct switchtec_status *port,
int lane_id)
1964 errno = SWITCHTEC_ERR_INVALID_LANE;
1985 default:
return lane;
2008 for (i = 0; i < ports; i++)
2013 errno = SWITCHTEC_ERR_INVALID_PORT;
2021 rc = __switchtec_calc_lane_id(&status[i], lane_id);
2038 int *phys_port_id,
int *port_lane_id,
2042 int ports, i, p, lane;
2049 if (lane_id >= 96) {
2050 if (dev->gen < SWITCHTEC_GEN5)
2051 p = lane_id - 96 + 48;
2053 p = lane_id - 96 + 56;
2055 for (i = 0; i < ports; i++)
2059 for (i = 0; i < ports; i++) {
2067 errno = SWITCHTEC_ERR_INVALID_PORT;
2079 if (
port->lane_reversal)
2083 *port_lane_id = lane;
2102 int lane_id,
int num_lanes,
int *lane_mask,
2106 int ports, i, l, lane;
2113 for (i = 0; i < ports; i++)
2118 errno = SWITCHTEC_ERR_INVALID_PORT;
2126 for (l = lane_id; l < lane_id + num_lanes; l++) {
2127 lane = __switchtec_calc_lane_id(&status[i], l);
2133 lane_mask[lane >> 5] |= 1 << (lane & 0x1F);
2151 if (dev->gen == SWITCHTEC_GEN4)
2152 return stack_id * 8 + port_id < 52;
2170 if (port_bif != 1 && port_bif != 2 && port_bif != 4 && port_bif != 8 &&
2176 if (dev->gen == SWITCHTEC_GEN4 && stack_id == 6)
2179 return (port_bif + 1) / 2;
2190 int port_bif[SWITCHTEC_PORTS_PER_STACK])
2193 .sub_cmd = MRPC_STACKBIF_GET,
2194 .stack_id = stack_id,
2198 ret =
switchtec_cmd(dev, MRPC_STACKBIF, &in,
sizeof(in), &out,
2203 for (i = 0; i < SWITCHTEC_PORTS_PER_STACK; i++) {
2209 switch (out.code & 0xF) {
2210 case 0x0: port_bif[i] = 0;
break;
2211 case 0x1: port_bif[i] = 2;
break;
2212 case 0x2: port_bif[i] = 4;
break;
2213 case 0x4: port_bif[i] = 8;
break;
2214 case 0x8: port_bif[i] = 16;
break;
2215 case 0xf: port_bif[i] = 1;
break;
2234 int port_bif[SWITCHTEC_PORTS_PER_STACK])
2237 .sub_cmd = MRPC_STACKBIF_SET,
2238 .stack_id = stack_id,
2242 for (i = 0; i < SWITCHTEC_PORTS_PER_STACK; i++) {
2243 switch (port_bif[i]) {
2244 case 0: in.code |= 0x0 << (i * 4);
break;
2245 case 1: in.code |= 0xf << (i * 4);
break;
2246 case 2: in.code |= 0x1 << (i * 4);
break;
2247 case 4: in.code |= 0x2 << (i * 4);
break;
2248 case 8: in.code |= 0x4 << (i * 4);
break;
2249 case 16: in.code |= 0x8 << (i * 4);
break;
2256 return switchtec_cmd(dev, MRPC_STACKBIF, &in,
sizeof(in), &out,