// Copyright(c) 2019-2020, Intel Corporation
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of Intel Corporation nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <glob.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <net/ethernet.h>
#include <opae/properties.h>
#include <opae/utils.h>
#include <opae/fpga.h>
#include <sys/ioctl.h>
#include "board_vc.h"
// sysfs paths
#define SYSFS_BMCFW_VER "spi-altera.*.auto/spi_master/spi*/spi*.*/bmcfw_flash_ctrl/bmcfw_version"
#define SYSFS_MAX10_VER "spi-altera.*.auto/spi_master/spi*/spi*.*/max10_version"
#define SYSFS_PCB_INFO "spi-altera.*.auto/spi_master/spi*/spi*.*/pcb_info"
#define SYSFS_PKVL_POLL_MODE "spi-altera.*.auto/spi_master/spi*/spi*.*/pkvl/polling_mode"
#define SYSFS_PKVL_STATUS "spi-altera.*.auto/spi_master/spi*/spi*.*/pkvl/status"
#define SYSFS_BS_ID "bitstream_id"
#define SYSFS_PHY_GROUP_INFO "pac_n3000_net*/misc/eth_group*.*"
#define SYSFS_PHY_GROUP_INFO_DEV "pac_n3000_net*/misc/eth_group*/dev"
#define SYSFS_EEPROM "*i2c*/i2c*/*/eeprom"
#define SYSFS_NVMEM "*i2c*/i2c*/*/nvmem"
#define SYSFS_PKVL_A_VER "spi-altera.*.auto/spi_master/spi*/spi*.*/pkvl/pkvl_a_version"
#define SYSFS_PKVL_B_VER "spi-altera.*.auto/spi_master/spi*/spi*.*/pkvl/pkvl_b_version"
// driver ioctl id
#define FPGA_PHY_GROUP_GET_INFO 0xB702
#define FPGA_BSID_SIZE 32
// fpga phy group mode
#define FPGA_PHYGROUP_MODE_4_25G 1
#define FPGA_PHYGROUP_MODE_6_25G 3
#define FPGA_PHYGROUP_MODE_2_2_25G 4
// Read BMC firmware version
fpga_result read_bmcfw_version(fpga_token token, char *bmcfw_ver, size_t len)
{
fpga_result res = FPGA_OK;
fpga_result resval = FPGA_OK;
uint32_t size = 0;
char buf[FPGA_VAR_BUF_LEN] = { 0 };
fpga_object bmcfw_object;
if (bmcfw_ver == NULL) {
FPGA_ERR("Invalid Input parameters");
return FPGA_INVALID_PARAM;
}
res = fpgaTokenGetObject(token, SYSFS_BMCFW_VER, &bmcfw_object, FPGA_OBJECT_GLOB);
if (res != FPGA_OK) {
OPAE_MSG("Failed to get token object");
return res;
}
res = fpgaObjectGetSize(bmcfw_object, &size, 0);
if (res != FPGA_OK) {
OPAE_ERR("Failed to read object size ");
resval = res;
goto out_destroy;
}
// Return error if object size bigger then buffer size
if (size > FPGA_VAR_BUF_LEN) {
FPGA_ERR("object size bigger then buffer size");
resval = FPGA_EXCEPTION;
goto out_destroy;
}
res = fpgaObjectRead(bmcfw_object, (uint8_t *)buf, 0, size, 0);
if (res != FPGA_OK) {
OPAE_ERR("Failed to read object ");
resval = res;
goto out_destroy;
}
res = parse_fw_ver(buf, bmcfw_ver, len);
if (res != FPGA_OK) {
OPAE_ERR("Failed to parse version ");
resval = res;
goto out_destroy;
}
out_destroy:
res = fpgaDestroyObject(&bmcfw_object);
if (res != FPGA_OK) {
OPAE_ERR("Failed to destroy object");
}
return resval;
}
fpga_result parse_fw_ver(char *buf, char *fw_ver, size_t len)
{
uint8_t rev = 0;
uint32_t var = 0;
fpga_result res = FPGA_OK;
int retval = 0;
if (buf == NULL ||
fw_ver == NULL) {
FPGA_ERR("Invalid Input parameters");
return FPGA_INVALID_PARAM;
}
/* BMC FW version format reading
NIOS II Firmware Build 0x0 32 RW[23:0] 24 hFFFFFF Build version of NIOS II Firmware
NIOS FW is up e.g. 1.0.1 for first release
[31:24] 8hFF Firmware Support Revision - ASCII code
0xFF is the default value without NIOS FW, will be changed after NIOS FW is up
0x41(A)-For RevA
0x42(B)-For RevB
0x43(C)-For RevC
0x44(D)-For RevD
*/
errno = 0;
var = strtoul(buf, NULL, 16);
if (var == 0 &&
errno != 0) {
OPAE_ERR("Failed to covert buffer to integer: %s", strerror(errno));
return FPGA_EXCEPTION;
}
rev = (var >> 24) & 0xff;
if ((rev >= 'A') && (rev <= 'Z')) {// range from 'A' to 'Z'
retval = snprintf(fw_ver, len, "%c.%u.%u.%u", (char)rev, (var >> 16) & 0xff, (var >> 8) & 0xff, var & 0xff);
if (retval < 0) {
FPGA_ERR("error in formatting version");
return FPGA_EXCEPTION;
}
} else {
OPAE_ERR("Invalid firmware version");
res = FPGA_EXCEPTION;
}
return res;
}
// Read MAX10 firmware version
fpga_result read_max10fw_version(fpga_token token, char *max10fw_ver, size_t len)
{
fpga_result res = FPGA_OK;
fpga_result resval = FPGA_OK;
uint32_t size = 0;
char buf[FPGA_VAR_BUF_LEN] = { 0 };
fpga_object max10fw_object;
if (max10fw_ver == NULL) {
FPGA_ERR("Invalid input parameters");
return FPGA_INVALID_PARAM;
}
res = fpgaTokenGetObject(token, SYSFS_MAX10_VER, &max10fw_object, FPGA_OBJECT_GLOB);
if (res != FPGA_OK) {
OPAE_MSG("Failed to get token object");
return res;
}
res = fpgaObjectGetSize(max10fw_object, &size, 0);
if (res != FPGA_OK) {
OPAE_ERR("Failed to get object size ");
resval = res;
goto out_destroy;
}
// Return error if object size bigger then buffer size
if (size > FPGA_VAR_BUF_LEN) {
FPGA_ERR("object size bigger then buffer size");
resval = FPGA_EXCEPTION;
goto out_destroy;
}
res = fpgaObjectRead(max10fw_object, (uint8_t *)buf, 0, size, 0);
if (res != FPGA_OK) {
OPAE_ERR("Failed to read object ");
resval = res;
goto out_destroy;
}
res = parse_fw_ver(buf, max10fw_ver, len);
if (res != FPGA_OK) {
OPAE_ERR("Failed to parse version ");
resval = res;
goto out_destroy;
}
out_destroy:
res = fpgaDestroyObject(&max10fw_object);
if (res != FPGA_OK) {
OPAE_ERR("Failed to destroy object");
}
return resval;
}
// Read PCB information
fpga_result read_pcb_info(fpga_token token, char *pcb_info, size_t len)
{
fpga_result res = FPGA_OK;
fpga_result resval = FPGA_OK;
uint32_t size = 0;
fpga_object pcb_object;
if (pcb_info == NULL) {
FPGA_ERR("Invalid input parameters");
return FPGA_INVALID_PARAM;
}
res = fpgaTokenGetObject(token, SYSFS_PCB_INFO, &pcb_object, FPGA_OBJECT_GLOB);
if (res != FPGA_OK) {
OPAE_MSG("Failed to get token Object");
return res;
}
res = fpgaObjectGetSize(pcb_object, &size, 0);
if (res != FPGA_OK) {
OPAE_ERR("Failed to read object size");
resval = res;
goto out_destroy;
}
// Return error if object size bigger then pcb info length
if (size > len) {
FPGA_ERR("object size bigger then pcb info size");
resval = FPGA_EXCEPTION;
goto out_destroy;
}
res = fpgaObjectRead(pcb_object, (uint8_t *)pcb_info, 0, size, 0);
if (res != FPGA_OK) {
OPAE_ERR("Failed to read object ");
resval = res;
}
out_destroy:
res = fpgaDestroyObject(&pcb_object);
if (res != FPGA_OK) {
OPAE_ERR("Failed to destroy object");
}
return resval;
}
// Read PKVL information
fpga_result read_pkvl_info(fpga_token token,
fpga_pkvl_info *pkvl_info,
int *fpga_mode)
{
fpga_result res = FPGA_OK;
fpga_result resval = FPGA_OK;
uint64_t bs_id = 0;
uint64_t poll_mode = 0;
uint64_t status = 0;
fpga_object poll_mode_object;
fpga_object status_object;
fpga_object bsid_object;
if (pkvl_info == NULL ||
fpga_mode == NULL) {
FPGA_ERR("Invalid Input parameters");
return FPGA_INVALID_PARAM;
}
res = fpgaTokenGetObject(token, SYSFS_BS_ID, &bsid_object, FPGA_OBJECT_GLOB);
if (res != FPGA_OK) {
OPAE_ERR("Failed to get token object");
return res;
}
res = fpgaTokenGetObject(token, SYSFS_PKVL_POLL_MODE, &poll_mode_object, FPGA_OBJECT_GLOB);
if (res != FPGA_OK) {
OPAE_ERR("Failed to get token object");
resval = res;
goto out_destroy_bsid;
}
res = fpgaTokenGetObject(token, SYSFS_PKVL_STATUS, &status_object, FPGA_OBJECT_GLOB);
if (res != FPGA_OK) {
OPAE_ERR("Failed to get token object");
resval = res;
goto out_destroy_poll;
}
res = fpgaObjectRead64(bsid_object, &bs_id, 0);
if (res != FPGA_OK) {
OPAE_ERR("Failed to read object ");
resval = res;
goto out_destroy_status;
}
*fpga_mode = (bs_id >> FPGA_BSID_SIZE) & 0xf;
res = fpgaObjectRead64(poll_mode_object, &poll_mode, 0);
if (res != FPGA_OK) {
OPAE_ERR("Failed to read object ");
resval = res;
goto out_destroy_status;
}
res = fpgaObjectRead64(status_object, &status, 0);
if (res != FPGA_OK) {
OPAE_ERR("Failed to read object ");
resval = res;
goto out_destroy_status;
}
pkvl_info->polling_mode = (uint32_t)poll_mode;
pkvl_info->status = (uint32_t)status;
out_destroy_status:
res = fpgaDestroyObject(&status_object);
if (res != FPGA_OK) {
OPAE_ERR("Failed to destroy object");
}
out_destroy_poll:
res = fpgaDestroyObject(&poll_mode_object);
if (res != FPGA_OK) {
OPAE_ERR("Failed to destroy object");
}
out_destroy_bsid:
res = fpgaDestroyObject(&bsid_object);
if (res != FPGA_OK) {
OPAE_ERR("Failed to destroy object");
}
return resval;
}
// Read PHY group information
fpga_result read_phy_group_info(fpga_token token,
fpga_phy_group_info *group_info,
uint32_t *group_num)
{
fpga_result res = FPGA_OK;
fpga_result resval = FPGA_OK;
char path[SYSFS_MAX_SIZE] = { 0, };
char cdevid[CDEV_ID_SIZE] = { 0, };
size_t i = 0;
uint32_t group_dev_count = 0;
uint32_t obj_size = 0;
fpga_object dev_obj;
fpga_object group_object;
fpga_object group_dev_object;
if (group_num == NULL) {
FPGA_ERR("Invalid Input parameters");
return FPGA_INVALID_PARAM;
}
res = fpgaTokenGetObject(token, SYSFS_PHY_GROUP_INFO,
&group_object, FPGA_OBJECT_GLOB);
if (res != FPGA_OK) {
OPAE_ERR("Failed to get token object");
return FPGA_NOT_FOUND;
}
res = fpgaTokenGetObject(token, SYSFS_PHY_GROUP_INFO_DEV,
&group_dev_object, FPGA_OBJECT_GLOB);
if (res != FPGA_OK) {
OPAE_ERR("Failed to get token object");
resval = res;
goto out_destroy_group;
}
res = fpgaObjectGetSize(group_dev_object, &group_dev_count, FPGA_OBJECT_GLOB);
if (res != FPGA_OK) {
OPAE_ERR("Failed to get object size");
resval = res;
goto out_destroy_group_dev;
}
// Return number of group.
if (group_info == NULL) {
*group_num = group_dev_count;
resval = FPGA_OK;
goto out_destroy_group_dev;
}
// Return error if group device count bigger then group info array size
if (group_dev_count > *group_num) {
FPGA_ERR("group device count bigger then group info array size");
resval = FPGA_EXCEPTION;
goto out_destroy_group_dev;
}
for (i = 0; i < group_dev_count; i++) {
res = fpgaObjectGetObjectAt(group_dev_object, i, &dev_obj);
if (res != FPGA_OK) {
OPAE_ERR("Failed to get device node object from group device object");
resval = res;
continue;
}
res = fpgaObjectGetSize(dev_obj, &obj_size, 0);
if (res != FPGA_OK) {
OPAE_ERR("Failed to get object size");
resval = res;
res = fpgaDestroyObject(&dev_obj);
if (res != FPGA_OK) {
OPAE_ERR("Failed to destroy object");
}
continue;
}
if (obj_size > CDEV_ID_SIZE) {
OPAE_ERR("Device node obj size size bigger then buffer ");
resval = FPGA_EXCEPTION;
res = fpgaDestroyObject(&dev_obj);
if (res != FPGA_OK) {
OPAE_ERR("Failed to destroy object");
}
continue;
}
res = fpgaObjectRead(dev_obj, (uint8_t *)cdevid, 0, obj_size, 0);
if (res != FPGA_OK) {
OPAE_ERR("Failed to read device node");
resval = res;
res = fpgaDestroyObject(&dev_obj);
if (res != FPGA_OK) {
OPAE_ERR("Failed to destroy object");
}
continue;
}
res = fpgaDestroyObject(&dev_obj);
if (res != FPGA_OK) {
resval = res;
OPAE_ERR("Failed to destroy object");
}
// append null char
cdevid[obj_size - 1] = '\0';
strncpy(path, "/dev/char/", 11);
strncat(path, cdevid, sizeof(path) - obj_size - 1);
res = get_phy_info(path, &group_info[i]);
if (res != FPGA_OK) {
OPAE_ERR("Failed to get phy group info");
resval = res;
}
} // end for loop
out_destroy_group_dev:
res = fpgaDestroyObject(&group_dev_object);
if (res != FPGA_OK) {
OPAE_ERR("Failed to destroy object");
}
out_destroy_group:
res = fpgaDestroyObject(&group_object);
if (res != FPGA_OK) {
OPAE_ERR("Failed to destroy object");
}
return resval;
}
// get pyh group information
fpga_result get_phy_info(char *dev_path, fpga_phy_group_info *info)
{
fpga_result res = FPGA_OK;
int fd = 0;
if (dev_path == NULL ||
info == NULL) {
FPGA_ERR("Invalid Input parameters");
return FPGA_INVALID_PARAM;
}
fd = open(dev_path, O_RDWR);
if (fd < 0) {
OPAE_ERR("Open %s failed\n", dev_path);
return FPGA_INVALID_PARAM;
}
memset(info, 0, sizeof(fpga_phy_group_info));
info->argsz = sizeof(fpga_phy_group_info);
if (0 != ioctl(fd, FPGA_PHY_GROUP_GET_INFO, info)) {
OPAE_ERR("ioctl FPGA_PHY_GROUP_GET_INFO error\n");
}
close(fd);
return res;
}
// Read mac information
fpga_result read_mac_info(fpga_token token, unsigned char *mac_info, size_t len)
{
fpga_result res = FPGA_OK;
fpga_result resval = FPGA_OK;
unsigned char buf[8] = {0};
fpga_object mac_object;
if (!token || !mac_info || !len) {
FPGA_ERR("Invalid Input parameters");
return FPGA_INVALID_PARAM;
}
res = fpgaTokenGetObject(token, SYSFS_EEPROM, &mac_object, FPGA_OBJECT_GLOB);
if (res != FPGA_OK) {
OPAE_ERR("Failed to get token object");
return res;
}
res = fpgaObjectRead(mac_object, (uint8_t *)buf, 0, sizeof(buf), 0);
if (res != FPGA_OK) {
OPAE_ERR("Failed to read object ");
resval = res;
goto out_destroy_mac;
}
memcpy(mac_info, buf, len);
out_destroy_mac:
res = fpgaDestroyObject(&mac_object);
if (res != FPGA_OK) {
OPAE_ERR("Failed to destroy object");
}
return resval;
}
// Read pkvl versoin
fpga_result print_pkvl_version(fpga_token token)
{
fpga_result res = FPGA_OK;
fpga_result resval = FPGA_OK;
char ver_a_buf[FPGA_VAR_BUF_LEN] = { 0 };
char ver_b_buf[FPGA_VAR_BUF_LEN] = { 0 };
uint32_t size = 0;
fpga_object pkvl_a_object;
fpga_object pkvl_b_object;
res = fpgaTokenGetObject(token, SYSFS_PKVL_A_VER, &pkvl_a_object, FPGA_OBJECT_GLOB);
if (res != FPGA_OK) {
OPAE_MSG("Failed to get token object");
return res;
}
res = fpgaTokenGetObject(token, SYSFS_PKVL_B_VER, &pkvl_b_object, FPGA_OBJECT_GLOB);
if (res != FPGA_OK) {
OPAE_MSG("Failed to get token object");
resval = res;
goto out_destroy_obj_a;
}
res = fpgaObjectGetSize(pkvl_a_object, &size, FPGA_OBJECT_GLOB);
if (res != FPGA_OK) {
OPAE_ERR("Failed to get object size");
resval = res;
goto out_destroy_obj_b;
}
if (size > FPGA_VAR_BUF_LEN) {
OPAE_ERR("pkvl A version buffer bigger then version buffer");
resval = FPGA_EXCEPTION;
goto out_destroy_obj_b;
}
res = fpgaObjectRead(pkvl_a_object, (uint8_t *)ver_a_buf, 0, size, 0);
if (res != FPGA_OK) {
OPAE_ERR("Failed to read object ");
resval = res;
goto out_destroy_obj_b;
}
res = fpgaObjectGetSize(pkvl_b_object, &size, FPGA_OBJECT_GLOB);
if (res != FPGA_OK) {
OPAE_ERR("Failed to get object size");
resval = res;
goto out_destroy_obj_b;
}
if (size > FPGA_VAR_BUF_LEN) {
OPAE_ERR("pkvl B version buffer bigger then version buffer");
resval = FPGA_EXCEPTION;
goto out_destroy_obj_b;
}
res = fpgaObjectRead(pkvl_b_object, (uint8_t *)ver_b_buf, 0, size, 0);
if (res != FPGA_OK) {
OPAE_ERR("Failed to read object ");
resval = res;
goto out_destroy_obj_b;
}
printf("%-32s : %s", "Retimer A Version", ver_a_buf);
printf("%-32s : %s", "Retimer B Version", ver_b_buf);
out_destroy_obj_b:
res = fpgaDestroyObject(&pkvl_b_object);
if (res != FPGA_OK) {
OPAE_ERR("Failed to destroy object");
}
out_destroy_obj_a:
res = fpgaDestroyObject(&pkvl_a_object);
if (res != FPGA_OK) {
OPAE_ERR("Failed to destroy object");
}
return resval;
}
// print mac information
fpga_result print_mac_info(fpga_token token)
{
fpga_result res = FPGA_OK;
unsigned char buf[MAC_BUF_SIZE] = { 0 };
int i = 0;
int n = 0;
pkvl_mac mac;
res = read_mac_info(token, buf, MAC_BUF_SIZE);
if (res != FPGA_OK) {
OPAE_ERR("Failed to read mac information");
return res;
}
n = (int)buf[6];
printf("%-32s : %d\n", "Number of MACs", n);
mac.byte[0] = buf[5];
mac.byte[1] = buf[4];
mac.byte[2] = buf[3];
mac.byte[3] = 0;
for (i = 0; i < n; ++i) {
printf("%s %-20d : %02X:%02X:%02X:%02X:%02X:%02X\n",
"MAC address", i, buf[0], buf[1], buf[2],
mac.byte[2], mac.byte[1], mac.byte[0]);
mac.dword += 1;
}
return res;
}
// print board information
fpga_result print_board_info(fpga_token token)
{
fpga_result res = FPGA_OK;
char bmc_ver[FPGA_VAR_BUF_LEN] = { 0 };
char max10_ver[FPGA_VAR_BUF_LEN] = { 0 };
char pcb_ver[FPGA_VAR_BUF_LEN] = { 0 };
res = read_bmcfw_version(token, bmc_ver, FPGA_VAR_BUF_LEN);
if (res != FPGA_OK) {
OPAE_MSG("Failed to read bmc version");
}
res = read_max10fw_version(token, max10_ver, FPGA_VAR_BUF_LEN);
if (res != FPGA_OK) {
OPAE_MSG("Failed to read max10 version");
}
res = read_pcb_info(token, pcb_ver, FPGA_VAR_BUF_LEN);
if (res != FPGA_OK) {
OPAE_MSG("Failed to read pcb version");
}
printf("Board Management Controller, MAX10 NIOS FW version: %s \n", bmc_ver);
printf("Board Management Controller, MAX10 Build version: %s \n", max10_ver);
printf("PCB version: %s \n", pcb_ver);;
return res;
}
// print phy group information
fpga_result print_phy_info(fpga_token token)
{
fpga_result res = FPGA_OK;
fpga_phy_group_info *phy_info_array = NULL;
uint32_t group_num = 0;
int fpga_mode = 0;
uint32_t i = 0;
int j = 0;
char mode[VER_BUF_SIZE] = { 0 };
fpga_pkvl_info pkvl_info;
res = read_phy_group_info(token, NULL, &group_num);
if (res != FPGA_OK) {
OPAE_ERR("Failed to read phy group count");
return res;
}
phy_info_array = calloc(sizeof(fpga_phy_group_info), group_num);
if (phy_info_array == NULL) {
OPAE_ERR(" Failed to allocate memory");
return FPGA_NO_MEMORY;
}
res = read_phy_group_info(token, phy_info_array, &group_num);
if (res != FPGA_OK) {
OPAE_ERR("Failed to read phy group array");
goto out_free;
}
res = read_pkvl_info(token, &pkvl_info, &fpga_mode);
if (res != FPGA_OK) {
OPAE_ERR("Failed to read pkvl info");
goto out_free;
}
for (i = 0; i < group_num; i++) {
printf("//****** PHY GROUP %d ******//\n", i);
printf("%-32s : %s\n", "Direction",
phy_info_array[i].group_id == 0 ? "Line side" : "Fortville side");
printf("%-32s : %d Gbps\n", "Speed", phy_info_array[i].speed);
printf("%-32s : %d\n", "Number of PHYs", phy_info_array[i].phy_num);
}
int mask = 0;
if (phy_info_array[0].speed == 10) {
mask = 0xff;
} else if (phy_info_array[0].speed == 25) {
if (phy_info_array[0].phy_num == 4) {
switch (fpga_mode) {
case FPGA_PHYGROUP_MODE_4_25G: /* 4x25g */
/* FALLTHROUGH */
case FPGA_PHYGROUP_MODE_6_25G: /* 6x25g */
mask = 0xf;
break;
case FPGA_PHYGROUP_MODE_2_2_25G: /* 2x2x25g */
mask = 0x33;
break;
default:
mask = 0xff;
break;
}
} else {
/* 2*1*25g */
mask = 0x11;
}
}
printf("//****** Intel C827 Retimer ******//\n");
strncpy(mode, phy_info_array[0].speed == 25 ? "25G" : "10G", 4);
for (i = 0, j = 0; i < MAX_PORTS; i++) {
if (mask&(1 << i)) {
printf("Port%-2d%-26s : %s\n", j, mode, pkvl_info.status&(1 << i) ? "Up" : "Down");
j++;
}
}
res = print_pkvl_version(token);
if (res != FPGA_OK) {
OPAE_MSG("Failed to read pkvl version");
goto out_free;
}
out_free:
if (phy_info_array)
free(phy_info_array);
return res;
}