provide ptypes、fw_version、module info/eeprom ops.

Signed-off-by: Junlong Wang <wang.junlong1@zte.com.cn>
---
 drivers/net/zxdh/zxdh_ethdev.c     |  30 +++++
 drivers/net/zxdh/zxdh_ethdev_ops.c | 200 +++++++++++++++++++++++++++++
 drivers/net/zxdh/zxdh_ethdev_ops.h |   5 +
 drivers/net/zxdh/zxdh_msg.h        |  37 +++++-
 4 files changed, 271 insertions(+), 1 deletion(-)

diff --git a/drivers/net/zxdh/zxdh_ethdev.c b/drivers/net/zxdh/zxdh_ethdev.c
index 3bdbc2fe6d..5546b6bfc3 100644
--- a/drivers/net/zxdh/zxdh_ethdev.c
+++ b/drivers/net/zxdh/zxdh_ethdev.c
@@ -1343,6 +1343,32 @@ zxdh_txq_info_get(struct rte_eth_dev *dev, uint16_t tx_queue_id, struct rte_eth_
     qinfo->queue_state = dev->data->tx_queue_state[tx_queue_id];
 }
 
+static const uint32_t *
+zxdh_dev_supported_ptypes_get(struct rte_eth_dev *dev, size_t *ptype_sz)
+{
+    static const uint32_t ptypes[] = {
+        RTE_PTYPE_L2_ETHER,
+        RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
+        RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
+        RTE_PTYPE_L4_NONFRAG,
+        RTE_PTYPE_L4_FRAG,
+        RTE_PTYPE_L4_TCP,
+        RTE_PTYPE_L4_UDP,
+        RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
+        RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
+        RTE_PTYPE_INNER_L4_NONFRAG,
+        RTE_PTYPE_INNER_L4_FRAG,
+        RTE_PTYPE_INNER_L4_TCP,
+        RTE_PTYPE_INNER_L4_UDP,
+        RTE_PTYPE_UNKNOWN
+    };
+
+    if (!dev->rx_pkt_burst)
+        return NULL;
+    *ptype_sz = sizeof(ptypes);
+    return ptypes;
+}
+
 /* dev_ops for zxdh, bare necessities for basic operation */
 static const struct eth_dev_ops zxdh_eth_dev_ops = {
     .dev_configure             = zxdh_dev_configure,
@@ -1378,6 +1404,10 @@ static const struct eth_dev_ops zxdh_eth_dev_ops = {
     .xstats_get_names         = zxdh_dev_xstats_get_names,
     .xstats_reset             = zxdh_dev_stats_reset,
     .mtu_set                 = zxdh_dev_mtu_set,
+    .fw_version_get             = zxdh_dev_fw_version_get,
+    .get_module_info         = zxdh_dev_get_module_info,
+    .get_module_eeprom         = zxdh_dev_get_module_eeprom,
+    .dev_supported_ptypes_get = zxdh_dev_supported_ptypes_get,
 };
 
 static int32_t
diff --git a/drivers/net/zxdh/zxdh_ethdev_ops.c b/drivers/net/zxdh/zxdh_ethdev_ops.c
index 74cf058957..3e88860765 100644
--- a/drivers/net/zxdh/zxdh_ethdev_ops.c
+++ b/drivers/net/zxdh/zxdh_ethdev_ops.c
@@ -2023,3 +2023,203 @@ zxdh_dev_xstats_get_names(struct rte_eth_dev *dev,
     }
     return nstats;
 }
+
+int
+zxdh_dev_fw_version_get(struct rte_eth_dev *dev,
+         char *fw_version, size_t fw_size __rte_unused)
+{
+    struct zxdh_hw *hw = dev->data->dev_private;
+    struct zxdh_msg_info msg_info = {0};
+    struct zxdh_msg_reply_info reply_info = {0};
+    char fw_ver[ZXDH_FWVERS_LEN] = {0};
+    uint32_t ret = 0;
+
+    zxdh_agent_msg_build(hw, ZXDH_FLASH_FIR_VERSION_GET, &msg_info);
+
+    struct zxdh_msg_recviver_mem rsp_data = {
+            .recv_buffer = (void *)&reply_info,
+            .buffer_len = sizeof(struct zxdh_msg_reply_info),
+    };
+
+    ret = zxdh_send_msg_to_riscv(dev, &msg_info, sizeof(struct zxdh_msg_info),
+                &reply_info, sizeof(struct zxdh_msg_reply_info),
+                ZXDH_MODULE_FLASH);
+    if (ret) {
+        PMD_DRV_LOG(ERR, "Failed to send msg: port 0x%x msg type %d",
+                hw->vport.vport, ZXDH_FLASH_FIR_VERSION_GET);
+        return -1;
+    }
+    struct zxdh_msg_reply_body *ack_msg =
+             &(((struct zxdh_msg_reply_info *)rsp_data.recv_buffer)->reply_body);
+
+    memcpy(fw_ver, ack_msg->flash_msg.firmware_version, ZXDH_FWVERS_LEN);
+    snprintf(fw_version, ZXDH_FWVERS_LEN - 1, "%s", fw_ver);
+
+    return 0;
+}
+
+static uint8_t
+zxdh_en_module_eeprom_read(struct rte_eth_dev *dev,
+         struct zxdh_mac_module_eeprom_msg *query, uint8_t *data)
+{
+    struct zxdh_hw *hw = dev->data->dev_private;
+    struct zxdh_msg_info msg_info = {0};
+    struct zxdh_msg_reply_info reply_info = {0};
+    uint8_t ret = 0;
+
+    zxdh_agent_msg_build(hw, ZXDH_MAC_MODULE_EEPROM_READ, &msg_info);
+
+    msg_info.data.module_eeprom_msg.i2c_addr = query->i2c_addr;
+    msg_info.data.module_eeprom_msg.bank = query->bank;
+    msg_info.data.module_eeprom_msg.page = query->page;
+    msg_info.data.module_eeprom_msg.offset = query->offset;
+    msg_info.data.module_eeprom_msg.length = query->length;
+
+    struct zxdh_msg_recviver_mem rsp_data = {
+            .recv_buffer = (void *)&reply_info,
+            .buffer_len = sizeof(struct zxdh_msg_reply_info),
+    };
+
+    ret = zxdh_send_msg_to_riscv(dev, &msg_info, sizeof(struct zxdh_msg_info),
+                &reply_info, sizeof(struct zxdh_msg_reply_info),
+                ZXDH_BAR_MODULE_MAC);
+    if (ret) {
+        PMD_DRV_LOG(ERR, "Failed to send msg: port 0x%x msg type %d",
+                hw->vport.vport, ZXDH_MAC_MODULE_EEPROM_READ);
+        return -1;
+    }
+    struct zxdh_msg_reply_body *ack_msg =
+             &(((struct zxdh_msg_reply_info *)rsp_data.recv_buffer)->reply_body);
+
+    if (data)
+        memcpy(data, ack_msg->module_eeprom_msg.data, ack_msg->module_eeprom_msg.length);
+
+    return ack_msg->module_eeprom_msg.length;
+}
+
+int
+zxdh_dev_get_module_info(struct rte_eth_dev *dev,
+             struct rte_eth_dev_module_info *modinfo)
+{
+    struct zxdh_hw *hw = dev->data->dev_private;
+    struct zxdh_mac_module_eeprom_msg query = {0};
+    uint8_t read_bytes;
+    uint8_t data[2] = {0};
+
+    if (!hw->is_pf)
+        return -EOPNOTSUPP;
+
+    query.i2c_addr = ZXDH_SFF_I2C_ADDRESS_LOW;
+    query.page = 0;
+    query.offset = 0;
+    query.length = 2;
+
+    read_bytes = zxdh_en_module_eeprom_read(dev, &query, data);
+    if (read_bytes != query.length) {
+        PMD_DRV_LOG(ERR, "zxdh_en_module_eeprom_read failed!");
+        return -EIO;
+    }
+
+    switch (data[0]) {
+    case ZXDH_MODULE_ID_SFP:
+        modinfo->type       = RTE_ETH_MODULE_SFF_8472;
+        modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
+        break;
+    case ZXDH_MODULE_ID_QSFP:
+        modinfo->type       = RTE_ETH_MODULE_SFF_8436;
+        modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8436_MAX_LEN;
+        break;
+    case ZXDH_MODULE_ID_QSFP_PLUS:
+    case ZXDH_MODULE_ID_QSFP28:
+        if (data[1] < 3) {
+            modinfo->type       = RTE_ETH_MODULE_SFF_8436;
+            modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8436_MAX_LEN;
+        } else {
+            modinfo->type       = RTE_ETH_MODULE_SFF_8636;
+            modinfo->eeprom_len = RTE_ETH_MODULE_SFF_8636_MAX_LEN;
+        }
+        break;
+    default:
+        PMD_DRV_LOG(ERR, "can not recognize module identifier 0x%x!", data[0]);
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+
+int
+zxdh_dev_get_module_eeprom(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *info)
+{
+    struct zxdh_mac_module_eeprom_msg query = {0};
+    uint32_t offset = info->offset;
+    uint32_t length = info->length;
+    uint32_t offset_boundary = 0;
+    uint32_t total_read_bytes = 0;
+    uint8_t read_bytes = 0;
+    uint8_t identifier;
+    uint8_t *data = NULL;
+
+    if (!info->length)
+        return -EINVAL;
+
+    data = info->data;
+    memset(data, 0, info->length);
+
+    query.i2c_addr = ZXDH_SFF_I2C_ADDRESS_LOW;
+    query.bank = 0;
+    query.page = 0;
+    query.offset = 0;
+    query.length = 1;
+    read_bytes = zxdh_en_module_eeprom_read(dev, &query, &identifier);
+    if (read_bytes != query.length) {
+        PMD_DRV_LOG(ERR, "read eeprom failed(read_bytes %d != query.length %d)!",
+             read_bytes, query.length);
+        return -EIO;
+    }
+
+    while (total_read_bytes < info->length) {
+        if (identifier == ZXDH_MODULE_ID_SFP) {
+            if (offset < 256) {
+                query.i2c_addr = ZXDH_SFF_I2C_ADDRESS_LOW;
+                query.page = 0;
+                query.offset = offset;
+            } else {
+                query.i2c_addr = ZXDH_SFF_I2C_ADDRESS_HIGH;
+                query.page = 0;
+                query.offset = offset - 256;
+            }
+            offset_boundary = (query.offset < 128) ? 128 : 256;
+            query.length = ((query.offset + length) > offset_boundary) ?
+                         (offset_boundary - query.offset) : length;
+        } else if (identifier == ZXDH_MODULE_ID_QSFP ||
+                identifier == ZXDH_MODULE_ID_QSFP_PLUS ||
+                identifier == ZXDH_MODULE_ID_QSFP28) {
+            query.i2c_addr = ZXDH_SFF_I2C_ADDRESS_LOW;
+            if (offset < 256) {
+                query.page = 0;
+                query.offset = offset;
+            } else {
+                query.page = (offset - 256) / 128 + 1;
+                query.offset = offset - 128 * query.page;
+            }
+            offset_boundary = (query.offset < 128) ? 128 : 256;
+            query.length = ((query.offset + length) > offset_boundary) ?
+                         (offset_boundary - query.offset) : length;
+        } else {
+            PMD_DRV_LOG(ERR, "can not recognize module identifier 0x%x!", identifier);
+            return -EINVAL;
+        }
+
+        read_bytes = zxdh_en_module_eeprom_read(dev, &query, data + total_read_bytes);
+        if (read_bytes != query.length) {
+            PMD_DRV_LOG(ERR, "read eeprom failed(read_bytes %d != query.length %d)",
+                 read_bytes, query.length);
+            return -EIO;
+        }
+        total_read_bytes = (total_read_bytes + read_bytes) % UINT32_MAX;
+        offset += read_bytes;
+        length -= read_bytes;
+    }
+    return 0;
+}
diff --git a/drivers/net/zxdh/zxdh_ethdev_ops.h b/drivers/net/zxdh/zxdh_ethdev_ops.h
index 37d0299f23..08b9e3341b 100644
--- a/drivers/net/zxdh/zxdh_ethdev_ops.h
+++ b/drivers/net/zxdh/zxdh_ethdev_ops.h
@@ -103,5 +103,10 @@ int32_t zxdh_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstat
 int32_t zxdh_dev_xstats_get_names(struct rte_eth_dev *dev,
             struct rte_eth_xstat_name *xstats_names,
             __rte_unused unsigned int limit);
+int zxdh_dev_fw_version_get(struct rte_eth_dev *dev, char *fw_version,
+                 size_t fw_size __rte_unused);
+int zxdh_dev_get_module_info(struct rte_eth_dev *dev,
+             struct rte_eth_dev_module_info *modinfo);
+int zxdh_dev_get_module_eeprom(struct rte_eth_dev *dev, struct rte_dev_eeprom_info *info);
 
 #endif /* ZXDH_ETHDEV_OPS_H */
diff --git a/drivers/net/zxdh/zxdh_msg.h b/drivers/net/zxdh/zxdh_msg.h
index cb830fa2da..b3e202c026 100644
--- a/drivers/net/zxdh/zxdh_msg.h
+++ b/drivers/net/zxdh/zxdh_msg.h
@@ -48,10 +48,17 @@
 #define ZXDH_MSG_REPLY_BODY_MAX_LEN  \
         (ZXDH_MSG_PAYLOAD_MAX_LEN - sizeof(struct zxdh_msg_reply_head))
 
-#define ZXDH_MSG_HEAD_LEN 8
+#define ZXDH_MSG_HEAD_LEN            8
 #define ZXDH_MSG_REQ_BODY_MAX_LEN  \
         (ZXDH_MSG_PAYLOAD_MAX_LEN - ZXDH_MSG_HEAD_LEN)
 
+#define ZXDH_FWVERS_LEN              32
+
+#define ZXDH_SFF_I2C_ADDRESS_LOW     (0x50)
+#define ZXDH_SFF_I2C_ADDRESS_HIGH    (0x51)
+
+#define ZXDH_MODULE_EEPROM_DATA_LEN   128
+
 #define ZXDH_MAC_FILTER            0xaa
 #define ZXDH_MAC_UNFILTER          0xff
 #define ZXDH_PROMISC_MODE          1
@@ -180,13 +187,25 @@ enum pciebar_layout_type {
     ZXDH_URI_MAX,
 };
 
+enum zxdh_module_id {
+    ZXDH_MODULE_ID_SFP       = 0x3,
+    ZXDH_MODULE_ID_QSFP      = 0xC,
+    ZXDH_MODULE_ID_QSFP_PLUS = 0xD,
+    ZXDH_MODULE_ID_QSFP28    = 0x11,
+    ZXDH_MODULE_ID_QSFP_DD   = 0x18,
+    ZXDH_MODULE_ID_OSFP      = 0x19,
+    ZXDH_MODULE_ID_DSFP      = 0x1B,
+};
+
 /* riscv msg opcodes */
 enum zxdh_agent_msg_type {
     ZXDH_MAC_STATS_GET = 10,
     ZXDH_MAC_STATS_RESET,
     ZXDH_MAC_LINK_GET = 14,
+    ZXDH_MAC_MODULE_EEPROM_READ = 20,
     ZXDH_VQM_DEV_STATS_GET = 21,
     ZXDH_VQM_DEV_STATS_RESET,
+    ZXDH_FLASH_FIR_VERSION_GET = 23,
     ZXDH_VQM_QUEUE_STATS_GET = 24,
     ZXDH_VQM_QUEUE_STATS_RESET,
 };
@@ -320,6 +339,19 @@ enum zxdh_reps_flag {
     ZXDH_REPS_INVALID = 0xee,
 };
 
+struct __rte_packed_begin zxdh_mac_module_eeprom_msg {
+    uint8_t i2c_addr;
+    uint8_t bank;
+    uint8_t page;
+    uint8_t offset;
+    uint8_t length;
+    uint8_t data[ZXDH_MODULE_EEPROM_DATA_LEN];
+} __rte_packed_end;
+
+struct zxdh_flash_msg {
+    uint8_t firmware_version[ZXDH_FWVERS_LEN];
+};
+
 struct zxdh_np_stats_updata_msg {
     uint32_t clear_mode;
 };
@@ -352,6 +384,8 @@ struct __rte_packed_begin zxdh_msg_reply_body {
         struct zxdh_rss_hf rss_hf;
         struct zxdh_hw_vqm_stats vqm_stats;
         struct zxdh_np_stats_updata_msg np_stats_query;
+        struct zxdh_flash_msg flash_msg;
+        struct zxdh_mac_module_eeprom_msg module_eeprom_msg;
     } __rte_packed_end;
 } __rte_packed_end;
 
@@ -438,6 +472,7 @@ struct __rte_packed_begin zxdh_msg_info {
         struct zxdh_rss_enable rss_enable;
         struct zxdh_rss_hf rss_hf;
         struct zxdh_np_stats_updata_msg np_stats_query;
+        struct zxdh_mac_module_eeprom_msg module_eeprom_msg;
     } __rte_packed_end data;
 } __rte_packed_end;
 
-- 
2.27.0